From 1500a15be1d935db7c59f3ee2070dd187c9a253e Mon Sep 17 00:00:00 2001 From: JOJO <1498581755@qq.com> Date: Tue, 14 Apr 2026 13:44:06 +0800 Subject: [PATCH] fix: enhance manage_personalization tool display --- core/main_terminal_parts/tools_execution.py | 1 + .../components/chat/actions/ToolAction.vue | 176 ++++++++++++++++++ utils/tool_result_formatter.py | 39 ++++ 3 files changed, 216 insertions(+) diff --git a/core/main_terminal_parts/tools_execution.py b/core/main_terminal_parts/tools_execution.py index 556180e..6a53280 100644 --- a/core/main_terminal_parts/tools_execution.py +++ b/core/main_terminal_parts/tools_execution.py @@ -1424,6 +1424,7 @@ class MainTerminalToolsExecutionMixin: "success": True, "message": f"字段 '{field}' 更新成功", "updated_field": field, + "old_value": old_value, "updated_value": value } diff --git a/static/src/components/chat/actions/ToolAction.vue b/static/src/components/chat/actions/ToolAction.vue index e287a35..55f18b1 100644 --- a/static/src/components/chat/actions/ToolAction.vue +++ b/static/src/components/chat/actions/ToolAction.vue @@ -163,6 +163,11 @@ function renderEnhancedToolResult(): string { return renderUpdateMemory(result, args); } + // 个性化管理类 + else if (name === 'manage_personalization') { + return renderManagePersonalization(result, args); + } + // 待办事项类 else if (name === 'todo_create') { return renderTodoCreate(result, args); @@ -702,6 +707,116 @@ function renderUpdateMemory(result: any, args: any): string { return html; } +function formatPersonalizationFieldLabel(field: string): string { + const labelMap: Record = { + enabled: '个性化功能', + self_identify: 'AI 自称', + user_name: '用户称呼', + profession: '用户职业', + tone: '交流语气', + considerations: '注意事项', + theme: '主题配色', + communication_style: '交流风格' + }; + return labelMap[field] || field; +} + +function formatPersonalizationFieldValue(field: string, value: any): string { + if (value === null || value === undefined || value === '') { + return '未设置'; + } + + if (field === 'enabled') { + return value ? '开启' : '关闭'; + } + if (field === 'theme') { + const themeMap: Record = { + classic: 'classic(经典)', + light: 'light(明亮)', + dark: 'dark(暗黑)' + }; + return themeMap[String(value)] || String(value); + } + if (field === 'communication_style') { + const styleMap: Record = { + default: 'default(标准 AI 风格)', + human_like: 'human_like(拟人聊天风格)' + }; + return styleMap[String(value)] || String(value); + } + if (field === 'considerations') { + if (!Array.isArray(value) || value.length === 0) { + return '未设置'; + } + return value.map((item) => String(item)).join('、'); + } + + return String(value); +} + +function renderManagePersonalization(result: any, args: any): string { + const action = String(args.action || result.action || 'read'); + const status = formatToolStatusLabel( + result, + action === 'update' ? '✓ 已更新' : '✓ 已读取' + ); + + let html = '
'; + html += `
操作:${escapeHtml(action === 'update' ? '更新配置' : '读取配置')}
`; + html += `
状态:${status}
`; + + if (!result?.success) { + if (result?.error) { + html += `
错误:${escapeHtml(String(result.error))}
`; + } + if (Array.isArray(result?.validation_errors) && result.validation_errors.length > 0) { + html += `
校验:${escapeHtml(result.validation_errors.join(';'))}
`; + } + html += '
'; + return html; + } + + if (action === 'update') { + const field = String(result.updated_field || args.field || ''); + const oldValue = result.old_value ?? args.old_value; + const newValue = result.updated_value ?? args.value; + + if (field) { + html += `
字段:${escapeHtml(formatPersonalizationFieldLabel(field))}
`; + html += `
新值:${escapeHtml(formatPersonalizationFieldValue(field, newValue))}
`; + if (oldValue !== undefined) { + html += `
旧值:${escapeHtml(formatPersonalizationFieldValue(field, oldValue))}
`; + } + } + if (result?.theme_changed && result?.new_theme) { + html += `
主题刷新:${escapeHtml(formatPersonalizationFieldValue('theme', result.new_theme))}
`; + } + html += ''; + + return html; + } + + const data = result?.data && typeof result.data === 'object' ? result.data : {}; + const entries = Object.entries(data); + html += `
配置项:${entries.length} 项
`; + html += ''; + + if (entries.length > 0) { + html += '
'; + html += '
当前个性化配置
'; + html += '
'; + entries.forEach(([field, value]) => { + html += '
'; + html += `${escapeHtml(formatPersonalizationFieldLabel(field))}`; + html += `${escapeHtml(formatPersonalizationFieldValue(field, value))}`; + html += '
'; + }); + html += '
'; + } + + return html; +} + // ===== 待办事项类 ===== function renderTodoCreate(result: any, args: any): string { const status = formatToolStatusLabel(result, '✓ 已创建'); @@ -1102,4 +1217,65 @@ function renderEasterEgg(result: any, args: any): string { font-size: 12px; line-height: 1.5; } + +/* 个性化管理 */ +.personalization-message { + padding: 12px; + background: rgba(0, 0, 0, 0.02); + border-radius: 6px; + font-size: 13px; + line-height: 1.6; + white-space: pre-wrap; +} + +:root[data-theme='dark'] .personalization-message { + background: rgba(255, 255, 255, 0.05); +} + +.personalization-config-title { + font-weight: 600; + margin-bottom: 8px; + color: rgba(0, 0, 0, 0.8); +} + +:root[data-theme='dark'] .personalization-config-title { + color: rgba(255, 255, 255, 0.9); +} + +.personalization-config-list { + display: grid; + gap: 6px; +} + +.config-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 6px 10px; + background: rgba(0, 0, 0, 0.02); + border-radius: 4px; + font-size: 12px; +} + +:root[data-theme='dark'] .config-item { + background: rgba(255, 255, 255, 0.05); +} + +.config-label { + color: rgba(0, 0, 0, 0.6); + font-weight: 500; +} + +:root[data-theme='dark'] .config-label { + color: rgba(255, 255, 255, 0.6); +} + +.config-value { + color: rgba(0, 0, 0, 0.9); + font-weight: 400; +} + +:root[data-theme='dark'] .config-value { + color: rgba(255, 255, 255, 0.9); +} diff --git a/utils/tool_result_formatter.py b/utils/tool_result_formatter.py index 01370a2..a2c6a2f 100644 --- a/utils/tool_result_formatter.py +++ b/utils/tool_result_formatter.py @@ -800,6 +800,44 @@ def _format_command_result(label: str, result_data: Dict[str, Any]) -> str: return "\n".join(lines) +def _format_manage_personalization(result_data: Dict[str, Any]) -> str: + action = result_data.get("action") or "read" + if not result_data.get("success"): + validation_errors = result_data.get("validation_errors") or [] + base = _format_failure("manage_personalization", result_data) + if validation_errors: + return base + "\n校验失败: " + ";".join(str(item) for item in validation_errors) + return base + + if action == "update" or result_data.get("updated_field"): + field = result_data.get("updated_field") or "未知字段" + old_value = result_data.get("old_value") + new_value = result_data.get("updated_value") + parts = [f"个性化字段已更新: {field}"] + if old_value is not None: + parts.append(f"旧值: {old_value}") + if new_value is not None: + parts.append(f"新值: {new_value}") + if result_data.get("theme_changed") and result_data.get("new_theme"): + parts.append(f"主题已切换为: {result_data.get('new_theme')}") + message = result_data.get("message") + if message: + parts.append(str(message)) + return "\n".join(parts) + + config = result_data.get("data") or {} + if not isinstance(config, dict): + return result_data.get("message") or "个性化配置读取成功" + + lines = ["当前个性化配置:"] + for key, value in config.items(): + lines.append(f"- {key}: {value}") + message = result_data.get("message") + if message: + lines.append(str(message)) + return "\n".join(lines) + + def _summarize_todo_tasks(todo: Optional[Dict[str, Any]]) -> str: if not isinstance(todo, dict): return "" @@ -831,6 +869,7 @@ TOOL_FORMATTERS = { "todo_create": _format_todo_create, "todo_update_task": _format_todo_update_task, "update_memory": _format_update_memory, + "manage_personalization": _format_manage_personalization, "create_sub_agent": _format_create_sub_agent, "wait_sub_agent": _format_wait_sub_agent, "close_sub_agent": _format_close_sub_agent,