新增: 批次工作落地(推进链/评估闭环/事件总线/并发/加固) + 技术债清理 + 文档整理
后端: - 工作流推进链(D-03):advance_task/状态机/闸门走 df-nodes Node trait,conditions 条件引擎扩展 - 想法评估闭环:启发式评分+对抗评估,df-ideas/scoring + df-storage/idea_eval_repo + idea 前端打通 - 全局事件数据总线:df-ai/context+context_helpers+augmentation 跨模块解耦 - AI planner/plan_hint/intent:aichat B 路线并行多轮基础 - patch_file 加固(TD-03/04):读改写整体锁防 lost update,expected_hash 合约闭环 - 压缩超时兜底(F-15 卡死根治) - F-09 多会话并发:LlmConcurrency per-conv + streamingGuard 前端守护 + verify 脚本 - 知识注入 DRY/skills/audit 扩展 清理: - aichat 技术债(误报 allow/死导入/过时注释 30 项) - URGENT.md 删除(11 项加急全解决/迁 todo) - 文档整理(todo/待决策/待审查/ARCHITECTURE/INDEX + 总线/技术债审查新文档)
This commit is contained in:
@@ -9,6 +9,7 @@ import { useAppSettingsStore } from '@/stores/appSettings'
|
||||
import { state } from '@/stores/ai'
|
||||
import { notifyConversationChanged } from './useAiEvents'
|
||||
import { persistUiState } from './useAiPanel'
|
||||
import { setStreaming } from './streamingGuard'
|
||||
import { nextMsgId } from './aiShared'
|
||||
import { t } from '@/i18n/i18n-helpers'
|
||||
import type { AiMessage, AiToolCallInfo } from '@/api/types'
|
||||
@@ -70,7 +71,7 @@ async function newConversation() {
|
||||
state.messages = []
|
||||
state.currentText = ''
|
||||
state.pendingApprovals = []
|
||||
state.streaming = false
|
||||
setStreaming(false, { reason: 'newConversation' })
|
||||
// F-09 决策e(真并发):newConversation 对齐 switchConversation 并行语义——旧 conv 后台 loop 继续,
|
||||
// 不清 generatingConvs(保留旧 conv 生成态跟踪,侧栏显双会话生成,AiCompleted/AiError 按
|
||||
// conversation_id 正确收尾旧 conv)。原 state.generatingConvs.clear() 是 A 路线 F-260616-09
|
||||
@@ -96,6 +97,12 @@ export async function switchConversation(id: string) {
|
||||
if (mySwitchId !== _latestSwitchId) return
|
||||
state.activeConversationId = id
|
||||
void appSettings.set('df-ai-active-conv', id)
|
||||
// P1#6 技术债审查(2026-06-21):streaming 是全局单值,切到非生成会话需按目标 conv 生成态重算,
|
||||
// 否则残留 stop 按钮(ChatInput.vue:88 v-if=streaming)→ 点击 store.stopChat 传 activeConversationId
|
||||
// 发错会话。对齐 newConversation 复位语义;目标在后台生成时保留 true(stop/流式显示正确)。
|
||||
// 根治归 F-09 B 路线:streaming 改 per-conv 态。此处为 A 路线过渡补丁。
|
||||
// 走 setStreaming guard 收敛写入口(convId=id 联动幂等——has(id) 决定值,add/delete 幂等无副作用)。
|
||||
setStreaming(state.generatingConvs.has(id), { convId: id, reason: 'switchConversation-recompute' })
|
||||
|
||||
try {
|
||||
const rawMsgs = typeof detail.messages === 'string'
|
||||
@@ -181,18 +188,41 @@ export async function switchConversation(id: string) {
|
||||
state.currentText = ''
|
||||
// 恢复该对话积压的待审批:重启后后端从审计表重建了 pending_approvals,
|
||||
// 此处查回并把对应 toolCard.status 置 pending_approval,使审批卡片重新可见
|
||||
// 阶段4:按 IPC 返的 kind 渲染——'path' 类显 once/always/deny(tc.kind='path' + 推 path/dir 文案),
|
||||
// 'risk' 类显 approve/reject(tc.kind='risk'/缺省)。对齐阶段3b 统一审批模型(两 kind 都可恢复)。
|
||||
try {
|
||||
const pending = await aiApi.pendingToolCalls(id)
|
||||
// 第二 await 后二次比对:切换 A→B 期间避免用 A 的 pending 覆写 B 的 pendingApprovals
|
||||
if (mySwitchId !== _latestSwitchId) return
|
||||
if (pending.length) {
|
||||
// kind 索引:tool_call_id → kind('risk'/'path'),供恢复 tc/pendingApprovals 按类型渲染
|
||||
const pendingKindMap = new Map(pending.map(p => [p.tool_call_id, p.kind]))
|
||||
const pendingIds = new Set(pending.map(p => p.tool_call_id))
|
||||
const restored: AiToolCallInfo[] = []
|
||||
for (const m of state.messages) {
|
||||
for (const tc of (m.toolCalls || [])) {
|
||||
if (pendingIds.has(tc.id)) {
|
||||
tc.status = 'pending_approval'
|
||||
restored.push({ id: tc.id, name: tc.name, args: tc.args, status: 'pending_approval' })
|
||||
const kind = pendingKindMap.get(tc.id) ?? 'risk'
|
||||
tc.kind = kind
|
||||
// path 类审批:从 tc.args.path 推 path/dir 文案(后端 IPC 仅返 kind,无 dir/path;
|
||||
// 此处从工具参数派生,供 ToolCard 审批提示展示)。缺 path 参数的 path 类回退空。
|
||||
if (kind === 'path') {
|
||||
const p = (tc.args as { path?: string } | null)?.path
|
||||
tc.path = p
|
||||
tc.dir = p ?? undefined
|
||||
tc.reason = t('aiChat.dirAuthHint', { tool: tc.name, path: p ?? '' })
|
||||
}
|
||||
restored.push({
|
||||
id: tc.id,
|
||||
name: tc.name,
|
||||
args: tc.args,
|
||||
status: 'pending_approval',
|
||||
kind,
|
||||
path: tc.path,
|
||||
dir: tc.dir,
|
||||
reason: tc.reason,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user