已开启
[Feature]: ScienceDiscovery 插件化架构 #80
wang_cheng_zhao创建于  9月12日
wang_cheng_zhao成员
9月12日 创建

🚀 背景描述

将 ScienceDiscovery 现有能力逐步组织为可信、可独立配置和组合的插件包,让新增工具、Skill、连接器、上下文策略、调度能力和前端视图不必持续修改核心业务分支,并为后续受控的组件级演进提供版本化基础。

本提案专门描述 ScienceDiscovery 自身插件化,不包含跨仓能力复用分析。关联实现:PR #116。

设计思路

采用“稳定基座 + 构建期安装的可信插件 + 显式贡献接口”,不另起一套 harness,也不替换现有 AgentLoop。

模块 职责
基座 保留 AgentLoop、ToolRegistry、ContextAssembler、NativeAgent、SessionStore、权限审批、Runner 与 CAS;负责装配与治理
插件 SDK 与安装清单 manifest 描述 ID/API 版本、入口、依赖、必需/可选服务、权限、配置和贡献;分开表达安装、可用、授权、激活
API / Web 宿主 注入领域 Ports,管理 create/start/dispose;装配工具、上下文、状态、批处理策略、设置和视图
状态与上下文 插件拥有领域状态;基座在固定检查点采集 StateView;全部 contributor 读同一视图,Recorder 与实际模型输入关联同组 revision
配置与 Bridge global → project → session 继承;运行组合 nextRun 冻结,主/子/reviewer 一致;认证且限定作用域的 query/command/subscribe
最小候选闭环 固定基线与指定替换项,准备实验、记录比较、显式审批、受控 ApplyPort;冲突/拒绝不得应用候选

首批迁移 Skill、MCP、UniProt、默认多 Agent 调度、Plan 和 JSON Artifact 查看器。运行算法和业务领域逻辑继续复用既有包,插件主要拥有贡献和装配入口,避免旧/新路径双写。

非目标:插件市场、任意或不可信代码热加载、完整自动演进平台、模型参数训练、替换底层 AgentLoop。插件声明权限不是安全沙箱,也不能绕过工具权限和审批。

涉及到的对外API

  • 插件 manifest、生命周期与贡献接口,面向可信包维护者。
  • RuntimeSettingsOverrides.plugins:按插件 ID/配置字段继承;省略表示继承,enabled:false 关闭下一次运行的贡献。
  • /api/projects/:projectId/plugins:安装清单、诊断、配置 revision;Session 通过作用域限定。
  • /bridge 与 /events:受认证的查询、命令和变更通知。命令携带 revision,订阅只通知失效,不写权威状态。
  • /candidates 及候选操作:准备、比较、审批、应用、拒绝。保留实验记录,不承诺确定性重放或外部副作用回滚。
  • 保持经典设置、工具名、审批、存储与默认运行行为兼容;经典设置和插件命令共用设置写入边界。

与其他模块的相关性描述

NativeAgent 在现有运行链装配插件贡献;ContextAssembler 负责预算和最终模型上下文,Recorder 负责同检查点溯源。ToolRegistry 与 Runner 保持既有执行及权限语义。Web 通过独立入口贡献设置、项目面板与 Artifact 预览,不直接访问数据库。workspace、CI、构建和发布产物均需覆盖插件包。

测试设计与测试计划

  • 生命周期、依赖/合同版本、必需/可选服务、启停、配置继承和权限分离单测。
  • StateView 固定读、领域命令协调、Recorder/model revision 一致性与缺失快照失败测试。
  • Bridge 身份/作用域/字段所有权/CAS/取消/订阅释放测试。
  • 经典设置、Bridge 和 ApplyPort 并发回归,覆盖全局继承、项目、会话和 Composer 路径;应用回执事务回滚、重试与重启持久化。
  • 用户旅程验证项目启停、会话覆盖、真实 Plan、候选实验/审批/应用、JSON 预览;关闭执行贡献后仍可读取历史。
  • typecheck、architecture check、受影响构建和打包验证;完整进展与证据在本 Issue 评论和 PR 更新。

其他信息

本 Issue 记录目标与验收范围;实现细节和当前进展放在后续评论与仓内维护文档中。关联 PR 的合入与 Issue 关闭由维护者确认,不依赖自动关闭行为。

likedislike
Wwang_cheng_zhao成员
9月12日 添加了label:feature
openJiuwen-bot成员
9月12日 评论:

欢迎来到 openJiuwen 社区

Hey @wang_cheng_zhao , 感谢你对社区的贡献.

机器人使用手册

有关指令的使用,可以点击 此处 查看详情。开发人员可以在每个PR或Issue下方评论特定指令来触发机器人任务。

likedislike
wang_cheng_zhao成员
9月12日 评论:

当前进展

实现位于 PR #116,当前提交 7017ab3edf9ed42a753ae352f3a792b7a09ce928,尚未合入。可信插件宿主、六个功能包、固定 StateView、分层配置/Bridge 和最小候选闭环已接线;本次进一步修复了经典设置与 ApplyPort/Bridge 的共同互斥,并补充 仓内插件机制与维护文档。

底座架构

安装清单 + 分层配置 → 能力协商 → 固定 Run 组合
                                  │
                         NativeAgent / 插件宿主
                   ┌──────────────┼─────────────┐
                   ▼              ▼             ▼
             tools/批策略   contextFactories  stateProviders
                   │              └─ StateView ─┘
                   ▼                    ▼
             ToolRegistry         ContextAssembler
                   └────── AgentLoop ───┘
                              │
                  原权限/审批/Runner/CAS/Recorder

