diff --git a/crates/df-workflow/Cargo.toml b/crates/df-workflow/Cargo.toml index 343df98..5c55277 100644 --- a/crates/df-workflow/Cargo.toml +++ b/crates/df-workflow/Cargo.toml @@ -11,7 +11,7 @@ edition = "2021" # 开启时:节点收集 inputs 前,对带 condition 的入边以 source output 为 context 求值; # 求值 false 则该前驱 input 不收集,且若该节点所有入边(含 condition)均被过滤, # 则跳过该节点执行(保持 Pending),实现条件路由。 -default = [] +default = ["conditions-eval"] conditions-eval = [] [dependencies] diff --git a/docs/todo.md b/docs/todo.md index 2d2c713..b785d8b 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -15,7 +15,13 @@ - [ ] **L2 Enrichment 可见**: @[项目] 发送前展开 enrichment 摘要 - [ ] **L3 完整上下文**: 可展开面板查看 system_prompt / augmentations ---- +### 💡 2026-06-27 统一 Inbox 设计(讨论产出) + +> 思路:所有需要用户注意的事项(审批/知识待审/灵感确认/其他通知)集中到一个统一入口, +> 不阻塞对话。 +> +> 审批留在对话内(需要即时上下文),知识/灵感/通知放 Inbox。 +> 后续做详细设计方案。 ## 🎯 统一规划(2026-06-26 全景) @@ -65,10 +71,10 @@ graph TD | **G1** 目标钉扎 | 🔨 代码✅`8ce18cb` 待实测 | G1/G2/G4 落地 | — | | **父①** 小bug攒批 | ✅ 完成 | ①.2 白名单✅(settings.rs) / ①.3 priority✅(idea.rs) / ①.1 BUG层1❌过时(F-260619-03 方案①取代,层2待决策) / ①.4 雷达图→归父⑤ | — | | **父②** 知识图谱Phase1 | ✅ Phase1完成 | ②.1 V29迁移✅ / ②.2 TaskRecord+TaskLinkRepo✅ / ②.3 IPC(create_task扩展+task_link CRUD+move_queue+get_tree)✅ / ②.4 父聚合✅(set_status_for_aggregation绕status收口) / ②.5 AI工具6✅(基线38) | G1(弱) | -| **父③** AI对话体验 | 🔨 ③.1✅ / ③.2待办 | ③.1 B-260619-04 ToolCard✅(跨轮收起已有+标题增强) / ③.2 REFACTOR-260619-04 审批状态机拆分 | — | +| **父③** AI对话体验 | 🔨 ③.1✅ / ③.2待办 | ③.1 B-260619-04 ToolCard✅(跨轮收起已有+标题增强) / ③.2 REFACTOR-260619-04 审批状态机拆分 / 对话透明化 L1🟡待定 | — | | **父④** F-09 per-conv | ✅ 前端per-conv | ④.1 streaming/currentText per-conv Map(accessor委派,单会话回归零变化,BUG-260624-01根因清除,vue-tsc 0) | — | | **父⑤** 灵感模块 | ✅ 完成 | ⑤.1 软删除✅ / ①.4 雷达图✅ / ⑤.2 #05✅/#06拆const✅/#09/#10表单(逗号tags)✅ / #07 DEC-02保留purge(不改) / 附:priority_from_i32跨层映射修复(对齐前端0=critical) | #07→②.1 | -| **父⑥** Phase2-5 | 🔨 Phase4 注入进行中 | ⑥.1事件流✅(V30) / ⑥.2基础设施✅(V31) / ⑥.3注入✅(resolver 增强+extra 渲染) / ⑥.4前端📋 +| **父⑥** Phase2-5 | 🔨 Phase4 注入进行中 | ⑥.1事件流✅(V30) / ⑥.2基础设施✅(V31) / ⑥.3注入✅(resolver 增强+extra 渲染) / ⑥.4前端(C 方案展开摘要✅已决待实施) | | **父⑦** 技术债 | 📋 待办 | SMELL-P1-6 / conditions / CR缓存 / UX分页 / 审批超时 / miniapp / 双监听器 | — (穿插) | > **推进路径**:父①先行(攒批提交)→ 父②主线 workflow → 父③/④并行 → 父⑤/⑥/⑦穿插。每父任务一个 workflow 批,子任务相关文件批量读改减少交互。**状态更新约定**:子项完成→父状态 🔨;全子完成→父 ✅;每批提交后同步此表。 diff --git a/docs/待决策.md b/docs/待决策.md index 1886724..fb5201c 100644 --- a/docs/待决策.md +++ b/docs/待决策.md @@ -244,4 +244,51 @@ - [2026-06.md](./07-项目管理/待决策归档/2026-06.md) — 2026-06 已决策/已实施/已排期/已解决历史(③类产品取舍 12 项 / ④类设计方向 6 项 / 重投入排期 8 项 / ④类续 5 项 / C类已解决 2 项) -> 新月份拍板项累积时,新建 `YYYY-MM.md` 承载。 +### 2026-06-27 讨论已决 + +#### DEC-260627-01 F-09 B 路线(多会话真并发) +- **决策**:✅ 需要实施 +- **记录**:用户确认需要推进多会话并发架构 +- **状态**:✅ 已决 + +#### DEC-260627-02 Conditions 条件引擎 +- **决策**:✅ 需要接入使用(开启 feature flag + 可视化) +- **记录**:用户确认需要启用条件引擎并接入工作流执行器 +- **状态**:✅ 已决 + +#### DEC-260627-03 @项目展开摘要(⑥.4 Phase4 前端) +- **决策**:✅ C 方案展开摘要 +- **记录**:@[项目] 发送前可展开查看 enrichment 内容 +- **状态**:✅ 已决 + +#### DEC-260627-04 历史消息渲染 +- **决策**:✅ C 暂缓 +- **记录**:长对话渲染卡顿暂不处理 +- **状态**:✅ 已决 + +### 2026-06-27 讨论待定 + +#### 对话透明化 L1(目标钉扎可见) +- **背景**:G1 目标钉扎已落地,但用户完全看不见自己设了哪些目标 +- **选项**: + - A: 不做 + - B: 对话顶部显示目标列表 + - C: 显示 + 可删除过时目标 + 持久化 +- **决策**:✅ C 方案。对话顶部 🎯 显示目标列表(✅/🔄/⏳ 状态),可清除/编辑,持久化到 ai_conversations 表 +- **配套**:模型选择器折叠缩小腾空间 +- **状态**:✅ 已决 + +#### 灵感来源采集 +- **背景**:灵感捕捉时没有自动记录来源 +- **选项**: + - A: 对话自动采集 + - B: 手动录入增强 + - C: 暂缓 +- **决策**:✅ C 暂缓。与知识库抽取共用一次 AI 调用,但灵感需用户确认后才创建(非自动写入)。需前端通知机制,当前不做 +- **状态**:✅ 已决 — 暂缓 + +--- + +## 已决归档 + +按月归档(随时间增长追加月份文件,防主文件膨胀): diff --git a/src/components/workflow/WorkflowDagDisplay.vue b/src/components/workflow/WorkflowDagDisplay.vue new file mode 100644 index 0000000..c43576f --- /dev/null +++ b/src/components/workflow/WorkflowDagDisplay.vue @@ -0,0 +1,131 @@ + + + {{ $t('taskDetail.workflowDagTitle') || '工作流结构' }} + + + + + ⬡ + {{ node.id }} + {{ nodeTypeLabel[node.node_type] || node.node_type }} + + + + + + + {{ edge.source }} → {{ edge.target }} + + {{ edge.condition }} + + + 无条件 + + + + + + {{ $t('taskDetail.workflowDagEmpty') || '暂无工作流数据' }} + + + + + + diff --git a/src/views/TaskDetail.vue b/src/views/TaskDetail.vue index 0afebaa..bf43767 100644 --- a/src/views/TaskDetail.vue +++ b/src/views/TaskDetail.vue @@ -168,6 +168,7 @@ import { } from '../constants/project' import type { TaskRecord, ProjectRecord, IdeaRecord, DfDataChangedPayload, WorkflowEventPayload } from '@/api/types' import TaskOutputCard from '@/components/task/TaskOutputCard.vue' +import WorkflowDagDisplay from '@/components/workflow/WorkflowDagDisplay.vue' const { t } = useI18n() const route = useRoute() @@ -198,6 +199,15 @@ let _wfResultTimer: ReturnType | null = null const wfProgressHint = computed(() => wfResult.value !== null) const wfCompletedHint = computed(() => wfResult.value === 'completed') const wfFailedHint = computed(() => wfResult.value === 'failed') + +// 工作流 DAG 结构展示 +const wfDagJson = ref('') +async function refreshWorkflowDag(execId: string) { + try { + const record = await workflowApi.getExecution(execId) + if (record?.dag_json) wfDagJson.value = record.dag_json + } catch { /* 静默 */ } +} const wfDoneTotal = computed(() => wfTotalNodes.value) const taskId = computed(() => route.params.id as string) @@ -337,6 +347,7 @@ async function handleWorkflowAdvance(target: string) { ) wfExecId.value = execId errorMsg.value = '' + await refreshWorkflowDag(execId) } catch (e: any) { wfAdvancing.value = false wfExecId.value = null