修复: aichat P0 三项(AR-2 新建对话守卫 + AR-3 审批卡片可读化 + AR-4 create_project 双审)

- AR-2 ai_conversation_create 加 generating 守卫(clear 前,防审批态新建清空 session 致 generating 永不复位卡死)
- AR-3 audit.rs build_approval_reason 按 9 工具特化拼对象名(id/field/path/title/name)+ ToolCard resultSummary 补 restore/purge case + ARG_LABEL_MAP id 加友好标签 + i18n 双语补 4 key
- AR-4 create_project schema 加 path/stack + handler 有 path 时合并绑定(spawn_blocking 探测栈,复用 bind_directory 逻辑,消除双审双 API)
- cargo check / vue-tsc 0 error
- 审查 boundary 全误判(并行同工作区 git diff 污染),主代理独立核查三任务全正确
This commit is contained in:
2026-06-14 15:51:49 +08:00
parent f0c525d0e7
commit 057a2121a5
6 changed files with 146 additions and 10 deletions

View File

@@ -31,7 +31,7 @@
<div v-if="tc.status === 'pending_approval'" class="ai-tool-approval">
<div v-if="toolArgsEntries(tc.args).length" class="ai-tool-approval-args">
<div v-for="arg in toolArgsEntries(tc.args)" :key="arg.key" class="ai-tool-arg">
<span class="ai-tool-arg-key">{{ arg.key }}</span>
<span class="ai-tool-arg-key">{{ arg.label }}</span>
<span class="ai-tool-arg-val">{{ formatArgValue(arg.val) }}</span>
</div>
</div>
@@ -119,6 +119,8 @@ interface ToolResult {
title?: string
field?: string
deleted?: boolean
restored?: boolean
purged?: boolean
}
/** 内联 SVG 图标字符串(经 v-html 注入,常量安全;图标库改造见决策记录) */
@@ -145,10 +147,29 @@ function formatJson(data: unknown): string {
}
}
/** 审批参数 key → 友好标签映射(静态,不查 store);未命中回退原 key */
const ARG_LABEL_MAP: Record<string, string> = {
id: 'ID',
project_id: '项目 ID',
name: '名称',
title: '标题',
description: '描述',
field: '字段',
value: '新值',
path: '路径',
priority: '优先级',
tags: '标签',
source: '来源',
}
/** 审批参数转键值对数组(非对象/空时返回空数组,防 args 非 object 时 v-for 报错) */
function toolArgsEntries(args: unknown): Array<{ key: string; val: unknown }> {
function toolArgsEntries(args: unknown): Array<{ key: string; label: string; val: unknown }> {
if (args && typeof args === 'object' && !Array.isArray(args)) {
return Object.entries(args as Record<string, unknown>).map(([key, val]) => ({ key, val }))
return Object.entries(args as Record<string, unknown>).map(([key, val]) => ({
key,
label: ARG_LABEL_MAP[key] || key,
val,
}))
}
return []
}
@@ -282,6 +303,8 @@ function toolResultSummary(tc: AiToolCallInfo): string {
case 'create_task': return r.title ? t('aiTool.createdWithName', { name: r.title }) : t('aiTool.created')
case 'update_project': return r.field ? t('aiTool.updatedField', { field: r.field }) : t('aiTool.updated')
case 'delete_project': return r.deleted ? t('aiTool.deleted') : t('aiTool.deleteIneffective')
case 'restore_project': return r.restored ? t('aiTool.restored') : t('aiTool.restoreIneffective')
case 'purge_project': return r.purged ? t('aiTool.purged') : t('aiTool.purgeIneffective')
case 'run_workflow': return t('aiTool.workflowHint')
default: return ''
}

View File

@@ -26,6 +26,10 @@ export default {
updated: 'Updated',
deleted: 'Deleted',
deleteIneffective: 'Delete ineffective',
restored: 'Restored',
restoreIneffective: 'Restore ineffective (not in trash)',
purged: 'Purged',
purgeIneffective: 'Purge ineffective',
workflowHint: 'Run it on the workflow page',
},
}

View File

@@ -28,6 +28,10 @@ export default {
updated: '已更新',
deleted: '已删除',
deleteIneffective: '删除未生效',
restored: '已恢复',
restoreIneffective: '恢复未生效(项目不在回收站)',
purged: '已彻底删除',
purgeIneffective: '清除未生效',
workflowHint: '请到工作流页面运行',
},
}