重构: AI聊天可靠性批次(审批累计计数/write_file diff预览/会话隔离补清/token缓存)

This commit is contained in:
2026-06-16 19:56:29 +08:00
parent ba7f35552b
commit d00b30f0ba
12 changed files with 238 additions and 45 deletions

View File

@@ -36,6 +36,10 @@
</div>
</div>
<div v-if="tc.reason" class="ai-tool-approval-reason"> {{ tc.reason }}</div>
<!-- AE-2025-03: write_file 审批 diff 预览红删绿增行级旧文件不存在tc.diff 为空回退显上方 args content -->
<div v-if="tc.diff" class="ai-tool-approval-diff">
<pre class="ai-tool-diff-pre"><code><span v-for="(ln, idx) in diffLines" :key="idx" class="ai-tool-diff-line" :class="'ai-tool-diff-line--' + ln.kind">{{ ln.text }}{{ '\n' }}</span></code></pre>
</div>
<div class="ai-tool-actions">
<button class="ai-tool-btn ai-tool-btn--approve"
:disabled="approving"
@@ -382,6 +386,23 @@ onBeforeUnmount(() => {
/** 一次解析结果供模板多次读(模板引用 6 次,computed 避免每次 patch 重 parse) */
const parsed = computed(() => parseResult(props.tc.result))
/**
* AE-2025-03: write_file 审批 diff 行解析。
* 后端 generate_diff 输出 '+新行/-旧行/ 上下文行',逐行拆 → {kind, text} 供模板按 kind 着色。
* kind: 'add'(+, 绿)/'del'(-, 红)/'ctx'(空格, 灰)。computed 在 diff 变化(新审批)时重算。
*/
const diffLines = computed(() => {
const d = props.tc.diff
if (!d) return []
return d.split('\n').map(line => {
// 注意 generate_diff 末尾保留单尾换行 → split 末尾有空串元素,过滤
if (line === '') return null
if (line.startsWith('+')) return { kind: 'add', text: line }
if (line.startsWith('-')) return { kind: 'del', text: line }
return { kind: 'ctx', text: line }
}).filter((x): x is { kind: string; text: string } => x !== null)
})
/**
* 按 id 查项目名(覆盖活跃 + 回收站):审批 delete/restore/purge 各阶段都可能引用项目,
* 故先查 projects 再查 deletedProjects,找到即返回(提前退出),无则返回 undefined(调用方走 fallback)。
@@ -652,6 +673,37 @@ function toolResultSummary(tc: AiToolCallInfo): string {
border-radius: var(--df-radius-sm, 4px);
}
/* AE-2025-03: write_file 审批 diff 预览区(红删绿增行级,复用 --df-danger/--df-success token */
.ai-tool-approval-diff {
margin: 0 10px 8px;
border: 0.5px solid var(--df-border);
border-radius: var(--df-radius-sm, 4px);
overflow: hidden;
}
.ai-tool-diff-pre {
margin: 0;
padding: 6px 0;
max-height: 240px;
overflow: auto;
font-family: var(--df-font-mono);
font-size: 11px;
line-height: 1.5;
background: var(--df-bg-card);
}
.ai-tool-diff-pre code {
display: block;
white-space: pre;
}
.ai-tool-diff-line {
display: block;
padding: 0 10px;
white-space: pre-wrap;
word-break: break-all;
}
.ai-tool-diff-line--add { color: var(--df-success, #3ddb9c); background: var(--df-success-bg, rgba(61, 219, 160, 0.08)); }
.ai-tool-diff-line--del { color: var(--df-danger, #f06565); background: var(--df-danger-bg, rgba(240, 101, 101, 0.08)); }
.ai-tool-diff-line--ctx { color: var(--df-text-dim, #888); }
/* -- 审批按钮 -- */
.ai-tool-actions {
display: flex;