Web 插件(设置/项目面板/产物视图)
           │ 认证 + Project/Session scope
           ▼
     Bridge query / command / subscribe
           │ command 才写入;subscribe 只通知失效
           ▼
      SessionStore / 领域命令

AgentLoop 不改写,ToolRegistry 保留工具调度和治理,ContextAssembler 保留预算/裁剪/校验。NativeAgent 负责绑定插件贡献与运行上下文。原领域存储、权限审批和 CAS 仍是权威;插件不是第二套 store,也不是另一套 harness。

主要入口:packages/plugin-sdk 是合同;services/api/src/plugins/{catalog,runtime,control,http}.ts 是安装/运行/控制面;apps/web/src/plugins/ 是前端宿主。plugins/* 拥有对应功能的 manifest、运行贡献和 Web 入口。

插件机制与状态一致性

  • 包与安装:可信 workspace 包按构建期登记。manifest 声明身份/API、入口、依赖、必需/可选服务及版本、权限、配置和贡献。安装、可用、启用、授权、激活分开;缺必需服务或合同不符有诊断,不能将“安装了”当成“Run 已启动”。
  • 生命周期:按依赖顺序 create/start,取消信号传递,失败清理,逆序 dispose。插件仅接收所需领域 Ports;此进程内约束不是不可信代码沙箱。
  • 运行扩展:RuntimeContribution 包含工具、上下文工厂、状态 Provider、批处理策略和可选可靠结果提交。主/子/reviewer 复用同一冻结组合,在各自作用域装配,不保留同能力的旧/新双写执行路径。
  • 模型状态:NativeAgent 在模型调用前固定 StateView;每个片段有 ID、schemaVersion、revision、value 与 fidelity。contributor 声明 stateReads,按固定视图投影;Recorder 绑定同一检查点和实际输入。Plan 更新与捕获经 StateCoordinator,缺少 StateView 必须失败。外部引用不冒充远程原子事务。
  • 前端扩展:独立 web 入口提供宿主登记的设置、项目面板与 Artifact 视图,宿主提供 UI 能力与认证 Bridge;不是上传任意组件即热加载。历史 Plan/Artifact 仍可读取。

已完成插件化的能力

插件包 / ID 已迁移贡献 复用底座
plugins/skill / skill Skill 工具、目录/已读状态上下文、选择设置 既有 Skill 目录/库版本、DurableContextStore 和权限
plugins/mcp / mcp MCP 工具、结果提交、设置与 Composer 选择入口 既有 MCP 客户端、来源治理、授权
plugins/uniprot / connector.uniprot 真实 UniProt 来源注册与按组合过滤 既有 MCP Source/connector broker;不再重复 builtin 注册
plugins/scheduler / scheduler 默认 task 调度工具 既有 orchestration/subagent 分发,不另造调度算法
plugins/plan / plan update_plan、批策略、协调状态、固定上下文和项目显示 原 PlanStore/事件记录与 Web 宿主
plugins/artifact-json / artifact-json JSON Artifact 预览 原 Artifact 读取;关闭后原文仍可读

包封装贡献与装配,不要求把底层领域实现全部搬进 plugins。workspace 构建、依赖和发布收集包含这些包。新增同类能力主要增加插件及安装/Ports 绑定,不需要改 AgentLoop;新增一种贡献类型仍需扩展宿主合同。

配置与受控候选

配置 global → project → session,省略继承、enabled:false 显式关闭。六个当前插件都声明 nextRun,运行中设置不改已冻结工具集。manifest 的 restart 是未来进程级合同,不代表已实现通用热替换。插件 enabled/authorized 不能代替原工具逐次授权。

Bridge 复用 API bearer 与项目/会话归属;query 只读,configure 仅写声明字段,host.settings.replace 保存完整表单,SSE changed 仅通知刷新。经典设置、Composer、Bridge 与 ApplyPort 共享 SessionStore 的 catalog 级设置锁,锁内比较 revision/检查取消再写入;全局继承变化也覆盖。经典 PUT 保留后写覆盖,CAS 则拒绝过期修改。

固定当前组合与指定资产 → 仅替换允许的配置/Skill 项
             ↓
prepare:两个普通实验 Session → 两边完成同一任务
             ↓
compare:记录实际结果(observed-runs)
             ↓
approve:显式管理审批 → apply:基线/资产检查 + 设置/回执同事务

候选不提前修改活动组合,配置/资产冲突或拒绝不应用。prepare 的实验在 apply/reject 后保留,用户可通过现有 Session 删除入口显式清理;删除后不保证候选引用仍可完整回看。比较不是自动判优或确定性重放,Apply 不回滚外部工具副作用。

验证与边界

验证层 结果与基线
本次检视后回归 7017ab3e:160 项受影响测试通过;包含四种经典写入与 Apply 的屏障并发、Bridge 继承 CAS、失败后继续保存
类型、架构、构建 本 HEAD 全 workspace 通过;架构检查 218 源文件
新增真实 HTTP 用户旅程 本 HEAD 5/5 步通过:认证、继承与过期编辑、双编辑冲突、拒绝保留实验、重启一致
原完整 UI/运行证据 22dff188:332 Node、650 Web;2 条 Playwright 旅程共 9 步通过,覆盖运行启停、主子 Plan、实验审批应用与 JSON 查看器;属于原版本证据

当前不做插件市场、不可信代码热加载、完整自动演进、模型训练或替换 AgentLoop。本次未重跑浏览器视觉旅程、真实外部模型/UniProt 服务或独立 Runner SEA 无 Node 分发验证;不将已有能力、源码验证与这些未执行验证混为一谈。

维护者从仓内 docs/zh/explanation/plugins.md 阅读新增插件步骤;PR 检视回复记录本次具体修复。后续合入仍由 Maintainer 检视确认。

likedislike