重构: 审批交互重设计

This commit is contained in:
lxy
2026-10-05 14:59:12 +08:00
parent 24d6803ecc
commit 2eea0118db
7 changed files with 254 additions and 30 deletions
+16
View File
@@ -42,6 +42,8 @@ export function handleToolEvent(event: AiChatEvent): boolean {
tc.status = 'completed'
tc.result = event.result
tc.completedAt = Date.now()
// 清流式缓冲:结果由 result 渲染,流式行是执行中间态,留着会双显
tc.streamLines = undefined
}
// 移除待审批(含 per-conv 集合,后台会话集合里的同 id 挂起一并清)
removePendingApprovalById(event.id)
@@ -57,6 +59,20 @@ export function handleToolEvent(event: AiChatEvent): boolean {
return true
}
case 'AiCommandOutput': {
// 工具执行实时流式(run_command shell 行级 / ask_uclaw 进度块级):
// 按 id 路由到对应工具卡,streamLines 追加(上限 200 行防长任务刷爆响应式数组,
// 超限丢头保尾——最新进度更有价值)。Completed 时清空(结果由 result 渲染,防双显)。
// 找不到工具卡(极早到/已收尾)静默忽略。
const tc = findToolCall(event.id)
if (tc) {
if (!tc.streamLines) tc.streamLines = []
tc.streamLines.push(event.line)
if (tc.streamLines.length > 200) tc.streamLines.splice(0, tc.streamLines.length - 200)
}
return true
}
case 'AiApprovalRequired': {
clearStreamWatchdog(event.conversation_id || undefined) // 等用户审批,不计整流超时
const info: AiToolCallInfo = {
+16
View File
@@ -38,6 +38,9 @@ const HIGH_RISK_TOOLS_FALLBACK = new Set<string>([
/** 后端注册表投影的 High 风险名单;null = 尚未拉到元数据(走兜底名单) */
let registryHighRisk: Set<string> | null = null
/** 后端注册表投影的 Medium 风险名单;null = 尚未拉到元数据(无兜底,安全侧降级不显徽章) */
let registryMediumRisk: Set<string> | null = null
/**
* 用后端 ai_list_tools 元数据构建 High 风险名单(权威源,整体覆盖兜底)。
* 空结果不覆盖:注册表为空/数据异常时保留兜底名单,安全侧不放松。
@@ -46,6 +49,8 @@ let registryHighRisk: Set<string> | null = null
export function syncHighRiskTools(tools: { name: string; risk: string }[]): void {
const high = tools.filter((t) => t.risk === 'high').map((t) => t.name)
if (high.length > 0) registryHighRisk = new Set(high)
const med = tools.filter((t) => t.risk === 'medium').map((t) => t.name)
if (med.length > 0) registryMediumRisk = new Set(med)
}
/** 审批二次确认门控:优先注册表投影,未拉到元数据时退兜底名单。
@@ -54,6 +59,17 @@ export function isHighRiskTool(name: string): boolean {
return (registryHighRisk ?? HIGH_RISK_TOOLS_FALLBACK).has(name)
}
/**
* 工具风险等级判定(high/medium/low):审批卡着色条+徽章数据源。
* high 优先注册表投影、未拉到时退兜底名单(与 isHighRiskTool 同口径);
* medium 仅注册表投影,无兜底——未拉到元数据时不误标中危(安全侧降级:少显徽章优于乱标)。
*/
export function toolRiskLevel(name: string): 'high' | 'medium' | 'low' {
if ((registryHighRisk ?? HIGH_RISK_TOOLS_FALLBACK).has(name)) return 'high'
if (registryMediumRisk?.has(name)) return 'medium'
return 'low'
}
/**
* 审批 IPC 分派(共享):按 tc.kind 决定调 aiApi.authorizeDir(path 类)或 aiApi.approve(risk 类)。
*