关联 #129、#127、#123、#122;外部协议接入与 Inbox 分别关联 #124、#126。
本 Issue 承接 #129 的静态装配和生命周期约定,进一步分析业务扩展点的缺口,并明确“扩展机制本身是否应该成为 ext”。以下为设计建议与待实施范围,不表示相关重构已经完成。现状依据当前工作区代码,部分装配文件仍有未提交修改,实施时应以届时主线复核。
问题与目标
目前已经可以贡献 Skill、IOA、Flags、Config、Tool、Command、AOP 和 Hook,但这些概念属于不同层次。继续向中央 Extension API 添加 RegisterX,会使新领域反过来耦合生命周期框架。
目标是:新增 Provider、压缩算法或资源解析器时,只需增加领域实现并调整 Profile 装配,无需修改 core/extension,也不要求其他 ext 实现新方法。
1. 区分四类职责
| 层次 |
示例 |
接入方式 |
| 声明与配置 |
Flags、Config、静态 Skill、模板 |
普通值和声明函数,入口在运行资源启动前收集 |
| 业务能力 |
Provider、IOA、Tool、Command、存储 |
构造注入、小接口、领域注册方法 |
| 执行干预与观察 |
Hook、AOP |
typed 控制点、事实发布与消费者 |
| 生命周期 |
Extension、Set、Scope |
初始化、完整图发布、回滚、取消、排空与释放 |
一个 ext 可以贡献多个领域。只有需要初始化、订阅、后台任务或资源清理的部分才接入 Extension;纯声明和纯算法不增加空 Load/Close。
2. 扩展点现状与优先级
优先级表示设计与实施顺序,不表示能力完全缺失。
| 机制 |
当前边界 |
建议 |
优先级 |
| Provider 构造与模型路由 |
调用已有 Provider 接口;默认构造仍通过 switch 选择协议 |
打通 Profile 到 App/Runtime 的构造注入;确有按名称选择需求时才增加领域工厂表;重试和路由用组合实现 |
高 |
| Prompt / Context 组合 |
已有 SystemPromptFn、TransformContext、BeforeRun 和 Context Hook;产品 Runtime 仍集中构建提示词 |
复用现有入口,定义提示词段和动态上下文贡献的顺序、来源、预算、失败行为与求值时机 |
高 |
| 压缩和历史裁剪 |
BeforeCompact 可以取消执行,自动压缩仍直接调用 compactHistory |
注入压缩算法,自动压缩与 /compact 共用;历史提交和会话一致性继续由 Runtime 管理 |
高 |
| 输入引用解析 |
Expander 可注入文件和 Skill 读取函数,但引用类型固定为 file/skill |
按引用类型接入 Resolver,支持 finding、traffic、session 等;明确取消、大小限制和错误语义 |
高 |
| 权限、审批和执行策略 |
typed Hook 已有执行控制点和错误策略 |
策略通过现有 Hook 接入;需要交互审批时定义宿主无关的请求/响应契约 |
中 |
| 存储与恢复 |
Web Service 依赖具体 SQLiteStore;Agent 恢复直接读取历史文件 |
按消费需求提取 Session/Event/Artifact 等小接口;连接、迁移和关闭归实现所有者 |
中 |
| 执行环境 |
Files、Terminal、Proxy 已有资源边界 |
有本地、容器、远程等真实替换需求时开放文件和进程执行接口,保持执行控制点覆盖真实 IO |
中 |
| 外部输入渠道与协议绑定 |
已有 Inbox、IOA、AOP namespace 和宿主绑定 |
渠道负责转换及投递,Runtime 负责准入,渠道所有者负责连接、认证和排空 |
中 |
| 展示、输出与诊断 |
已有 Console Bindings、timeline renderer、EventOutput、Probe Registry |
完善各宿主的贡献接口,事实继续使用现有事件流 |
按需 |
| Loop、工作流和调度 |
agent.Loop 已可替换,并已有调度机制 |
新算法复用 Loop;调度和工作流通过具体能力接入,保持 Session 生命周期单一所有者 |
按需 |
Hook 适合介入执行,Provider 接口适合替换能力。不要通过 Hook 隐式接管整套模型调用、压缩或存储,否则返回值、错误传播和所有权会难以追踪。
代码核查入口:
agent/provider/provider.go:NewProviderFromResolved。
pkg/app/app.go:Dependencies、initProvider 及初始化路径。
agent/types.go、agent/hooks/points.go:已有 Loop、Prompt、Context、压缩前置契约。
pkg/exts/agent/runtime.go:产品提示词与 Agent Config 装配。
agent/loop.go、agent/compact.go:自动和手动压缩路径。
agent/inbox/expand.go:固定引用类型解析。
pkg/web/service/service.go:具体 SQLiteStore 依赖。
pkg/console/api/bindings.go、web/frontend/src/lib/chat-extensions.tsx:已有展示接入点。
3. 扩展机制本身是否做成 ext
| 所指的机制 |
建议 |
理由 |
| Set、Scope、依赖排序、回滚和关闭 |
保留独立的最小内核 |
必须有外部所有者负责启动与关闭;内核不能依赖由自己加载的 ext 才完成自举 |
| Tool Registry、Prompt 组装器、Provider 路由器等领域机制 |
独立领域模块;需要生命周期时接入 ext |
分离业务契约与默认实现即可实现解耦,纯声明和算法不需要额外生命周期包装 |
| 发现、配置驱动装配、扩展管理界面 |
可以独立为模块,暂不引入动态 Loader |
当前静态 Profile 足够;未来发现模块可返回候选装配描述,由外层宿主负责图的建立和替换 |
当前 Tool/Command Registry 已作为图中的生命周期节点加载并排空调用,可直接复用;无需增加仅转发生命周期的 tool-system-ext 或 command-system-ext。
Flags/Config 必须遵守:声明选项 → 解析及校验 → Profile 选择与构造 → Set.Load → 发布。普通 ext 的 Load 不能成为参数声明和 help 生成的前提。
领域消费者依赖业务能力,生命周期适配器依赖领域实现,Profile 同时知道双方并负责接线。新增领域无需在 core/extension 中登记中央能力枚举。
4. 方案对比
| 方案 |
收益 |
代价 |
结论 |
| 中央 ExtensionAPI 不断增加 RegisterX |
入口集中、易发现 |
每个新领域都修改中央接口,形成大接口和依赖聚集 |
不采用 |
| 最小生命周期内核 + 领域接口 + 显式 Profile 装配 |
类型和所有权明确,新领域不改内核 |
Profile 需要显式接线 |
推荐,延续 #129 |
| Context 服务容器 + 动态插件树 |
动态发现、运行时装卸、作用域覆盖 |
引入动态依赖、撤销、重载及诊断复杂度 |
有明确动态需求后单独评估 |
DSH 的 Prompt 贡献、压缩契约/实现/触发器分离值得借鉴;不据此复制通用服务容器和动态作用域树。Cordis 自身也区分核心生命周期与可选 Loader/HMR,并非把全部自举责任交给普通插件。
参考:
5. 建议实施范围与验收
第一阶段优先补齐已有能力的注入路径和明确缺失的替换契约。中优先级领域以真实第二实现需求为触发条件,不一次性预建全部 Registry。
本 Issue 不引入中央 ExtensionAPI、通用 Contribution/Provide/Require、服务定位器、插件自举递归、运行时单节点热替换或第二套 Session 生命周期。
关联 #129、#127、#123、#122;外部协议接入与 Inbox 分别关联 #124、#126。
本 Issue 承接 #129 的静态装配和生命周期约定,进一步分析业务扩展点的缺口,并明确“扩展机制本身是否应该成为 ext”。以下为设计建议与待实施范围,不表示相关重构已经完成。现状依据当前工作区代码,部分装配文件仍有未提交修改,实施时应以届时主线复核。
问题与目标
目前已经可以贡献 Skill、IOA、Flags、Config、Tool、Command、AOP 和 Hook,但这些概念属于不同层次。继续向中央 Extension API 添加 RegisterX,会使新领域反过来耦合生命周期框架。
目标是:新增 Provider、压缩算法或资源解析器时,只需增加领域实现并调整 Profile 装配,无需修改 core/extension,也不要求其他 ext 实现新方法。
1. 区分四类职责
一个 ext 可以贡献多个领域。只有需要初始化、订阅、后台任务或资源清理的部分才接入 Extension;纯声明和纯算法不增加空 Load/Close。
2. 扩展点现状与优先级
优先级表示设计与实施顺序,不表示能力完全缺失。
Hook 适合介入执行,Provider 接口适合替换能力。不要通过 Hook 隐式接管整套模型调用、压缩或存储,否则返回值、错误传播和所有权会难以追踪。
代码核查入口:
agent/provider/provider.go:NewProviderFromResolved。pkg/app/app.go:Dependencies、initProvider及初始化路径。agent/types.go、agent/hooks/points.go:已有 Loop、Prompt、Context、压缩前置契约。pkg/exts/agent/runtime.go:产品提示词与 Agent Config 装配。agent/loop.go、agent/compact.go:自动和手动压缩路径。agent/inbox/expand.go:固定引用类型解析。pkg/web/service/service.go:具体 SQLiteStore 依赖。pkg/console/api/bindings.go、web/frontend/src/lib/chat-extensions.tsx:已有展示接入点。3. 扩展机制本身是否做成 ext
当前 Tool/Command Registry 已作为图中的生命周期节点加载并排空调用,可直接复用;无需增加仅转发生命周期的 tool-system-ext 或 command-system-ext。
Flags/Config 必须遵守:声明选项 → 解析及校验 → Profile 选择与构造 → Set.Load → 发布。普通 ext 的 Load 不能成为参数声明和 help 生成的前提。
领域消费者依赖业务能力,生命周期适配器依赖领域实现,Profile 同时知道双方并负责接线。新增领域无需在 core/extension 中登记中央能力枚举。
4. 方案对比
DSH 的 Prompt 贡献、压缩契约/实现/触发器分离值得借鉴;不据此复制通用服务容器和动态作用域树。Cordis 自身也区分核心生命周期与可选 Loader/HMR,并非把全部自举责任交给普通插件。
参考:
5. 建议实施范围与验收
第一阶段优先补齐已有能力的注入路径和明确缺失的替换契约。中优先级领域以真实第二实现需求为触发条件,不一次性预建全部 Registry。
本 Issue 不引入中央 ExtensionAPI、通用 Contribution/Provide/Require、服务定位器、插件自举递归、运行时单节点热替换或第二套 Session 生命周期。