Merge remote-tracking branch 'origin/master' into worktree-config-settings-seam

# Conflicts:
#	docs/cordis-catalog/events.md
#	docs/core-data-structures/core.i18n.yaml
#	docs/event-producer-consumer.md
#	packages/README.i18n.yaml
#	packages/cordis/tool-cordis/src/api-catalog.ts
#	scripts/doc-budgets.manifest.json
This commit is contained in:
Yichen Jiang
2026-07-30 13:13:59 +08:00
1335 changed files with 57634 additions and 9812 deletions

View File

@@ -3,4 +3,4 @@
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/cordis/README.md
README.md: a47b9ba20789bb6b9a36b1af9b3942b90e61b365
README.zh.md: cc91e68f0dfa9fb343c332eba2579c2a077beb64
README.zh.md: 3ee1ddb1db28352cd05b3e79e88228035bc39ac4

View File

@@ -2,8 +2,8 @@
[English](README.md) | 中文
面向模型、作用于 agent(智能体)所在实时 Cordis 运行时的工具:检查当前 DSH 进程,并挂载或卸载仅存于内存的临时 Plugin。设计归档见[工具集 Agent Note(agent 决策记录)](../../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md)。
这些面向模型的工具作用于 agent(智能体)自身所在的实时 Cordis 运行时,可检查已加载的插件和服务接口、挂载模型编写的插件,并将其 dispose(资源释放)。设计说明见[工具集 Agent Note(agent 决策记录)](../../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md)。
| 包(package) | 角色 | ctx 键 |
|---|---|---|
| [`tool-cordis/`](tool-cordis/README.md) | `cordis_inspect`/`cordis_mount`/`cordis_unmount` 工具:读取当前进程运行时,并在一个自有分组 fiber 下管理临时 Plugin | 注册到 `ctx.tools` |
| [`tool-cordis/`](tool-cordis/README.md) | `cordis_inspect`/`cordis_mount`/`cordis_unmount` 工具:读取当前进程运行时,并在一个自有分组 fiber 下管理内存中的临时插件 | 注册到 `ctx.tools` |

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/cordis/tool-cordis/README.md
README.md: 5b58e665dae95aea0d0ad094238fef5d3dc0fb97
README.zh.md: 11e5be11dca84247b19888fefa7d70e5d74da174
README.md: eda135d93e2912bbb4e111af40d176409b383b5b
README.zh.md: 6eef10086142d56dd809e5114b4e0e712f726ecc

View File

@@ -28,7 +28,7 @@ The sandbox isolates globals but is not a security boundary. Node globals are ab
## The generated API catalog
`src/api-catalog.ts` is generated by `scripts/gen-cordis-api.ts` from the same AST walk as [docs/cordis-catalog](../../../docs/cordis-catalog/services.md) and freshness-gated by `pnpm run verify-cordis-api` (in `doc-sync`) — never edit it by hand. `cordis_inspect` intersects it with the live service store at call time. Broad `api` / `events` reports render summaries and signatures only; an exact `name` opts into the retained method/event JSDoc, and unknown or non-running service targets fail loud.
`src/api-catalog.ts` is generated from the same Typert `FaceModel` projection as [docs/cordis-catalog](../../../docs/cordis-catalog/services.md) and freshness-gated by `pnpm run verify-cordis-api` (in `doc-sync`) — never edit it by hand. `scripts/gen-cordis-api.ts` is a compatibility entry point for that unified projection, not a second collector. `cordis_inspect` intersects the committed catalog with the live service store at call time; it has no runtime Typert dependency. Broad `api` / `events` reports render summaries and signatures only; an exact `name` opts into the retained method/event JSDoc, and unknown or non-running service targets fail loud.
## Rendering

View File

