agent-Specialization/static/src/utils/chatDisplay.ts

276 lines
8.1 KiB
TypeScript

import { TOOL_ICON_MAP } from './icons';
type ToolPayload = Record<string, any> | null | undefined;
const RUNNING_ANIMATIONS: Record<string, string> = {
create_file: 'file-animation',
read_file: 'read-animation',
delete_file: 'file-animation',
rename_file: 'file-animation',
modify_file: 'file-animation',
append_to_file: 'file-animation',
create_folder: 'file-animation',
focus_file: 'focus-animation',
unfocus_file: 'focus-animation',
web_search: 'search-animation',
extract_webpage: 'search-animation',
save_webpage: 'file-animation',
run_python: 'code-animation',
run_command: 'terminal-animation',
update_memory: 'memory-animation',
sleep: 'wait-animation',
terminal_session: 'terminal-animation',
terminal_input: 'terminal-animation',
terminal_snapshot: 'terminal-animation',
terminal_reset: 'terminal-animation',
todo_create: 'file-animation',
todo_update_task: 'file-animation',
todo_finish: 'file-animation',
todo_finish_confirm: 'file-animation',
create_sub_agent: 'terminal-animation',
wait_sub_agent: 'wait-animation'
};
const RUNNING_STATUS_TEXTS: Record<string, string> = {
create_file: '正在创建文件...',
sleep: '正在等待...',
delete_file: '正在删除文件...',
rename_file: '正在重命名文件...',
modify_file: '正在修改文件...',
append_to_file: '正在追加文件...',
create_folder: '正在创建文件夹...',
focus_file: '正在聚焦文件...',
unfocus_file: '正在取消聚焦...',
web_search: '正在搜索网络...',
extract_webpage: '正在提取网页...',
save_webpage: '正在保存网页...',
run_python: '调用 run_python',
run_command: '调用 run_command',
update_memory: '正在更新记忆...',
terminal_session: '正在管理终端会话...',
terminal_input: '调用 terminal_input',
terminal_snapshot: '正在获取终端快照...',
terminal_reset: '正在重置终端...'
};
const COMPLETED_STATUS_TEXTS: Record<string, string> = {
create_file: '文件创建成功',
delete_file: '文件删除成功',
sleep: '等待完成',
rename_file: '文件重命名成功',
modify_file: '文件修改成功',
append_to_file: '文件追加完成',
create_folder: '文件夹创建成功',
focus_file: '文件聚焦成功',
unfocus_file: '取消聚焦成功',
web_search: '搜索完成',
extract_webpage: '网页提取完成',
save_webpage: '网页保存完成(纯文本)',
run_python: '代码执行完成',
run_command: '命令执行完成',
update_memory: '记忆更新成功',
terminal_session: '终端操作完成',
terminal_input: '终端输入完成',
terminal_snapshot: '终端快照已返回',
terminal_reset: '终端已重置'
};
const LANGUAGE_CLASS_MAP: Record<string, string> = {
py: 'language-python',
js: 'language-javascript',
html: 'language-html',
css: 'language-css',
json: 'language-json',
md: 'language-markdown',
txt: 'language-plain'
};
const SEARCH_TOPIC_MAP: Record<string, string> = {
general: '通用',
news: '新闻',
finance: '金融'
};
const RELATIVE_TIME_RANGE_MAP: Record<string, string> = {
day: '过去24小时',
week: '过去7天',
month: '过去30天',
year: '过去365天'
};
export function getToolIcon(tool: any): string {
const toolName = typeof tool === 'string' ? tool : tool?.name;
return TOOL_ICON_MAP[toolName as keyof typeof TOOL_ICON_MAP] || 'settings';
}
export function getToolAnimationClass(tool: any): string {
if (!tool) {
return '';
}
if (tool.status === 'hinted') {
return 'hint-animation pulse-slow';
}
if (tool.status === 'preparing') {
return 'preparing-animation';
}
if (tool.status === 'running') {
return RUNNING_ANIMATIONS[tool.name] || 'default-animation';
}
return '';
}
function describeReadFileResult(tool: any): string {
if (!tool?.result || typeof tool.result !== 'object') {
return '文件读取完成';
}
const readType = String(tool.result.type || 'read').toLowerCase();
if (readType === 'search') {
const query = tool.result.query ? `${tool.result.query}` : '';
const count =
typeof tool.result.returned_matches === 'number'
? tool.result.returned_matches
: tool.result.actual_matches || 0;
return `搜索${query},得到${count}个结果`;
}
if (readType === 'extract') {
const segments = Array.isArray(tool.result.segments) ? tool.result.segments : [];
const totalLines = segments.reduce((sum: number, seg: any) => {
const start = Number(seg.line_start) || 0;
const end = Number(seg.line_end) || 0;
if (!start || !end || end < start) {
return sum;
}
return sum + (end - start + 1);
}, 0);
const displayLines = totalLines || tool.result.char_count || 0;
return `提取了${displayLines}`;
}
return '文件读取完成';
}
export function getToolStatusText(tool: any): string {
if (!tool) {
return '';
}
if (tool.message) {
return tool.message;
}
if (tool.status === 'hinted') {
return `可能需要 ${tool.name}...`;
}
if (tool.status === 'preparing') {
return `准备调用 ${tool.name}...`;
}
if (tool.status === 'running') {
if (tool.name === 'read_file') {
const readType = String(
tool.argumentSnapshot?.type || tool.arguments?.type || 'read'
).toLowerCase();
const runningMap: Record<string, string> = {
read: '正在读取文件...',
search: '正在执行搜索...',
extract: '正在提取内容...'
};
return runningMap[readType] || '正在读取文件...';
}
const label =
RUNNING_STATUS_TEXTS[tool.name] ||
tool.display_name ||
tool.name ||
'';
return label ? label : '调用工具中';
}
if (tool.status === 'completed') {
if (tool.name === 'read_file') {
return describeReadFileResult(tool);
}
return COMPLETED_STATUS_TEXTS[tool.name] || '执行完成';
}
return `${tool.name} - ${tool.status}`;
}
export function getToolDescription(tool: any): string {
if (!tool) {
return '';
}
const args = tool.argumentSnapshot || tool.arguments;
const argumentLabel = tool.argumentLabel || buildToolLabel(args);
if (argumentLabel) {
return argumentLabel;
}
if (tool.statusDetail) {
return tool.statusDetail;
}
if (tool.result && typeof tool.result === 'object' && tool.result.path) {
return String(tool.result.path).split('/').pop() || '';
}
return '';
}
export function cloneToolArguments(args: any): any {
if (!args || typeof args !== 'object') {
return null;
}
try {
return JSON.parse(JSON.stringify(args));
} catch (error) {
console.warn('无法克隆工具参数:', error);
return { ...args };
}
}
export function buildToolLabel(args: any): string {
if (!args || typeof args !== 'object') {
return '';
}
if (args.command) {
return args.command;
}
if (args.path) {
return String(args.path).split('/').pop() || '';
}
if (args.target_path) {
return String(args.target_path).split('/').pop() || '';
}
if (args.query) {
return `"${args.query}"`;
}
if (typeof args.seconds !== 'undefined') {
return `${args.seconds}`;
}
if (args.name) {
return args.name;
}
return '';
}
export function formatSearchTopic(filters: ToolPayload): string {
const topic = filters?.topic ? String(filters.topic).toLowerCase() : 'general';
return SEARCH_TOPIC_MAP[topic] || '通用';
}
export function formatSearchTime(filters: ToolPayload): string {
if (!filters) {
return '未限定时间';
}
if (filters.time_range) {
const key = String(filters.time_range).toLowerCase();
return RELATIVE_TIME_RANGE_MAP[key] || `相对范围:${filters.time_range}`;
}
if (typeof filters.days === 'number') {
return `过去${filters.days}`;
}
if (filters.start_date && filters.end_date) {
return `${filters.start_date}${filters.end_date}`;
}
return '未限定时间';
}
export function getLanguageClass(path: string): string {
if (!path) {
return 'language-plain';
}
const ext = path.split('.').pop()?.toLowerCase() || '';
return LANGUAGE_CLASS_MAP[ext] || 'language-plain';
}