API 与类型
每个 config: 块均可由 cordis.yml 条目设置:针对每个可加载的 harness 包,原样列出其 apply 函数或服务构造函数接收的配置声明(包括 JSDoc),并附上所有引用类型——包内类型直接粘贴,其他类型则提供链接。粘贴的内容是插件声明的完整配置类型——运行时 schema 有意排除的字段是仅供运行时使用的 seam(其自身的 JSDoc 会如此说明),不能通过 cordis.yml 设置。这是以部署为轴的参考文档——插件作者所依据的连接方式请参阅各子系统页面中的生成 cordis-surface 区域,面向模型的工具 schema 请参阅工具目录,而 subsystems/ 则记录了这些声明所引用的类型。
英文源文件由源代码(scripts/gen-config-catalog.ts)生成,并通过 pnpm run verify-config-catalog(doc-sync 的一部分)验证新鲜度;本中文文件作为经评审对侧通过双语配对维护。声明块使用 ts config-catalog 围栏(doc-typecheck 会跳过它,因为单独引用导入项的声明无法独立编译)。英文生成器还会将运行时 schemastery schema 与粘贴的声明进行交叉核对——每个经 schema 验证的键(包括嵌套键)都必须能在声明的配置类型中找到——因此,粘贴内容无法隐藏加载器接受的字段。
Requires: 行列出插件通过 inject 注入的服务键:其 cordis.yml 树还必须加载这些服务的提供者。范围限定为 harness 层级(packages/);配置树还可能加载的 vendored cordis 插件(hmr、控制台日志记录器等)固定为上游源代码(参见 vendoring policy),未收录于此目录。
已发布插件向 ctx.tools 提供的所有面向模型的工具:模型通过系统提示词组装获得的 name、description 和 JSON Schema parameters。本目录是子系统页面(类型及每页生成的 cordis-surface 接线区域)的补充;本页列出的是向 agent(智能体)提供的工具。
英文源文件由系统生成,并通过 pnpm run verify-tool-catalog(doc-sync(文档同步门禁)的一部分)验证新鲜度;本中文文件作为经评审对侧通过双语配对维护。与 Cordis 目录(纯源码 AST 处理)不同,英文生成器会在真实上下文中启动每个工具插件并读取 ctx.tools.schemas(),因为工具 schema 无法通过静态分析完全确定,例如运行时展开的枚举、拼接的描述、由配置决定的名称以及使用原始 JSON Schema 的 MCP 工具。完整性守卫会 glob 匹配 packages/*/tool-*;如果生成器的启动 manifest(元数据清单)遗漏任何包,检查就会失败,因此新工具不会在无人察觉的情况下缺少文档。参见工具 schema 目录 Agent Note。
范围:packages/*/tool-* 下已发布的产品工具,每个工具均使用其默认配置启动;但如果某个 Config 字段是必填项且没有默认值,生成器就必须作出选择,对应包的说明会记录本页展示的是哪个分支。注册的工具名称可以是加载时配置,例如 tool-subagent 的 toolName,因此部署可能以不同名称或额外名称提供某个包;如果存在随产品发布的别名,对应包的说明会予以记录。examples/ 中的演示工具(例如 echo)不在范围内,这与 Cordis 目录仅涵盖包的范围一致。
会话持久事件日志中可能出现的所有事件类型:完整持久化的 SessionEvent 信封,以及可通过合并扩展的 SessionEventMap 中的每个成员,包括 @deepseek-ai/dsh-session 所属的词汇和本仓库中每个插件对 @deepseek-ai/dsh-session/types 的声明合并,并附有源 JSDoc、完整 payload 声明、surface 标记和声明位置。本文档是 session.md(surface 排序与 deriveMessages() 投影)、persistence.md(如何让日志持久化)和 session.md 中生成区域(实时总线接线;日志事件不是 cordis 事件,它通过唯一的 session/event emit 到达监听器)的补充。
英文源文件根据源码生成(scripts/gen-persistence-catalog.ts),并由 pnpm run verify-persistence-catalog(doc-sync(文档同步门禁)的一部分)验证新鲜度;本中文文件作为经评审对侧通过双语配对维护。声明块保留源码声明和嵌套属性的 JSDoc,只移除其所在接口/模块带来的缩进,并使用 ts persistence-catalog 围栏(doc-typecheck 会跳过这些围栏,因为声明引用了其所属模块中的类型)。payload 中的类型名称会链接到记录该类型的页面。参见 persistence-log-catalog Agent Note。
以下信封声明组合了每个事件的 type、单调递增的 seq、以 epoch 毫秒表示的 time、data、可选的未知类型跳过标记 ignorable,以及条件字段 surfaceOp/sourceEventSeqs。surface 表示 SurfaceEventType 成员:它会生成一条 LLM(大语言模型)消息,并声明该事件如何加入 surface 列表。log-only 表示其他所有事件:这类记录可持久化、可回放,但不参与派生历史。每个 payload 均可进行 JSON 序列化(在 Session.append 处强制执行),整个格式固定为 SESSION_FORMAT_VERSION = 0:这是预发布格式,不暗示任何兼容性(参见版本立场)。范围仅限本仓库中的包;下游插件可以继续合并其他事件类型,而这些类型按设计不属于本目录。
上下文是 Cordis 的核心对象:所有服务、事件和生命周期 API 都通过 ctx 访问。事件方法见事件,副作用与当前 fiber 见 Fiber,插件加载见注册表。
Cordis 插件的根依赖容器和子依赖容器。
上下文是一个代理:普通属性读取通过服务解析器进行,而 extend()、isolate() 和 intercept() 会创建有作用域的子上下文,且不修改其父上下文。
ctx.extend(meta?)
Section titled “ctx.extend(meta?)”/** * Create a child context with extra metadata on top of the current scope. * * The child prototypally inherits every property of this context; own * properties of `meta` shadow the inherited ones. The parent is not mutated. * * @param meta — own properties (including symbol keys) to define on the child. * @returns a child context inheriting from this one. */extend(meta = {}): this在当前作用域之上创建一个带有额外元数据的子上下文。
子上下文通过原型继承当前上下文的所有属性;meta 的自有属性会遮蔽继承的同名属性。父上下文不会被修改。
meta:要在子上下文上定义的自有属性,包括以 symbol 为键的属性。
返回继承自当前上下文的子上下文。
ctx.isolate(name, label?)
Section titled “ctx.isolate(name, label?)”/** * Create a child context with an independent service scope for `name`. * * Below the returned context, reads and writes of the service `name` * resolve against the new label instead of the parent's, so a different * implementation can be provided without affecting the parent scope. * Passing the same `label` to two `isolate()` calls joins their scopes. * * @param name — the service name to isolate. * @param label — scope label to join; defaults to a fresh unique symbol. * @returns a child context whose `name` service resolves in the new scope. */isolate(name: string, label?: symbol)创建一个子上下文,使 name 拥有独立的服务作用域。
在返回的上下文之下,对服务 name 的读写会根据新标签解析,而不再根据父上下文的标签解析,因此可以提供不同的实现而不影响父作用域。将同一个 label 传给两次 isolate() 调用,可使二者加入同一作用域。
name:要隔离的服务名称。label:要加入的作用域标签;默认为一个新建的唯一 symbol。
返回一个子上下文,其 name 服务在新作用域中解析。
ctx.intercept(name, config)
Section titled “ctx.intercept(name, config)”/** * Add service-specific intercept config for plugins started below this * context. * * Plugins loaded under the returned context see `config` merged into the * service's resolved config (ancestor entries first; see * `Service[symbols.resolveConfig]`). The parent context is not affected. * * @param name — the service name whose config to intercept. * @param config — the intercept config to merge for that service. * @returns a child context carrying the additional intercept entry. */intercept<K extends InjectKey>(name: K, config: Context[K] extends { [symbols.config]: infer T } ? T : never): thisintercept(name: string, config: any): this为在此上下文之下启动的插件添加服务专属的拦截配置。
在返回的上下文下加载的插件会看到 config 已合并到服务解析后的配置中(祖先条目在前;见 Service[symbols.resolveConfig])。父上下文不受影响。
name:要拦截其配置的服务名称。config:要为该服务合并的拦截配置。
返回一个携带额外拦截条目的子上下文。
ctx.root
Section titled “ctx.root”/** The root context of the application (every child context shares it). @experimental */root: this应用的根上下文,所有子上下文均共享它。@experimental
ctx.baseUrl
Section titled “ctx.baseUrl”/** Base URL used to resolve relative plugin/module specifiers, if the runtime sets one. */baseUrl?: string用于解析相对插件/模块说明符的基础 URL,前提是运行时设置了该值。
ctx.events
Section titled “ctx.events”/** The event bus. Its methods are also mixed onto `ctx` (`ctx.on`, `ctx.emit`, ...). */events: EventsService事件总线。它的方法也会混入 ctx(ctx.on、ctx.emit 等)。
ctx.logger
Section titled “ctx.logger”/** The logging service. Call `ctx.logger(name)` for a named logger. */logger: LoggerService日志服务。调用 ctx.logger(name) 可获取具名 logger。
ctx.reflect
Section titled “ctx.reflect”/** The reflection layer backing the context proxy (`ctx.get`, `ctx.provide`, ...). */reflect: ReflectService为上下文代理提供支持的反射层(ctx.get、ctx.provide 等)。
ctx.registry
Section titled “ctx.registry”/** The plugin registry. Its methods are mixed onto `ctx` (`ctx.plugin`, `ctx.inject`). */registry: RegistryService插件注册表。它的方法会混入 ctx(ctx.plugin、ctx.inject)。
每个上下文中都混入了事件分发 API。Harness 事件声明及其分发模式会生成到各自所属的子系统页面。
ctx.parallel(name, …args)
Section titled “ctx.parallel(name, …args)”/** * Dispatch an event, running all listeners concurrently. * * @param name — the event name. * @param args — arguments passed to every listener. * @returns a promise resolving once every listener has settled. */parallel<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): Promise<void>parallel<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): Promise<void>分发一个事件,并发运行所有监听器。
name:事件名称。args:传递给每个监听器的参数。
返回值:一个 Promise,在所有监听器均已完成后兑现。
ctx.emit(name, …args)
Section titled “ctx.emit(name, …args)”/** * Dispatch an event synchronously, ignoring listener return values. * * @param name — the event name. * @param args — arguments passed to every listener. */emit<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): voidemit<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): void同步分发一个事件,忽略监听器的返回值。
name:事件名称。args:传递给每个监听器的参数。
ctx.serial(name, …args)
Section titled “ctx.serial(name, …args)”/** * Dispatch an event, awaiting listeners in order until one bails. * * @param name — the event name. * @param args — arguments passed to each listener. * @returns the first bail value (non-null, non-false, non-undefined), if any. */serial<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): Promisify<ReturnType<Events[K]>>serial<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): Promisify<ReturnType<Events[K]>>分发一个事件,依次等待各监听器,直到其中一个提前终止分发。
name:事件名称。args:传递给每个监听器的参数。
返回值:第一个提前终止值(非 null、非 false 且非 undefined);如果没有,则不返回此类值。
ctx.bail(name, …args)
Section titled “ctx.bail(name, …args)”/** * Dispatch an event, calling listeners in order until one bails. * * @param name — the event name. * @param args — arguments passed to each listener. * @returns the first bail value (non-null, non-false, non-undefined), if any. */bail<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>bail<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>分发一个事件,依次调用各监听器,直到其中一个提前终止分发。
name:事件名称。args:传递给每个监听器的参数。
返回值:第一个提前终止值(非 null、非 false 且非 undefined);如果没有,则不返回此类值。
ctx.waterfall(name, …args)
Section titled “ctx.waterfall(name, …args)”/** * Dispatch an event whose last argument is a `next` continuation. * * Each listener wraps the rest of the chain: calling `next()` invokes the * next listener (finally the built-in behavior); not calling it vetoes. * * @param name — the event name. * @param args — listener arguments; the final one is the innermost `next`. * @returns the outermost listener's return value. */waterfall<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>waterfall<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>分发一个事件,其最后一个参数是续接执行的 next 回调。
每个监听器都会包装调用链的其余部分:调用 next() 会执行下一个监听器,最终执行内置行为;不调用则会否决后续执行。
name:事件名称。args:监听器参数;最后一个参数是最内层的next。
返回值:最外层监听器的返回值。
ctx.on(name, listener, options?)
Section titled “ctx.on(name, listener, options?)”/** * Register an event listener owned by the current fiber. * * @param name — the event name to listen for. * @param listener — called with the dispatch arguments. * @param options — listener options; a boolean is shorthand for `prepend`. * @returns a disposer removing the listener; `true` if it was still registered. */on<K extends keyof Events>(name: K, listener: Events[K], options?: boolean | EventOptions): () => boolean注册一个归当前 fiber 所有的事件监听器。
name:要监听的事件名称。listener:使用分发参数调用的监听器。options:监听器选项;布尔值可作为prepend的简写。
返回值:一个用于移除监听器的资源释放函数;如果调用该函数时监听器仍处于注册状态,则返回 true。
ctx.once(name, listener, options?)
Section titled “ctx.once(name, listener, options?)”/** * Same as `on()`, but the listener disposes itself after its first call. * * @param name — the event name to listen for. * @param listener — called at most once with the dispatch arguments. * @param options — listener options; a boolean is shorthand for `prepend`. * @returns a disposer removing the listener; `true` if it was still registered. */once<K extends keyof Events>(name: K, listener: Events[K], options?: boolean | EventOptions): () => boolean与 on() 相同,但监听器在首次调用后会自行注销。
name:要监听的事件名称。listener:使用分发参数调用,最多调用一次。options:监听器选项;布尔值可作为prepend的简写。
返回值:一个用于移除监听器的资源释放函数;如果调用该函数时监听器仍处于注册状态,则返回 true。
fiber 是一个已加载的插件实例,包含其生命周期状态、经过校验的配置以及已注册的作用。ctx.fiber 是当前 fiber,ctx.effect() 会将调用委托给它。
ctx.effect(execute, label?)
Section titled “ctx.effect(execute, label?)”/** * Register a cleanup-aware effect on this fiber. * * `execute` runs immediately; the disposers it produces are collected and * run (in reverse order) either when the returned disposer is called or * when the fiber unloads, whichever comes first. Calling the disposer twice * is a no-op. Throws `CordisError('INACTIVE_EFFECT')` if the fiber is * already disposed, and `TypeError` if `execute` returns an invalid shape. * * @param execute — the effect body; see {@link Effect} for accepted shapes. * @param label — effect label shown in `getEffects()` diagnostics. * @returns a disposer that tears the effect down and settles once done. */effect(execute: () => SyncEffect, label?: string): Disposable<Promise<void>>effect(execute: () => Effect, label?: string): AsyncDisposable<Promise<void>>在此 fiber 上注册一个支持清理的作用。
execute 会立即运行;它产生的清理函数将被收集,并在调用返回的清理函数或卸载 fiber 时按相反顺序运行,以先发生者为准。重复调用清理函数不会产生任何效果。如果 fiber 已经 dispose(资源释放),则抛出 CordisError('INACTIVE_EFFECT');如果结构无效,则抛出 TypeError,表示 execute 返回了不受支持的结果。
execute:作用主体;可接受的结构见Effect。label:在getEffects()诊断信息中显示的作用标签。
返回一个用于撤销该作用的清理函数,并在清理完成后结算。
ctx.fiber
Section titled “ctx.fiber”/** The fiber (plugin runtime instance) that owns this context. */fiber: Fiber拥有此上下文的 fiber(插件运行时实例)。
插件加载与依赖注入。
ctx.inject(deps, callback)
Section titled “ctx.inject(deps, callback)”/** * Run a callback once the requested services are available. * * Shorthand for `ctx.plugin({ inject, apply: callback })`: the callback * is unloaded and re-run whenever a required service changes. * * @param deps — required services, as an array or a name → config map. * @param callback — plugin body called with `(ctx, config)`. * @returns the fiber; awaiting it settles once loading finished. */inject(deps: Inject, callback: Plugin.Function<void>): Fiber & PromiseLike<Fiber>请求的服务可用后,运行回调。
这是 ctx.plugin({ inject, apply: callback }) 的简写形式:每当某个必需服务发生变化时,系统都会卸载并重新运行该回调。
deps:必需服务,形式可以是数组,也可以是从名称到配置的映射。callback:以(ctx, config)调用的插件主体。
返回 fiber;对其执行 await 会在加载完成后结束等待。
ctx.plugin(plugin, …args)
Section titled “ctx.plugin(plugin, …args)”/** * Load a plugin in the current context. * * @param plugin — a function, class, or `{ apply }` object plugin. * @param args — the plugin config, validated against its `Config` schema. * @returns the fiber; awaiting it settles once loading finished * (rejecting on config or startup errors). */plugin<P extends Plugin>(plugin: P, ...args: Spread<GetPluginConfig<P>>): Fiber & PromiseLike<Fiber>在当前上下文中加载插件。
plugin:函数、类或{ apply }对象形式的插件。args:插件配置,会根据其Configschema 进行校验。
返回 fiber;对其执行 await 会在加载完成后结束等待(如果发生配置错误或启动错误,则会被拒绝)。
上下文服务的基类。以插件形式加载的子类会将自身注册为 ctx.<name>。
用于在 ctx 上公开具名 API 的服务基类。
子类在构造函数中调用 super(ctx, name)。服务会立即注册,并随所属 fiber 自动移除。
service.name
Section titled “service.name”/** The service name this instance is registered under. */public name!: string此实例注册时使用的服务名称。