@@ -2,19 +2,19 @@
[English](README.md) | 中文
自引用 Cordis 工具集:三个面向模型的工具,操作当前 DSH 进程中的存活运行时。设计归属(沙箱语义、临时 Plugin 生命周期与组合、生成的 API 目录、既定决策)见[工具集 Agent Note](../../../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md)。
自引用 Cordis 工具集:三个面向模型的工具,操作当前 DSH 进程中的实时运行时。沙箱语义、临时插件生命周期与组合、生成的 API 目录及既定决策详见[工具集 Agent Note(agent 决策记录)](../../../.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md)。
## 功能
- `cordis_inspect`:当前进程运行时的只读报告,包括服务、全部存活 Plugin fiber、已注册工具、`cordis_mount` 临时 Plugin 子集,以及目录支持的 `api`/`events` 参考。精确的 `name` 配合 `what: "api"` 或 `what: "events"` 可缩窄报告,并附上原始源代码 JSDoc。
- `cordis_mount`:立即求值模型编写的 JavaScript 且不保存到任何位置;代码必须返回一个以 `dyn-<n>` 跟踪、仅存于内存的临时 Plugin。
- `cordis_unmount`:卸载一个 `dyn-<n>` 临时 Plugin,并只在其自有效果完全停稳后返回;它不能删除 Loader、配置或已安装的 Plugin。
- `cordis_inspect`:当前进程运行时的只读报告,包括服务、全部存活插件 fiber、已注册工具、`cordis_mount` 临时插件子集,以及目录支持的 `api`/`events` 参考。精确的 `name` 配合 `what: "api"` 或 `what: "events"` 可缩窄报告,并附上原始源代码 JSDoc。
- `cordis_mount`:立即求值模型编写的 JavaScript 且不保存到任何位置;代码必须返回一个仅存于内存、以 `dyn-<n>` 为标识进行跟踪的临时插件。
- `cordis_unmount`:卸载一个 `dyn-<n>` 临时插件,并只在其拥有的 effect 完全停稳后返回;它不能移除 Loader 插件、已配置插件或已安装插件。
精确的面向模型 schema 见[生成的工具目录](../../../docs/tool-catalog.md)。
面向模型的确切 schema 见[生成的工具目录](../../../docs/tool-catalog.md)。
规范成功值分别为检查字符串、挂载 `{ id, pluginName, state, provides, waitingFor }`,以及卸载 `{ id, pluginName }`。原生 renderer 会说明临时 Plugin 正在运行还是等待中,并说明它可用至被卸载或 DSH 重启;卸载结果确认它已移除。
规范成功结果分别为检查字符串、挂载 `{ id, pluginName, state, provides, waitingFor }`,以及卸载 `{ id, pluginName }`。原生渲染会说明临时插件正在运行还是等待中,并说明它可用至被卸载或 DSH 重启;卸载结果确认它已移除。
临时 Plugin 只存在于共享 DSH 进程内存中。它可跨后续 turn 保持活跃,也可能影响同一进程中的其他 session,但会在 `cordis_unmount`、工具集卸载或 DSH 重启后消失。它不会创建 Plugin 文件、安装 package、修改 `cordis.yml` 或个人/项目配置、跨重启存续,也不能自动转为正式 Plugin。若要保留实验结果,应让 Agent 通过常规开发流程实现普通的本地、项目或仓库 Plugin。
临时插件只存在于共享 DSH 进程内存中。它可跨后续轮次保持活跃,也可能影响同一进程中的其他会话,但会在 `cordis_unmount`、工具集卸载或 DSH 重启后消失。它不会创建插件文件、安装任何包(package)、修改 `cordis.yml` 或个人/项目配置、跨重启存续,也不能自动转为正式插件。若要保留实验结果,应让 agent(智能体)通过常规开发流程实现普通的本地、项目或仓库插件。
## 信任立场
@@ -24,17 +24,17 @@
| 字段 | 默认值 | 含义 |
|---|---|---|
| `vmTimeoutMs` | `5000` | 临时 Plugin 代码求值中同步部分的边界;async 主体可逃出该边界 |
| `vmTimeoutMs` | `5000` | 临时插件代码求值中同步部分的边界;async 主体可逃出该边界 |
## 生成的 API 目录
`src/api-catalog.ts` 由 `scripts/gen-cordis-api.ts` 生成,使用与 [docs/cordis-catalog](../../../docs/cordis-catalog/services.md) 相同的 AST 遍历,并由 `pnpm run verify-cordis-api`(位于 `doc-sync` 中)实施新鲜度门禁,绝不可手工编辑。`cordis_inspect` 在调用时把该目录与存活服务 store 取交集。宽泛的 `api`/`events` 报告只渲染摘要与签名;精确 `name` 会选择保留的方法/事件 JSDoc,未知或未运行的服务目标会高声失败。
`src/api-catalog.ts` 与 [docs/cordis-catalog](../../../docs/cordis-catalog/services.md) 由同一个 Typert `FaceModel` 投影生成,并由 `pnpm run verify-cordis-api`(位于 `doc-sync` 中)实施新鲜度门禁,绝不可手工编辑。`scripts/gen-cordis-api.ts` 是该统一投影的兼容入口,而非第二套收集器。`cordis_inspect` 在调用时把已提交的目录与存活服务 store 取交集;它在运行时不依赖 Typert。宽泛的 `api`/`events` 报告只渲染摘要与签名;精确 `name` 会选择保留的方法/事件 JSDoc,未知或未运行的服务目标会高声失败。
## 渲染
三个工具都渲染 `generic` 卡片(`read`/`execute`/`delete`);`cordis_mount` 以 `rawInput` 携带临时 Plugin 代码。presenter 是 args 的纯函数;结果保留默认文本渲染。
三个工具都渲染 `generic` 卡片(`read`/`execute`/`delete`);`cordis_mount` 以 `rawInput` 携带临时插件代码。presenter 是 args 的纯函数;结果保留默认文本渲染。
## 导出形状
## 导出形式
Namespace 插件:命名导出 `name`/`inject`/`Config`/`apply`,无默认导出([docs/postmortem/0001](../../../docs/postmortem/0001-acp-default-export-drops-inject.md))。
@@ -58,29 +58,29 @@ Namespace 插件:命名导出 `name`/`inject`/`Config`/`apply`,无默
#### 模型看到的内容
检查会精确地用 `## <section>` 加换行及数据相关主体来拼接选中区段,各区段之间留一个空行;`what: "temporary"` 使用 `## Temporary Plugins` 标题。每个临时 Plugin 行都会报告 running/pending 状态、提供与等待的服务,以及持续至卸载或 DSH 重启的生命周期;空状态说明 `cordis_mount` Plugin 会在重启时消失。宽泛的 API/事件报告省略 JSDoc;`name` 配合 `what: "api"` 或 `what: "events"` 返回一个精确目标及其原始 JSDoc。挂载返回 `Temporary Plugin <id> is running (...)` 或 `Temporary Plugin <id> is pending (...)`;卸载返回 `Temporary Plugin <id> was unmounted and removed.`。提交的程序保留在 assistant 工具调用历史中。
检查会精确地用 `## <section>` 加换行及取决于数据的正文来拼接选中区段,各区段之间留一个空行;`what: "temporary"` 使用 `## Temporary Plugins` 标题。每个临时插件行都会报告 running/pending 状态,以及其提供和等待的服务,以及持续至卸载或 DSH 重启的生命周期;空状态说明 `cordis_mount` 插件会在重启时消失。宽泛的 API/事件报告省略 JSDoc;`name` 配合 `what: "api"` 或 `what: "events"` 返回一个精确目标及其原始 JSDoc。挂载返回 `Temporary Plugin <id> is running (...)` 或 `Temporary Plugin <id> is pending (...)`;卸载返回 `Temporary Plugin <id> was unmounted and removed.`。提交的程序保留在 assistant 工具调用历史中。
#### Token 影响
检查输出与挂载代码取决于数据,并在压缩前重复发送;生命周期确认文本很短。
检查输出与挂载代码取决于数据,并在压缩(compaction)前重复发送;生命周期确认文本很短。
#### KV Cache 影响
仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV-cache 配置项失效。
仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV-cache 条目失效。
### cordis_mount 后的后续请求
#### 模型看到的内容
临时 Plugin 可以注册工具、提示词贡献或监听器,改变其目标 scope 的后续请求;`cordis_unmount` 会在完全停稳后移除这些贡献。
临时插件可以注册工具、提示词贡献或监听器,改变其目标 scope 的后续请求;`cordis_unmount` 会在完全停稳后移除这些贡献。
#### Token 影响
间接 token 影响等于临时 Plugin 的贡献,且只在其进程内生命周期内持续。
间接 token 影响等于临时插件的贡献,且只在其进程内生命周期内持续。
#### KV Cache 影响
挂载或卸载提示词/工具贡献会改变后续请求前缀,并可能使从第一个变化的贡献起的复用失效;临时 Plugin 集合不变时,前缀保持稳定。
挂载或卸载提示词/工具贡献会改变后续请求前缀,并可能使从第一个变化的贡献起的复用失效;临时插件集合不变时,前缀保持稳定。
## 已知限制与暂缓事项

