Skip to content

插件扩展面:盘点现状、确立边界、排定后续行动(RFC 0011) #384

Description

@NWYLZW

背景

One Works 的插件扩展面是分多轮长出来的:plugins 配置与 manifest、client/server 双运行时、extension point 与 plugin API、@oneworks/hooks 中间件链、marketplace 分发。每一层都有实现,但没有单一事实源描述"插件到底能做什么"。

具体后果有两个:

  1. 内部评审对现有能力的判断会出错。 本次调研过程中,对自身扩展面出现过三次错误判断(详见下方"已知误判"),而调研是拿着完整代码库做的。插件作者只会更容易出错。
  2. 新增扩展点缺少可引用的边界依据,每次都要重新论证。

同时,DeepSeek Harness(DSH,基于 Cordis)提供了有价值的对照:它把几乎全部运行时能力做成了命名 seam,配套生成式能力目录,社区在数月内长出了与 One Works 产品面高度重叠的插件。

已完成的工作

调研已完成并沉淀为 RFC 0011(拆五章,见关联 PR):

  • 总览与结论.oo/rfcs/0011-plugin-extensibility.md
  • 现有扩展面盘点 — 带源码位置的能力基线
  • DSH / Cordis 结构对照 — 钉在固定上游 revision
  • 边界与设计纪律 — 七条可引用纪律
  • 行动项与优先级 — 按是否需要产品决策分组

调研方法:直接阅读本仓库源码;拉取此前未 checkout 的 vendors/cordiverse/cordis submodule 阅读 packages/core;克隆 deepseek-ai/deepseek-harness 后由四个并行子任务分别调研 subagent provider 体系、ACP 与外部 agent 集成、workflow 与 preset 编排、插件生态与官方文档。

主要结论

扩展面比内部认知的更完整。 依赖装配(extension point 的 onAvailable 等待语义、pluginApis.call 的挂起队列、epoch 竞态保护)、视图侧声明式渲染(toolUsePresentations)、agent loop 拦截(15 个 hook 事件,含 PreToolUse 否决权)都已存在并在生产使用。

真正缺失的是"注册型 seam"。 现有 seam 全是拦截型——宿主回调插件、插件可否决或增补,但不提供实现。缺的是"插件提供一个实现并成为运行时一部分"(典型是 model provider)。这不是遗漏:hook 传输是"每事件一次子进程往返",对拦截型契合、对注册型不成立。要开注册型 seam 需走常驻 server plugin runtime,不是扩 hook 事件表。

结构性差异只有一条:seam vs 编译期内置。 16 个适配器在深度上显著超过 DSH 的 3 个 out-of-process provider(统一 hook 协议、账号池、历史导入、权限镜像),但它们是编译期内置;DSH 的是 SubagentProvider seam,第三方发 npm 包、用户配置加一行即可接入。

已知误判

保留在 RFC 中作为"为什么需要生成式能力目录"的证据:

误判 实际情况
"插件之间不能声明依赖" children 是组合依赖;extensionPoints.onAvailable + pluginApis.call 是完整的运行时依赖装配
"没有视图侧扩展点" toolUsePresentations 是完整的声明式渲染扩展,cua-driver / browser-driver / external-browser-driver 已在用
"agent loop 没有任何 seam" @oneworks/hooks 有 15 个事件,含否决权、system prompt 改写权、停机权

后续行动项

P0(纯技术改进,不需要产品决策)

  • 抽通用 ACP 适配器层 —— agentclientprotocol 目前在 packages/adapters/{cline,dsh,goose} 各实现一遍,无共享层。抽出后接入新 ACP agent 从"写适配器"降为"加配置"
  • 生成式能力目录 + CI 门禁 —— scripts/gen-plugin-api.ts 从 ctx 的 TS 声明生成结构化目录,加 --check 接入现有检查;首次运行即可量化 ui-runtime.md 的漂移
  • 补 ErrorBoundary —— apps/client/src/plugins/components/plugins/ 下零个 ErrorBoundaryPluginHost.tsx:275 裸渲染,插件页面异常直接白屏

P1

  • Hook 权限面对 marketplace 场景的审视 —— <packageId>/hooks export 一装即自动进中间件链(plugin-entry-cache.ts:43-53 解析链上无 gate),而 hook 插件握有 PreToolUse 否决权、GenerateSystemPrompt 改写权、continue: false 停机权。这条线是命令行时代的设计,marketplace 接上后同一条链变成了分发面

P2(需要先有开放程度的产品决策)

  • Model provider seam —— 目录目前硬编码(packages/model-provider-catalog/src/catalog.ts),第三方加 provider 只能提 PR。关系 RFC 0006 的商业路径
  • 适配器 seam 化 —— 影响最大的一项,涉及维护成本、质量控制与品牌

待核实

  • 同 scope 内 parent 与 child 的 command id 撞名如何处理
  • 插件详情页 hooks tab 的确切数据来源(资产 hooks vs 运行时 hook 插件)
  • 16 个适配器的上游版本漂移防护是否都达到 dsh 适配器的水平

需要的决策

技术上"要不要开 seam、开哪些"RFC 已给出建议;但扩展面开放到什么程度才能让社区帮我们长产品,同时不让 marketplace 变成提权通道 —— 该权衡涉及商业路径、维护成本与品牌控制,需要产品侧拍板。P2 两项在此之前不启动。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions