(params: Record<string, unknown>, context: ToolExecutionContext)
| 21 | } |
| 22 | |
| 23 | async function handler(params: Record<string, unknown>, context: ToolExecutionContext): Promise<ToolResult> { |
| 24 | const { locale, segmentText } = context |
| 25 | const isZh = isChineseLocale(locale) |
| 26 | const days = (params.days as number) || 30 |
| 27 | const topN = (params.top_n as number) || 50 |
| 28 | |
| 29 | if (!segmentText) { |
| 30 | const text = isZh ? '当前环境不支持分词功能' : 'Text segmentation is not available in this environment' |
| 31 | return { content: text, data: null } |
| 32 | } |
| 33 | |
| 34 | const sql = ` |
| 35 | SELECT content FROM message |
| 36 | WHERE type = 0 AND content IS NOT NULL AND LENGTH(content) > 1 |
| 37 | AND ts > unixepoch('now', '-' || @days || ' days') |
| 38 | LIMIT 50000 |
| 39 | ` |
| 40 | const rows = await context.dataProvider!.executeParameterizedSql<TextRow>(sql, { days }) |
| 41 | if (!rows || rows.length === 0) { |
| 42 | const text = isZh ? '该时间范围内没有文本消息' : 'No text messages in this time range' |
| 43 | return { content: text, data: null } |
| 44 | } |
| 45 | |
| 46 | const texts = rows.map((r) => r.content) |
| 47 | const segLocale: string = locale?.startsWith('ja') ? 'ja-JP' : locale?.startsWith('zh') ? 'zh-CN' : 'en-US' |
| 48 | const freqResult = segmentText(texts, segLocale, { |
| 49 | minCount: 2, |
| 50 | topN, |
| 51 | posFilterMode: 'meaningful', |
| 52 | enableStopwords: true, |
| 53 | }) |
| 54 | |
| 55 | if (freqResult.words.size === 0) { |
| 56 | const text = isZh ? '分词后没有有意义的高频词' : 'No meaningful high-frequency words found after segmentation' |
| 57 | return { content: text, data: null } |
| 58 | } |
| 59 | |
| 60 | const ranking = [...freqResult.words.entries()].map(([word, count], i) => ({ |
| 61 | rank: i + 1, |
| 62 | word, |
| 63 | count, |
| 64 | })) |
| 65 | |
| 66 | const data = { |
| 67 | period: isZh ? `近${days}天` : `Last ${days} days`, |
| 68 | totalMessages: rows.length, |
| 69 | totalKeywords: ranking.length, |
| 70 | keywords: ranking.map((r) => `${r.rank}. ${r.word} (${r.count}${isZh ? '次' : ''})`), |
| 71 | } |
| 72 | |
| 73 | return { content: JSON.stringify(data), data } |
| 74 | } |
| 75 | |
| 76 | export const keywordFrequencyTool: ToolDefinition = { |
| 77 | name: 'keyword_frequency', |
nothing calls this directly
no test coverage detected