From aea7e2540c4f26c4f12a70a79edef63a51ca0779 Mon Sep 17 00:00:00 2001 From: liuyy2 <2487945449@qq.com> Date: Mon, 21 Sep 2026 11:29:12 +0800 Subject: [PATCH] fix(ai): respect time ranges in analysis tools --- .../src/definitions/keyword-frequency.ts | 30 +++++++++++++++---- .../src/definitions/response-time-analysis.ts | 30 +++++++++++++++---- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/packages/tools/src/definitions/keyword-frequency.ts b/packages/tools/src/definitions/keyword-frequency.ts index 9f0ddf36..0289be4f 100644 --- a/packages/tools/src/definitions/keyword-frequency.ts +++ b/packages/tools/src/definitions/keyword-frequency.ts @@ -6,7 +6,9 @@ */ import type { ToolDefinition, ToolExecutionContext, ToolResult, JsonSchema } from '../types' -import { isChineseLocale } from '../utils/format' +import { formatTimeRange, isChineseLocale } from '../utils/format' +import { parseExtendedTimeParams, type ExtendedTimeParams } from '../utils/time-params' +import { timeParamProperties } from '../utils/schemas' interface TextRow { content: string @@ -15,8 +17,12 @@ interface TextRow { const inputSchema: JsonSchema = { type: 'object', properties: { - days: { type: 'number', description: '分析最近多少天的数据,默认 30' }, + days: { + type: 'number', + description: 'Recent days to analyze when no explicit or selected time range is available; defaults to 30', + }, top_n: { type: 'number', description: '返回前多少个高频词,默认 50' }, + ...timeParamProperties, }, } @@ -31,13 +37,20 @@ async function handler(params: Record, context: ToolExecutionCo return { content: text, data: null } } + const effectiveTimeFilter = parseExtendedTimeParams(params as ExtendedTimeParams, context.timeFilter) + const timeCondition = effectiveTimeFilter + ? 'ts >= @startTs AND ts <= @endTs' + : "ts > unixepoch('now', '-' || @days || ' days')" const sql = ` SELECT content FROM message WHERE type = 0 AND content IS NOT NULL AND LENGTH(content) > 1 - AND ts > unixepoch('now', '-' || @days || ' days') + AND ${timeCondition} LIMIT 50000 ` - const rows = await context.dataProvider!.executeParameterizedSql(sql, { days }) + const rows = await context.dataProvider!.executeParameterizedSql( + sql, + effectiveTimeFilter ? { ...effectiveTimeFilter } : { days } + ) if (!rows || rows.length === 0) { const text = isZh ? '该时间范围内没有文本消息' : 'No text messages in this time range' return { content: text, data: null } @@ -63,8 +76,15 @@ async function handler(params: Record, context: ToolExecutionCo count, })) + const formattedRange = formatTimeRange(effectiveTimeFilter, locale) + const period = + typeof formattedRange === 'string' + ? isZh + ? `近${days}天` + : `Last ${days} days` + : `${formattedRange.start} – ${formattedRange.end}` const data = { - period: isZh ? `近${days}天` : `Last ${days} days`, + period, totalMessages: rows.length, totalKeywords: ranking.length, keywords: ranking.map((r) => `${r.rank}. ${r.word} (${r.count}${isZh ? '次' : ''})`), diff --git a/packages/tools/src/definitions/response-time-analysis.ts b/packages/tools/src/definitions/response-time-analysis.ts index 3f3dddb1..183a77be 100644 --- a/packages/tools/src/definitions/response-time-analysis.ts +++ b/packages/tools/src/definitions/response-time-analysis.ts @@ -6,7 +6,9 @@ import { computeResponseTimeStats } from '@openchatlab/core' import type { ToolDefinition, ToolExecutionContext, ToolResult, JsonSchema } from '../types' -import { isChineseLocale } from '../utils/format' +import { formatTimeRange, isChineseLocale } from '../utils/format' +import { parseExtendedTimeParams, type ExtendedTimeParams } from '../utils/time-params' +import { timeParamProperties } from '../utils/schemas' interface MsgRow { sender_id: number @@ -17,8 +19,12 @@ interface MsgRow { const inputSchema: JsonSchema = { type: 'object', properties: { - days: { type: 'number', description: '分析最近多少天的数据,默认 30' }, + days: { + type: 'number', + description: 'Recent days to analyze when no explicit or selected time range is available; defaults to 30', + }, top_n: { type: 'number', description: '返回前多少名,默认 10' }, + ...timeParamProperties, }, } @@ -28,15 +34,22 @@ async function handler(params: Record, context: ToolExecutionCo const days = (params.days as number) || 30 const topN = (params.top_n as number) || 10 + const effectiveTimeFilter = parseExtendedTimeParams(params as ExtendedTimeParams, context.timeFilter) + const timeCondition = effectiveTimeFilter + ? 'msg.ts >= @startTs AND msg.ts <= @endTs' + : "msg.ts > unixepoch('now', '-' || @days || ' days')" const sql = ` SELECT msg.sender_id, COALESCE(m.group_nickname, m.account_name) AS name, msg.ts FROM message msg JOIN member m ON msg.sender_id = m.id WHERE msg.type = 0 - AND msg.ts > unixepoch('now', '-' || @days || ' days') + AND ${timeCondition} ORDER BY msg.ts ASC ` - const rows = await context.dataProvider!.executeParameterizedSql(sql, { days }) + const rows = await context.dataProvider!.executeParameterizedSql( + sql, + effectiveTimeFilter ? { ...effectiveTimeFilter } : { days } + ) if (!rows || rows.length < 2) { const text = isZh ? '该时间范围内消息不足,无法分析响应时间' @@ -69,8 +82,15 @@ async function handler(params: Record, context: ToolExecutionCo count: s.responseCount, })) + const formattedRange = formatTimeRange(effectiveTimeFilter, locale) + const period = + typeof formattedRange === 'string' + ? isZh + ? `近${days}天` + : `Last ${days} days` + : `${formattedRange.start} – ${formattedRange.end}` const data = { - period: isZh ? `近${days}天` : `Last ${days} days`, + period, totalResponders: stats.length, ranking: ranking.map( (r) =>