引擎契约

August 14, 2026 · View on GitHub

一个引擎是「实现 DSH Agent 接口的驱动」,由下游插件经 ctx.engineSwitch.register(engine) 注册:

字段必填说明
id引擎 id(非空字符串;deepseek 是保留字,注册抛错)。同时是预设目录名(by-id 映射锚点)
name预设显示名
description预设描述
presetDir预设目录绝对路径(含 agent.cordis.yml + preset.yml);有则框架落地到 ~/.dsh/.agent-presets/<id>/
makeAgent(loopCtx, id, options, session, engineConfig) => DSH Agent

makeAgent

产出一个实现 DSH Agent 接口的完整驱动(与原生 ReactLoop 同接口:send/followup/steer/inject/cancel/whenIdle/status/ctx/scope/session/inbox)。框架直接发布它,session 直接驱动它——通信原样到达引擎,不改写、不翻译。

透明性约束

  1. 引擎无感知预设makeAgent 不接收 preset 概念。preset → 引擎的路由由框架完成,引擎只看到 session/options/engineConfig
  2. 会话无感知 switch:session 只跟 Agent 打交道;换引擎 = 空白期内换驱动它的 Agent,session 自身不感知。

注册

下游插件 inject: ["engineSwitch"],在 apply 里注册:

export const inject = ["engineSwitch"];
export function apply(ctx) {
  ctx.engineSwitch.register({
    id: "my-engine",
    name: "My Engine",
    description: "…",
    presetDir: fileURLToPath(new URL("./presets/my-engine/", import.meta.url)),
    makeAgent(loopCtx, id, options, session, engineConfig) {
      return new MyEngineAgent(loopCtx, id, options, session, engineConfig);
    },
  });
}

引擎私有配置

引擎的私有配置放 config.engines[engine.id](框架原样转发为 engineConfig,不解析、不校验);引擎自行校验 + 给默认值。

约束

  • makeAgent 返回的 Agent 必须暴露 dsh-agent 的 Agent 契约(send/cancel/whenIdle/scope/ctx/session),路由工厂的 dispose/publish 依赖它。
  • deepseek 不是注册进来的引擎,是 defaultEngine 兜底的委托哨兵。