View File

@@ -264,6 +264,16 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
},
],
},
{
key: 'directoryPicker',
summary: 'Abstract directory-picking service.',
methods: [
{
signature: 'abstract capability(): DirectoryPickerCapability',
jsDoc: '/**\n * The backend\'s interaction capability.\n * @returns the discriminated capability consumers switch on.\n */',
},
],
},
{
key: 'fs',
summary: 'Abstract filesystem provider.',
@@ -414,6 +424,10 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
signature: 'current(events: readonly SessionEvent[]): string',
jsDoc: '/**\n * Resolve the preset matching the effective knob values. A still-matching\n * last selection wins shared-bundle ties; otherwise the first table match\n * wins, or {@link CUSTOM_PRESET} when no entry matches.\n * @param events - the session\'s events in log order.\n * @returns the effective preset name, or `custom` when nothing matches.\n */',
},
{
signature: 'selectFor(state: KnobState): PermissionSelect',
jsDoc: '/**\n * Build the whole select value for one folded knob state: every table\n * option in declaration order, `custom` appended exactly while derived.\n * @param state - the folded knob overrides.\n * @returns the `permissions` projection payload.\n */',
},
{
signature: 'resolve(name: string): PresetSpec',
jsDoc: '/**\n * Resolve a preset\'s knob bundle.\n * @param name - the preset name to resolve.\n * @returns the configured bundle.\n * @throws when `name` is not in the table.\n */',
@@ -475,7 +489,7 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
jsDoc: '/**\n * Deliver an allowed signal through an owned backend session.\n * @param owner - exact session owner.\n * @param id - target PTY identity.\n * @param signal - allowed POSIX signal name.\n * @returns delivered foreground process-group identity.\n */',
},
{
signature: 'async kill(owner: Agent, id: PtySessionId, reason = \'model request\'): Promise<boolean>',
signature: 'async kill(owner: Agent, id: PtySessionId, reason: string = \'model request\'): Promise<boolean>',
jsDoc: '/**\n * Close one owned session and remove it only after quiescent backend cleanup.\n * @param owner - exact session owner.\n * @param id - target PTY identity.\n * @param reason - diagnostic cleanup reason.\n * @returns true for a newly closed session, false when the same close is already in flight.\n */',
},
{
@@ -665,7 +679,7 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
summary: 'Exact-read consumer that prepares immutable cross-session message context.',
methods: [
{
signature: 'async listCandidates( agent: Agent, query = \'\', limit = this.config.candidateLimit, signal?: AbortSignal, ): Promise<SessionReferenceCandidate[]>',
signature: 'async listCandidates( agent: Agent, query: string = \'\', limit: number = this.config.candidateLimit, signal?: AbortSignal, ): Promise<SessionReferenceCandidate[]>',
jsDoc: '/**\n * List reference candidates, ranked by working-directory affinity.\n * @param agent - target agent; self is excluded and its cwd drives ranking.\n * @param query - optional case-insensitive session-id/cwd/title substring.\n * @param limit - optional positive result cap.\n * @param signal - optional cancellation boundary for host autocomplete teardown.\n * @returns candidates labeled by latest title or, when absent, session id.\n */',
},
{
@@ -720,6 +734,10 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
signature: 'get(session: Session): SessionTitleSnapshot | undefined',
jsDoc: '/**\n * Read the latest folded title from one live or replayed session.\n * @param session - session whose log is the title source of truth.\n * @returns latest title snapshot, or `undefined` before eligible input.\n */',
},
{
signature: 'rename(session: Session, title: string): SessionTitleSnapshot',
jsDoc: '/**\n * Accept an explicit user title. Appends a `session/title` event with the\n * `user` source, which pins the title: in-flight automatic generation is\n * superseded and later user messages schedule none (an explicit\n * {@link SessionTitleService.refresh} remains the deliberate unpin).\n * @param session - exact live session to rename.\n * @param title - raw user input; normalized before acceptance.\n * @returns the accepted title snapshot.\n * @throws {SessionTitleInvalidError} when the title normalizes to empty.\n * @throws {Error} when the session is not live or the service is disposed.\n */',
},
{
signature: 'async refresh(session: Session, signal?: AbortSignal): Promise<SessionTitleSnapshot | undefined>',
jsDoc: '/**\n * Explicitly retry the registered provider, or materialize the built-in\n * fallback when no provider is registered.\n * @param session - exact live session to refresh.\n * @param signal - optional caller cancellation.\n * @returns latest accepted title, or `undefined` when no eligible text exists.\n */',
@@ -761,16 +779,20 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
summary: 'Registry of skill providers.',
methods: [
{
signature: 'registerProvider(provider: SkillProvider): () => void',
jsDoc: '/**\n * Register a borrowed same-process provider synchronously during plugin apply. Duplicate and\n * reserved names throw; remote initialization belongs in `list()`. Fiber disposal unregisters\n * the provider and invalidates catalog caches.\n * @param provider - the provider to register by `provider.name`.\n * @returns the exact Cordis effect disposer that unregisters this provider;\n * composite effects may yield it directly to preserve teardown ordering.\n */',
signature: 'registerProvider(create: (control: SkillProviderControl) => SkillProvider): () => void',
jsDoc: '/**\n * Register a borrowed same-process provider synchronously during plugin apply. Duplicate and\n * reserved names throw; remote initialization belongs in `list()`. Fiber disposal unregisters\n * the provider and invalidates catalog caches.\n * @param create - synchronous factory receiving this registration\'s lifecycle and invalidation control.\n * @returns the exact Cordis effect disposer that unregisters this provider;\n * composite effects may yield it directly to preserve teardown ordering.\n */',
},
{
signature: 'register(skill: SkillRegistration): () => void',
jsDoc: '/**\n * Register a borrowed readonly runtime skill. Project entries outrank runtime entries, which\n * outrank user entries. Same-name runtime entries are first-wins; a duplicate logs a warning and\n * receives a no-op disposer so it cannot remove the winner.\n * @param skill - the complete skill definition to expose for discovery.\n * @returns the exact Cordis effect disposer, preserving composite teardown order and invalidating caches.\n */',
jsDoc: '/**\n * Register a borrowed readonly runtime skill. Project entries outrank runtime entries, which\n * outrank user entries. Same-name runtime entries are first-wins; a duplicate logs a warning and\n * receives a no-op disposer so it cannot remove the winner.\n * @param skill - the skill definition input; omitted invocation and provider fields receive defaults.\n * @returns the exact Cordis effect disposer, preserving composite teardown order and invalidating caches.\n */',
},
{
signature: 'async list(options: SkillLookupOptions = {}): Promise<SkillSummary[]>',
jsDoc: '/**\n * List model-invocable skill summaries for a workspace. Lookup options and\n * provider candidates are readonly same-process values borrowed throughout\n * discovery.\n * @param options - lookup options; `cwd` selects project roots and `signal` cancels discovery.\n * @returns sorted summaries, excluding skills disabled for model invocation.\n */',
jsDoc: '/**\n * List invocation-neutral skill summaries for a workspace. Consumers apply\n * model or user invocation policy at their operational boundary. Lookup\n * options and provider candidates are readonly same-process values borrowed\n * throughout discovery.\n * @param options - lookup options; `cwd` selects project roots and `signal` cancels discovery.\n * @returns all sorted winning summaries.\n */',
},
{
signature: 'async snapshot(options: SkillLookupOptions = {}): Promise<SkillCatalogSnapshot>',
jsDoc: '/**\n * Observe the current invocation-neutral catalog and whether discovery completed within a stable revision.\n * Incomplete observations are never cached, allowing consumers to retain last-good state and\n * retry on their next request boundary.\n * @param options - lookup options; `cwd` selects project roots and `signal` cancels discovery.\n * @returns sorted summaries plus discovery-completeness state.\n */',
},
{
signature: 'async get(name: string, options: SkillLookupOptions = {}): Promise<SkillDefinition | undefined>',
@@ -1006,6 +1028,40 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
},
],
},
{
key: 'typert',
summary: 'Registry of generated schemas and package reflection.',
methods: [
{
signature: 'register(contribution: TypertContribution): () => void',
jsDoc: '/**\n * Register one generated contribution atomically for the calling fiber.\n * Duplicate package-face identities or schema keys reject the whole batch.\n * @param contribution - generated schemas and package metadata.\n * @returns the exact effect disposer that removes this contribution.\n */',
},
{
signature: 'get(key: string): TypertSchemaRecord | undefined',
jsDoc: '/**\n * Look up one schema by `<package>#<name>`.\n * @param key - global schema key.\n * @returns the live schema record, or `undefined` when absent.\n */',
},
{
signature: 'resolve(key: string): TypertSchemaRecord',
jsDoc: '/**\n * Resolve one required schema.\n * @param key - global schema key.\n * @returns the live schema record.\n * @throws when the key is malformed, the package face is absent, or the schema is not contributed.\n */',
},
{
signature: 'list(filter: TypertSchemaFilter = {}): TypertSchemaRecord[]',
jsDoc: '/**\n * Enumerate live schemas in registration order.\n * @param filter - optional package and face restriction.\n * @returns matching schema records.\n */',
},
{
signature: 'getPackage(packageName: string, face: TypertFace = \'host\'): TypertPackageRecord | undefined',
jsDoc: '/**\n * Look up generated reflection for one package face.\n * @param packageName - exact npm package name.\n * @param face - face to query; defaults to the host runtime.\n * @returns the live package record, or `undefined` when absent.\n */',
},
{
signature: 'listPackages(filter: TypertPackageFilter = {}): TypertPackageRecord[]',
jsDoc: '/**\n * Enumerate generated package reflection in registration order.\n * @param filter - optional package and face restriction.\n * @returns matching package records.\n */',
},
{
signature: 'toJSONSchema(key: string, params?: z.core.ToJSONSchemaParams): z.core.JSONSchema.BaseSchema',
jsDoc: '/**\n * Project a live Zod schema to JSON Schema without caching the result.\n * @param key - global schema key.\n * @param params - Zod projection parameters.\n * @returns a fresh JSON Schema document.\n */',
},
],
},
{
key: 'userInteraction',
summary: '`ctx.userInteraction`: one active UI provider plus an `ask()` surface.',
@@ -1120,24 +1176,31 @@ export const EVENT_API: readonly EventApiEntry[] = [
{
name: 'agent/inbox/dequeue',
mode: 'emit',
signature: '\'agent/inbox/dequeue\'( this: Scoped<Agent>, agent: Agent, message: UserMessage, placement: InboxPlacement, ): void',
jsDoc: '/**\n * The driver claimed one item out of the inbox: a queued item at a turn\n * boundary, or steering drained between steps. Fires after the item leaves\n * its FIFO and before it becomes a durable message.\n * @param agent - the agent whose inbox item was claimed.\n * @param message - the claimed message.\n * @param placement - the FIFO that claimed this occurrence; together with\n * `message.id`, it matches the earliest outstanding enqueue in that FIFO.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode emit\n */',
signature: '\'agent/inbox/dequeue\'(this: Scoped<Agent>, agent: Agent, item: InboxItem): void',
jsDoc: '/**\n * The driver claimed one item out of the inbox: a queued item at a turn\n * boundary, or steering drained between steps. Fires after the item leaves\n * its FIFO and before it becomes a durable message.\n * @param agent - the agent whose inbox item was claimed.\n * @param item - the exact claimed occurrence.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode emit\n */',
summary: 'The driver claimed one item out of the inbox: a queued item at a turn boundary, or steering drained between steps.',
},
{
name: 'agent/inbox/discard',
mode: 'emit',
signature: '\'agent/inbox/discard\'(this: Scoped<Agent>, agent: Agent, messages: UserMessage[]): void',
jsDoc: '/**\n * Pending inbox items were dropped without delivering them, so every\n * enqueue occurrence receives exactly one terminal `agent/inbox/dequeue` OR\n * `agent/inbox/discard`. `cancel()` without `keepInbox`, including disposal,\n * emits this after `agent/cancel-requested` when applicable and before\n * aborting the active work. Fires once per drop with every dropped item.\n * @param agent - the agent whose inbox items were dropped.\n * @param messages - the discarded messages in FIFO order (queued then steering); never empty.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode emit\n */',
signature: '\'agent/inbox/discard\'(this: Scoped<Agent>, agent: Agent, items: InboxItem[]): void',
jsDoc: '/**\n * Pending inbox items were dropped without delivering them, so every\n * enqueue occurrence receives exactly one terminal `agent/inbox/dequeue` OR\n * `agent/inbox/discard`. `cancel()` without `keepInbox`, including disposal,\n * emits this after `agent/cancel-requested` when applicable and before\n * aborting the active work. Fires once per drop with every dropped item.\n * @param agent - the agent whose inbox items were dropped.\n * @param items - the discarded occurrences in FIFO order (queued then steering); never empty.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode emit\n */',
summary: 'Pending inbox items were dropped without delivering them, so every enqueue occurrence receives exactly one terminal `agent/inbox/dequeue` OR `agent/inbox/discard`.',
},
{
name: 'agent/inbox/enqueue',
mode: 'emit',
signature: '\'agent/inbox/enqueue\'(this: Scoped<Agent>, agent: Agent, message: UserMessage, placement: InboxPlacement): void',
jsDoc: '/**\n * An item entered the queued or steering inbox. `placement` is the\n * acceptance-time routing result; listeners must not reconstruct it from\n * later agent or session state.\n * @param agent - the owning agent.\n * @param message - accepted content, source, and correlation identity.\n * @param placement - resolved queued or steering placement.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode emit\n */',
signature: '\'agent/inbox/enqueue\'(this: Scoped<Agent>, agent: Agent, item: InboxItem): void',
jsDoc: '/**\n * An item entered the queued or steering inbox. `placement` is the\n * acceptance-time routing result; listeners must not reconstruct it from\n * later agent or session state.\n * @param agent - the owning agent.\n * @param item - accepted occurrence, message, and resolved placement.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode emit\n */',
summary: 'An item entered the queued or steering inbox.',
},
{
name: 'agent/inbox/update',
mode: 'emit',
signature: '\'agent/inbox/update\'(this: Scoped<Agent>, agent: Agent, item: InboxItem): void',
jsDoc: '/**\n * A still-pending queued item changed content. The item id, placement, and\n * position remain stable while the event carries the replacement message.\n * @param agent - the owning agent.\n * @param item - the complete post-update occurrence.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode emit\n */',
summary: 'A still-pending queued item changed content.',
},
{
name: 'agent/prompt-submit',
mode: 'waterfall',
@@ -1286,32 +1349,11 @@ export const EVENT_API: readonly EventApiEntry[] = [
summary: 'Committed change to one registered namespace\'s resolved value.',
},
{
name: 'slash/input-begin-command',
mode: 'bail',
signature: '\'slash/input-begin-command\'(request: BeginCommandRequest): true | undefined',
jsDoc: '/**\n * Applies one command claim to the scoped Input. Dispatched with the\n * session\'s scope carrier; the owning session\'s input listener returns\n * `true` only after the phase and span CAS checks pass and the machine\n * actually mutated — producers treat anything else as "not applied".\n * @param request - Claim and menu-time span CAS.\n * @mode bail\n */',
summary: 'Applies one command claim to the scoped Input.',
},
{
name: 'slash/input-consume-token',
mode: 'bail',
signature: '\'slash/input-consume-token\'(request: ConsumeTokenRequest): true | undefined',
jsDoc: '/**\n * Consumes one command token after business success (popup settle /\n * menu-pick execute). Same carrier routing and applied-truth contract.\n * @param request - Exact span or bare-token guard.\n * @mode bail\n */',
summary: 'Consumes one command token after business success (popup settle / menu-pick execute).',
},
{
name: 'slash/input-insert-reference',
mode: 'bail',
signature: '\'slash/input-insert-reference\'(request: InsertReferenceRequest): true | undefined',
jsDoc: '/**\n * Inserts one reference into the scoped Input (same carrier routing and\n * applied-truth contract as begin-command).\n * @param request - Reference and menu-time span CAS.\n * @mode bail\n */',
summary: 'Inserts one reference into the scoped Input (same carrier routing and applied-truth contract as begin-command).',
},
{
name: 'slash/input-insert-text',
mode: 'bail',
signature: '\'slash/input-insert-text\'(request: InsertTextRequest): true | undefined',
jsDoc: '/**\n * Replaces the trigger token span with literal text — the plain-text\n * reference path (decision 21). Same carrier routing and applied-truth\n * contract; the draft gains ordinary characters, no occurrence entry.\n * @param request - Replacement text and menu-time span CAS.\n * @mode bail\n */',
summary: 'Replaces the trigger token span with literal text — the plain-text reference path (decision 21).',
name: 'skills/change',
mode: 'emit',
signature: '\'skills/change\'(): void',
jsDoc: '/**\n * A skill provider, runtime contribution, or provider-backed catalog may\n * have changed. This is an unfiltered invalidation notification; consumers\n * refetch the catalog for their own lookup options. Listener failures are\n * contained and cannot veto the registry mutation.\n * @mode emit\n */',
summary: 'A skill provider, runtime contribution, or provider-backed catalog may have changed.',
},
{
name: 'subagent/end',
@@ -1452,7 +1494,7 @@ export const EVENT_API: readonly EventApiEntry[] = [
export const TYPE_API: readonly TypeApiEntry[] = [
{
name: 'Agent',
declaration: 'export interface Agent {\n readonly id: SessionId;\n readonly options: AgentOptions;\n readonly session: Session;\n readonly status: AgentStatus;\n readonly acceptsNextStep: boolean;\n readonly ctx: Context;\n send(message: UserMessage, options: SendOptions): void;\n cancel(cause: AgentCancelCause, options?: CancelOptions): void;\n whenIdle(): Promise<void>;\n followup(message: UserMessage): void;\n steer(message: UserMessage): void;\n inject(message: UserMessage): void;\n}',
declaration: 'export interface Agent {\n readonly id: SessionId;\n readonly options: AgentOptions;\n readonly session: Session;\n readonly status: AgentStatus;\n readonly acceptsNextStep: boolean;\n readonly ctx: Context;\n send(message: UserMessage, options: SendOptions): void;\n updateInbox(id: InboxItemId, action: InboxAction): InboxActionResult;\n cancel(cause: AgentCancelCause, options?: CancelOptions): void;\n whenIdle(): Promise<void>;\n followup(message: UserMessage): void;\n steer(message: UserMessage): void;\n inject(message: UserMessage): void;\n}',
},
{
name: 'AgentCancelCause',
@@ -1682,6 +1724,30 @@ export const TYPE_API: readonly TypeApiEntry[] = [
name: 'DiffResultView',
declaration: 'export interface DiffResultView {\n card: \'diff\';\n title?: string;\n diffs: FileDiff[];\n}',
},
{
name: 'DirectoryEntry',
declaration: 'export interface DirectoryEntry {\n name: string;\n path: string;\n hidden: boolean;\n}',
},
{
name: 'DirectoryListing',
declaration: 'export interface DirectoryListing {\n path: string;\n home: string;\n crumbs: DirectoryEntry[];\n entries: DirectoryEntry[];\n truncated: boolean;\n}',
},
{
name: 'DirectoryPickerBrowseCapability',
declaration: 'export interface DirectoryPickerBrowseCapability {\n kind: \'browse\';\n list(path?: string, signal?: AbortSignal): Promise<DirectoryListing>;\n createDirectory(path: string, name: string): Promise<string>;\n}',
},
{
name: 'DirectoryPickerCapabilities',
declaration: 'export interface DirectoryPickerCapabilities {\n native: DirectoryPickerNativeCapability;\n browse: DirectoryPickerBrowseCapability;\n}',
},
{
name: 'DirectoryPickerCapability',
declaration: 'export type DirectoryPickerCapability = DirectoryPickerCapabilities[keyof DirectoryPickerCapabilities];',
},
{
name: 'DirectoryPickerNativeCapability',
declaration: 'export interface DirectoryPickerNativeCapability {\n kind: \'native\';\n pick(signal: AbortSignal): Promise<string | null>;\n}',
},
{
name: 'Domain',
declaration: 'export interface Domain<S extends DomainSpec> {\n readonly name: string;\n readonly global: DomainGlobalHandleOf<S>;\n table<N extends keyof S[\'tables\'] & string>(name: N): KvTable<TableKeyOf<S, N>, TableValueOf<S, N>>;\n close(): Promise<void>;\n}',
@@ -1822,6 +1888,18 @@ export const TYPE_API: readonly TypeApiEntry[] = [
name: 'GoalView',
declaration: 'export interface GoalView extends GoalSnapshot {\n readonly roundsStarted: number;\n readonly createdAt: number;\n readonly updatedAt: number;\n readonly activation: GoalActivation;\n}',
},
{
name: 'InboxAction',
declaration: 'export type InboxAction = {\n readonly kind: \'edit\';\n readonly content: ContentBlock[];\n} | {\n readonly kind: \'remove\';\n};',
},
{
name: 'InboxActionResult',
declaration: 'export type InboxActionResult = \'applied\' | \'not-found\';',
},
{
name: 'InboxItemId',
declaration: 'export type InboxItemId = Branded<\'InboxItemId\'>;',
},
{
name: 'InvariantFailure',
declaration: 'export type InvariantFailure = (message: string) => never;',
@@ -1846,6 +1924,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [
name: 'JsonValue',
declaration: 'export type JsonValue = null | boolean | number | string | JsonValue[] | {\n [key: string]: JsonValue;\n};',
},
{
name: 'KnobState',
declaration: 'export interface KnobState {\n preset: string | null;\n sandbox: SandboxMode | null;\n approval: ApprovalPolicy | null;\n}',
},
{
name: 'KvTable',
declaration: 'export interface KvTable<K extends string, V> {\n get(key: K): V | undefined;\n entries(): IterableIterator<[\n K,\n V\n ]>;\n keys(): IterableIterator<K>;\n readonly size: number;\n put(key: K, value: V): Promise<void>;\n delete(key: K): Promise<boolean>;\n update(key: K, fn: (current: V) => V): Promise<V>;\n}',
@@ -1914,6 +1996,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [
name: 'ObjectJsonSchema',
declaration: 'export type ObjectJsonSchema = JsonSchemaNode & {\n type: \'object\';\n};',
},
{
name: 'PermissionSelect',
declaration: 'export interface PermissionSelect {\n options: PresetOption[];\n currentValue: string;\n}',
},
{
name: 'PreparedLlmCall',
declaration: 'export interface PreparedLlmCall {\n readonly config: LlmCallConfig;\n stream(options: GenerateOptions): AsyncIterable<StreamChunk>;\n}',
@@ -2312,7 +2398,7 @@ export const TYPE_API: readonly TypeApiEntry[] = [
},
{
name: 'SessionTitleSource',
declaration: 'export type SessionTitleSource = {\n readonly kind: \'fallback\';\n} | {\n readonly kind: \'provider\';\n readonly provider: SessionTitleProviderId;\n readonly model?: SessionTitleModelProvenance;\n};',
declaration: 'export type SessionTitleSource = {\n readonly kind: \'fallback\';\n} | {\n readonly kind: \'provider\';\n readonly provider: SessionTitleProviderId;\n readonly model?: SessionTitleModelProvenance;\n} | {\n readonly kind: \'user\';\n};',
},
{
name: 'SessionTitleUserMessage',
@@ -2342,21 +2428,37 @@ export const TYPE_API: readonly TypeApiEntry[] = [
name: 'SkillCandidate',
declaration: 'export interface SkillCandidate extends SkillSummary {\n readonly rank: number;\n readonly locator: unknown;\n readonly path?: string;\n readonly metadata?: Readonly<Record<string, unknown>>;\n}',
},
{
name: 'SkillCatalogSnapshot',
declaration: 'export interface SkillCatalogSnapshot {\n readonly skills: SkillSummary[];\n readonly complete: boolean;\n}',
},
{
name: 'SkillDefinition',
declaration: 'export interface SkillDefinition extends SkillSummary {\n readonly content: string;\n readonly path?: string;\n readonly metadata?: Readonly<Record<string, unknown>>;\n}',
},
{
name: 'SkillInvocationPolicy',
declaration: 'export interface SkillInvocationPolicy {\n readonly modelInvocable: boolean;\n readonly userInvocable: boolean;\n}',
},
{
name: 'SkillLookupOptions',
declaration: 'export interface SkillLookupOptions {\n readonly cwd?: string | undefined;\n readonly signal?: AbortSignal | undefined;\n}',
},
{
name: 'SkillProvider',
declaration: 'export interface SkillProvider {\n readonly name: string;\n readonly list: (options: SkillLookupOptions) => Promise<readonly SkillCandidate[]>;\n readonly get: (candidate: SkillCandidate, options: SkillLookupOptions) => Promise<SkillDefinition | undefined>;\n}',
declaration: 'export interface SkillProvider {\n readonly name: string;\n readonly list: (options: SkillLookupOptions) => Promise<readonly SkillCandidate[] | SkillProviderObservation>;\n readonly get: (candidate: SkillCandidate, options: SkillLookupOptions) => Promise<SkillDefinition | undefined>;\n}',
},
{
name: 'SkillProviderControl',
declaration: 'export interface SkillProviderControl {\n readonly signal: AbortSignal;\n readonly invalidate: () => void;\n}',
},
{
name: 'SkillProviderObservation',
declaration: 'export interface SkillProviderObservation {\n readonly candidates: readonly SkillCandidate[];\n readonly complete: boolean;\n}',
},
{
name: 'SkillRegistration',
declaration: 'export type SkillRegistration = Omit<SkillDefinition, \'provider\'> & {\n readonly provider?: string;\n};',
declaration: 'export type SkillRegistration = Omit<SkillDefinition, \'invocation\' | \'provider\'> & {\n readonly invocation?: SkillInvocationPolicy;\n readonly provider?: string;\n};',
},
{
name: 'SkillResourceBase',
@@ -2368,7 +2470,7 @@ export const TYPE_API: readonly TypeApiEntry[] = [
},
{
name: 'SkillSummary',
declaration: 'export interface SkillSummary {\n readonly name: string;\n readonly description: string;\n readonly whenToUse?: string;\n readonly disableModelInvocation?: boolean;\n readonly source: SkillSource;\n readonly provider: string;\n readonly resourceBase?: SkillResourceBase;\n}',
declaration: 'export interface SkillSummary {\n readonly name: string;\n readonly description: string;\n readonly whenToUse?: string;\n readonly invocation: SkillInvocationPolicy;\n readonly source: SkillSource;\n readonly provider: string;\n readonly resourceBase?: SkillResourceBase;\n}',
},
{
name: 'SpillLocator',
@@ -2674,6 +2776,62 @@ export const TYPE_API: readonly TypeApiEntry[] = [
name: 'TurnTriggerMap',
declaration: 'export interface TurnTriggerMap {\n message: {\n kind: \'message\';\n source: MessageSource;\n };\n retry: {\n kind: \'retry\';\n };\n injection: {\n kind: \'injection\';\n source: MessageSource;\n };\n}',
},
{
name: 'TypertContribution',
declaration: 'export interface TypertContribution {\n readonly package: string;\n readonly face: TypertFace;\n readonly schemas: readonly TypertSchema[];\n readonly model: TypertPackageModel;\n}',
},
{
name: 'TypertDocTag',
declaration: 'export interface TypertDocTag {\n readonly name: string;\n readonly argument?: string;\n readonly comment?: string;\n readonly text: string;\n}',
},
{
name: 'TypertDocumentation',
declaration: 'export interface TypertDocumentation {\n readonly description?: string;\n readonly summary?: string;\n readonly tags: readonly TypertDocTag[];\n readonly jsDoc?: string;\n}',
},
{
name: 'TypertEventModel',
declaration: 'export interface TypertEventModel extends TypertDocumentation {\n readonly name: string;\n readonly mode?: string;\n readonly signature: string;\n}',
},
{
name: 'TypertMemberModel',
declaration: 'export interface TypertMemberModel {\n readonly kind: \'property\' | \'method\' | \'getter\' | \'setter\' | \'call\' | \'construct\' | \'index\';\n readonly name: string;\n readonly signature: string;\n readonly summary?: string;\n readonly jsDoc?: string;\n}',
},
{
name: 'TypertObjectModel',
declaration: 'export interface TypertObjectModel extends TypertDocumentation {\n readonly name: string;\n readonly exportName: string;\n readonly members: readonly TypertMemberModel[];\n readonly types: readonly TypertTypeModel[];\n}',
},
{
name: 'TypertPackageFilter',
declaration: 'export interface TypertPackageFilter {\n readonly package?: string;\n readonly face?: TypertFace;\n}',
},
{
name: 'TypertPackageModel',
declaration: 'export interface TypertPackageModel {\n readonly services: readonly TypertServiceModel[];\n readonly events: readonly TypertEventModel[];\n readonly objects: readonly TypertObjectModel[];\n}',
},
{
name: 'TypertPackageRecord',
declaration: 'export interface TypertPackageRecord {\n readonly package: string;\n readonly face: TypertFace;\n readonly key: string;\n readonly model: TypertPackageModel;\n}',
},
{
name: 'TypertSchema',
declaration: 'export interface TypertSchema {\n readonly name: string;\n readonly schema: z.ZodType;\n}',
},
{
name: 'TypertSchemaFilter',
declaration: 'export interface TypertSchemaFilter {\n readonly package?: string;\n readonly face?: TypertFace;\n}',
},
{
name: 'TypertSchemaRecord',
declaration: 'export interface TypertSchemaRecord extends TypertSchema {\n readonly package: string;\n readonly face: TypertFace;\n readonly key: string;\n}',
},
{
name: 'TypertServiceModel',
declaration: 'export interface TypertServiceModel extends TypertDocumentation {\n readonly key: string;\n readonly exportName: string;\n readonly members: readonly TypertMemberModel[];\n readonly types: readonly TypertTypeModel[];\n}',
},
{
name: 'TypertTypeModel',
declaration: 'export interface TypertTypeModel {\n readonly name: string;\n readonly declaration: string;\n}',
},
{
name: 'UserInteractionProvider',
declaration: 'export interface UserInteractionProvider {\n ask(request: AskUserQuestionRequest): Promise<AskUserQuestionAnswer>;\n}',