## 背景 OpenCLI Admin 当前已有数据采集、工作流运行、事件持久化和原生 HDA 能力,但用户在 Studio 画布中仍无法用清晰、稳定、可组合的 L1 业务节点完成通用数据采集。 当前体验存在以下问题: - 数据采集节点的业务颗粒度和命名混乱,A 股示例、OpenCLI、HDA、数据集等概念混在一起。 - 网页、API、RSS、CLI 没有作为四类独立的 L1 采集节点暴露。 - 一个节点无法自然管理多个同类来源。 - CLI 采集仍存在自由文本命令入口,不符合安全和可发现性要求。 - Merge 使用固定输入端口,不能像 Houdini Merge 一样连接任意数量的上游。 - 节点缺少按来源的成功、失败、新鲜度和重试反馈。 - AI 编辑能力没有形成可审阅、可并发、不会覆盖人工修改的节点级提案流程。 本 Epic 将工作流主路径统一为: `开始 → 网页/API/RSS/CLI 采集 → Merge → 清洗 → 结束` 其中四种采集节点均为 L1 业务节点;底层 L2 能力继续封装实现细节。股票数据仅作为真实测试项目,不进入通用产品模型。 ## 目标 1. 在节点工具架提供四类清晰独立的 L1 采集节点:网页、API、RSS、CLI。 2. 每个采集节点实例允许配置多个同类型来源。 3. 提供可直接人工编辑的节点配置体验,并支持 Agent 生成结构化修改提案。 4. 统一采集输出、来源级执行状态、数据新鲜度和部分成功语义。 5. 将 Merge 改造成可连接任意数量上游的纯合并节点。 6. 以增量、兼容、可回滚方式上线,不破坏旧工作流和下游图谱/仿真链路。 ## 非目标 - 本期不扩展图谱、Persona、仿真、访谈、报告或报告问答功能。 - 本期不把清洗、去重、摘要、分类或推理塞入 Merge。 - 本期不允许 CLI 节点执行用户输入的任意 Shell、脚本或命令行。 - 本期不做破坏性数据库迁移,也不批量重写已保存工作流。 - 本期不把 A 股字段或网站写入通用节点契约。 ## 产品与交互设计 ### 节点工具架 新增四个一级节点条目: | Catalog ID | 展示名称 | 用途 | | --- | --- | --- | | `collection.source.web` | 网页采集 | 从多个网页或站点配置采集内容 | | `collection.source.api` | API 采集 | 从多个 HTTP API 配置采集结构化数据 | | `collection.source.rss` | RSS 采集 | 从多个 RSS/Atom Feed 采集条目 | | `collection.source.cli` | CLI 采集 | 从已注册 OpenCLI 工具目录选择工具并运行 | 节点命名只表达业务动作和来源类型,不在名称中混入 OpenCLI、HDA、项目名或数据集名。 ### 节点编辑 选中采集节点后,右侧 Inspector 提供来源列表编辑器: - 添加、删除、启用、停用和排序同类型来源。 - 每个来源显示名称、配置摘要、认证状态和最近验证状态。 - 支持“测试此来源”和“测试全部来源”。 - 支持逐来源重试失败项。 - 支持手动保存;运行前进行确定性校验。 - 预览最多展示 50 条采集结果,同时显示成功数、失败数、新鲜度和来源状态。 各节点只暴露本类型字段: - 网页:URL、抓取模式、选择器/提取规则、分页或时间窗口、凭证引用。 - API:URL、方法、查询参数、Header 模板、Body 模板、分页、响应映射、凭证引用。 - RSS:Feed URL、时间窗口、条目限制。 - CLI:已注册 `adapterNodeId`、目录中声明的 typed arguments、凭证引用。 CLI 编辑器必须从 OpenCLI 工具目录选择已注册工具,不提供自由文本 Shell 输入。以下字段不得进入可保存节点配置:`shell`、`commandLine`、`scriptText`、`rawCommand`、明文 token、password、cookie 或 authorization。 ### Agent 编辑 Agent 不能直接并发写画布。Agent 只生成节点级结构化 Proposal: ```ts type CollectorNodeProposal = { proposalId: string nodeId: string baseRevision: string summary: string operations: CollectorPatchOperation[] } ``` 交互规则: - 多个 Agent 可以基于同一版本并行生成提案。 - 用户逐条查看差异并接受或拒绝。 - 接受时使用 `baseRevision` 做 CAS 校验。 - 版本未变化则原子应用。 - 版本已变化则重新验证;可安全重放时生成 rebased proposal,否则展示冲突。 - 禁止静默覆盖人工修改或其他已接受提案。 - 手动编辑必须先完整可用;Agent 是增强入口,不是必需路径。 ## 数据契约 ### 节点参数 四类节点共享外层结构,并用 `kind` 形成 discriminated union: ```ts type CollectorNodeParams = { version: 1 execution: { concurrency?: number timeoutMs?: number retry?: { maxAttempts: number backoffMs?: number } } sources: SourceDefinition[] } ``` `SourceDefinition` 分为 `web | api | rss | cli`。单个节点中的每个来源必须与节点类型一致,并拥有稳定 `sourceId`。 ### 成功数据 ```ts type CollectedItemV1 = { itemId: string sourceId: string sourceType: "web" | "api" | "rss" | "cli" title?: string | null url?: string | null content?: string | null data?: unknown publishedAt: string | null fetchedAt: string lineage: Record<string, unknown> } ``` - `publishedAt` 表示来源实际发布/发送时间;来源未提供时为 `null`。 - `fetchedAt` 表示系统获取时间。 - 两者禁止相互 fallback。 ### 来源执行结果 ```ts type SourceExecutionResult = { sourceId: string status: "completed" | "failed" | "skipped" itemCount: number attempts: number startedAt: string finishedAt: string error?: { code: string message: string retryable: boolean } } ``` 节点标准输出: ```ts type CollectorOutputV1 = { items: CollectedItemV1[] sourceResults: SourceExecutionResult[] } ``` 规则: - `items` 仅包含成功采集的数据。 - 单个或部分来源失败时,节点继续输出成功数据并记录失败。 - 所有启用来源均失败时,节点执行失败并阻断下游。 - 停用来源记录为 `skipped`。 - 重试只针对失败且 `retryable=true` 的来源。 ## Merge 契约 Merge 是纯合并节点: - 输入端口 `cardinality=many`,最少连接 1 个上游,不保存 `in1/in2/in3/in4` 这类固定端口 schema。 - 运行时读取所有实际入边,按确定性顺序拼接成功 items。 - 汇总并保留全部 `sourceResults` 和 lineage。 - 不执行清洗、去重、排序、摘要、分类或隐式字段改写。 - 旧固定双输入 Merge 继续可加载和运行;保存为新格式时采用兼容升级,不做全库迁移。 ## 兼容与回滚 - 新节点和新契约采用 additive v1。 - 旧 `site + command` OpenCLI 配置在运行时归一化为单条 legacy source,不修改原始已保存图。 - 旧来源节点和旧工作流保持可加载、可编辑、可运行。 - 下游只在边界增加 `CollectorOutputV1` 适配,不修改图谱/仿真等业务逻辑。 - 使用 feature flag 控制四类新节点的工具架入口;关闭后隐藏新建入口,但不影响已保存节点运行。 - 不进行破坏性迁移,不删除旧节点类型。 ## 实施拆分 ### 子任务 1:强类型采集契约与兼容层 - 前后端定义 `CollectorNodeParams`、四类 `SourceDefinition`、`CollectorOutputV1`。 - 加入 schema 校验、版本字段和禁止字段校验。 - 实现旧 `site + command` 到单条 legacy source 的只读归一化。 - 为下游建立统一输出适配边界。 ### 子任务 2:四类节点目录与人工编辑器 - 注册网页/API/RSS/CLI 四个 L1 节点。 - 复用现有工具架、命令面板、Inspector 和模板创建链路。 - 实现多来源列表编辑、类型专属字段、验证和测试操作。 - CLI 只允许目录选择和 typed args。 ### 子任务 3:四类运行时与多来源 fan-out - 为四类节点绑定运行时执行器。 - 同一节点内按配置并发/限流执行多个来源。 - 统一生成 items、时间字段和 lineage。 - 凭证只通过 credential reference 解析,不写入节点配置和执行输出。 ### 子任务 4:部分成功、重试与可观测性 - 生成逐来源 `sourceResults`。 - 实现部分成功、全失败、跳过和可重试语义。 - Run Trace 与 Inspector 预览展示来源状态、失败原因、attempts 和新鲜度。 - 支持只重试失败来源。 ### 子任务 5:Variadic Merge - 将 Merge 契约改为 many-cardinality。 - 画布支持同一目标端口的多条入边。 - 运行时按实际入边合并。 - 保留旧双输入图兼容。 ### 子任务 6:节点级多 Agent Proposal/CAS 编辑 - 定义结构化 patch operation 白名单。 - Proposal 绑定 `nodeId + baseRevision`。 - 实现差异预览、逐条接受/拒绝、CAS、rebase 和冲突展示。 - Agent 不获得直接写画布权限。 ### 子任务 7:下游兼容、端到端验证与回滚演练 - 验证清洗及后续现有链路可消费统一输出。 - 建立四类来源、部分失败、全失败、Merge、多 Agent 冲突和旧工作流的 E2E。 - 验证 feature flag 回滚和无破坏升级。 依赖关系: `1 → {2,3} → 4 → 5 → 7` `2 → 6 → 7` ## 验收标准 1. 工具架只以“网页采集、API 采集、RSS 采集、CLI 采集”展示四类新 L1 节点。 2. 每个节点可配置至少 2 个同类型来源,并可增删、停用、排序和保存。 3. 不同类型来源不能被保存到错误的节点类型中。 4. CLI 节点只能选择已注册工具及 typed args;任意 Shell/命令文本在 UI 和 API 层均被拒绝。 5. 节点运行输出严格包含 `items[]` 与 `sourceResults[]`。 6. `publishedAt` 缺失时保持 `null`,`fetchedAt` 始终为实际采集时间,两者不互相替代。 7. 一个来源失败、另一个成功时,成功 items 继续进入下游,失败来源可在 Trace 中定位并单独重试。 8. 所有启用来源失败时,节点失败且下游不执行。 9. Inspector 预览最多显示 50 条,明确展示成功数、失败数、来源状态和数据新鲜度。 10. Merge 可连接 1 个、2 个和 5 个上游,保存模型不生成固定 `in3/in4` 字段。 11. Merge 仅拼接数据并保留 lineage/sourceResults,不执行隐式清洗或去重。 12. 两个 Agent 基于同一 revision 提案时,第一个可接受;第二个不得覆盖新状态,必须安全 rebase 或展示冲突。 13. 旧来源节点、旧双输入 Merge 和旧 `site + command` 工作流仍可加载和运行。 14. 关闭 feature flag 后,新节点从创建入口隐藏,已保存的新节点仍可运行。 ## 测试计划 - Schema 单元测试:四类合法配置、跨类型配置、禁止 CLI 字段、旧格式归一化。 - Runtime 单元测试:单来源、多来源、部分失败、全失败、跳过、重试、时间字段和 lineage。 - Merge 单元测试:1/2/5 上游、确定性顺序、空输入、错误传播、旧双输入兼容。 - Proposal/CAS 单元测试:正常接受、陈旧 proposal、可重放 patch、冲突、拒绝和幂等回放。 - 前端组件测试:工具架创建、来源列表编辑、CLI 目录选择、预览 50 条边界、失败重试。 - API/集成测试:节点保存校验、凭证引用、运行事件、来源结果持久化和恢复。 - 端到端测试:真实 Web/API/RSS/CLI 各至少一个来源,经 Merge 和清洗到结束节点。 - 回归验证:后端全量测试、前端测试、TypeScript、ESLint、生产构建和真实 Chrome 核心路径。 ## 完成定义 - 以上 14 条验收标准全部自动化或人工验证通过。 - 新增测试覆盖所有新契约分支和关键失败路径。 - 后端全量测试、前端测试、TypeScript、ESLint 和生产构建通过。 - 至少完成一次真实 Chrome 端到端演练和一次 feature flag 回滚演练。 - 独立代码审查和架构边界审查无阻断项。 - 规格、兼容策略、运行输出和用户操作文档同步完成。 ## 主要代码落点 - `frontend/lib/workflow/node-catalog.ts` - `frontend/lib/workflow/node-contracts.ts` - `frontend/lib/workflow/node-templates.ts` - `frontend/components/flow/inspector.tsx` - `frontend/components/flow/workflow-node.tsx` - `frontend/components/flow/workflow-editor.tsx` - `frontend/components/flow/command-palette.tsx` - `frontend/lib/workflow/to-react-flow.ts` - `frontend/lib/workflow/proposal.ts` - `frontend/lib/workflow/workflow-agent-proposal.ts` - `backend/schemas/workflow.py` - `backend/workflow/runtime_contracts.py` - `backend/workflow/runtime_registry.py` - `backend/services/opencli_hda_tracer.py` - `backend/pipeline/normalizer.py` - `backend/models/source_credential.py` - `backend/models/workflow_run.py` ## 风险 - 画布当前只渲染首个 target handle,Variadic Merge 需要同时修正 UI 连线和运行时契约。 - 现有来源执行输出以节点为粒度,需要保证来源级状态不会破坏事件回放和崩溃恢复。 - API/Web 配置可能包含敏感认证信息,必须只持久化凭证引用并对日志、Trace 和 Proposal 做字段过滤。 - Agent Proposal 的 rebase 仅对明确白名单操作开放;不确定的 patch 必须进入冲突状态。 - 旧节点兼容必须以测试固定,避免保存新版工作流时无意重写旧配置。
背景
OpenCLI Admin 当前已有数据采集、工作流运行、事件持久化和原生 HDA 能力,但用户在 Studio 画布中仍无法用清晰、稳定、可组合的 L1 业务节点完成通用数据采集。
当前体验存在以下问题:
本 Epic 将工作流主路径统一为:
开始 → 网页/API/RSS/CLI 采集 → Merge → 清洗 → 结束其中四种采集节点均为 L1 业务节点;底层 L2 能力继续封装实现细节。股票数据仅作为真实测试项目,不进入通用产品模型。
目标
非目标
产品与交互设计
节点工具架
新增四个一级节点条目:
collection.source.webcollection.source.apicollection.source.rsscollection.source.cli节点命名只表达业务动作和来源类型,不在名称中混入 OpenCLI、HDA、项目名或数据集名。
节点编辑
选中采集节点后,右侧 Inspector 提供来源列表编辑器:
各节点只暴露本类型字段:
adapterNodeId、目录中声明的 typed arguments、凭证引用。CLI 编辑器必须从 OpenCLI 工具目录选择已注册工具,不提供自由文本 Shell 输入。以下字段不得进入可保存节点配置:
shell、commandLine、scriptText、rawCommand、明文 token、password、cookie 或 authorization。Agent 编辑
Agent 不能直接并发写画布。Agent 只生成节点级结构化 Proposal:
交互规则:
baseRevision做 CAS 校验。数据契约
节点参数
四类节点共享外层结构,并用
kind形成 discriminated union:SourceDefinition分为web | api | rss | cli。单个节点中的每个来源必须与节点类型一致,并拥有稳定sourceId。成功数据
publishedAt表示来源实际发布/发送时间;来源未提供时为null。fetchedAt表示系统获取时间。来源执行结果
节点标准输出:
规则:
items仅包含成功采集的数据。skipped。retryable=true的来源。Merge 契约
Merge 是纯合并节点:
cardinality=many,最少连接 1 个上游,不保存in1/in2/in3/in4这类固定端口 schema。sourceResults和 lineage。兼容与回滚
site + commandOpenCLI 配置在运行时归一化为单条 legacy source,不修改原始已保存图。CollectorOutputV1适配,不修改图谱/仿真等业务逻辑。实施拆分
子任务 1:强类型采集契约与兼容层
CollectorNodeParams、四类SourceDefinition、CollectorOutputV1。site + command到单条 legacy source 的只读归一化。子任务 2:四类节点目录与人工编辑器
子任务 3:四类运行时与多来源 fan-out
子任务 4:部分成功、重试与可观测性
sourceResults。子任务 5:Variadic Merge
子任务 6:节点级多 Agent Proposal/CAS 编辑
nodeId + baseRevision。子任务 7:下游兼容、端到端验证与回滚演练
依赖关系:
1 → {2,3} → 4 → 5 → 72 → 6 → 7验收标准
items[]与sourceResults[]。publishedAt缺失时保持null,fetchedAt始终为实际采集时间,两者不互相替代。in3/in4字段。site + command工作流仍可加载和运行。测试计划
完成定义
主要代码落点
frontend/lib/workflow/node-catalog.tsfrontend/lib/workflow/node-contracts.tsfrontend/lib/workflow/node-templates.tsfrontend/components/flow/inspector.tsxfrontend/components/flow/workflow-node.tsxfrontend/components/flow/workflow-editor.tsxfrontend/components/flow/command-palette.tsxfrontend/lib/workflow/to-react-flow.tsfrontend/lib/workflow/proposal.tsfrontend/lib/workflow/workflow-agent-proposal.tsbackend/schemas/workflow.pybackend/workflow/runtime_contracts.pybackend/workflow/runtime_registry.pybackend/services/opencli_hda_tracer.pybackend/pipeline/normalizer.pybackend/models/source_credential.pybackend/models/workflow_run.py风险