fix: show tool parameters and skip duplicate calls
This commit is contained in:
+29
-3
@@ -7,7 +7,7 @@ import { api, post, put, subscribeRun } from './api';
|
||||
const { Title, Text, Paragraph } = Typography;
|
||||
const kinds: Record<string, string> = { import: '导入学生材料', course_ingest: '课程资料入库', create_batch: '创建评分批次', start_batch: '启动/重试评分批次', review: '教师复核', export: '导出成绩或反馈', index_retry: '重试索引任务' };
|
||||
const categories: Record<string, string> = { stage1: '阶段报告1', stage2: '阶段报告2', stage3: '阶段报告3', final_report: '最终报告', presentation: '汇报PPT/PDF' };
|
||||
const statusColor = (status: string) => status === 'completed' || status === 'ready' ? 'green' : status === 'failed' || status === 'stale' ? 'red' : 'orange';
|
||||
const statusColor = (status: string) => status === 'completed' || status === 'ready' ? 'green' : status === 'failed' || status === 'stale' ? 'red' : status === 'skipped' ? 'default' : 'orange';
|
||||
const reportError = (error: unknown) => message.error(error instanceof Error ? error.message : String(error));
|
||||
|
||||
function ImportEditor({ action, conversationId, reload }: { action: any; conversationId: number; reload: () => void }) {
|
||||
@@ -108,6 +108,32 @@ function Citations({ items }: { items: any[] }) {
|
||||
if (!unique.length) return null;
|
||||
return <section className="chat-citations" aria-label="引用资料"><details className="chat-citation-group"><summary><Text strong>引用 · {unique.length}</Text></summary><CitationCards items={unique} /></details></section>;
|
||||
}
|
||||
const argumentLabels: Record<string, string> = {
|
||||
query: '查询词 (query)', course_version_id: '课程版本 ID', batch_id: '评分批次 ID', project_id: '学生项目 ID',
|
||||
score_id: '评分 ID', task_id: '任务 ID', rubric_version_id: '量规版本 ID', criterion_id: '评分项 ID',
|
||||
project_offset: '项目偏移量', criterion_offset: '评分项偏移量', offset: '偏移量', limit: '数量上限',
|
||||
status: '状态筛选', student_no: '学号', relative_dir: '目录', score: '分数', format: '格式',
|
||||
};
|
||||
function visibleArguments(call: any) {
|
||||
const args: Record<string, unknown> = call.arguments && typeof call.arguments === 'object' && !Array.isArray(call.arguments)
|
||||
? { ...call.arguments } : {};
|
||||
let missing = Number(args.omitted_text_fields || args.omitted_fields || 0);
|
||||
delete args.omitted_text_fields;
|
||||
delete args.omitted_fields;
|
||||
// Older score calls kept their effective offsets in the result but dropped them from arguments.
|
||||
if (call.name === 'get_scores') for (const field of ['project_offset', 'criterion_offset']) {
|
||||
if (!(field in args) && typeof call.result?.[field] === 'number') {
|
||||
args[field] = call.result[field];
|
||||
missing = Math.max(0, missing - 1);
|
||||
}
|
||||
}
|
||||
if (['search_course_material', 'search_project_material'].includes(call.name) && !('query' in args) && missing > 0) {
|
||||
args.query = '历史调用未保存查询词';
|
||||
missing -= 1;
|
||||
}
|
||||
if (missing > 0) args['历史未保存参数'] = `${missing} 项`;
|
||||
return Object.fromEntries(Object.entries(args).map(([field, value]) => [argumentLabels[field] || field, value]));
|
||||
}
|
||||
function Tools({ calls }: { calls: any[] }) {
|
||||
if (!calls?.length) return null;
|
||||
const active = calls.filter(call => call.status === 'running').length;
|
||||
@@ -115,9 +141,9 @@ function Tools({ calls }: { calls: any[] }) {
|
||||
return <section className="chat-tools" aria-label="工具调用"><details className="chat-tool-group"><summary><Text strong>工具调用 · {calls.length}</Text>
|
||||
{active > 0 && <Tag color="processing">{active} 项进行中</Tag>}{failed > 0 && <Tag color="red">{failed} 项失败</Tag>}</summary>
|
||||
<div className="chat-tool-list">{calls.map((call, index) => <details key={call.id || index} className="chat-tool"><summary><Space wrap size="small"><Text code>{call.name || '未知工具'}</Text>
|
||||
<Tag color={statusColor(call.status || 'completed')}>{call.status === 'running' ? '进行中' : call.status === 'failed' ? '失败' : '成功'}</Tag>
|
||||
<Tag color={statusColor(call.status || 'completed')}>{call.status === 'running' ? '进行中' : call.status === 'failed' ? '失败' : call.status === 'skipped' ? '已跳过' : '成功'}</Tag>
|
||||
<Text type="secondary">{call.status === 'running' ? '正在执行' : call.error ? String(call.error).slice(0, 80) : call.summary || (typeof call.result === 'string' ? call.result : '已完成')}</Text></Space></summary>
|
||||
<div className="tool-detail"><Text strong>调用参数</Text><pre>{JSON.stringify(call.arguments || {}, null, 2)}</pre>
|
||||
<div className="tool-detail"><Text strong>调用参数</Text><pre>{JSON.stringify(visibleArguments(call), null, 2)}</pre>
|
||||
<Text strong>{call.error ? '错误' : '调用结果'}</Text><pre>{call.error || (typeof call.result === 'string' ? call.result : JSON.stringify(call.result ?? '运行中', null, 2))}</pre></div>
|
||||
</details>)}</div></details></section>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user