From 39f55a049f1d9ca92226e1f631cc07332b5746f2 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Thu, 13 Aug 2026 01:59:32 +0800 Subject: [PATCH] fix: rebase --- docs/subsystems/README.md | 2 +- docs/subsystems/README.zh.md | 2 +- ...ication.i18n.yaml => extensions.i18n.yaml} | 6 +- ...{self-modification.zh.md => extensions.md} | 22 +- ...{self-modification.md => extensions.zh.md} | 22 +- packages/api/remotes/tests/built-lib.e2e.ts | 4 +- packages/api/remotes/tsconfig.client.json | 2 +- packages/api/remotes/tsconfig.host.json | 2 +- .../cordis-client-runner/src/client/guard.ts | 14 +- .../cordis-client-runner/src/client/index.ts | 4 +- .../src/client/providers.ts | 4 +- .../src/client/runtime.ts | 4 +- .../tests/guard.client.spec.ts | 6 +- .../tests/plugin.client.spec.ts | 4 +- .../tests/runner.client.spec.ts | 8 +- .../cordis-client-runner/tsconfig.json | 2 +- .../cordis-host-runner/package.json | 4 +- .../cordis-host-runner/src/index.ts | 4 +- .../cordis-host-runner/tsconfig.json | 4 +- .../extensions/tool-cordis/src/api-catalog.ts | 1892 +++++++++--- packages/extensions/tool-cordis/tsconfig.json | 2 +- packages/extensions/ui-cordis/package.json | 6 +- .../extensions/ui-cordis/src/client/index.ts | 6 +- packages/extensions/ui-cordis/tsconfig.json | 4 +- pnpm-lock.yaml | 2715 +++++++++-------- scripts/gen-cordis-catalog.ts | 9 +- 26 files changed, 3031 insertions(+), 1723 deletions(-) rename docs/subsystems/{self-modification.i18n.yaml => extensions.i18n.yaml} (67%) rename docs/subsystems/{self-modification.zh.md => extensions.md} (90%) rename docs/subsystems/{self-modification.md => extensions.zh.md} (90%) diff --git a/docs/subsystems/README.md b/docs/subsystems/README.md index 74111204c7..a1c2262f40 100644 --- a/docs/subsystems/README.md +++ b/docs/subsystems/README.md @@ -32,7 +32,7 @@ One page per subsystem of the DeepSeek Harness: what it is, the data structures | [terminal.md](terminal.md) | persistent terminal ids, backend/session contracts, send readiness, bounded reads, and owner-visible snapshots | | [sandbox.md](sandbox.md) | per-session policy resolution and the process-confinement seam: file-effect modes, execution/provider policies, `ConfinedArgv`, enforcement and fail-closed errors | | [code-runtime.md](code-runtime.md) | the code-execution seam: `CodeRunRequest`/`Result`, binding namespaces, captured logs, the `CodeRunFailure` taxonomy | -| [self-modification.md](self-modification.md) | versioned dynamic Cordis Plugins and Packages, Host/Client activation, approval, runtime inspection, and lifecycle teardown | +| [extensions.md](extensions.md) | versioned dynamic Cordis Plugins and Packages, Host/Client activation, approval, runtime inspection, and lifecycle teardown | | [filesystem.md](filesystem.md) | the filesystem seam: `FsTarget`, read/write/edit outcomes, observed-file state, `FsErrorCode` | | [lsp.md](lsp.md) | the LSP navigation seam: `LspQueryRequest`/`Result`, `LspProvider`/`Service`, four operations, `LspError` | | [skills.md](skills.md) | the skill service: discovery priority, `SkillSummary`/`SkillDefinition`, session-prefix catalog, model-facing `skill` loading | diff --git a/docs/subsystems/README.zh.md b/docs/subsystems/README.zh.md index 7cd9bbf2f9..0b5c00e632 100644 --- a/docs/subsystems/README.zh.md +++ b/docs/subsystems/README.zh.md @@ -32,7 +32,7 @@ | [terminal.md](terminal.md) | 持久化终端 ID、后端/会话约定、发送就绪状态、有界读取与 owner 可见快照 | | [sandbox.md](sandbox.md) | 每会话策略解析与进程约束 seam:文件效果模式、执行/提供方策略、`ConfinedArgv`、强制执行与故障关闭错误 | | [code-runtime.md](code-runtime.md) | 代码执行 seam:`CodeRunRequest`/`Result`、绑定命名空间、捕获日志、`CodeRunFailure` 分类体系 | -| [self-modification.md](self-modification.md) | 带版本的动态 Cordis Plugin 与 Package、Host/Client 激活、审批、运行时检查和生命周期撤销 | +| [extensions.md](extensions.md) | 带版本的动态 Cordis Plugin 与 Package、Host/Client 激活、审批、运行时检查和生命周期撤销 | | [filesystem.md](filesystem.md) | 文件系统 seam:`FsTarget`、读/写/编辑结果、观测到的文件状态、`FsErrorCode` | | [lsp.md](lsp.md) | LSP 导航 seam:`LspQueryRequest`/`Result`、`LspProvider`/`Service`、四种操作、`LspError` | | [skills.md](skills.md) | skill(技能)服务:发现优先级、`SkillSummary`/`SkillDefinition`、会话前缀目录、面向模型的 `skill` 加载 | diff --git a/docs/subsystems/self-modification.i18n.yaml b/docs/subsystems/extensions.i18n.yaml similarity index 67% rename from docs/subsystems/self-modification.i18n.yaml rename to docs/subsystems/extensions.i18n.yaml index 6da3bee9f6..bd02afe3f3 100644 --- a/docs/subsystems/self-modification.i18n.yaml +++ b/docs/subsystems/extensions.i18n.yaml @@ -1,6 +1,6 @@ # Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each # 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 docs/subsystems/self-modification.md -self-modification.md: 90ee02eb69149c6729635f9916fbd3946d4ae477 -self-modification.zh.md: a22bb38b1fe398da19b11384e6e38b9dde6d0c3e +# pnpm run verify-translation-pairing --write docs/subsystems/extensions.md +extensions.md: 90ee02eb69149c6729635f9916fbd3946d4ae477 +extensions.zh.md: a22bb38b1fe398da19b11384e6e38b9dde6d0c3e diff --git a/docs/subsystems/self-modification.zh.md b/docs/subsystems/extensions.md similarity index 90% rename from docs/subsystems/self-modification.zh.md rename to docs/subsystems/extensions.md index a22bb38b1f..f212f99704 100644 --- a/docs/subsystems/self-modification.zh.md +++ b/docs/subsystems/extensions.md @@ -1,8 +1,8 @@ -# 运行时自修改 +# Extensions -[English](self-modification.md) | 中文 +English | [中文](extensions.zh.md) -self-modification 子系统允许 agent(智能体)定义带版本的 Cordis 包、运行其 host 与浏览器两半,并在编写代码前查询获准公开的运行时元数据。包生命周期与沙箱行为由 [`packages/self-modification`](../../packages/self-modification/README.md) 包组说明。 +The extensions subsystem lets an agent define versioned Cordis packages, run their host and browser halves, and query approved runtime metadata before writing code. Package lifecycle and sandbox behavior belong to the [`packages/extensions`](../../packages/extensions/README.md) package group. @@ -62,7 +62,7 @@ resolveClientQuery( agent: Agent, requestId: CordisInspectRequestId, resolution: Types: [Agent](core.md) -Source: [`packages/self-modification/cordis-host-runner/src/inspect-registry.ts:46`](../../packages/self-modification/cordis-host-runner/src/inspect-registry.ts) +Source: [`packages/extensions/cordis-host-runner/src/inspect-registry.ts:46`](../../packages/extensions/cordis-host-runner/src/inspect-registry.ts) @@ -254,7 +254,7 @@ inspectPackage( agent: Agent, pluginId: CordisDynamicPluginId, packageId: Cordis Types: [Agent](core.md) -Source: [`packages/self-modification/cordis-host-runner/src/index.ts:124`](../../packages/self-modification/cordis-host-runner/src/index.ts) +Source: [`packages/extensions/cordis-host-runner/src/index.ts:124`](../../packages/extensions/cordis-host-runner/src/index.ts) @@ -275,7 +275,7 @@ One exact Plugin/Package activation is now live in the Host. 'cordis/dynamic-package'(pkg: DynamicCordisPackage): void ``` -Source: [`packages/self-modification/cordis-host-runner/src/types.ts:379`](../../packages/self-modification/cordis-host-runner/src/types.ts) +Source: [`packages/extensions/cordis-host-runner/src/types.ts:379`](../../packages/extensions/cordis-host-runner/src/types.ts) @@ -292,7 +292,7 @@ One exact activation was withdrawn. 'cordis/dynamic-retract'(retracted: DynamicCordisRetracted): void ``` -Source: [`packages/self-modification/cordis-host-runner/src/types.ts:385`](../../packages/self-modification/cordis-host-runner/src/types.ts) +Source: [`packages/extensions/cordis-host-runner/src/types.ts:385`](../../packages/extensions/cordis-host-runner/src/types.ts) @@ -309,7 +309,7 @@ Request a live read-only query from the Client inspect registry. 'cordis/inspect-query'(request: CordisInspectQueryRequest): void ``` -Source: [`packages/self-modification/cordis-host-runner/src/types.ts:391`](../../packages/self-modification/cordis-host-runner/src/types.ts) +Source: [`packages/extensions/cordis-host-runner/src/types.ts:391`](../../packages/extensions/cordis-host-runner/src/types.ts) @@ -326,7 +326,7 @@ Notify every Client that an inspect query has settled or been cancelled. 'cordis/inspect-query-resolved'(resolved: CordisInspectQueryResolved): void ``` -Source: [`packages/self-modification/cordis-host-runner/src/types.ts:397`](../../packages/self-modification/cordis-host-runner/src/types.ts) +Source: [`packages/extensions/cordis-host-runner/src/types.ts:397`](../../packages/extensions/cordis-host-runner/src/types.ts) @@ -343,7 +343,7 @@ A Client-bearing activation needs a browser page, and may require a user decisio 'cordis/request-run'(request: DynamicCordisRunRequest): void ``` -Source: [`packages/self-modification/cordis-host-runner/src/types.ts:367`](../../packages/self-modification/cordis-host-runner/src/types.ts) +Source: [`packages/extensions/cordis-host-runner/src/types.ts:367`](../../packages/extensions/cordis-host-runner/src/types.ts) @@ -360,5 +360,5 @@ A pending Client activation request left the answerable state. 'cordis/request-run-resolved'(resolved: DynamicCordisRequestResolved): void ``` -Source: [`packages/self-modification/cordis-host-runner/src/types.ts:373`](../../packages/self-modification/cordis-host-runner/src/types.ts) +Source: [`packages/extensions/cordis-host-runner/src/types.ts:373`](../../packages/extensions/cordis-host-runner/src/types.ts) diff --git a/docs/subsystems/self-modification.md b/docs/subsystems/extensions.zh.md similarity index 90% rename from docs/subsystems/self-modification.md rename to docs/subsystems/extensions.zh.md index 90ee02eb69..717b14951d 100644 --- a/docs/subsystems/self-modification.md +++ b/docs/subsystems/extensions.zh.md @@ -1,8 +1,8 @@ -# Runtime self-modification +# 扩展 -English | [中文](self-modification.zh.md) +[English](extensions.md) | 中文 -The self-modification subsystem lets an agent define versioned Cordis packages, run their host and browser halves, and query approved runtime metadata before writing code. Package lifecycle and sandbox behavior belong to the [`packages/self-modification`](../../packages/self-modification/README.md) package group. +extensions 子系统允许 agent(智能体)定义带版本的 Cordis 包、运行其 host 与浏览器两半,并在编写代码前查询获准公开的运行时元数据。包生命周期与沙箱行为由 [`packages/extensions`](../../packages/extensions/README.md) 包组说明。 @@ -62,7 +62,7 @@ resolveClientQuery( agent: Agent, requestId: CordisInspectRequestId, resolution: Types: [Agent](core.md) -Source: [`packages/self-modification/cordis-host-runner/src/inspect-registry.ts:46`](../../packages/self-modification/cordis-host-runner/src/inspect-registry.ts) +Source: [`packages/extensions/cordis-host-runner/src/inspect-registry.ts:46`](../../packages/extensions/cordis-host-runner/src/inspect-registry.ts) @@ -254,7 +254,7 @@ inspectPackage( agent: Agent, pluginId: CordisDynamicPluginId, packageId: Cordis Types: [Agent](core.md) -Source: [`packages/self-modification/cordis-host-runner/src/index.ts:124`](../../packages/self-modification/cordis-host-runner/src/index.ts) +Source: [`packages/extensions/cordis-host-runner/src/index.ts:124`](../../packages/extensions/cordis-host-runner/src/index.ts) @@ -275,7 +275,7 @@ One exact Plugin/Package activation is now live in the Host. 'cordis/dynamic-package'(pkg: DynamicCordisPackage): void ``` -Source: [`packages/self-modification/cordis-host-runner/src/types.ts:379`](../../packages/self-modification/cordis-host-runner/src/types.ts) +Source: [`packages/extensions/cordis-host-runner/src/types.ts:379`](../../packages/extensions/cordis-host-runner/src/types.ts) @@ -292,7 +292,7 @@ One exact activation was withdrawn. 'cordis/dynamic-retract'(retracted: DynamicCordisRetracted): void ``` -Source: [`packages/self-modification/cordis-host-runner/src/types.ts:385`](../../packages/self-modification/cordis-host-runner/src/types.ts) +Source: [`packages/extensions/cordis-host-runner/src/types.ts:385`](../../packages/extensions/cordis-host-runner/src/types.ts) @@ -309,7 +309,7 @@ Request a live read-only query from the Client inspect registry. 'cordis/inspect-query'(request: CordisInspectQueryRequest): void ``` -Source: [`packages/self-modification/cordis-host-runner/src/types.ts:391`](../../packages/self-modification/cordis-host-runner/src/types.ts) +Source: [`packages/extensions/cordis-host-runner/src/types.ts:391`](../../packages/extensions/cordis-host-runner/src/types.ts) @@ -326,7 +326,7 @@ Notify every Client that an inspect query has settled or been cancelled. 'cordis/inspect-query-resolved'(resolved: CordisInspectQueryResolved): void ``` -Source: [`packages/self-modification/cordis-host-runner/src/types.ts:397`](../../packages/self-modification/cordis-host-runner/src/types.ts) +Source: [`packages/extensions/cordis-host-runner/src/types.ts:397`](../../packages/extensions/cordis-host-runner/src/types.ts) @@ -343,7 +343,7 @@ A Client-bearing activation needs a browser page, and may require a user decisio 'cordis/request-run'(request: DynamicCordisRunRequest): void ``` -Source: [`packages/self-modification/cordis-host-runner/src/types.ts:367`](../../packages/self-modification/cordis-host-runner/src/types.ts) +Source: [`packages/extensions/cordis-host-runner/src/types.ts:367`](../../packages/extensions/cordis-host-runner/src/types.ts) @@ -360,5 +360,5 @@ A pending Client activation request left the answerable state. 'cordis/request-run-resolved'(resolved: DynamicCordisRequestResolved): void ``` -Source: [`packages/self-modification/cordis-host-runner/src/types.ts:373`](../../packages/self-modification/cordis-host-runner/src/types.ts) +Source: [`packages/extensions/cordis-host-runner/src/types.ts:373`](../../packages/extensions/cordis-host-runner/src/types.ts) diff --git a/packages/api/remotes/tests/built-lib.e2e.ts b/packages/api/remotes/tests/built-lib.e2e.ts index f3ea7b1cde..232cf9b2f6 100644 --- a/packages/api/remotes/tests/built-lib.e2e.ts +++ b/packages/api/remotes/tests/built-lib.e2e.ts @@ -51,7 +51,7 @@ describe.skipIf(!requiredArtifacts)('Goal Remote built LIB chain', () => { const { Context } = cordis const { default: AgentRegistry } = await import(urls.agent) const connectionHost = await import(urls.connectionHost) - const { default: TypertGatewayService } = await import(urls.apiGatewayHost) + const { default: TypertRemoteService } = await import(urls.apiGatewayHost) const { default: GoalService } = await import(urls.goal) const { TYPERT } = await import(urls.goalTypert) const { default: TypertRegistry } = await import(urls.registryHost) @@ -70,7 +70,7 @@ describe.skipIf(!requiredArtifacts)('Goal Remote built LIB chain', () => { await host.plugin({ inject: connectionHost.inject, apply: connectionHost.apply }) await host.plugin(TypertRegistry) await host.plugin(AgentRegistry) - await host.plugin(TypertGatewayService) + await host.plugin(TypertRemoteService) await host.plugin(GoalService) host.typert.register(TYPERT) diff --git a/packages/api/remotes/tsconfig.client.json b/packages/api/remotes/tsconfig.client.json index 0f5fc31211..a0161dd047 100644 --- a/packages/api/remotes/tsconfig.client.json +++ b/packages/api/remotes/tsconfig.client.json @@ -25,7 +25,7 @@ }, { - "path": "../../self-modification/cordis-host-runner" + "path": "../../extensions/cordis-host-runner" }, { "path": "../../goal/goal" diff --git a/packages/api/remotes/tsconfig.host.json b/packages/api/remotes/tsconfig.host.json index 6c3131944f..61eae810f4 100644 --- a/packages/api/remotes/tsconfig.host.json +++ b/packages/api/remotes/tsconfig.host.json @@ -38,7 +38,7 @@ "path": "../../session/session-persistence" }, { - "path": "../../self-modification/cordis-host-runner" + "path": "../../extensions/cordis-host-runner" }, { "path": "../../settings/settings" diff --git a/packages/extensions/cordis-client-runner/src/client/guard.ts b/packages/extensions/cordis-client-runner/src/client/guard.ts index 8f71f9ced1..831209f7a4 100644 --- a/packages/extensions/cordis-client-runner/src/client/guard.ts +++ b/packages/extensions/cordis-client-runner/src/client/guard.ts @@ -6,7 +6,7 @@ * carry extra machinery: `slots`, where the register proxy assigns the * shadowing priority and ledgers the registration — invoking the service with * the traced receiver so the effect lands on the CALLING plugin's fiber - * (SlotsService.register must stay a prototype method for exactly that + * (SlotRegistry.register must stay a prototype method for exactly that * reason) — and `theme`, whose override source is pinned to the package id. * * This is API discipline, not a security boundary: a dynamic package's code is @@ -15,8 +15,8 @@ import { Context } from '@deepseek-ai/cordis' import type { DynamicCordisPackage } from '@deepseek-ai/dsh-api-remotes/client' -import type { SlotsService } from '@deepseek-ai/dsh-client-runtime/client' -import type { ThemeService } from '@deepseek-ai/dsh-client-ui-theme/client' +import type { SlotRegistry } from '@deepseek-ai/dsh-client-runtime/client' +import type { ThemeRuntime } from '@deepseek-ai/dsh-client-ui-theme/client' /** Facade verbs beyond declared services (host CTX_VERBS twin). */ const CTX_VERBS = new Set([ @@ -93,7 +93,7 @@ interface ErasedSlotOptions { * The slots seat: automatic shadowing priority and ledger recording around the * traced service's own register. */ -function guardedSlots(slots: SlotsService, env: DynamicCordisGuardEnv): unknown { +function guardedSlots(slots: SlotRegistry, env: DynamicCordisGuardEnv): unknown { return new Proxy(slots, { get(target, prop) { const value = Reflect.get(target, prop, target) as unknown @@ -145,7 +145,7 @@ function guardedSlots(slots: SlotsService, env: DynamicCordisGuardEnv): unknown * keep the returned handle (slots parity — register hangs its own cleanup). * Everything else forwards through the generic guard. */ -function guardedTheme(theme: ThemeService, env: DynamicCordisGuardEnv, ctx: Context): unknown { +function guardedTheme(theme: ThemeRuntime, env: DynamicCordisGuardEnv, ctx: Context): unknown { return new Proxy(theme, { get(target, prop) { if (prop !== 'overrideTokens') { @@ -205,8 +205,8 @@ export function dynamicCordisContext(ctx: Context, env: DynamicCordisGuardEnv): if (requireDeclaration && !declared.has(name)) return denyRead(name) const service = denyContext(ctx.get(name), name, env) if (service === null || (typeof service !== 'object' && typeof service !== 'function')) return service - if (name === 'slots') return guardedSlots(service as SlotsService, env) - if (name === 'theme') return guardedTheme(service as ThemeService, env, ctx) + if (name === 'slots') return guardedSlots(service as SlotRegistry, env) + if (name === 'theme') return guardedTheme(service as ThemeRuntime, env, ctx) return guardedService(service, name, env) } return new Proxy({}, { diff --git a/packages/extensions/cordis-client-runner/src/client/index.ts b/packages/extensions/cordis-client-runner/src/client/index.ts index b0c52d4fb0..f54bfc2318 100644 --- a/packages/extensions/cordis-client-runner/src/client/index.ts +++ b/packages/extensions/cordis-client-runner/src/client/index.ts @@ -16,7 +16,7 @@ import type { DynamicCordisInventoryRow, } from '@deepseek-ai/dsh-api-remotes/client' import type { ClientModuleSystem } from '@deepseek-ai/dsh-client-modules/client' -import type { SlotsService } from '@deepseek-ai/dsh-client-runtime/client' +import type { SlotRegistry } from '@deepseek-ai/dsh-client-runtime/client' // The Client Remote assembly is the one place the two planes meet: it mounts the // `dynamicCordisRunner` namespace and re-exports its payload vocabulary, so this // package names what it sends without importing a Host package. @@ -206,7 +206,7 @@ export function apply(ctx: Context): void { ctx, loader: ctx.loader, modules: ctx.get('modules') as ClientModuleSystem, - slots: ctx.get('slots') as SlotsService, + slots: ctx.get('slots') as SlotRegistry, invoke: async (pluginId, pluginRunId, method, args) => { // Model-authored arguments reach this boundary untyped; the namespace's // generated codec is what validates them as JSON, and its rejection is a diff --git a/packages/extensions/cordis-client-runner/src/client/providers.ts b/packages/extensions/cordis-client-runner/src/client/providers.ts index 1099cc5409..3d06f41402 100644 --- a/packages/extensions/cordis-client-runner/src/client/providers.ts +++ b/packages/extensions/cordis-client-runner/src/client/providers.ts @@ -2,7 +2,7 @@ import type { Context } from '@deepseek-ai/cordis' import type { JsonValue } from '@deepseek-ai/dsh-api-remotes/client' -import type { SlotsService } from '@deepseek-ai/dsh-client-runtime/client' +import type { SlotRegistry } from '@deepseek-ai/dsh-client-runtime/client' import type {} from '@deepseek-ai/dsh-client-ui-theme/client' import { queryEventApi, queryServiceApi } from './api-catalog.ts' import type { ClientCordisInspectProviderRegistration } from './inspect-registry.ts' @@ -169,7 +169,7 @@ function readExact(input: JsonValue | undefined, field: string): string | undefi } /* jscpd:ignore-end */ -type LiveSlotNode = ReturnType[number] +type LiveSlotNode = ReturnType[number] const SLOT_CATALOG = new Map(CLIENT_SLOT_API.map(entry => [entry.key, entry])) diff --git a/packages/extensions/cordis-client-runner/src/client/runtime.ts b/packages/extensions/cordis-client-runner/src/client/runtime.ts index 114031fc93..8f5b356de7 100644 --- a/packages/extensions/cordis-client-runner/src/client/runtime.ts +++ b/packages/extensions/cordis-client-runner/src/client/runtime.ts @@ -21,7 +21,7 @@ import type { } from '@deepseek-ai/dsh-api-remotes/client' import type { SessionId } from '@deepseek-ai/dsh-client-connection/client' import type { ClientModuleSystem } from '@deepseek-ai/dsh-client-modules/client' -import type { SlotsService } from '@deepseek-ai/dsh-client-runtime/client' +import type { SlotRegistry } from '@deepseek-ai/dsh-client-runtime/client' import { DynamicCordisStyles, evaluateClientHalf, DYNAMIC_CLIENT_REDIRECTS } from './evaluator.ts' import type { DynamicCordisEvaluatedPlugin } from './evaluator.ts' import { dynamicCordisContext } from './guard.ts' @@ -121,7 +121,7 @@ export interface DynamicCordisRunnerEnv { /** Module table, for factory invalidation before every (re-)registration. */ modules: ClientModuleSystem /** Slot registry, for the entry-crash supervision seam. */ - slots: SlotsService + slots: SlotRegistry /** Route one `host.call` to the package's host half through the Remote namespace. */ invoke( pluginId: CordisDynamicPluginId, diff --git a/packages/extensions/cordis-client-runner/tests/guard.client.spec.ts b/packages/extensions/cordis-client-runner/tests/guard.client.spec.ts index cd492fa6ac..5d81d8798b 100644 --- a/packages/extensions/cordis-client-runner/tests/guard.client.spec.ts +++ b/packages/extensions/cordis-client-runner/tests/guard.client.spec.ts @@ -16,7 +16,7 @@ import type { CordisDynamicPluginRunId, DynamicCordisPackage, } from '@deepseek-ai/dsh-api-remotes/client' -import { SlotsService } from '@deepseek-ai/dsh-client-runtime/client' +import { SlotRegistry } from '@deepseek-ai/dsh-client-runtime/client' import { dynamicCordisContext } from '../src/client/guard.ts' import type { DynamicCordisSlotLedgerRow } from '../src/client/guard.ts' @@ -37,7 +37,7 @@ type Facade = Record & { get(name: string): unknown } interface Bench { ctx: Context - slots: SlotsService + slots: SlotRegistry facade: Facade ledger: DynamicCordisSlotLedgerRow[] /** Components the facade claimed for the package, in registration order. */ @@ -53,7 +53,7 @@ interface Bench { */ async function boot(inject: string[], extras: Record = {}): Promise { const ctx = new Context() - await ctx.plugin(SlotsService) + await ctx.plugin(SlotRegistry) const themeLayerDispose = vi.fn() const overrideTokens = vi.fn(() => themeLayerDispose) ctx.reflect.provide('theme', { diff --git a/packages/extensions/cordis-client-runner/tests/plugin.client.spec.ts b/packages/extensions/cordis-client-runner/tests/plugin.client.spec.ts index ba1d0125b7..a97a15e8b3 100644 --- a/packages/extensions/cordis-client-runner/tests/plugin.client.spec.ts +++ b/packages/extensions/cordis-client-runner/tests/plugin.client.spec.ts @@ -18,7 +18,7 @@ import type { SessionId } from '@deepseek-ai/dsh-client-connection/client' import type { DynamicCordisInvokeResult } from '@deepseek-ai/dsh-api-remotes/client' // Type-only: resolves `ctx.remote` and with it the `$on`/`$dispatch` surface. import type {} from '@deepseek-ai/dsh-api-gateway/client' -import { SlotsService } from '@deepseek-ai/dsh-client-runtime/client' +import { SlotRegistry } from '@deepseek-ai/dsh-client-runtime/client' import * as NodeHalf from '../src/index.ts' import * as Invariant from '../src/invariant.ts' import * as ClientHalf from '../src/client/index.ts' @@ -80,7 +80,7 @@ interface Bench { /** Mount the browser half over a module table and a loader standing on real fibers. */ async function boot(): Promise { const ctx = new Context() - await ctx.plugin(SlotsService) + await ctx.plugin(SlotRegistry) const factories = new Map unknown>() const fibers = new Map() let next = 0 diff --git a/packages/extensions/cordis-client-runner/tests/runner.client.spec.ts b/packages/extensions/cordis-client-runner/tests/runner.client.spec.ts index cdb453edd2..5505620245 100644 --- a/packages/extensions/cordis-client-runner/tests/runner.client.spec.ts +++ b/packages/extensions/cordis-client-runner/tests/runner.client.spec.ts @@ -19,7 +19,7 @@ import type { } from '@deepseek-ai/dsh-api-remotes/client' import type { SessionId } from '@deepseek-ai/dsh-client-connection/client' import type { ClientModuleSystem } from '@deepseek-ai/dsh-client-modules/client' -import { SlotsService } from '@deepseek-ai/dsh-client-runtime/client' +import { SlotRegistry } from '@deepseek-ai/dsh-client-runtime/client' import { DYNAMIC_CLIENT_REDIRECTS } from '../src/client/evaluator.ts' import { DynamicCordisPackageRunner } from '../src/client/runtime.ts' import type { DynamicCordisClientHalf, DynamicCordisRenderFailure } from '../src/client/runtime.ts' @@ -48,7 +48,7 @@ function half(overrides: Partial = {}): DynamicCordisCl interface Bench { ctx: Context - slots: SlotsService + slots: SlotRegistry runner: DynamicCordisPackageRunner invalidated: string[] removed: string[] @@ -83,7 +83,7 @@ function seated(fiber: T): T { async function boot(): Promise { const ctx = new Context() - await ctx.plugin(SlotsService) + await ctx.plugin(SlotRegistry) const invalidated: string[] = [] const removed: string[] = [] const created: string[] = [] @@ -128,7 +128,7 @@ async function boot(): Promise { listener = fn return () => { listener = undefined } }, - } as unknown as SlotsService, + } as unknown as SlotRegistry, invoke, reportGuardFailure: () => {}, reportRenderFailure: (agentId, pluginId, pluginRunId, failure) => { diff --git a/packages/extensions/cordis-client-runner/tsconfig.json b/packages/extensions/cordis-client-runner/tsconfig.json index 7dbd8762ec..a93e5c0fb0 100644 --- a/packages/extensions/cordis-client-runner/tsconfig.json +++ b/packages/extensions/cordis-client-runner/tsconfig.json @@ -33,7 +33,7 @@ "path": "../../client/ui-theme" }, { - "path": "../../support/invariants" + "path": "../../runtime-diagnostics/invariants" } ] } diff --git a/packages/extensions/cordis-host-runner/package.json b/packages/extensions/cordis-host-runner/package.json index 7d19b058a5..13e97cbcc5 100644 --- a/packages/extensions/cordis-host-runner/package.json +++ b/packages/extensions/cordis-host-runner/package.json @@ -61,7 +61,7 @@ "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/dsh-type-meta": "workspace:^" + "@deepseek-ai/dsh-typert-protocol": "workspace:^" }, "devDependencies": { "@deepseek-ai/cordis": "workspace:^", @@ -73,6 +73,6 @@ "@deepseek-ai/dsh-scope": "workspace:^", "@deepseek-ai/dsh-session": "workspace:^", "@deepseek-ai/dsh-tools": "workspace:^", - "@deepseek-ai/dsh-type-meta": "workspace:^" + "@deepseek-ai/dsh-typert-protocol": "workspace:^" } } diff --git a/packages/extensions/cordis-host-runner/src/index.ts b/packages/extensions/cordis-host-runner/src/index.ts index f1b92322c4..b032248009 100644 --- a/packages/extensions/cordis-host-runner/src/index.ts +++ b/packages/extensions/cordis-host-runner/src/index.ts @@ -10,7 +10,7 @@ import z from '@deepseek-ai/schemastery' import type { Agent } from '@deepseek-ai/dsh-agent' import { createUserMessage } from '@deepseek-ai/dsh-llm' import type { JsonValue } from '@deepseek-ai/dsh-session/types' -import { GatewayService, Remote } from '@deepseek-ai/dsh-type-meta' +import { TypertRemoteService, Remote } from '@deepseek-ai/dsh-typert-protocol' import { isPlugin, normalizeHandler } from './guard.ts' import { CordisInspectRegistryService } from './inspect-registry.ts' import { missingServices, startHostHalf } from './lifecycle.ts' @@ -121,7 +121,7 @@ interface ActivationPlan { } /** Dynamic Plugin registry and Host-half lifecycle. */ -export class DynamicCordisRunnerService extends GatewayService { +export class DynamicCordisRunnerService extends TypertRemoteService { static inject = ['tools'] static Config: z = z.object({ diff --git a/packages/extensions/cordis-host-runner/tsconfig.json b/packages/extensions/cordis-host-runner/tsconfig.json index 640a2f675e..b14e68a5ec 100644 --- a/packages/extensions/cordis-host-runner/tsconfig.json +++ b/packages/extensions/cordis-host-runner/tsconfig.json @@ -39,10 +39,10 @@ "path": "../../llm/llm" }, { - "path": "../../support/invariants" + "path": "../../runtime-diagnostics/invariants" }, { - "path": "../../typert/type-meta" + "path": "../../typert/protocol" } ] } diff --git a/packages/extensions/tool-cordis/src/api-catalog.ts b/packages/extensions/tool-cordis/src/api-catalog.ts index fca96a1923..989b926264 100644 --- a/packages/extensions/tool-cordis/src/api-catalog.ts +++ b/packages/extensions/tool-cordis/src/api-catalog.ts @@ -4,33 +4,50 @@ * `pnpm run verify-cordis-api` in doc-sync). * * The machine-readable cordis API catalog `cordis_inspect` serves to the - * model: harness services (summary + public method signatures/JSDoc), - * harness events (mode + signature/JSDoc), and the inherited `ctx` API. Produced by + * model: harness services (summary + structured public method contracts), + * harness events (mode + structured listener contracts), and the inherited `ctx` API. Produced by * the same AST walk as docs/cordis-catalog, so this data and the rendered * docs cannot diverge. * * @module @deepseek-ai/dsh-tool-cordis/api-catalog */ -/** One public service method and its source-owned contract. */ +/* jscpd:ignore-start */ +/** One named parameter in a Service method or Event listener. */ +export interface ApiParameter { + /** Parameter name from the exact signature. */ + name: string + /** Source-owned parameter contract. */ + description: string +} + +/** One public service member and its source-owned contract. */ export interface ServiceApiMethod { /** Public method signature with its body stripped. */ signature: string - /** Original method JSDoc, with only container indentation removed. */ - jsDoc: string + /** Method purpose and behavior. */ + description: string + /** Named parameters in signature order. */ + parameters: readonly ApiParameter[] + /** Non-void result contract when documented. */ + returns?: string + /** Documented failure conditions. */ + throws?: readonly string[] } -/** One harness `ctx.` service: its one-line summary and public methods. */ +/** One harness `ctx.` service and its public methods. */ export interface ServiceApiEntry { /** The `ctx.` name, e.g. `tools`. */ key: string /** First sentence of the service class JSDoc. */ summary: string + /** Complete service description. */ + description: string /** Public methods, bodies stripped, in source order. */ methods: readonly ServiceApiMethod[] } -/** One harness event: its dispatch mode, exact signature, and one-line summary. */ +/** One harness event: its dispatch mode, exact signature, and listener contract. */ export interface EventApiEntry { /** The scoped event name, e.g. `agent/status`. */ name: string @@ -38,10 +55,12 @@ export interface EventApiEntry { mode: string /** The exact listener signature, whitespace-normalized. */ signature: string - /** Original event JSDoc, with only container indentation removed. */ - jsDoc: string /** First sentence of the event JSDoc. */ summary: string + /** Complete event description. */ + description: string + /** Named listener parameters in signature order. */ + parameters: readonly ApiParameter[] } /** One inherited (cordis core + loader/hmr/timer) `ctx` member group with its summary. */ @@ -52,7 +71,7 @@ export interface InheritedApiEntry { summary: string } -/** One named type shape the service signatures reference. */ +/** One named type declaration referenced by a Service or Event signature. */ export interface TypeApiEntry { /** The exported type/interface name, e.g. `ShellRunResult`. */ name: string @@ -65,1336 +84,2066 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [ { key: 'agentDefaultModel', summary: 'Owns the default model selection independently of any Host or transport.', + description: 'Owns the default model selection independently of any Host or transport. The composition entry remains usable without a settings provider; when one is mounted, its user layer is read live.', methods: [ { signature: 'currentSelection(): ModelSelection', - jsDoc: '/**\n * Read the current default model selection.\n * @returns a detached provider, model, and optional reasoning selection.\n */', + description: 'Read the current default model selection.', + parameters: [], + returns: 'a detached provider, model, and optional reasoning selection.', }, { signature: 'async saveSelection(next: ModelSelection): Promise', - jsDoc: '/**\n * Save the complete default model selection. A deployment without a settings\n * provider keeps its composition entry.\n * @param next - resolved selection accepted by an entry point.\n * @returns fulfillment after the optional settings write settles.\n */', + description: 'Save the complete default model selection. A deployment without a settings provider keeps its composition entry.', + parameters: [{ name: 'next', description: 'resolved selection accepted by an entry point.' }], + returns: 'fulfillment after the optional settings write settles.', }, ], }, { key: 'agentLoop', summary: 'Concrete agent factory and driver service.', + description: 'Concrete agent factory and driver service.', methods: [ + { + signature: 'readonly config: ResolvedConfig', + description: 'Validated configuration owned by the agent-loop service.', + parameters: [], + }, { signature: 'create(id: SessionId, options: AgentOptions = {}, meta: Pick = {}): Agent', - jsDoc: '/**\n * Create an agent and session under one caller-supplied identity, owned by\n * the accessing fiber. Constructor-driven config calls mint a fresh combined\n * id before entering this boundary.\n * @param id - shared agent/session identity.\n * @param options - concrete loop options.\n * @param meta - optional fresh-session workspace metadata.\n * @returns the published running agent.\n */', + description: 'Create an agent and session under one caller-supplied identity, owned by the accessing fiber. Constructor-driven config calls mint a fresh combined id before entering this boundary.', + parameters: [{ name: 'id', description: 'shared agent/session identity.' }, { name: 'options', description: 'concrete loop options.' }, { name: 'meta', description: 'optional fresh-session workspace metadata.' }], + returns: 'the published running agent.', }, { signature: 'async createAgent(ownerCtx: Context, options: CreateAgentOptions): Promise', - jsDoc: '/**\n * Create an owned agent on a caller-supplied session id.\n * @param ownerCtx - caller context that structurally owns the lifecycle.\n * @param options - identities, session seed/metadata, loop options, setup, and cancellation.\n * @returns the published handle.\n */', + description: 'Create an owned agent on a caller-supplied session id.', + parameters: [{ name: 'ownerCtx', description: 'caller context that structurally owns the lifecycle.' }, { name: 'options', description: 'identities, session seed/metadata, loop options, setup, and cancellation.' }], + returns: 'the published handle.', }, { signature: 'async resume(ownerCtx: Context, options: ResumeAgentOptions): Promise', - jsDoc: '/**\n * Resume an owned agent from the configured persistence service.\n * @param ownerCtx - caller context that owns load, setup, and the live lifecycle.\n * @param options - persisted identity, loop options, setup, and cancellation.\n * @returns the published handle.\n */', + description: 'Resume an owned agent from the configured persistence service.', + parameters: [{ name: 'ownerCtx', description: 'caller context that owns load, setup, and the live lifecycle.' }, { name: 'options', description: 'persisted identity, loop options, setup, and cancellation.' }], + returns: 'the published handle.', }, ], }, { key: 'agentPresets', summary: 'Registry over the deployment\'s agent presets.', + description: 'Registry over the deployment\'s agent presets.\n\nDiscovery is unmemoized: `list()` and `resolve()` re-read the roots on every call so a preset authored while the process runs is visible immediately, and a preset deleted underneath a picker disappears from the next read.', methods: [ { signature: 'async list(): Promise', - jsDoc: '/**\n * Every preset the configured roots currently supply.\n * @returns the presets, first-root-wins per id.\n */', + description: 'Every preset the configured roots currently supply.', + parameters: [], + returns: 'the presets, first-root-wins per id.', }, { signature: 'async resolve(id?: string): Promise', - jsDoc: '/**\n * Resolve one preset by id.\n *\n * A broken preset resolves — deleting one, reading one, and reporting one\n * all need the row — and the mounting paths refuse it AFTER resolution\n * through {@link resolveMountable}.\n * @param id - the preset id, or `undefined` for {@link defaultId}.\n * @returns the resolved preset.\n * @throws when no configured root supplies that id.\n */', + description: 'Resolve one preset by id.\n\nA broken preset resolves — deleting one, reading one, and reporting one all need the row — and the mounting paths refuse it AFTER resolution through resolveMountable.', + parameters: [{ name: 'id', description: 'the preset id, or `undefined` for {@link defaultId}.' }], + returns: 'the resolved preset.', + throws: ['when no configured root supplies that id.'], }, { signature: 'async mount(agentCtx: Context, id?: string): Promise', - jsDoc: '/**\n * Compose one agent from a preset: ensure the preset\'s standing mount, then\n * parent the agent\'s scope key to it so the mount\'s registrations and\n * listeners cover this agent.\n *\n * Call from the agent factory\'s `setup(agentCtx)`; a rejection there rolls\n * the agent creation back, so a broken preset never yields a half-composed\n * session.\n * @param agentCtx - the agent\'s scope context.\n * @param id - the preset id, or `undefined` for {@link defaultId}.\n * @returns the preset that was composed, for the caller to record.\n * @throws when the preset is unknown or its composition is unusable.\n */', + description: 'Compose one agent from a preset: ensure the preset\'s standing mount, then parent the agent\'s scope key to it so the mount\'s registrations and listeners cover this agent.\n\nCall from the agent factory\'s `setup(agentCtx)`; a rejection there rolls the agent creation back, so a broken preset never yields a half-composed session.', + parameters: [{ name: 'agentCtx', description: 'the agent\'s scope context.' }, { name: 'id', description: 'the preset id, or `undefined` for {@link defaultId}.' }], + returns: 'the preset that was composed, for the caller to record.', + throws: ['when the preset is unknown or its composition is unusable.'], }, { signature: 'composeFrom(agentCtx: Context, parentCtx: Context): string | undefined', - jsDoc: '/**\n * Join one agent to the SAME standing composition another already runs on.\n *\n * This is how a child agent inherits its parent\'s capabilities. It is a bind,\n * not a mount: the parent\'s generation is already composed, so the child gets\n * that exact instance — the same plugin objects, the same tool registrations,\n * the same prompt sections. Re-resolving the parent\'s preset by id instead\n * would re-read the roster, and a composition file edited since the parent\n * started would hand the child a DIFFERENT generation than the one its\n * parent\'s history was produced under (and a preset deleted since would fail\n * the child outright while its parent keeps running).\n *\n * Synchronous, and with no composition failure mode of its own — it reads no\n * roster, mounts nothing, and touches no file — which is what lets a child\n * creation window use it: the two in-process subagent drivers compose their\n * children inside a synchronous `setup`. It still rejects a caller error, as\n * the `@throws` below record.\n *\n * A parent that joined no preset — a rosterless deployment — yields no join\n * and no error: there, the model-facing rows sit in the host composition and\n * the child already sees them through the global layer.\n * @param agentCtx - the joining agent\'s scope context.\n * @param parentCtx - the scope context of the agent whose composition to join.\n * @returns the preset id joined, or undefined when the parent joined none.\n * @throws when `agentCtx` carries no scope, or has already joined a preset.\n */', + description: 'Join one agent to the SAME standing composition another already runs on.\n\nThis is how a child agent inherits its parent\'s capabilities. It is a bind, not a mount: the parent\'s generation is already composed, so the child gets that exact instance — the same plugin objects, the same tool registrations, the same prompt sections. Re-resolving the parent\'s preset by id instead would re-read the roster, and a composition file edited since the parent started would hand the child a DIFFERENT generation than the one its parent\'s history was produced under (and a preset deleted since would fail the child outright while its parent keeps running).\n\nSynchronous, and with no composition failure mode of its own — it reads no roster, mounts nothing, and touches no file — which is what lets a child creation window use it: the two in-process subagent drivers compose their children inside a synchronous `setup`. It still rejects a caller error, as the `@throws` below record.\n\nA parent that joined no preset — a rosterless deployment — yields no join and no error: there, the model-facing rows sit in the host composition and the child already sees them through the global layer.', + parameters: [{ name: 'agentCtx', description: 'the joining agent\'s scope context.' }, { name: 'parentCtx', description: 'the scope context of the agent whose composition to join.' }], + returns: 'the preset id joined, or undefined when the parent joined none.', + throws: ['when `agentCtx` carries no scope, or has already joined a preset.'], }, { signature: 'composedPreset(agentCtx: Context): string | undefined', - jsDoc: '/**\n * The preset one live agent runs on.\n *\n * Read from the live scope chain rather than from the session, so it answers\n * for an agent whose session has not recorded a preset yet — a child agent\n * whose durable header is being built from its parent\'s composition.\n * @param agentCtx - the agent\'s scope context.\n * @returns the preset id, or undefined when the agent joined none.\n */', + description: 'The preset one live agent runs on.\n\nRead from the live scope chain rather than from the session, so it answers for an agent whose session has not recorded a preset yet — a child agent whose durable header is being built from its parent\'s composition.', + parameters: [{ name: 'agentCtx', description: 'the agent\'s scope context.' }], + returns: 'the preset id, or undefined when the agent joined none.', }, { signature: 'async read(id: string): Promise', - jsDoc: '/**\n * Read one preset\'s composition text.\n * @param id - the preset id.\n * @returns the composition exactly as stored.\n * @throws when no configured root supplies that id.\n */', + description: 'Read one preset\'s composition text.', + parameters: [{ name: 'id', description: 'the preset id.' }], + returns: 'the composition exactly as stored.', + throws: ['when no configured root supplies that id.'], }, { signature: 'async copy(from: string, id: string, name?: string): Promise', - jsDoc: '/**\n * Create a locally authored preset by copying an existing one whole.\n *\n * Copy is the only authoring write. Composition text never crosses this\n * seam: the source is named by id and its directory is copied as it stands,\n * so the copy is exactly as loadable as its source and authoring grants no\n * capability the roster did not already carry. The copy is NOT mounted to\n * validate — a source that mounts today yields a copy that mounts today.\n * @param from - the preset the copy starts from; shipped presets are the\n * primary source, so any trust is accepted.\n * @param id - the new preset\'s id, which becomes its directory name.\n * @param name - display name for the copy; absent falls back to the id.\n * @throws when the source is unknown, the id is unusable or already taken,\n * or the deployment configures no writable root.\n */', + description: 'Create a locally authored preset by copying an existing one whole.\n\nCopy is the only authoring write. Composition text never crosses this seam: the source is named by id and its directory is copied as it stands, so the copy is exactly as loadable as its source and authoring grants no capability the roster did not already carry. The copy is NOT mounted to validate — a source that mounts today yields a copy that mounts today.', + parameters: [{ name: 'from', description: 'the preset the copy starts from; shipped presets are the primary source, so any trust is accepted.' }, { name: 'id', description: 'the new preset\'s id, which becomes its directory name.' }, { name: 'name', description: 'display name for the copy; absent falls back to the id.' }], + throws: ['when the source is unknown, the id is unusable or already taken, or the deployment configures no writable root.'], }, { signature: 'async remove(id: string): Promise', - jsDoc: '/**\n * Delete a locally authored preset.\n * @param id - the preset id.\n * @throws when the preset is unknown or ships with the deployment.\n */', + description: 'Delete a locally authored preset.', + parameters: [{ name: 'id', description: 'the preset id.' }], + throws: ['when the preset is unknown or ships with the deployment.'], }, { signature: 'serviceFor(agent: { ctx: Context }, name: K): Context[K] | undefined', - jsDoc: '/**\n * One agent\'s instance of a service its preset mounted.\n *\n * A preset publishes services behind `isolate` realms, which are invisible\n * outside the group that declares them — including to the host. This is how a\n * caller holding the agent reads one anyway: a request that is ABOUT a\n * session but arrives from outside it, which is every browser RPC.\n *\n * Read addressing only. A host row that `inject`s a service cannot use this,\n * because injection resolves before any session exists and has no agent to\n * key by; such a service belongs on the host plane instead.\n * @param agent - the agent whose composition to look inside.\n * @param name - the service name as the preset\'s rows resolve it.\n * @returns the agent\'s instance, or undefined when its preset mounts none.\n */', + description: 'One agent\'s instance of a service its preset mounted.\n\nA preset publishes services behind `isolate` realms, which are invisible outside the group that declares them — including to the host. This is how a caller holding the agent reads one anyway: a request that is ABOUT a session but arrives from outside it, which is every browser RPC.\n\nRead addressing only. A host row that `inject`s a service cannot use this, because injection resolves before any session exists and has no agent to key by; such a service belongs on the host plane instead.', + parameters: [{ name: 'agent', description: 'the agent whose composition to look inside.' }, { name: 'name', description: 'the service name as the preset\'s rows resolve it.' }], + returns: 'the agent\'s instance, or undefined when its preset mounts none.', }, { signature: 'async recompose(agentCtx: Context, id: string): Promise', - jsDoc: '/**\n * Re-link one agent to a different preset\'s standing composition.\n *\n * Only valid while the agent has produced nothing: swapping tools mid\n * conversation would leave logged tool calls the new composition cannot\n * make. The CALLER owns that check — this method does not read session\n * history.\n *\n * The swap is a parent re-link, not an unmount: standing mounts are shared\n * and permanent, so the old composition stays for its other agents and the\n * new one is ensured BEFORE the link moves. An unknown or unusable preset\n * therefore throws with the agent exactly as it was — there is no torn-down\n * state to restore. The re-link runs through the binding this roster kept\n * from the agent\'s mount — dsh-scope\'s only re-link authority. An agent\n * that never composed one has nothing to re-link: the switch is then the\n * agent\'s first bind, exactly a mount.\n * @param agentCtx - the agent\'s scope context.\n * @param id - the preset to compose the agent from instead.\n * @returns the preset now installed.\n * @throws when the preset is unknown or its composition is unusable.\n */', + description: 'Re-link one agent to a different preset\'s standing composition.\n\nOnly valid while the agent has produced nothing: swapping tools mid conversation would leave logged tool calls the new composition cannot make. The CALLER owns that check — this method does not read session history.\n\nThe swap is a parent re-link, not an unmount: standing mounts are shared and permanent, so the old composition stays for its other agents and the new one is ensured BEFORE the link moves. An unknown or unusable preset therefore throws with the agent exactly as it was — there is no torn-down state to restore. The re-link runs through the binding this roster kept from the agent\'s mount — dsh-scope\'s only re-link authority. An agent that never composed one has nothing to re-link: the switch is then the agent\'s first bind, exactly a mount.', + parameters: [{ name: 'agentCtx', description: 'the agent\'s scope context.' }, { name: 'id', description: 'the preset to compose the agent from instead.' }], + returns: 'the preset now installed.', + throws: ['when the preset is unknown or its composition is unusable.'], }, { signature: 'async standingKeyFor(id?: string): Promise', - jsDoc: '/**\n * The standing scope key of one preset, for a host reader with no agent.\n *\n * A cold transcript read resolves tool presenters against the composition\n * the session recorded, and the standing mount makes that possible without\n * resuming anything: ensuring the mount composes plugins but starts no\n * agent, no session, and no turn.\n * @param id - the preset id, or `undefined` for {@link defaultId}.\n * @returns the standing scope key readers pass as a registry view scope.\n * @throws when the preset is unknown or its composition is unusable.\n */', + description: 'The standing scope key of one preset, for a host reader with no agent.\n\nA cold transcript read resolves tool presenters against the composition the session recorded, and the standing mount makes that possible without resuming anything: ensuring the mount composes plugins but starts no agent, no session, and no turn.', + parameters: [{ name: 'id', description: 'the preset id, or `undefined` for {@link defaultId}.' }], + returns: 'the standing scope key readers pass as a registry view scope.', + throws: ['when the preset is unknown or its composition is unusable.'], }, ], }, { key: 'agents', summary: 'Agent service (`ctx.agents`): tracks live agents and carries the initiating Agent through one process-local asynchronous driver chain.', + description: 'Agent service (`ctx.agents`): tracks live agents and carries the initiating Agent through one process-local asynchronous driver chain. Agent *creation* is provided by whichever plugin implements the AgentFactory (`@deepseek-ai/dsh-agent-loop`), registered via setFactory.\n\nInitiator methods provide same-process causal attribution only. Ambient presence is neither liveness proof nor authorization; subjects and owners remain explicit, as does identity at worker, process, persistence, and wire boundaries. Returned Promise boundaries drain during teardown, except a nested lineage that starts an owning-fiber unload is excluded from its own drain.', methods: [ { signature: 'currentInitiator(): Agent | undefined', - jsDoc: '/**\n * Read the Agent that initiated the inherited asynchronous driver chain.\n * Use this optional form for logging, tracing, metrics, or host attribution\n * that also supports agentless calls. When a parent creates a child, setup\n * reports the causal parent while `agentCtx.agent` identifies the child.\n * @returns the inherited Agent, or `undefined` outside an initiator boundary\n * and inside an explicit clearing boundary.\n * @throws when this service instance has been disposed.\n */', + description: 'Read the Agent that initiated the inherited asynchronous driver chain. Use this optional form for logging, tracing, metrics, or host attribution that also supports agentless calls. When a parent creates a child, setup reports the causal parent while `agentCtx.agent` identifies the child.', + parameters: [], + returns: 'the inherited Agent, or `undefined` outside an initiator boundary and inside an explicit clearing boundary.', + throws: ['when this service instance has been disposed.'], }, { signature: 'requireInitiator(): Agent', - jsDoc: '/**\n * Read the initiating Agent and fail when no initiator boundary is active.\n * Use this for private helpers contractually below a driver, or for a\n * deployment-owned outbound request whose contract forbids agentless calls.\n * Generic or direct-call paths use optional lookup or explicit request fields.\n * @returns the inherited Agent.\n * @throws when no initiator is active or this service instance has been disposed.\n */', + description: 'Read the initiating Agent and fail when no initiator boundary is active. Use this for private helpers contractually below a driver, or for a deployment-owned outbound request whose contract forbids agentless calls. Generic or direct-call paths use optional lookup or explicit request fields.', + parameters: [], + returns: 'the inherited Agent.', + throws: ['when no initiator is active or this service instance has been disposed.'], }, { signature: 'withInitiator(agent: Agent, operation: () => T): T', - jsDoc: '/**\n * Run an operation with one exact Agent as its process-local initiator. The\n * exact synchronous value or Promise returned by the operation is preserved.\n * Custom drivers and test harnesses wrap their complete returned foreground\n * lifetime.\n * A queue or wire receiver may establish this boundary only after validating\n * explicit identity and resolving the exact live Agent; this method does neither.\n * Detached work remains owned by the subsystem that starts it.\n * @param agent - initiating Agent to inherit; presence is neither liveness proof nor authorization.\n * @param operation - synchronous or asynchronous operation to invoke.\n * @returns the exact value returned by `operation`.\n * @throws when the initiator scope is closing/disposed, or when `operation` throws.\n */', + description: 'Run an operation with one exact Agent as its process-local initiator. The exact synchronous value or Promise returned by the operation is preserved. Custom drivers and test harnesses wrap their complete returned foreground lifetime. A queue or wire receiver may establish this boundary only after validating explicit identity and resolving the exact live Agent; this method does neither. Detached work remains owned by the subsystem that starts it.', + parameters: [{ name: 'agent', description: 'initiating Agent to inherit; presence is neither liveness proof nor authorization.' }, { name: 'operation', description: 'synchronous or asynchronous operation to invoke.' }], + returns: 'the exact value returned by `operation`.', + throws: ['when the initiator scope is closing/disposed, or when `operation` throws.'], }, { signature: 'withoutInitiator(operation: () => T): T', - jsDoc: '/**\n * Run an operation inside a boundary that hides any inherited initiating\n * Agent. The exact synchronous value or Promise is preserved.\n * Use this while creating lazy shared timers, queue pumps, pool maintenance,\n * watchers, or exporters so they do not inherit the first Agent that happens\n * to initialize them. It clears only initiator attribution, not explicit\n * fields, and does not own or drain detached resources.\n * @param operation - synchronous or asynchronous operation to invoke without an initiator.\n * @returns the exact value returned by `operation`.\n * @throws when the initiator scope is closing/disposed, or when `operation` throws.\n */', + description: 'Run an operation inside a boundary that hides any inherited initiating Agent. The exact synchronous value or Promise is preserved. Use this while creating lazy shared timers, queue pumps, pool maintenance, watchers, or exporters so they do not inherit the first Agent that happens to initialize them. It clears only initiator attribution, not explicit fields, and does not own or drain detached resources.', + parameters: [{ name: 'operation', description: 'synchronous or asynchronous operation to invoke without an initiator.' }], + returns: 'the exact value returned by `operation`.', + throws: ['when the initiator scope is closing/disposed, or when `operation` throws.'], }, { signature: 'setFactory(factory: AgentFactory): () => void', - jsDoc: '/**\n * Register the agent-creation factory (the loop calls this on construction,\n * effect-scoped). A traced Cordis service is canonicalized to its concrete\n * target; each create/resume call is then traced through that caller\'s\n * context so ownership follows the caller without stacking proxy layers.\n * Throws if a factory is already registered. Returns the disposer; on\n * dispose the factory slot is cleared.\n * @param factory - the loop-owned factory {@link create}/{@link resume} delegate to.\n * @returns the disposer that clears the factory slot. The exact\n * Cordis effect disposer (single-shot): composite (generator) effects may\n * yield it directly — exact identity nests the teardown in order.\n */', + description: 'Register the agent-creation factory (the loop calls this on construction, effect-scoped). A traced Cordis service is canonicalized to its concrete target; each create/resume call is then traced through that caller\'s context so ownership follows the caller without stacking proxy layers. Throws if a factory is already registered. Returns the disposer; on dispose the factory slot is cleared.', + parameters: [{ name: 'factory', description: 'the loop-owned factory {@link create}/{@link resume} delegate to.' }], + returns: 'the disposer that clears the factory slot. The exact Cordis effect disposer (single-shot): composite (generator) effects may yield it directly — exact identity nests the teardown in order.', }, { signature: 'async create(options: CreateAgentOptions): Promise', - jsDoc: '/**\n * Create and publish a new agent through the registered factory.\n * Distinct from {@link register} (which records an already-constructed\n * agent): this constructs the agent and its session. Rejects if no factory is\n * registered or creation/setup fails. The resolved {@link AgentHandle} lets\n * the owner tear down exactly this agent.\n * @param options - shared identity, session seed/metadata, and agent options.\n * @returns the handle after setup, rollback-covered publication, and loop start complete.\n */', + description: 'Create and publish a new agent through the registered factory. Distinct from register (which records an already-constructed agent): this constructs the agent and its session. Rejects if no factory is registered or creation/setup fails. The resolved AgentHandle lets the owner tear down exactly this agent.', + parameters: [{ name: 'options', description: 'shared identity, session seed/metadata, and agent options.' }], + returns: 'the handle after setup, rollback-covered publication, and loop start complete.', }, { signature: 'async resume(options: ResumeAgentOptions): Promise', - jsDoc: '/**\n * Load a persisted session and resume an agent on it through the registered\n * factory. Rejects if no factory is registered; the factory rejects if\n * session persistence is not configured or persistence/setup fails.\n * @param options - persisted identity, configuration, and optional setup.\n * @returns the handle after setup, rollback-covered publication, and loop start complete.\n */', + description: 'Load a persisted session and resume an agent on it through the registered factory. Rejects if no factory is registered; the factory rejects if session persistence is not configured or persistence/setup fails.', + parameters: [{ name: 'options', description: 'persisted identity, configuration, and optional setup.' }], + returns: 'the handle after setup, rollback-covered publication, and loop start complete.', }, { signature: 'register(agent: Agent): () => void', - jsDoc: '/**\n * Register a live agent. Throws if an agent with the same id is already\n * registered. Emits `agent/created` on registration and `agent/disposed`\n * when the calling fiber is disposed — both with the agent\'s scope carrier\n * (`scopeTarget(agent, agent)`): the subject is the agent in hand, so the\n * emits are scope-filtered regardless of which context invoked `register`\n * (calling through `agent.ctx` scopes EFFECTS; dispatch scoping always\n * requires passing the carrier). Returns the disposer.\n * @param agent - the already-constructed agent to record in the store.\n * @returns the EXACT Cordis effect disposer (single-shot; a repeat call\n * returns undefined without awaiting an in-flight teardown). Exact\n * identity is load-bearing: a composite (generator) effect that owns a\n * teardown ORDER — the agent factory\'s lifecycle chain — must yield THIS\n * function so Cordis nests the unregistration at that yield position;\n * yielding a wrapper would leave it disposing as a concurrent sibling on\n * owner unload, unregistering the agent (and emitting `agent/disposed`)\n * while its final turn is still draining.\n */', + description: 'Register a live agent. Throws if an agent with the same id is already registered. Emits `agent/created` on registration and `agent/disposed` when the calling fiber is disposed — both with the agent\'s scope carrier (`scopeTarget(agent, agent)`): the subject is the agent in hand, so the emits are scope-filtered regardless of which context invoked `register` (calling through `agent.ctx` scopes EFFECTS; dispatch scoping always requires passing the carrier). Returns the disposer.', + parameters: [{ name: 'agent', description: 'the already-constructed agent to record in the store.' }], + returns: 'the EXACT Cordis effect disposer (single-shot; a repeat call returns undefined without awaiting an in-flight teardown). Exact identity is load-bearing: a composite (generator) effect that owns a teardown ORDER — the agent factory\'s lifecycle chain — must yield THIS function so Cordis nests the unregistration at that yield position; yielding a wrapper would leave it disposing as a concurrent sibling on owner unload, unregistering the agent (and emitting `agent/disposed`) while its final turn is still draining.', }, { signature: 'enter(agent: Agent, owner: Agent | undefined): () => void', - jsDoc: '/**\n * Insert an already-constructed agent without announcing it. This is the\n * advanced ordered-lifecycle primitive used by the async agent factory: it\n * first completes setup while the agent is unpublished, then assigns the\n * returned detach closure into its pre-installed composite teardown before\n * calling {@link announce}. Ordinary callers use {@link register}.\n * @param agent - the prepared, unpublished agent.\n * @param owner - live agent whose scoped context created this agent, or\n * undefined for a top-level runtime root. This is runtime ownership, not\n * the resumed session\'s durable parent lineage.\n * @returns an idempotent closure that removes this exact entry and emits\n * `agent/disposed` with listener failures contained. When called from a\n * synchronous `agent/created` listener, removal and disposal wait until\n * that creation dispatch unwinds.\n */', + description: 'Insert an already-constructed agent without announcing it. This is the advanced ordered-lifecycle primitive used by the async agent factory: it first completes setup while the agent is unpublished, then assigns the returned detach closure into its pre-installed composite teardown before calling announce. Ordinary callers use register.', + parameters: [{ name: 'agent', description: 'the prepared, unpublished agent.' }, { name: 'owner', description: 'live agent whose scoped context created this agent, or undefined for a top-level runtime root. This is runtime ownership, not the resumed session\'s durable parent lineage.' }], + returns: 'an idempotent closure that removes this exact entry and emits `agent/disposed` with listener failures contained. When called from a synchronous `agent/created` listener, removal and disposal wait until that creation dispatch unwinds.', }, { signature: 'announce(agent: Agent): void', - jsDoc: '/**\n * Announce an agent previously inserted with {@link enter}.\n * @param agent - the live inserted agent to announce.\n * @throws if `agent` is not the exact live registry entry for its id, or its\n * creation announcement already began (including a reentrant call from a\n * creation listener).\n */', + description: 'Announce an agent previously inserted with enter.', + parameters: [{ name: 'agent', description: 'the live inserted agent to announce.' }], + throws: ['if `agent` is not the exact live registry entry for its id, or its creation announcement already began (including a reentrant call from a creation listener).'], }, { signature: 'get(id: SessionId): Agent | undefined', - jsDoc: '/**\n * Look up a live agent.\n * @param id - the shared agent/session id to look up.\n * @returns the agent, or undefined when no live agent has that id.\n */', + description: 'Look up a live agent.', + parameters: [{ name: 'id', description: 'the shared agent/session id to look up.' }], + returns: 'the agent, or undefined when no live agent has that id.', }, { signature: 'isOwnedBy(id: SessionId, owner: Agent): boolean', - jsDoc: '/**\n * Test whether a live agent was created through one exact parent agent\'s\n * scoped context. Runtime ownership is independent of durable session\n * lineage and remains unambiguous when unrelated providers reuse an id.\n * @param id - the candidate child agent\'s shared agent/session id.\n * @param owner - the expected runtime creator agent.\n * @returns true only while the exact child entry is live under that owner.\n */', + description: 'Test whether a live agent was created through one exact parent agent\'s scoped context. Runtime ownership is independent of durable session lineage and remains unambiguous when unrelated providers reuse an id.', + parameters: [{ name: 'id', description: 'the candidate child agent\'s shared agent/session id.' }, { name: 'owner', description: 'the expected runtime creator agent.' }], + returns: 'true only while the exact child entry is live under that owner.', }, { signature: 'list(): Agent[]', - jsDoc: '/**\n * All live agents, in registration order.\n * @returns a fresh array; mutating it does not affect the registry.\n */', + description: 'All live agents, in registration order.', + parameters: [], + returns: 'a fresh array; mutating it does not affect the registry.', }, { signature: 'roots(): Agent[]', - jsDoc: '/**\n * All live top-level agents in registration order. A top-level agent was\n * created without an owning agent context; durable session lineage does not\n * affect this runtime relation, so a resumed fork may still be a root.\n * @returns a fresh array; mutating it does not affect the registry.\n */', + description: 'All live top-level agents in registration order. A top-level agent was created without an owning agent context; durable session lineage does not affect this runtime relation, so a resumed fork may still be a root.', + parameters: [], + returns: 'a fresh array; mutating it does not affect the registry.', + }, + ], + }, + { + key: 'apiProxy', + summary: 'Root interface of the unified API.', + description: 'Root interface of the unified API. New client-request domain = one new file pair + one field here + one map row.', + methods: [ + { + signature: 'downloads: DownloadsApi', + description: 'Host-only download surfaces (GET, no wire envelope); absent from IApiClient.', + parameters: [], + }, + { + signature: 'respond(message: ClientResponse): Promise', + description: 'Response entry for server requests; not a domain method.', + parameters: [{ name: 'message', description: 'Client response carrying the server request\'s rpcId.' }], + returns: 'Transport receipt for the response delivery.', }, ], }, { key: 'approval', summary: 'Approval service that applies session policy before answerers and logs every ask/outcome pair to the requesting session.', + description: 'Approval service that applies session policy before answerers and logs every ask/outcome pair to the requesting session. It exposes deterministic policy changes to the model through the runtime-context snapshot and switch notices.', methods: [ { signature: 'setPolicy(agent: Agent, policy: ApprovalPolicy): void', - jsDoc: '/**\n * Switch one live agent\'s policy and queue the transition for its next model\n * step. Session initialization uses {@link setApprovalPolicy} directly\n * because there is no previously visible policy to change.\n * @param agent - the live agent whose policy is changing.\n * @param policy - the new effective policy.\n */', + description: 'Switch one live agent\'s policy and queue the transition for its next model step. Session initialization uses setApprovalPolicy directly because there is no previously visible policy to change.', + parameters: [{ name: 'agent', description: 'the live agent whose policy is changing.' }, { name: 'policy', description: 'the new effective policy.' }], }, { signature: 'async request(req: ApprovalRequest): Promise', - jsDoc: '/**\n * Ask the composed answerers to decide one readonly same-process request.\n * The service borrows the request, agent, session, and live signal directly.\n * The request requires an open turn because the audit pair must be enclosed\n * by the durable log\'s commit/replay boundary; an idle ask rejects before\n * appending anything. The answerer phase always produces an outcome: an\n * aborted signal yields `\'cancelled\'`, a missing or throwing answerer yields\n * `\'unavailable\'` (fail closed), and a rogue non-vocabulary return value is\n * normalized to `\'unavailable\'`. A failure that prevents either audit append\n * from committing still rejects because returning an unlogged decision would\n * violate the pair. Session contains post-commit observer failures, so an\n * authoritative append cannot reject the request or suppress its matching\n * audit event.\n * @param req - the pending decision (agent, tool identity, reason, signal).\n * @returns the closed outcome; `\'allowed-once\'` is the only grant.\n * @throws when no turn is open or either audit event fails before the session\n * append commit point.\n */', + description: 'Ask the composed answerers to decide one readonly same-process request. The service borrows the request, agent, session, and live signal directly. The request requires an open turn because the audit pair must be enclosed by the durable log\'s commit/replay boundary; an idle ask rejects before appending anything. The answerer phase always produces an outcome: an aborted signal yields `\'cancelled\'`, a missing or throwing answerer yields `\'unavailable\'` (fail closed), and a rogue non-vocabulary return value is normalized to `\'unavailable\'`. A failure that prevents either audit append from committing still rejects because returning an unlogged decision would violate the pair. Session contains post-commit observer failures, so an authoritative append cannot reject the request or suppress its matching audit event.', + parameters: [{ name: 'req', description: 'the pending decision (agent, tool identity, reason, signal).' }], + returns: 'the closed outcome; `\'allowed-once\'` is the only grant.', + throws: ['when no turn is open or either audit event fails before the session append commit point.'], }, { signature: 'overrideOf(session: Session): ApprovalPolicy | undefined', - jsDoc: '/**\n * Read the session override without applying the configured default.\n * @param session - session whose log supplies the override.\n * @returns the last logged policy, or `undefined` without one.\n */', + description: 'Read the session override without applying the configured default.', + parameters: [{ name: 'session', description: 'session whose log supplies the override.' }], + returns: 'the last logged policy, or `undefined` without one.', }, ], }, { key: 'attachments', summary: 'Immutable binary attachment service.', + description: 'Immutable binary attachment service. Implementations validate bytes before publishing a reference.', methods: [ + { + signature: 'abstract readonly imageLimits: ImageAttachmentLimits', + description: 'Deployment-resolved image policy used by authoritative and fast-path validation.', + parameters: [], + }, { signature: 'abstract validateImage(input: SaveImageAttachment): Promise', - jsDoc: '/**\n * Validate one image without persisting it.\n * Batch callers validate every member before saving any member.\n * @param input - encoded bytes, declared media type, and optional display name.\n * @returns completion after the encoded raster has been fully decoded.\n */', + description: 'Validate one image without persisting it. Batch callers validate every member before saving any member.', + parameters: [{ name: 'input', description: 'encoded bytes, declared media type, and optional display name.' }], + returns: 'completion after the encoded raster has been fully decoded.', }, { signature: 'abstract saveImage(input: SaveImageAttachment): Promise', - jsDoc: '/**\n * Validate and durably commit one image before its owning session event is appended.\n * @param input - encoded bytes, declared media type, and optional display name.\n * @returns a durable content-addressed reference.\n */', + description: 'Validate and durably commit one image before its owning session event is appended.', + parameters: [{ name: 'input', description: 'encoded bytes, declared media type, and optional display name.' }], + returns: 'a durable content-addressed reference.', }, { signature: 'abstract readImage(ref: ImageAttachmentRef, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Read one image and verify that bytes still match the recorded reference.\n * @param ref - durable reference from the session log.\n * @param signal - optional cancellation for backend read and verification work.\n * @returns the verified bytes and canonical reference.\n * @throws the signal reason when aborted, or a storage error when verification fails.\n */', + description: 'Read one image and verify that bytes still match the recorded reference.', + parameters: [{ name: 'ref', description: 'durable reference from the session log.' }, { name: 'signal', description: 'optional cancellation for backend read and verification work.' }], + returns: 'the verified bytes and canonical reference.', + throws: ['the signal reason when aborted, or a storage error when verification fails.'], }, ], }, { key: 'clientModules', summary: 'The web plugin table service: incremental `dsh.client` scan + wire composition + bundle route + index tap.', + description: 'The web plugin table service: incremental `dsh.client` scan + wire composition + bundle route + index tap. Construction runs the activation scan synchronously — a malformed declaration or missing bundle among the already-loaded entries aggregates into one loud throw (FAILED fiber; the boot activation audit reports it).', methods: [ { signature: 'graph(): WebBootGraph', - jsDoc: '/**\n * Current composed entry graph (stable object between changes).\n * @returns the graph served as `window.__DSH_BOOT__`.\n */', + description: 'Current composed entry graph (stable object between changes).', + parameters: [], + returns: 'the graph served as `window.__DSH_BOOT__`.', }, { signature: 'clientPath(id: string): string | undefined', - jsDoc: '/**\n * Absolute path of an entry\'s client bundle.\n * @param id - entry id (package name).\n * @returns the path, or undefined for an unknown id.\n */', + description: 'Absolute path of an entry\'s client bundle.', + parameters: [{ name: 'id', description: 'entry id (package name).' }], + returns: 'the path, or undefined for an unknown id.', }, { signature: 'rebuilt(id: string): string | undefined', - jsDoc: '/**\n * Re-hash one bundle (the HMR watch\'s registration hook — the only entry\n * point through which bundle content changes reach the graph).\n * @param id - entry id (package name).\n * @returns the new rev, or undefined for an unknown id.\n */', + description: 'Re-hash one bundle (the HMR watch\'s registration hook — the only entry point through which bundle content changes reach the graph).', + parameters: [{ name: 'id', description: 'entry id (package name).' }], + returns: 'the new rev, or undefined for an unknown id.', }, { signature: 'onRebuilt(listener: (id: string, rev: string) => void): () => void', - jsDoc: '/**\n * Subscribe to bundle rebuilds; fires only when the re-hash changed the rev.\n * @param listener - receives the entry id and its new bundle rev.\n * @returns the unsubscriber.\n */', + description: 'Subscribe to bundle rebuilds; fires only when the re-hash changed the rev.', + parameters: [{ name: 'listener', description: 'receives the entry id and its new bundle rev.' }], + returns: 'the unsubscriber.', }, { signature: 'onGraphChanged(listener: () => void): () => void', - jsDoc: '/**\n * Fires after any flush that recomposed the graph (row added/removed, or a\n * rebuilt rev change). Pull model: listeners re-read {@link graph}.\n * @param listener - notified with no payload.\n * @returns the unsubscriber.\n */', + description: 'Fires after any flush that recomposed the graph (row added/removed, or a rebuilt rev change). Pull model: listeners re-read graph.', + parameters: [{ name: 'listener', description: 'notified with no payload.' }], + returns: 'the unsubscriber.', }, ], }, { key: 'codeRuntime', summary: 'Registers one `ctx.codeRuntime` implementation.', + description: 'Registers one `ctx.codeRuntime` implementation. Program, budget, abort, and substrate failures resolve in CodeRunResult; only Service Definition contract misuse rejects. Implementations bridge structured-cloneable bindings, materialize each declared namespace rejection class, treat programs as hostile peers, isolate runs from one another, and terminate and await in-flight runs during disposal.', methods: [ + { + signature: 'abstract readonly language: string', + description: 'The source language run expects `program` to be written in, as a lowercase identifier. Informational, not gating — a consumer that generates language-specific presentation (typed SDK stubs, usage instructions) switches on it and fails loud on a language it cannot present. Well-known values: `\'typescript\'` and `\'python\'`, those `dsh-tools` presents; only `\'typescript\'` has a published backend.', + parameters: [], + }, + { + signature: 'abstract readonly isolation: string', + description: 'The execution substrate, as a lowercase identifier. Informational, not gating — a descriptor so deployments and diagnostics can tell backends apart, not a security claim. Well-known values: `\'worker-thread\'`, `\'process\'`, `\'container\'`.', + parameters: [], + }, { signature: 'abstract run(request: CodeRunRequest): Promise', - jsDoc: '/**\n * Execute one program against the request\'s bindings and capture what it\n * emitted. See the class doc for the resolution contract (error is a result\n * field; rejection means Service Definition contract misuse only).\n * @param request - the program, its bindings, and the abort signal; the\n * request carries everything the runtime acts on, with no hidden defaults.\n * @returns the run\'s outcome: completion value (when transferable), the\n * ordered log capture, and the failure (if any).\n */', + description: 'Execute one program against the request\'s bindings and capture what it emitted. See the class doc for the resolution contract (error is a result field; rejection means Service Definition contract misuse only).', + parameters: [{ name: 'request', description: 'the program, its bindings, and the abort signal; the request carries everything the runtime acts on, with no hidden defaults.' }], + returns: 'the run\'s outcome: completion value (when transferable), the ordered log capture, and the failure (if any).', }, ], }, { key: 'commands', summary: 'Human-command registry.', + description: 'Human-command registry. Plain-context definitions are global; definitions registered through a command-injected child of an agent context shadow globals for that agent.', methods: [ { signature: 'register(definition: CommandDefinition): () => void', - jsDoc: '/**\n * Register a global or calling-agent-scoped command.\n * @param definition - discovery metadata and direct UI handler.\n * @returns the exact effect disposer that unregisters this definition.\n */', + description: 'Register a global or calling-agent-scoped command.', + parameters: [{ name: 'definition', description: 'discovery metadata and direct UI handler.' }], + returns: 'the exact effect disposer that unregisters this definition.', }, { signature: '@Remote list(agent: Agent): readonly CommandDescriptor[]', - jsDoc: '/**\n * List the effective immutable command descriptors for one agent.\n * @param agent - exact receiving agent and scoped-layer key.\n * @returns name-sorted descriptors after scoped shadowing.\n */', + description: 'List the effective immutable command descriptors for one agent.', + parameters: [{ name: 'agent', description: 'exact receiving agent and scoped-layer key.' }], + returns: 'name-sorted descriptors after scoped shadowing.', }, { signature: 'find(agent: Agent, name: string): CommandDefinition | undefined', - jsDoc: '/**\n * Resolve one effective command definition.\n * @param agent - exact receiving agent and scoped-layer key.\n * @param name - command name without a slash.\n * @returns the scoped shadow or global definition.\n */', + description: 'Resolve one effective command definition.', + parameters: [{ name: 'agent', description: 'exact receiving agent and scoped-layer key.' }, { name: 'name', description: 'command name without a slash.' }], + returns: 'the scoped shadow or global definition.', }, { signature: '@Remote async execute( agent: Agent, line: string, signal: AbortSignal, ): Promise', - jsDoc: '/**\n * Parse and execute a known command without sending it to the model.\n *\n * A resolved command\'s lifecycle is logged: `command/run` is appended\n * before the handler is invoked and `command/done` after settlement (a\n * thrown or aborted handler settles as `kind: \'error\'`). Both are direct\n * log-only appends — no turn wraps them, and persistence drains them at\n * ordinary checkpoints. Admission misses (syntax or unknown name) log\n * nothing — they never entered a handler. A `command/run` append failure\n * fails the execution loud; a `command/done` append failure on the\n * handler-failure path is contained so the handler\'s own error stays the\n * reported failure.\n *\n * @param agent - exact receiving agent.\n * @param line - complete slash-command line.\n * @param signal - cancellation signal owned by the UI request.\n * @returns the settled execution (result + lifecycle pairing id), or\n * `undefined` when syntax or name does not resolve.\n */', + description: 'Parse and execute a known command without sending it to the model.\n\nA resolved command\'s lifecycle is logged: `command/run` is appended before the handler is invoked and `command/done` after settlement (a thrown or aborted handler settles as `kind: \'error\'`). Both are direct log-only appends — no turn wraps them, and persistence drains them at ordinary checkpoints. Admission misses (syntax or unknown name) log nothing — they never entered a handler. A `command/run` append failure fails the execution loud; a `command/done` append failure on the handler-failure path is contained so the handler\'s own error stays the reported failure.', + parameters: [{ name: 'agent', description: 'exact receiving agent.' }, { name: 'line', description: 'complete slash-command line.' }, { name: 'signal', description: 'cancellation signal owned by the UI request.' }], + returns: 'the settled execution (result + lifecycle pairing id), or `undefined` when syntax or name does not resolve.', }, ], }, { key: 'compaction', summary: 'Abstract compaction service.', + description: 'Abstract compaction service. Implementations own trigger policy, retention, and summarization, and may consume a separate measurement service. A successful run replaces the selected surface span with one summary node and prevents concurrent compaction of the same session. The replacement user message uses compactCheckpointSource with the transaction identity so consumers recognize and correlate it independently of the backend. Load one implementation per context as `ctx.compaction`.', methods: [ { signature: 'abstract compactIfNeeded( agent: CompactionAgentContext, trigger: CompactionTrigger, signal: AbortSignal, ): Promise', - jsDoc: '/**\n * Consider automatic compaction for one explicit trigger. Pressure policy\n * uses the latest durable routed request, while context-overflow policy may\n * force a useful balanced reduction even below the normal threshold. Return\n * `null` when no safe range can be compacted. A single oversized retained\n * unit or request envelope cannot be repaired through surface compaction.\n *\n * @param agent - agent context owning the session surface and routing options.\n * @param trigger - normal pressure or provider-confirmed context overflow.\n * @param signal - cancellation signal; model-backed implementations must forward it.\n * @returns the compaction result, or `null` if no compaction was needed.\n */', + description: 'Consider automatic compaction for one explicit trigger. Pressure policy uses the latest durable routed request, while context-overflow policy may force a useful balanced reduction even below the normal threshold. Return `null` when no safe range can be compacted. A single oversized retained unit or request envelope cannot be repaired through surface compaction.', + parameters: [{ name: 'agent', description: 'agent context owning the session surface and routing options.' }, { name: 'trigger', description: 'normal pressure or provider-confirmed context overflow.' }, { name: 'signal', description: 'cancellation signal; model-backed implementations must forward it.' }], + returns: 'the compaction result, or `null` if no compaction was needed.', }, { signature: 'abstract compactNow( agent: ManualCompactAgentContext, signal: AbortSignal, sourceCommandId?: CommandId, ): Promise', - jsDoc: '/**\n * Explicitly compact useful history even below automatic pressure thresholds.\n * Implementations synchronously start an idle task before any asynchronous\n * work, select a useful range without writing on a no-op, then\n * append a standalone `compaction/start` before summarization. That durable\n * marker is the compaction lock until one `compaction/end` attempt. Later waking\n * prompts remain accepted in FIFO order and start only after the optional\n * durability checkpoint and idle-task settlement. Context injected while the\n * summary runs may sit between the marker pair; only the selected span must\n * remain stable.\n *\n * @param agent - idle agent whose durable history should be compacted.\n * @param signal - cancellation scoped to this compaction request.\n * @param sourceCommandId - initiating command identity for a manual compaction.\n * @returns the compaction result, or `null` when no safe useful range exists.\n * @throws {@link ManualCompactionError} for expected busy, agent-cancellation,\n * changed-span, summarization/shrink, commit-stage, or persistence failures;\n * an aborted request preserves its exact abort reason. Failed attempts remain\n * visible in the log.\n */', + description: 'Explicitly compact useful history even below automatic pressure thresholds. Implementations synchronously start an idle task before any asynchronous work, select a useful range without writing on a no-op, then append a standalone `compaction/start` before summarization. That durable marker is the compaction lock until one `compaction/end` attempt. Later waking prompts remain accepted in FIFO order and start only after the optional durability checkpoint and idle-task settlement. Context injected while the summary runs may sit between the marker pair; only the selected span must remain stable.', + parameters: [{ name: 'agent', description: 'idle agent whose durable history should be compacted.' }, { name: 'signal', description: 'cancellation scoped to this compaction request.' }, { name: 'sourceCommandId', description: 'initiating command identity for a manual compaction.' }], + returns: 'the compaction result, or `null` when no safe useful range exists.', + throws: ['{@link ManualCompactionError} for expected busy, agent-cancellation, changed-span, summarization/shrink, commit-stage, or persistence failures; an aborted request preserves its exact abort reason. Failed attempts remain visible in the log.'], }, { signature: 'abstract compactRegion( start: number, end: number, agent: CompactionAgentContext, signal?: AbortSignal, ): Promise', - jsDoc: '/**\n * Forcibly compact a range of surface nodes into a single summary node.\n * `start` and `end` name an inclusive span by surface position, not numeric seq\n * order; replacements can make visible seqs non-monotonic. Both edges must be\n * balanced so assistant tool calls remain paired with their results. A model-\n * backed implementation forwards cancellation and rejects active, missing,\n * reversed, or unbalanced ranges. The target session is `agent.session`.\n * Its replacement user message must use {@link compactCheckpointSource} with\n * the transaction\'s `CompactionId`.\n * Use {@link toolPairingBalancedBefore} and {@link toolPairingBalancedAfter}\n * for the edge checks.\n *\n * @param start - first surface seq, inclusive.\n * @param end - last surface seq, inclusive.\n * @param agent - context whose session is mutated and whose routing options guide summarization.\n * @param signal - optional cancellation; model-backed implementations must forward it.\n * @throws when compaction is active or the range is missing, reversed, or unbalanced.\n * @returns the appended event seqs, summary, replaced range, and token accounting.\n */', + description: 'Forcibly compact a range of surface nodes into a single summary node. `start` and `end` name an inclusive span by surface position, not numeric seq order; replacements can make visible seqs non-monotonic. Both edges must be balanced so assistant tool calls remain paired with their results. A model- backed implementation forwards cancellation and rejects active, missing, reversed, or unbalanced ranges. The target session is `agent.session`. Its replacement user message must use compactCheckpointSource with the transaction\'s `CompactionId`. Use toolPairingBalancedBefore and toolPairingBalancedAfter for the edge checks.', + parameters: [{ name: 'start', description: 'first surface seq, inclusive.' }, { name: 'end', description: 'last surface seq, inclusive.' }, { name: 'agent', description: 'context whose session is mutated and whose routing options guide summarization.' }, { name: 'signal', description: 'optional cancellation; model-backed implementations must forward it.' }], + returns: 'the appended event seqs, summary, replaced range, and token accounting.', + throws: ['when compaction is active or the range is missing, reversed, or unbalanced.'], }, ], }, { key: 'credentials', summary: 'Abstract credential service.', + description: 'Abstract credential service. Providers implement the four operations over their source layers; one seam-wide rule binds them all: an empty stored value is absent everywhere — `resolve` skips it, `describe` reports it unconfigured — so a blank never masquerades as a configured secret.', methods: [ { signature: 'abstract resolve(ref: CredentialRef): Promise', - jsDoc: '/**\n * Resolve one reference to its current value. Resolution is per call:\n * consumers re-resolve at each operation and must not cache across\n * operations — that per-operation read is what makes a changed credential\n * reach the next operation without a restart.\n * @param ref - the reference to resolve.\n * @returns the value and its source, or `undefined` while unconfigured.\n */', + description: 'Resolve one reference to its current value. Resolution is per call: consumers re-resolve at each operation and must not cache across operations — that per-operation read is what makes a changed credential reach the next operation without a restart.', + parameters: [{ name: 'ref', description: 'the reference to resolve.' }], + returns: 'the value and its source, or `undefined` while unconfigured.', }, { signature: 'abstract describe(ref: CredentialRef): Promise', - jsDoc: '/**\n * Describe one reference for configuration surfaces without exposing the\n * value.\n * @param ref - the reference to describe.\n * @returns configured state, supplying source, and writability.\n */', + description: 'Describe one reference for configuration surfaces without exposing the value.', + parameters: [{ name: 'ref', description: 'the reference to describe.' }], + returns: 'configured state, supplying source, and writability.', }, { signature: 'abstract set(ref: CredentialRef, value: string): Promise', - jsDoc: '/**\n * Durably store one value in the provider-managed writable source. Rejects\n * while a read-only source shadows the reference — the write would appear\n * to succeed while resolution keeps returning the shadowing value — and\n * rejects an empty value (use {@link unset}).\n * @param ref - the reference to store.\n * @param value - the non-empty secret value.\n */', + description: 'Durably store one value in the provider-managed writable source. Rejects while a read-only source shadows the reference — the write would appear to succeed while resolution keeps returning the shadowing value — and rejects an empty value (use unset).', + parameters: [{ name: 'ref', description: 'the reference to store.' }, { name: 'value', description: 'the non-empty secret value.' }], }, { signature: 'abstract unset(ref: CredentialRef): Promise', - jsDoc: '/**\n * Remove one reference from the provider-managed writable source; removing\n * an absent reference is a no-op. Rejects while a read-only source shadows\n * the reference, like {@link set}.\n * @param ref - the reference to remove.\n */', + description: 'Remove one reference from the provider-managed writable source; removing an absent reference is a no-op. Rejects while a read-only source shadows the reference, like set.', + parameters: [{ name: 'ref', description: 'the reference to remove.' }], }, ], }, { key: 'directoryPicker', summary: 'Abstract directory-picking service.', + description: 'Abstract directory-picking service. Subclass, implement `capability()`, and load the subclass as a plugin — it registers as `ctx.directoryPicker` (one implementation per context; loading a second throws, cordis\' standard duplicate-service behavior). The capability object must be stable for the service lifetime: consumers may capture it across calls.', methods: [ { signature: 'abstract capability(): DirectoryPickerCapability', - jsDoc: '/**\n * The backend\'s interaction capability.\n * @returns the discriminated capability consumers switch on.\n */', + description: 'The backend\'s interaction capability.', + parameters: [], + returns: 'the discriminated capability consumers switch on.', }, ], }, { key: 'e2b', summary: 'Creates one lazily consumable E2B SDK handle and deletes the sandbox at timeout or disposal.', + description: 'Creates one lazily consumable E2B SDK handle and deletes the sandbox at timeout or disposal. Creation begins at plugin construction; adapters await getSandbox before their first operation.', methods: [ + { + signature: 'readonly cwd: string', + description: 'Validated remote working directory shared by provider adapters.', + parameters: [], + }, + { + signature: 'readonly runtimeRoot: string', + description: 'Remote directory reserved for adapter-owned process and terminal state.', + parameters: [], + }, { signature: 'async getSandbox(): Promise', - jsDoc: '/**\n * Return the shared live SDK handle.\n * @returns the created sandbox after the configured cwd exists.\n * @throws when E2B rejects creation or the service is disposing.\n */', + description: 'Return the shared live SDK handle.', + parameters: [], + returns: 'the created sandbox after the configured cwd exists.', + throws: ['when E2B rejects creation or the service is disposing.'], }, ], }, { key: 'fs', summary: 'Abstract filesystem provider.', + description: 'Abstract filesystem provider. Targets must preserve identity across aliases; reads expose regular UTF-8 text or typed errors, listings are stable and content-free, and mutations are atomic. Optional guards add stale protection without changing the unguarded provider contract.', methods: [ { signature: 'abstract resolve(path: string, opts?: { cwd?: string; signal?: AbortSignal }): Promise', - jsDoc: '/**\n * Resolve a model/plugin-supplied path into a stable {@link FsTarget}. May perform I/O (a\n * remote/sandboxed backend may need a round-trip to map a path to a stable identity), hence\n * async even though the local backend only normalizes + realpaths.\n *\n * @param path - the path to resolve; relative paths resolve against `opts.cwd`.\n * @param opts - optional cwd override and cancellation signal.\n * @returns the stable target; the same file yields the same `targetKey`.\n */', + description: 'Resolve a model/plugin-supplied path into a stable FsTarget. May perform I/O (a remote/sandboxed backend may need a round-trip to map a path to a stable identity), hence async even though the local backend only normalizes + realpaths.', + parameters: [{ name: 'path', description: 'the path to resolve; relative paths resolve against `opts.cwd`.' }, { name: 'opts', description: 'optional cwd override and cancellation signal.' }], + returns: 'the stable target; the same file yields the same `targetKey`.', }, { signature: 'abstract processPath(target: FsTarget): string', - jsDoc: '/**\n * Return the canonical absolute path a subprocess in this filesystem\'s\n * execution world can open. The path is deliberately separate from\n * {@link FsTarget.targetKey}: consumers may pass this value to another OS\n * capability, but must continue treating the target key as opaque.\n * @param target - the resolved target whose process path is required.\n * @returns an absolute path in the backend\'s execution world.\n */', + description: 'Return the canonical absolute path a subprocess in this filesystem\'s execution world can open. The path is deliberately separate from FsTarget.targetKey: consumers may pass this value to another OS capability, but must continue treating the target key as opaque.', + parameters: [{ name: 'target', description: 'the resolved target whose process path is required.' }], + returns: 'an absolute path in the backend\'s execution world.', }, { signature: 'abstract fileUrl(target: FsTarget): string', - jsDoc: '/**\n * Return the canonical `file:` URI for a target in this filesystem\'s\n * execution world. Backends own URI encoding because the host platform may\n * differ from the execution platform.\n * @param target - the resolved target to encode.\n * @returns the target\'s canonical file URI.\n */', + description: 'Return the canonical `file:` URI for a target in this filesystem\'s execution world. Backends own URI encoding because the host platform may differ from the execution platform.', + parameters: [{ name: 'target', description: 'the resolved target to encode.' }], + returns: 'the target\'s canonical file URI.', }, { signature: 'abstract contains(parent: FsTarget, child: FsTarget): boolean', - jsDoc: '/**\n * Test canonical containment without exposing or parsing backend target\n * keys. Both targets must come from this provider.\n * @param parent - canonical directory target.\n * @param child - canonical candidate target.\n * @returns true when `child` is `parent` or a descendant of it.\n */', + description: 'Test canonical containment without exposing or parsing backend target keys. Both targets must come from this provider.', + parameters: [{ name: 'parent', description: 'canonical directory target.' }, { name: 'child', description: 'canonical candidate target.' }], + returns: 'true when `child` is `parent` or a descendant of it.', }, { signature: 'abstract stat(target: FsTarget, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Return target metadata, or `undefined` when the target does not exist.\n * @param target - the resolved target to stat.\n * @param signal - aborts the metadata round-trip.\n * @returns metadata only, never content; undefined for an absent target.\n */', + description: 'Return target metadata, or `undefined` when the target does not exist.', + parameters: [{ name: 'target', description: 'the resolved target to stat.' }, { name: 'signal', description: 'aborts the metadata round-trip.' }], + returns: 'metadata only, never content; undefined for an absent target.', }, { signature: 'abstract lstat(path: string, opts?: { cwd?: string }, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Return path metadata without following the final path component when it is a\n * symbolic link. This is intentionally path-shaped, not target-shaped:\n * {@link resolve} follows symlinks to produce the stable identity used by\n * normal reads/writes, while `lstat` lets a consumer reject the path itself\n * before that follow happens.\n *\n * `opts.cwd` follows {@link resolve}\'s cwd rules. `undefined` means the path is\n * absent.\n * @param path - the path to inspect; relative paths resolve against `opts.cwd`.\n * @param opts - `cwd` overrides the backend\'s default base for relative paths.\n * @param signal - aborts the metadata round-trip.\n * @returns metadata only, never content; undefined for an absent path.\n */', + description: 'Return path metadata without following the final path component when it is a symbolic link. This is intentionally path-shaped, not target-shaped: resolve follows symlinks to produce the stable identity used by normal reads/writes, while `lstat` lets a consumer reject the path itself before that follow happens.\n\n`opts.cwd` follows resolve\'s cwd rules. `undefined` means the path is absent.', + parameters: [{ name: 'path', description: 'the path to inspect; relative paths resolve against `opts.cwd`.' }, { name: 'opts', description: '`cwd` overrides the backend\'s default base for relative paths.' }, { name: 'signal', description: 'aborts the metadata round-trip.' }], + returns: 'metadata only, never content; undefined for an absent path.', }, { signature: 'abstract readText(target: FsTarget, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Read the whole regular text file as a single decoded string.\n * @param target - the resolved target to read.\n * @param signal - aborts the read.\n * @returns the full decoded UTF-8 content.\n */', + description: 'Read the whole regular text file as a single decoded string.', + parameters: [{ name: 'target', description: 'the resolved target to read.' }, { name: 'signal', description: 'aborts the read.' }], + returns: 'the full decoded UTF-8 content.', }, { signature: 'abstract streamText(target: FsTarget, signal?: AbortSignal): Promise>', - jsDoc: '/**\n * Stream the whole regular text file as decoded text chunks (same text\n * semantics as {@link readText}, for large files). The backend owns\n * cross-chunk UTF-8 decoding and binary rejection so the policy layer never\n * touches raw bytes.\n * @param target - the resolved target to read.\n * @param signal - aborts the stream, including between chunks.\n * @returns the chunk iterable, decoded and validated like {@link readText}.\n */', + description: 'Stream the whole regular text file as decoded text chunks (same text semantics as readText, for large files). The backend owns cross-chunk UTF-8 decoding and binary rejection so the policy layer never touches raw bytes.', + parameters: [{ name: 'target', description: 'the resolved target to read.' }, { name: 'signal', description: 'aborts the stream, including between chunks.' }], + returns: 'the chunk iterable, decoded and validated like {@link readText}.', }, { signature: 'abstract readBytes(target: FsTarget, signal: AbortSignal | undefined, maxBytes: number): Promise', - jsDoc: '/**\n * Read the whole regular file as raw bytes with no decoding or binary\n * rejection. The bound lives at this seam so a backend can never buffer an\n * unbounded file: a target known or discovered to exceed `maxBytes` fails\n * with `FS_TOO_LARGE` instead of returning a truncated result.\n * @param target - the resolved target to read.\n * @param signal - aborts the read.\n * @param maxBytes - inclusive byte cap on the complete content.\n * @returns the full raw content, at most `maxBytes` long.\n */', + description: 'Read the whole regular file as raw bytes with no decoding or binary rejection. The bound lives at this seam so a backend can never buffer an unbounded file: a target known or discovered to exceed `maxBytes` fails with `FS_TOO_LARGE` instead of returning a truncated result.', + parameters: [{ name: 'target', description: 'the resolved target to read.' }, { name: 'signal', description: 'aborts the read.' }, { name: 'maxBytes', description: 'inclusive byte cap on the complete content.' }], + returns: 'the full raw content, at most `maxBytes` long.', }, { signature: 'abstract listDir(target: FsTarget, signal?: AbortSignal): Promise', - jsDoc: '/**\n * List direct children of a directory in stable name order. Returns resolved\n * child targets plus cheap metadata only; never reads file contents.\n * @param target - the resolved directory target.\n * @param signal - aborts the listing.\n * @returns one entry per direct child, in stable name order.\n */', + description: 'List direct children of a directory in stable name order. Returns resolved child targets plus cheap metadata only; never reads file contents.', + parameters: [{ name: 'target', description: 'the resolved directory target.' }, { name: 'signal', description: 'aborts the listing.' }], + returns: 'one entry per direct child, in stable name order.', }, { signature: 'abstract writeText( target: FsTarget, content: string, expected?: FsWriteIntent, signal?: AbortSignal, sandboxPolicy?: SandboxExecutionPolicy, ): Promise', - jsDoc: '/**\n * Atomically create or replace UTF-8 text. `expected` guards intent and\n * staleness; omission allows unconditional overwrite.\n * @param target - the resolved target to write.\n * @param content - the full new file content.\n * @param expected - the write intent guarding the write; omit for unconditional.\n * @param signal - aborts before atomic publication takes effect.\n * @param sandboxPolicy - the per-call mode and workspace root this write\n * runs under; a sandboxing backend fences the write by it, the bare backend\n * ignores it. Omit to leave the backend its own default.\n * @returns the outcome, including the version the write produced.\n */', + description: 'Atomically create or replace UTF-8 text. `expected` guards intent and staleness; omission allows unconditional overwrite.', + parameters: [{ name: 'target', description: 'the resolved target to write.' }, { name: 'content', description: 'the full new file content.' }, { name: 'expected', description: 'the write intent guarding the write; omit for unconditional.' }, { name: 'signal', description: 'aborts before atomic publication takes effect.' }, { name: 'sandboxPolicy', description: 'the per-call mode and workspace root this write runs under; a sandboxing backend fences the write by it, the bare backend ignores it. Omit to leave the backend its own default.' }], + returns: 'the outcome, including the version the write produced.', }, { signature: 'abstract editText( target: FsTarget, edit: FsEditRequest, expected?: { version: FsVersion }, signal?: AbortSignal, sandboxPolicy?: SandboxExecutionPolicy, ): Promise', - jsDoc: '/**\n * Atomically edit literal text. When supplied, the version guard is checked\n * before matching so stale content reports `FS_STALE_VERSION`; omission edits\n * the current content without a freshness precondition.\n * @param target - the resolved target to edit.\n * @param edit - the literal search/replace request.\n * @param expected - the version guard; omit for an unconditional edit.\n * @param signal - aborts before atomic publication takes effect.\n * @param sandboxPolicy - the per-call mode and workspace root this edit runs\n * under; a sandboxing backend fences the edit by it, the bare backend\n * ignores it. Omit to leave the backend its own default.\n * @returns the outcome, including the version the edit produced.\n */', + description: 'Atomically edit literal text. When supplied, the version guard is checked before matching so stale content reports `FS_STALE_VERSION`; omission edits the current content without a freshness precondition.', + parameters: [{ name: 'target', description: 'the resolved target to edit.' }, { name: 'edit', description: 'the literal search/replace request.' }, { name: 'expected', description: 'the version guard; omit for an unconditional edit.' }, { name: 'signal', description: 'aborts before atomic publication takes effect.' }, { name: 'sandboxPolicy', description: 'the per-call mode and workspace root this edit runs under; a sandboxing backend fences the edit by it, the bare backend ignores it. Omit to leave the backend its own default.' }], + returns: 'the outcome, including the version the edit produced.', }, ], }, { key: 'goals', summary: 'Goal service (`ctx.goals`) backed exclusively by the owning session log.', + description: 'Goal service (`ctx.goals`) backed exclusively by the owning session log.', methods: [ { signature: 'get(agent: Agent): GoalView | undefined', - jsDoc: '/**\n * Read the current goal for one exact live agent.\n * @param agent - owning live agent.\n * @returns a fresh view or `undefined` when no goal is current.\n * @throws {@link GoalError} when the agent is not the registry\'s live instance.\n */', + description: 'Read the current goal for one exact live agent.', + parameters: [{ name: 'agent', description: 'owning live agent.' }], + returns: 'a fresh view or `undefined` when no goal is current.', + throws: ['{@link GoalError} when the agent is not the registry\'s live instance.'], }, { signature: 'disarm(agent: Agent): GoalView | undefined', - jsDoc: '/**\n * Remove process-local continuation authority without changing durable goal\n * phase or revision. Lifecycle owners use this before unloading a driver;\n * a later human-authorized {@link resume} records the new activation edge.\n * @param agent - owning live agent.\n * @returns a fresh disarmed view, or `undefined` when no goal is current.\n */', + description: 'Remove process-local continuation authority without changing durable goal phase or revision. Lifecycle owners use this before unloading a driver; a later human-authorized resume records the new activation edge.', + parameters: [{ name: 'agent', description: 'owning live agent.' }], + returns: 'a fresh disarmed view, or `undefined` when no goal is current.', }, { signature: 'create(agent: Agent, request: CreateGoalRequest): GoalView', - jsDoc: '/**\n * Create and arm a goal. A completed goal may be replaced; every other\n * current phase must be cleared or resumed instead.\n * @param agent - owning live agent.\n * @param request - objective and optional round cap.\n * @returns the created live view.\n */', + description: 'Create and arm a goal. A completed goal may be replaced; every other current phase must be cleared or resumed instead.', + parameters: [{ name: 'agent', description: 'owning live agent.' }, { name: 'request', description: 'objective and optional round cap.' }], + returns: 'the created live view.', }, { signature: '@Remote(\'edit\') edit(agent: Agent, ref: GoalRef, request: EditGoalRequest): GoalView', - jsDoc: '/**\n * Edit objective and/or round cap without changing phase.\n * @param agent - owning live agent.\n * @param ref - expected current revision.\n * @param request - at least one replacement field.\n * @returns the edited view.\n */', + description: 'Edit objective and/or round cap without changing phase.', + parameters: [{ name: 'agent', description: 'owning live agent.' }, { name: 'ref', description: 'expected current revision.' }, { name: 'request', description: 'at least one replacement field.' }], + returns: 'the edited view.', }, { signature: '@Remote(\'pause\') pause(agent: Agent, ref: GoalRef): GoalView', - jsDoc: '/**\n * Pause an active goal and disarm automatic continuation.\n * @param agent - owning live agent.\n * @param ref - expected current revision.\n * @returns the paused view.\n */', + description: 'Pause an active goal and disarm automatic continuation.', + parameters: [{ name: 'agent', description: 'owning live agent.' }, { name: 'ref', description: 'expected current revision.' }], + returns: 'the paused view.', }, { signature: '@Remote(\'resume\') resume(agent: Agent, ref: GoalRef): GoalView', - jsDoc: '/**\n * Resume and arm a stopped goal, or rearm an active goal after a\n * session-start edge, while its round budget still has capacity.\n * @param agent - owning live agent.\n * @param ref - expected current revision.\n * @returns the active view.\n */', + description: 'Resume and arm a stopped goal, or rearm an active goal after a session-start edge, while its round budget still has capacity.', + parameters: [{ name: 'agent', description: 'owning live agent.' }, { name: 'ref', description: 'expected current revision.' }], + returns: 'the active view.', }, { signature: '@Remote(\'complete\') complete(agent: Agent, ref: GoalRef): GoalView', - jsDoc: '/**\n * Mark a current non-complete goal complete and disarm it.\n * @param agent - owning live agent.\n * @param ref - expected current revision.\n * @returns the completed view.\n */', + description: 'Mark a current non-complete goal complete and disarm it.', + parameters: [{ name: 'agent', description: 'owning live agent.' }, { name: 'ref', description: 'expected current revision.' }], + returns: 'the completed view.', }, { signature: 'block(agent: Agent, ref: GoalRef, reason: GoalBlockReason): GoalView', - jsDoc: '/**\n * Mark an active goal blocked and disarm it.\n * @param agent - owning live agent.\n * @param ref - expected current revision.\n * @param reason - policy-owned stable code and human-readable explanation.\n * @returns the blocked view with its durable reason.\n */', + description: 'Mark an active goal blocked and disarm it.', + parameters: [{ name: 'agent', description: 'owning live agent.' }, { name: 'ref', description: 'expected current revision.' }, { name: 'reason', description: 'policy-owned stable code and human-readable explanation.' }], + returns: 'the blocked view with its durable reason.', }, { signature: '@Remote(\'clear\') clear(agent: Agent, ref: GoalRef): GoalRef', - jsDoc: '/**\n * Clear the current goal while retaining a durable tombstone and history.\n * @param agent - owning live agent.\n * @param ref - expected current revision.\n * @returns the tombstone ref whose revision is one past the cleared snapshot.\n */', + description: 'Clear the current goal while retaining a durable tombstone and history.', + parameters: [{ name: 'agent', description: 'owning live agent.' }, { name: 'ref', description: 'expected current revision.' }], + returns: 'the tombstone ref whose revision is one past the cleared snapshot.', }, { signature: '@Remote(\'create\') remoteExportCreate(agent: Agent, request: CreateGoalRequest): CreateGoalResult', - jsDoc: '/**\n * Create one Goal through the remote boundary.\n * @param agent - exact live Agent resolved from the wire identity.\n * @param request - objective and optional round cap.\n * @returns the created Goal identity.\n */', + description: 'Create one Goal through the remote boundary.', + parameters: [{ name: 'agent', description: 'exact live Agent resolved from the wire identity.' }, { name: 'request', description: 'objective and optional round cap.' }], + returns: 'the created Goal identity.', }, ], }, { key: 'invariants', summary: 'Package-owned invariant registry with global and regex-based selection.', + description: 'Package-owned invariant registry with global and regex-based selection.', methods: [ { signature: 'register(packageName: string, installer: InvariantInstaller): () => void', - jsDoc: '/**\n * Register one package\'s invariant installer. The package name is reserved\n * even when filtering disables its checks. Enabled installers run in a child\n * fiber; failure disposes that fiber and releases the reservation.\n * @param packageName - full npm package name that owns the contribution.\n * @param installer - listener or startup-check installer for the child context.\n * @returns an effect-scoped disposer for the registration.\n */', + description: 'Register one package\'s invariant installer. The package name is reserved even when filtering disables its checks. Enabled installers run in a child fiber; failure disposes that fiber and releases the reservation.', + parameters: [{ name: 'packageName', description: 'full npm package name that owns the contribution.' }, { name: 'installer', description: 'listener or startup-check installer for the child context.' }], + returns: 'an effect-scoped disposer for the registration.', }, ], }, { key: 'jobs', summary: 'Abstract background job registry.', + description: 'Abstract background job registry. Subclass, implement the abstract methods, and load the subclass as a plugin — it registers as `ctx.jobs` (one implementation per context; loading a second throws, which is cordis\' standard duplicate-service behavior).\n\nImplementations must honor these semantics:\n\n- Registrations outlive producer and controller fibers. Owner and service disposal cancel live work and await compliant producers; a throwing teardown cancel force-fails only the record. Teardown cancellation also marks the record reported, because a record its owner is being destroyed for has no reader left.\n- Owned-job access is fenced by the owner\'s session id. Ids are predictable, so authorization — not secrecy — is the boundary.\n- Settlement is first-wins: one terminal record, released waiters, and one round of contained listener notification, even against a late producer outcome. Completion is announced last, after the record is committed and every other observer of the settlement has seen it, because a reporter may open a model turn synchronously.\n- start refuses work while no attached job controller serves the spec\'s owner, so a producer cannot start work that owner cannot collect or stop. One registry serves every composition in the process, so this question — and completion-listener delivery — is owner-relative rather than process-wide: registrations made from an unscoped context serve every owner, and registrations made under an agent composition\'s scope serve exactly the agents composed under it.', methods: [ { signature: 'abstract start(spec: JobStart): JobId', - jsDoc: '/**\n * Preflight access, validation, owner cleanup, and implementation-owned\n * admission before starting and atomically registering work. Any preflight\n * rejection leaves no job id or execution resource. A throwing starter\n * leaves nothing registered; after it returns, registration cannot fail.\n * Settlement records the outcome, notifies listeners, and releases waiters.\n * @param spec - job identity, owner, and synchronous starter.\n * @returns the registry-issued `-N` id.\n */', + description: 'Preflight access, validation, owner cleanup, and implementation-owned admission before starting and atomically registering work. Any preflight rejection leaves no job id or execution resource. A throwing starter leaves nothing registered; after it returns, registration cannot fail. Settlement records the outcome, notifies listeners, and releases waiters.', + parameters: [{ name: 'spec', description: 'job identity, owner, and synchronous starter.' }], + returns: 'the registry-issued `-N` id.', }, { signature: 'abstract list(caller?: Agent): JobSnapshot[]', - jsDoc: '/**\n * List caller-owned and unowned jobs in registration order without exposing\n * another session\'s labels.\n * @param caller - reading agent; a non-agent caller sees only unowned jobs.\n * @returns fresh snapshots.\n */', + description: 'List caller-owned and unowned jobs in registration order without exposing another session\'s labels.', + parameters: [{ name: 'caller', description: 'reading agent; a non-agent caller sees only unowned jobs.' }], + returns: 'fresh snapshots.', }, { signature: 'abstract get(id: JobId, caller?: Agent): JobSnapshot', - jsDoc: '/**\n * Return a non-consuming snapshot without changing its read cursor or notice\n * state. Throws for an unknown or foreign job.\n * @param id - job to look up.\n * @param caller - reading agent checked against the owner.\n * @returns a fresh snapshot.\n */', + description: 'Return a non-consuming snapshot without changing its read cursor or notice state. Throws for an unknown or foreign job.', + parameters: [{ name: 'id', description: 'job to look up.' }, { name: 'caller', description: 'reading agent checked against the owner.' }], + returns: 'a fresh snapshot.', }, { signature: 'abstract read(id: JobId, caller?: Agent): JobRead', - jsDoc: '/**\n * Read the next stream delta, or the idempotent final output after settlement.\n * A terminal read marks the job reported. Throws for an unknown or foreign\n * job.\n * @param id - job to read.\n * @param caller - reading agent checked against the owner.\n * @returns output text and the post-read snapshot.\n */', + description: 'Read the next stream delta, or the idempotent final output after settlement. A terminal read marks the job reported. Throws for an unknown or foreign job.', + parameters: [{ name: 'id', description: 'job to read.' }, { name: 'caller', description: 'reading agent checked against the owner.' }], + returns: 'output text and the post-read snapshot.', }, { signature: 'abstract kill(id: JobId, caller?: Agent, reason?: string): \'requested\' | \'already-finished\'', - jsDoc: '/**\n * Request cancellation, then mark the job stopping and reported. A producer\n * throw propagates without changing job state. Throws for an unknown or\n * foreign job.\n * @param id - job to cancel.\n * @param caller - killing agent checked against the owner.\n * @param reason - logged reason forwarded to the producer.\n * @returns `requested` for live work, otherwise `already-finished`.\n */', + description: 'Request cancellation, then mark the job stopping and reported. A producer throw propagates without changing job state. Throws for an unknown or foreign job.', + parameters: [{ name: 'id', description: 'job to cancel.' }, { name: 'caller', description: 'killing agent checked against the owner.' }, { name: 'reason', description: 'logged reason forwarded to the producer.' }], + returns: '`requested` for live work, otherwise `already-finished`.', }, { signature: 'abstract wait(id: JobId, timeoutMs: number, caller?: Agent, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Wait for settlement or timeout without cancelling the job. Caller abort\n * rejects only while the job is live; after settlement the terminal\n * snapshot wins so a notice suppressed for this waiter is still delivered.\n * Throws for invalid, unknown, or foreign input.\n * @param id - job to wait for.\n * @param timeoutMs - positive finite wait bound in milliseconds.\n * @param caller - waiting agent checked against the owner.\n * @param signal - optional cancellation of the wait itself.\n * @returns snapshot at settlement or timeout.\n */', + description: 'Wait for settlement or timeout without cancelling the job. Caller abort rejects only while the job is live; after settlement the terminal snapshot wins so a notice suppressed for this waiter is still delivered. Throws for invalid, unknown, or foreign input.', + parameters: [{ name: 'id', description: 'job to wait for.' }, { name: 'timeoutMs', description: 'positive finite wait bound in milliseconds.' }, { name: 'caller', description: 'waiting agent checked against the owner.' }, { name: 'signal', description: 'optional cancellation of the wait itself.' }], + returns: 'snapshot at settlement or timeout.', }, { signature: 'abstract onJobDone(listener: JobDoneListener): () => void', - jsDoc: '/**\n * Register an effect-scoped completion listener. It receives the settlements\n * of the owners its registering context\'s scope covers; each listener is\n * contained; returned promises are observed but not awaited. No listener runs\n * after service disposal.\n * @param listener - receives each terminal snapshot and its exact owner.\n * @returns disposer that unregisters the listener.\n */', + description: 'Register an effect-scoped completion listener. It receives the settlements of the owners its registering context\'s scope covers; each listener is contained; returned promises are observed but not awaited. No listener runs after service disposal.', + parameters: [{ name: 'listener', description: 'receives each terminal snapshot and its exact owner.' }], + returns: 'disposer that unregisters the listener.', }, { signature: 'abstract onJobsChanged(listener: JobsChangedListener): () => void', - jsDoc: '/**\n/**\n * Register an effect-scoped observer of visible-set changes. It fires after\n * every commit that changes what {@link list} returns for that owner —\n * registration, every stopping transition (including the one teardown\n * performs before it awaits a slow producer), settlement, owner-disposal\n * removal, and the emptying that service disposal commits — so an observer\n * re-reads rather than accumulating deltas.\n *\n * Delivery is owner-relative on the same terms as {@link onJobDone}: an\n * observer registered from an unscoped context — a host composition\'s own\n * carrier — sees every owner, while one registered under an agent\n * composition\'s scope sees exactly the agents composed under it.\n *\n * This is not a superset of {@link onJobDone}: that one delivers the terminal\n * record under first-wins semantics a job controller couples to notice\n * delivery, while this one carries no delivery meaning and marks nothing\n * reported. Listeners are contained and never awaited.\n * @param listener - receives the owner whose visible set changed, or\n * `undefined` when an unowned job changed and every caller\'s set did.\n * @returns disposer that unregisters the listener.\n */', + description: '/** Register an effect-scoped observer of visible-set changes. It fires after every commit that changes what list returns for that owner — registration, every stopping transition (including the one teardown performs before it awaits a slow producer), settlement, owner-disposal removal, and the emptying that service disposal commits — so an observer re-reads rather than accumulating deltas.\n\nDelivery is owner-relative on the same terms as onJobDone: an observer registered from an unscoped context — a host composition\'s own carrier — sees every owner, while one registered under an agent composition\'s scope sees exactly the agents composed under it.\n\nThis is not a superset of onJobDone: that one delivers the terminal record under first-wins semantics a job controller couples to notice delivery, while this one carries no delivery meaning and marks nothing reported. Listeners are contained and never awaited.', + parameters: [{ name: 'listener', description: 'receives the owner whose visible set changed, or `undefined` when an unowned job changed and every caller\'s set did.' }], + returns: 'disposer that unregisters the listener.', }, { signature: 'abstract attachController(name: string): () => void', - jsDoc: '/**\n * Attach an effect-scoped controller that can read and stop jobs. It serves the\n * owners its registering context\'s scope covers, and {@link start} refuses an\n * owner no attached controller serves.\n * @param name - diagnostic label; duplicate names remain independent.\n * @returns disposer that detaches this controller.\n */', + description: 'Attach an effect-scoped controller that can read and stop jobs. It serves the owners its registering context\'s scope covers, and start refuses an owner no attached controller serves.', + parameters: [{ name: 'name', description: 'diagnostic label; duplicate names remain independent.' }], + returns: 'disposer that detaches this controller.', }, ], }, { key: 'llm', summary: 'The abstract `llm` service: an adapter registry plus a streaming model-call API, interceptable via the `llm/stream` waterfall.', + description: 'The abstract `llm` service: an adapter registry plus a streaming model-call API, interceptable via the `llm/stream` waterfall.', methods: [ { signature: 'registerAdapter(providers: string[], adapter: LlmAdapter): AdapterRegistrationHandle', - jsDoc: '/**\n * Register an adapter for the given provider routes. Throws `LlmError` with code\n * `DUPLICATE_ADAPTER` if any provider already has an adapter (all-or-nothing).\n * Disposed with the fiber.\n * @param providers - every provider route this adapter should serve.\n * @param adapter - the adapter that streams calls for those providers.\n * @returns the disposer, carrying {@link AdapterRegistrationHandle.replace}.\n */', + description: 'Register an adapter for the given provider routes. Throws `LlmError` with code `DUPLICATE_ADAPTER` if any provider already has an adapter (all-or-nothing). Disposed with the fiber.', + parameters: [{ name: 'providers', description: 'every provider route this adapter should serve.' }, { name: 'adapter', description: 'the adapter that streams calls for those providers.' }], + returns: 'the disposer, carrying {@link AdapterRegistrationHandle.replace}.', }, { signature: 'listProviders(): LlmProviderInfo[]', - jsDoc: '/**\n * Describe provider routes with a registered adapter.\n * @returns detached provider metadata in registration order.\n */', + description: 'Describe provider routes with a registered adapter.', + parameters: [], + returns: 'detached provider metadata in registration order.', }, { signature: 'registerConfigurableProviders(entries: readonly LlmConfigurableProvider[]): DirectoryRegistrationHandle', - jsDoc: '/**\n * Declare provider routes an adapter plugin can activate through\n * configuration. Registration is all-or-nothing: an empty list, invalid\n * entry, or a provider already declared by any registration throws\n * `LlmError` without registering the rest. Disposed with the fiber.\n * @param entries - every configurable provider this plugin owns.\n * @returns a handle that withdraws all of them, and can atomically replace them.\n */', + description: 'Declare provider routes an adapter plugin can activate through configuration. Registration is all-or-nothing: an empty list, invalid entry, or a provider already declared by any registration throws `LlmError` without registering the rest. Disposed with the fiber.', + parameters: [{ name: 'entries', description: 'every configurable provider this plugin owns.' }], + returns: 'a handle that withdraws all of them, and can atomically replace them.', }, { signature: 'listConfigurableProviders(): LlmConfigurableProvider[]', - jsDoc: '/**\n * List every declared configurable provider, registered or dormant.\n * @returns detached directory entries in declaration order.\n */', + description: 'List every declared configurable provider, registered or dormant.', + parameters: [], + returns: 'detached directory entries in declaration order.', }, { signature: 'registerModelDiscovery( settingsNs: string, discover: (request: LlmModelDiscoveryRequest) => Promise, ): () => void', - jsDoc: '/**\n * Offer to interrogate provider endpoints on behalf of the settings\n * namespace this plugin owns. The namespace is the key because that is what\n * a configuration surface already holds from the configurable-provider\n * directory, and because a provider being *added* has no route to name yet.\n * Disposed with the fiber.\n * @param settingsNs - the namespace whose profiles this discovery serves.\n * @param discover - interrogates one endpoint; must honor `request.signal`.\n * @returns the disposer that withdraws the offer.\n */', + description: 'Offer to interrogate provider endpoints on behalf of the settings namespace this plugin owns. The namespace is the key because that is what a configuration surface already holds from the configurable-provider directory, and because a provider being *added* has no route to name yet. Disposed with the fiber.', + parameters: [{ name: 'settingsNs', description: 'the namespace whose profiles this discovery serves.' }, { name: 'discover', description: 'interrogates one endpoint; must honor `request.signal`.' }], + returns: 'the disposer that withdraws the offer.', }, { signature: 'async discoverModels( settingsNs: string, request: LlmModelDiscoveryRequest, ): Promise', - jsDoc: '/**\n * Interrogate one provider endpoint for the models it advertises. The\n * request describes a draft, not a stored route, so nothing here reads or\n * writes settings or credentials — the caller owns both, and the reply is\n * candidate metadata a surface may offer for adoption.\n * @param settingsNs - namespace whose registered discovery serves this draft.\n * @param request - the endpoint, protocol, and one-shot credential to use.\n * @returns the advertised models, deduplicated in endpoint order.\n */', + description: 'Interrogate one provider endpoint for the models it advertises. The request describes a draft, not a stored route, so nothing here reads or writes settings or credentials — the caller owns both, and the reply is candidate metadata a surface may offer for adoption.', + parameters: [{ name: 'settingsNs', description: 'namespace whose registered discovery serves this draft.' }, { name: 'request', description: 'the endpoint, protocol, and one-shot credential to use.' }], + returns: 'the advertised models, deduplicated in endpoint order.', }, { signature: 'providerRetryPolicy(provider: string): ResolvedRetryPolicy', - jsDoc: '/**\n * Resolve the retry policy captured when one provider route was registered.\n * @param provider - registered provider route to inspect.\n * @returns the provider-owned policy, with normal defaults already resolved.\n */', + description: 'Resolve the retry policy captured when one provider route was registered.', + parameters: [{ name: 'provider', description: 'registered provider route to inspect.' }], + returns: 'the provider-owned policy, with normal defaults already resolved.', }, { signature: 'async listModels(provider: string): Promise', - jsDoc: '/**\n * Discover models advertised by one registered provider. Catalog membership\n * is advisory and never changes routing or request validation.\n * @param provider - registered provider route to inspect.\n * @returns detached model metadata in adapter-preferred order.\n */', + description: 'Discover models advertised by one registered provider. Catalog membership is advisory and never changes routing or request validation.', + parameters: [{ name: 'provider', description: 'registered provider route to inspect.' }], + returns: 'detached model metadata in adapter-preferred order.', }, { signature: 'async resolveModelInfo( provider: string, model: string, signal?: AbortSignal, ): Promise', - jsDoc: '/**\n * Resolve and validate all metadata from the adapter that owns one exact\n * route. The result is detached from adapter-owned objects; catalog\n * membership remains advisory and does not control request routing.\n * @param provider - registered provider route to inspect.\n * @param model - exact model id passed to the adapter.\n * @param signal - optional cancellation for adapter-owned asynchronous lookup.\n * @returns exact model identity plus available context and reasoning metadata.\n */', + description: 'Resolve and validate all metadata from the adapter that owns one exact route. The result is detached from adapter-owned objects; catalog membership remains advisory and does not control request routing.', + parameters: [{ name: 'provider', description: 'registered provider route to inspect.' }, { name: 'model', description: 'exact model id passed to the adapter.' }, { name: 'signal', description: 'optional cancellation for adapter-owned asynchronous lookup.' }], + returns: 'exact model identity plus available context and reasoning metadata.', }, { signature: 'async resolveCallConfig(config: LlmCallConfig, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Validate a conversation call config against its exact model capability and\n * materialize adapter-configured defaults. Unsupported explicit efforts\n * reject before provider I/O; no clamping or aliasing is performed. This\n * standalone query does not bind a later dispatch; use {@link prepareCall}\n * when logging and streaming must share one adapter registration.\n * @param config - provider/model route and optional request controls.\n * @param signal - optional cancellation for adapter-owned capability lookup.\n * @returns a detached config only when a default must be materialized.\n */', + description: 'Validate a conversation call config against its exact model capability and materialize adapter-configured defaults. Unsupported explicit efforts reject before provider I/O; no clamping or aliasing is performed. This standalone query does not bind a later dispatch; use prepareCall when logging and streaming must share one adapter registration.', + parameters: [{ name: 'config', description: 'provider/model route and optional request controls.' }, { name: 'signal', description: 'optional cancellation for adapter-owned capability lookup.' }], + returns: 'a detached config only when a default must be materialized.', }, { signature: 'async prepareCall(config: LlmCallConfig, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Resolve one call under its current adapter registration. The returned\n * one-shot handle keeps that registration across header logging and dispatch,\n * so HMR cannot combine one adapter\'s capability result with another adapter.\n * @param config - provider/model route and optional request controls.\n * @param signal - optional cancellation for adapter-owned capability lookup.\n * @returns a prepared config and its registration-bound stream entry point.\n */', + description: 'Resolve one call under its current adapter registration. The returned one-shot handle keeps that registration across header logging and dispatch, so HMR cannot combine one adapter\'s capability result with another adapter.', + parameters: [{ name: 'config', description: 'provider/model route and optional request controls.' }, { name: 'signal', description: 'optional cancellation for adapter-owned capability lookup.' }], + returns: 'a prepared config and its registration-bound stream entry point.', }, { signature: 'stream(options: GenerateOptions): AsyncIterable', - jsDoc: '/**\n * Stream one model call as raw chunks (token-level deltas). Replay state is\n * retained only when the same adapter instance owns its historical provider\n * and the target provider. Final adapter selection remains fixed through\n * asynchronous exact-model resolution and dispatch. Adapter selection,\n * dispatch, and iteration failures become terminal `error` or `aborted`\n * finish chunks; middleware, nested-call, cleanup, and consumer failures\n * remain thrown.\n * @param options - the full request; `options.provider` selects the adapter.\n * @returns the chunk stream, possibly wrapped by `llm/stream` listeners.\n */', + description: 'Stream one model call as raw chunks (token-level deltas). Replay state is retained only when the same adapter instance owns its historical provider and the target provider. Final adapter selection remains fixed through asynchronous exact-model resolution and dispatch. Adapter selection, dispatch, and iteration failures become terminal `error` or `aborted` finish chunks; middleware, nested-call, cleanup, and consumer failures remain thrown.', + parameters: [{ name: 'options', description: 'the full request; `options.provider` selects the adapter.' }], + returns: 'the chunk stream, possibly wrapped by `llm/stream` listeners.', + }, + ], + }, + { + key: 'lsp', + summary: 'The LSP capability seam (`ctx.lsp`).', + description: 'The LSP capability seam (`ctx.lsp`). Owns provider registration/selection and normalized query execution; exposes exactly the four operations and no protocol escape hatch.', + methods: [ + { + signature: 'registerProvider(provider: LspProvider): () => void', + description: 'Register a provider, atomically reserving its id and every normalized extension. Any conflict or invalid input publishes nothing and throws `LspError`; the returned disposer releases all reservations. Disposed with the calling fiber.', + parameters: [{ name: 'provider', description: 'the backend to register.' }], + returns: 'a synchronous disposer releasing the id and all extension reservations.', + }, + { + signature: 'query(request: LspQueryRequest, signal?: AbortSignal): Promise', + description: 'Select a provider by the file\'s extension and run one query. Selection is per-query and order-independent; no match throws `LspError` `LSP_UNAVAILABLE`.', + parameters: [{ name: 'request', description: 'the normalized query.' }, { name: 'signal', description: 'optional cancellation forwarded to the selected provider.' }], + returns: 'the normalized, closed-union result.', }, ], }, { key: 'messageFeedback', summary: 'Storage-domain sidecar service.', + description: 'Storage-domain sidecar service. It inspects persisted Session history and never creates or resumes an Agent or Session.', methods: [ { signature: '@Remote(\'list\') async list(request: MessageFeedbackListRequest): Promise', - jsDoc: '/**\n * Read feedback belonging to the current persisted Session lifecycle.\n * A stale row from a reused Session id is invisible.\n * @param request - Session identity to inspect and list.\n * @returns current immutable items or `session-not-found`.\n */', + description: 'Read feedback belonging to the current persisted Session lifecycle. A stale row from a reused Session id is invisible.', + parameters: [{ name: 'request', description: 'Session identity to inspect and list.' }], + returns: 'current immutable items or `session-not-found`.', }, { signature: '@Remote(\'put\') put(request: MessageFeedbackPutRequest): Promise', - jsDoc: '/**\n * Create or replace feedback for one derived append-origin assistant\n * message. Every request must match the addressed item\'s current version;\n * a matching no-op returns the stored item without changing its revision.\n * @param request - target, desired value, and observed item version.\n * @returns the committed item or an explicit business failure.\n */', + description: 'Create or replace feedback for one derived append-origin assistant message. Every request must match the addressed item\'s current version; a matching no-op returns the stored item without changing its revision.', + parameters: [{ name: 'request', description: 'target, desired value, and observed item version.' }], + returns: 'the committed item or an explicit business failure.', }, { signature: '@Remote(\'delete\') delete(request: MessageFeedbackDeleteRequest): Promise', - jsDoc: '/**\n * Delete one feedback item. Absence is successful regardless of the\n * supplied version; an existing item requires an exact version match.\n * @param request - Session, message, and observed item version.\n * @returns the stable absent postcondition, or an explicit failure.\n */', + description: 'Delete one feedback item. Absence is successful regardless of the supplied version; an existing item requires an exact version match.', + parameters: [{ name: 'request', description: 'Session, message, and observed item version.' }], + returns: 'the stable absent postcondition, or an explicit failure.', }, ], }, { key: 'permissionPresets', summary: 'Owns the deployment\'s permission presets and their write path.', + description: 'Owns the deployment\'s permission presets and their write path. Requires a confining `ctx.shell` executor and `ctx.approval`; unmatched knob values are reported as CUSTOM_PRESET, not an error.', methods: [ { 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 */', + description: 'Resolve the preset matching the effective knob values. A still-matching last selection wins shared-bundle ties; otherwise the first table match wins, or CUSTOM_PRESET when no entry matches.', + parameters: [{ name: 'events', description: 'the session\'s events in log order.' }], + returns: 'the effective preset name, or `custom` when nothing matches.', }, { 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 */', + description: 'Build the whole select value for one folded knob state: every table option in declaration order, `custom` appended exactly while derived.', + parameters: [{ name: 'state', description: 'the folded knob overrides.' }], + returns: 'the `permissions` projection payload.', }, { 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 */', + description: 'Resolve a preset\'s knob bundle.', + parameters: [{ name: 'name', description: 'the preset name to resolve.' }], + returns: 'the configured bundle.', + throws: ['when `name` is not in the table.'], }, { signature: 'optionOf(name: string): PresetOption', - jsDoc: '/**\n * Build the client option for a table entry or {@link CUSTOM_PRESET}. A\n * missing label falls back to the table key.\n * @param name - a table key, or `custom`.\n * @returns the option a client renders.\n * @throws when `name` is neither a table key nor `custom`.\n */', + description: 'Build the client option for a table entry or CUSTOM_PRESET. A missing label falls back to the table key.', + parameters: [{ name: 'name', description: 'a table key, or `custom`.' }], + returns: 'the option a client renders.', + throws: ['when `name` is neither a table key nor `custom`.'], }, { signature: 'set(session: Session, name: string): void', - jsDoc: '/**\n * Record a changed preset, then update each changed knob through its own\n * setter. Selecting the effective preset again appends nothing.\n * @param session - the session the switch belongs to.\n * @param name - the preset to switch to; unknown names throw.\n */', + description: 'Record a changed preset, then update each changed knob through its own setter. Selecting the effective preset again appends nothing.', + parameters: [{ name: 'session', description: 'the session the switch belongs to.' }, { name: 'name', description: 'the preset to switch to; unknown names throw.' }], }, ], }, { key: 'planMode', summary: '`ctx.planMode`: owns logged plan state, applies and narrates selected state at step start, the `plan:policy` section, the `/plan` command, and the stable exit tool.', + description: '`ctx.planMode`: owns logged plan state, applies and narrates selected state at step start, the `plan:policy` section, the `/plan` command, and the stable exit tool. UIs observe committed flips through `session/event`; there is no live mirror.', methods: [ { signature: 'get(agent: Agent): { active: boolean; pending?: boolean }', - jsDoc: '/**\n * Read the logged plan state and any selected state awaiting the next\n * accepted in-turn pre-step.\n *\n * @param agent The agent to read.\n * @returns Current logged state plus a pending selection, when present.\n */', + description: 'Read the logged plan state and any selected state awaiting the next accepted in-turn pre-step.', + parameters: [{ name: 'agent', description: 'The agent to read.' }], + returns: 'Current logged state plus a pending selection, when present.', }, { signature: 'set(agent: Agent, active: boolean): \'committed\' | \'queued\' | \'cancelled\' | \'noop\'', - jsDoc: '/**\n * Select whether plan mode should be active. Between turns the method\n * appends the change immediately because no in-turn pre-step will run until\n * another prompt starts a turn. The open-turn fold is the idle signal:\n * agent status stays `running` through post-turn checkpointing, when no\n * further in-turn pre-step runs. During an open turn the selection remains\n * pending until the next accepted in-turn pre-step. Repeated selection of\n * the current or already-pending state is a no-op.\n *\n * @param agent The agent to switch.\n * @param active Whether plan mode should be active.\n * @returns what happened: `committed` (logged now), `queued` (awaiting the\n * next accepted in-turn pre-step), `cancelled` (an opposite pending selection\n * was cleared; the logged state already matches), or `noop` (already in that\n * state).\n */', + description: 'Select whether plan mode should be active. Between turns the method appends the change immediately because no in-turn pre-step will run until another prompt starts a turn. The open-turn fold is the idle signal: agent status stays `running` through post-turn checkpointing, when no further in-turn pre-step runs. During an open turn the selection remains pending until the next accepted in-turn pre-step. Repeated selection of the current or already-pending state is a no-op.', + parameters: [{ name: 'agent', description: 'The agent to switch.' }, { name: 'active', description: 'Whether plan mode should be active.' }], + returns: 'what happened: `committed` (logged now), `queued` (awaiting the next accepted in-turn pre-step), `cancelled` (an opposite pending selection was cleared; the logged state already matches), or `noop` (already in that state).', }, ], }, { key: 'sandbox', summary: 'Abstract process-sandbox service.', + description: 'Abstract process-sandbox service. confine must return enforcing argv or fail closed at wrap or runner-execution time; silent unconfined passthrough is forbidden. Functional probes arbitrate multi-runner chains and may be skipped for a sole candidate, whose own refusal remains the fail-closed end.', methods: [ { signature: 'abstract confine(argv: readonly string[], policy: SandboxPolicy): ConfinedArgv', - jsDoc: '/**\n * Wrap `argv` so it executes confined under `policy` on this host; the\n * caller spawns the returned argv in place of its own.\n * @param argv - the exact argv the caller is about to spawn (program plus\n * arguments), NOT a shell string — a shell-shaped consumer passes\n * `[\'bash\', \'-c\', command]`.\n * @param policy - the file-effect policy this execution runs under,\n * carried per call (see {@link SandboxPolicy}).\n * @returns the argv to spawn instead, plus the enforcement completeness\n * the selected backend achieves for it.\n */', + description: 'Wrap `argv` so it executes confined under `policy` on this host; the caller spawns the returned argv in place of its own.', + parameters: [{ name: 'argv', description: 'the exact argv the caller is about to spawn (program plus arguments), NOT a shell string — a shell-shaped consumer passes `[\'bash\', \'-c\', command]`.' }, { name: 'policy', description: 'the file-effect policy this execution runs under, carried per call (see {@link SandboxPolicy}).' }], + returns: 'the argv to spawn instead, plus the enforcement completeness the selected backend achieves for it.', }, ], }, { key: 'sandboxPolicy', summary: 'The sandbox-policy service (`ctx.sandboxPolicy`).', + description: 'The sandbox-policy service (`ctx.sandboxPolicy`). Owns the deployment default mode, fallback workspace root, and current request-time policy section. Tool layers call resolve for each execution so a session\'s mode log and immutable cwd travel together to every enforcing capability.', methods: [ + { + signature: 'readonly defaultMode: SandboxMode', + description: 'The deployment default mode — the fallback beneath a session override.', + parameters: [], + }, + { + signature: 'readonly workspaceRoot: string', + description: 'The absolute `workspace-write` fallback root for calls without a session cwd.', + parameters: [], + }, { signature: 'resolve(request: SandboxPolicyRequest = {}): SandboxExecutionPolicy', - jsDoc: '/**\n * Resolve the complete policy for one capability call. An approved explicit\n * mode outranks the session\'s last `sandbox/mode` event, which outranks the\n * deployment default. A session cwd is its workspace-write boundary; the\n * configured root is the fallback for agentless calls and sessions without a\n * cwd.\n * @param request - optional session and approved mode override.\n * @returns the fully resolved per-call mode and absolute workspace root.\n */', + description: 'Resolve the complete policy for one capability call. An approved explicit mode outranks the session\'s last `sandbox/mode` event, which outranks the deployment default. A session cwd is its workspace-write boundary; the configured root is the fallback for agentless calls and sessions without a cwd.', + parameters: [{ name: 'request', description: 'optional session and approved mode override.' }], + returns: 'the fully resolved per-call mode and absolute workspace root.', }, { signature: 'overrideOf(session: Session): SandboxMode | undefined', - jsDoc: '/**\n * Read the session override without applying the deployment default.\n * @param session - session whose log supplies the override.\n * @returns the last logged mode, or `undefined` without one.\n */', + description: 'Read the session override without applying the deployment default.', + parameters: [{ name: 'session', description: 'session whose log supplies the override.' }], + returns: 'the last logged mode, or `undefined` without one.', }, ], }, { key: 'sessionPersistence', summary: 'Durable append-only session storage.', + description: 'Durable append-only session storage. Implementations preserve contiguous, losslessly JSON-serializable events; append resolves only after durability, and load balances a complete interrupted tail without rewriting committed events.', methods: [ { signature: 'abstract locate(meta: SessionHeader): SessionLocation | undefined', - jsDoc: '/**\n * Resolve this backend\'s independent local artifact for a session without\n * reading, creating, flushing, or otherwise materializing it. Backends such\n * as SQLite that do not own one artifact per session return `undefined`.\n * @param meta - the immutable session header whose artifact is requested.\n * @returns the backend-specific absolute location, when one exists.\n */', + description: 'Resolve this backend\'s independent local artifact for a session without reading, creating, flushing, or otherwise materializing it. Backends such as SQLite that do not own one artifact per session return `undefined`.', + parameters: [{ name: 'meta', description: 'the immutable session header whose artifact is requested.' }], + returns: 'the backend-specific absolute location, when one exists.', + }, + { + signature: 'abstract readonly supportsRawArtifacts: boolean', + description: 'Whether this backend exposes one verbatim raw artifact per session. A backend that declares `true` must override readRaw.', + parameters: [], }, { signature: 'readRaw(_id: SessionId, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Read a session\'s backend-owned artifact text verbatim — the exact durable\n * bytes the backend wrote (decoded from its physical encoding, e.g. a\n * decompressed JSONL). The returned `content` is the raw text, not a\n * reconstruction from parsed events, so it preserves backend-specific\n * serialization (chunk packing, key order, line breaks). Callers first test\n * {@link supportsRawArtifacts}; `undefined` then means only that the requested\n * session has no materialized artifact.\n * @param _id - the persisted session to read (unused by the default: no\n * per-session artifact).\n * @param signal - optional cancellation for backend read work.\n * @returns the raw artifact plus its parsed header, or `undefined` when the\n * session is absent.\n * @throws when this backend does not expose per-session raw artifacts.\n */', + description: 'Read a session\'s backend-owned artifact text verbatim — the exact durable bytes the backend wrote (decoded from its physical encoding, e.g. a decompressed JSONL). The returned `content` is the raw text, not a reconstruction from parsed events, so it preserves backend-specific serialization (chunk packing, key order, line breaks). Callers first test supportsRawArtifacts; `undefined` then means only that the requested session has no materialized artifact.', + parameters: [{ name: '_id', description: 'the persisted session to read (unused by the default: no per-session artifact).' }, { name: 'signal', description: 'optional cancellation for backend read work.' }], + returns: 'the raw artifact plus its parsed header, or `undefined` when the session is absent.', + throws: ['when this backend does not expose per-session raw artifacts.'], }, { signature: 'abstract create(meta: SessionHeader): Promise', - jsDoc: '/**\n * Register a new session\'s metadata. A backend MAY defer the physical write\n * until the first {@link append} (lazy materialization), in which case a\n * created-but-never-appended session is absent from {@link list}\n * — abandoned sessions leave nothing behind.\n * @param meta - the immutable header (id, version, cwd, lineage) to record.\n */', + description: 'Register a new session\'s metadata. A backend MAY defer the physical write until the first append (lazy materialization), in which case a created-but-never-appended session is absent from list — abandoned sessions leave nothing behind.', + parameters: [{ name: 'meta', description: 'the immutable header (id, version, cwd, lineage) to record.' }], }, { signature: 'abstract append(id: SessionId, events: readonly SessionEvent[]): Promise', - jsDoc: '/**\n * Durably persist a batch of events. Honors the append-only and contiguous-\n * seq contracts: the first event\'s `seq` MUST equal the stored next-seq\n * (after `load` has durably closed any interrupted turn). Rejects non-JSON-\n * serializable `event.data` with an error naming the offending event type.\n * @param id - the session the batch belongs to.\n * @param events - the contiguous batch to persist, in seq order.\n */', + description: 'Durably persist a batch of events. Honors the append-only and contiguous- seq contracts: the first event\'s `seq` MUST equal the stored next-seq (after `load` has durably closed any interrupted turn). Rejects non-JSON- serializable `event.data` with an error naming the offending event type.', + parameters: [{ name: 'id', description: 'the session the batch belongs to.' }, { name: 'events', description: 'the contiguous batch to persist, in seq order.' }], }, { signature: 'async prepare(id: SessionId, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Prepare the exact unpublished Session used by resume. Implementations may\n * reuse object graphs retained by an earlier {@link inspect} after confirming\n * their durable revision is still current; disposal releases an unpublished\n * reservation. Revision retries require the durable log to remain unchanged\n * for one read/check round trip; continuous external writers may delay completion.\n * @param id - persisted session to prepare.\n * @param signal - optional cancellation for preparation work.\n * @returns one owned unpublished Session preparation.\n */', + description: 'Prepare the exact unpublished Session used by resume. Implementations may reuse object graphs retained by an earlier inspect after confirming their durable revision is still current; disposal releases an unpublished reservation. Revision retries require the durable log to remain unchanged for one read/check round trip; continuous external writers may delay completion.', + parameters: [{ name: 'id', description: 'persisted session to prepare.' }, { name: 'signal', description: 'optional cancellation for preparation work.' }], + returns: 'one owned unpublished Session preparation.', }, { signature: 'abstract load(id: SessionId): Promise', - jsDoc: '/**\n * Load an immutable balanced logical view and commit any required cold\n * recovery. A complete interrupted final turn is preserved and durably\n * closed with missing tool errors plus any open step and turn boundaries;\n * only a torn final record is discarded. Unknown versions and corruption in\n * the committed prefix reject. Implementations MUST NOT crash-repair an\n * identity still bound to a live Session: a balanced live log may return as a\n * durable snapshot, while an open live turn rejects. Returned values may be\n * shared with immutable live or prepared state and must not be mutated.\n * Revision-based implementations may wait for one stable read/check round trip.\n * @param id - the persisted session to reload.\n * @returns the header and a log ending on a balanced `turn/end`.\n */', + description: 'Load an immutable balanced logical view and commit any required cold recovery. A complete interrupted final turn is preserved and durably closed with missing tool errors plus any open step and turn boundaries; only a torn final record is discarded. Unknown versions and corruption in the committed prefix reject. Implementations MUST NOT crash-repair an identity still bound to a live Session: a balanced live log may return as a durable snapshot, while an open live turn rejects. Returned values may be shared with immutable live or prepared state and must not be mutated. Revision-based implementations may wait for one stable read/check round trip.', + parameters: [{ name: 'id', description: 'the persisted session to reload.' }], + returns: 'the header and a log ending on a balanced `turn/end`.', }, { signature: 'abstract inspect(id: SessionId, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Inspect an immutable logical session without committing recovery or\n * publishing it. A cold complete interrupted turn receives synthetic closers\n * in memory and a torn physical tail remains untouched. An already-live\n * Session instead yields its current immutable snapshot, which may contain an\n * open turn and its `session/end-seed` boundary. Coordinator-backed\n * implementations retain the exact cold unpublished Session for bounded\n * reuse by a later {@link prepare}. A stale ready source is reloaded; a source\n * already committing or reserved for resume remains exclusive, and inspection\n * may borrow its immutable view. Callers borrow only the immutable header and\n * log. Continuous external writers may delay revision convergence.\n * @param id - the persisted session to inspect.\n * @param signal - optional cancellation for queued and backend read work.\n * @returns the validated header and current logical event log.\n */', + description: 'Inspect an immutable logical session without committing recovery or publishing it. A cold complete interrupted turn receives synthetic closers in memory and a torn physical tail remains untouched. An already-live Session instead yields its current immutable snapshot, which may contain an open turn and its `session/end-seed` boundary. Coordinator-backed implementations retain the exact cold unpublished Session for bounded reuse by a later prepare. A stale ready source is reloaded; a source already committing or reserved for resume remains exclusive, and inspection may borrow its immutable view. Callers borrow only the immutable header and log. Continuous external writers may delay revision convergence.', + parameters: [{ name: 'id', description: 'the persisted session to inspect.' }, { name: 'signal', description: 'optional cancellation for queued and backend read work.' }], + returns: 'the validated header and current logical event log.', }, { signature: 'abstract readFrom(id: SessionId, fromSeq: number, signal?: AbortSignal): Promise<{ meta: SessionHeader; events: SessionEvent[] }>', - jsDoc: '/**\n * Read the stored events from `fromSeq` onward — the read-from-seq\n * primitive for read models that resume from a watermark (e.g. a persisted\n * projection cache folding only the tail past its checkpoint). Unlike\n * {@link inspect}, it is a detached physical suffix read: no preparation\n * cache, torn-tail truncation, synthetic closers, or coordinator-state\n * publication. Only events from the valid contiguous stored prefix are\n * returned, so a torn fragment never reaches the caller. `fromSeq` at or\n * beyond the stored prefix returns an empty event list (never an error).\n * Backends whose medium can seek by seq\n * (SQLite) read only the suffix; sequential media (JSONL, both encodings)\n * still parse the whole artifact and skip forward — the primitive bounds\n * what is RETURNED and refolded, not every backend\'s physical read.\n * @param id - the persisted session to read.\n * @param fromSeq - first event seq to include; a non-negative safe integer.\n * @param signal - optional cancellation for queued and backend read work.\n * @returns the header and the stored events with `seq >= fromSeq`.\n */', + description: 'Read the stored events from `fromSeq` onward — the read-from-seq primitive for read models that resume from a watermark (e.g. a persisted projection cache folding only the tail past its checkpoint). Unlike inspect, it is a detached physical suffix read: no preparation cache, torn-tail truncation, synthetic closers, or coordinator-state publication. Only events from the valid contiguous stored prefix are returned, so a torn fragment never reaches the caller. `fromSeq` at or beyond the stored prefix returns an empty event list (never an error). Backends whose medium can seek by seq (SQLite) read only the suffix; sequential media (JSONL, both encodings) still parse the whole artifact and skip forward — the primitive bounds what is RETURNED and refolded, not every backend\'s physical read.', + parameters: [{ name: 'id', description: 'the persisted session to read.' }, { name: 'fromSeq', description: 'first event seq to include; a non-negative safe integer.' }, { name: 'signal', description: 'optional cancellation for queued and backend read work.' }], + returns: 'the header and the stored events with `seq >= fromSeq`.', }, { signature: 'abstract list(signal?: AbortSignal): Promise', - jsDoc: '/**\n * Lightweight listing from metadata, without a full-log parse.\n * @param signal - optional cancellation for backend listing work.\n * @returns one header per materialized session.\n */', + description: 'Lightweight listing from metadata, without a full-log parse.', + parameters: [{ name: 'signal', description: 'optional cancellation for backend listing work.' }], + returns: 'one header per materialized session.', }, { signature: 'abstract listSnapshots(signal?: AbortSignal): Promise', - jsDoc: '/**\n * List materialized sessions with cheap per-log change tokens.\n *\n * Repeated observations of an unchanged log return the same revision. A\n * successful mutating {@link load} repair changes the next listed revision.\n * Revisions also distinguish independently backed stores so backend-local\n * counters cannot compare equal across different persistence sources.\n * @param signal - optional cancellation for backend snapshot-listing work.\n * @returns one header and opaque revision per materialized session without loading full logs.\n */', + description: 'List materialized sessions with cheap per-log change tokens.\n\nRepeated observations of an unchanged log return the same revision. A successful mutating load repair changes the next listed revision. Revisions also distinguish independently backed stores so backend-local counters cannot compare equal across different persistence sources.', + parameters: [{ name: 'signal', description: 'optional cancellation for backend snapshot-listing work.' }], + returns: 'one header and opaque revision per materialized session without loading full logs.', }, ], }, { key: 'sessionProjectionCache', summary: 'The persisted projection cache service.', + description: 'The persisted projection cache service. Opens the `session_projcache` domain at init, checkpoints live sessions on a throttled write-behind (count/interval triggers from Config) plus two mandatory points — `turn/end` and session disposal (the live-to-cold moment) — and serves the cold-read ladder: cached row, persistence `readFrom` tail, registry `restore`, durable write-back. Every durable write is fail-soft: failures log a warning and the cache self-heals on the next write or cold read.', methods: [ { signature: 'cachedSnapshot(meta: SessionHeader): ProjectionSnapshot | undefined', - jsDoc: '/**\n * The zero-I/O listing read: whole values viewed straight from the stored\n * rows (version-matching keys only), each cut carried with its watermark\n * so a client value store can seed under its higher-seq-wins rule — as\n * stale as the last durable checkpoint but never wrong, and never from an\n * unrelated log (the caller\'s header is the identity witness). Fresher\n * paths (the history tail baseline, {@link coldSnapshot}) supersede these\n * values whenever a session is actually opened.\n * @param meta - the listed session\'s header (identity witness; no log read).\n * @returns the cut (`asOfSeq` = lowest served-row watermark), or\n * `undefined` when no usable row exists for this lifecycle.\n */', + description: 'The zero-I/O listing read: whole values viewed straight from the stored rows (version-matching keys only), each cut carried with its watermark so a client value store can seed under its higher-seq-wins rule — as stale as the last durable checkpoint but never wrong, and never from an unrelated log (the caller\'s header is the identity witness). Fresher paths (the history tail baseline, coldSnapshot) supersede these values whenever a session is actually opened.', + parameters: [{ name: 'meta', description: 'the listed session\'s header (identity witness; no log read).' }], + returns: 'the cut (`asOfSeq` = lowest served-row watermark), or `undefined` when no usable row exists for this lifecycle.', }, { signature: 'async write(session: Session): Promise', - jsDoc: '/**\n * Durably checkpoint one live session NOW (both mandatory points call\n * this; tests and carriers may too). The registry cut is snapshotted at\n * this boundary (states are live references), then the whole record is\n * replaced. NOT fail-soft — callers on the fail-soft paths contain it.\n * @param session - the live session to checkpoint.\n * @returns resolution after durability and event emission.\n */', + description: 'Durably checkpoint one live session NOW (both mandatory points call this; tests and carriers may too). The registry cut is snapshotted at this boundary (states are live references), then the whole record is replaced. NOT fail-soft — callers on the fail-soft paths contain it.', + parameters: [{ name: 'session', description: 'the live session to checkpoint.' }], + returns: 'resolution after durability and event emission.', }, { signature: 'async coldSnapshot(id: SessionId, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Cold-read one persisted session\'s projections with zero full-log load:\n * cached rows + a persistence `readFrom` tail from the registry\'s restore\n * floor, refolded by the registry and written back (fail-soft) so the next\n * cold read starts closer. A cache row invalidated by a shrunk log\n * (crash-repair truncation) triggers one full re-read from seq 0 — the\n * ladder\'s slow rung, still no crash. Rejects when the session has no\n * persisted log (`not found` from the persistence seam).\n * @param id - the persisted session to read.\n * @param signal - optional cancellation for the persistence reads.\n * @returns the snapshot cut at the stored log end.\n */', + description: 'Cold-read one persisted session\'s projections with zero full-log load: cached rows + a persistence `readFrom` tail from the registry\'s restore floor, refolded by the registry and written back (fail-soft) so the next cold read starts closer. A cache row invalidated by a shrunk log (crash-repair truncation) triggers one full re-read from seq 0 — the ladder\'s slow rung, still no crash. Rejects when the session has no persisted log (`not found` from the persistence seam).', + parameters: [{ name: 'id', description: 'the persisted session to read.' }, { name: 'signal', description: 'optional cancellation for the persistence reads.' }], + returns: 'the snapshot cut at the stored log end.', }, ], }, { key: 'sessionProjections', summary: '`ctx.sessionProjections`: the projection unit table and its drive.', + description: '`ctx.sessionProjections`: the projection unit table and its drive. The service subscribes to `session/event` once; every committed event passes every registered unit\'s `apply` (eager drive), and a changed state reference notifies the change feed with the schema-validated view. Cells build lazily — a unit registered after events flowed, or a session older than the registry, folds `init` over the in-memory log on first touch (event or read). Registration is an effect (disposer rides the calling fiber): an unloaded domain plugin\'s key disappears from snapshots and clients read it as capability absence. Domain plugins register under `ctx.inject([\'sessionProjections\'], …)` so headless assemblies without the registry stay unaffected. Registrants sharing a key share one unit and are counted: the same tool package mounted in N agent presets registers N times, and the key survives until the last one unloads.', methods: [ { signature: 'register(definition: ProjectionDefinition): () => void', - jsDoc: '/**\n * Register one domain\'s unit. The registration is an effect on the calling\n * context\'s fiber: disposing the fiber (or calling the returned disposer)\n * removes the key — and the unit\'s cached cells — from subsequent drives\n * and snapshots.\n * @param definition - key, state schema, pure unit functions, and stateVersion.\n * @returns the exact disposer that unregisters this unit.\n */', + description: 'Register one domain\'s unit. The registration is an effect on the calling context\'s fiber: disposing the fiber (or calling the returned disposer) removes the key — and the unit\'s cached cells — from subsequent drives and snapshots.', + parameters: [{ name: 'definition', description: 'key, state schema, pure unit functions, and stateVersion.' }], + returns: 'the exact disposer that unregisters this unit.', }, { signature: 'onChanged(listener: ProjectionChangeListener): () => void', - jsDoc: '/**\n * Subscribe to the change feed. The registration is an effect on the\n * calling context\'s fiber.\n * @param listener - called once per unit whose state reference changed, per committed event.\n * @returns the exact disposer that unsubscribes.\n */', + description: 'Subscribe to the change feed. The registration is an effect on the calling context\'s fiber.', + parameters: [{ name: 'listener', description: 'called once per unit whose state reference changed, per committed event.' }], + returns: 'the exact disposer that unsubscribes.', }, { signature: 'snapshot(session: Session): ProjectionSnapshot', - jsDoc: '/**\n * One consistent cut over every registered unit for one session, read from\n * the watermark cache (missing cells fold lazily over the in-memory log).\n * Fully synchronous — every value and `asOfSeq` reflect the same log\n * position. Each value passes its unit\'s schema before leaving.\n * @param session - the session whose projection values are read.\n * @returns the snapshot; `values` is empty when no unit is registered.\n */', + description: 'One consistent cut over every registered unit for one session, read from the watermark cache (missing cells fold lazily over the in-memory log). Fully synchronous — every value and `asOfSeq` reflect the same log position. Each value passes its unit\'s schema before leaving.', + parameters: [{ name: 'session', description: 'the session whose projection values are read.' }], + returns: 'the snapshot; `values` is empty when no unit is registered.', }, { signature: 'checkpoint(session: Session): ProjectionCheckpoint', - jsDoc: '/**\n * State-level checkpoint of every registered unit for one session, read\n * from the watermark cache (missing cells fold lazily over the in-memory\n * log). This is the write side of the persisted projection cache: the\n * returned rows are the `(key → {ver, seq, val})` part of the durable\n * `(sessionId, key, ver, seq, val)`\n * rows. Every `val` is a DETACHED structured clone — never the live\n * cell reference: the watermark cache is this registry\'s authoritative\n * mutable state, and a caller reaching the live reference could corrupt\n * every subsequent snapshot and frame through it (plain JSON by the unit\n * contract, so the clone is total).\n * @param session - the session whose unit states are checkpointed.\n * @returns one row per registered key; empty when no unit is registered.\n */', + description: 'State-level checkpoint of every registered unit for one session, read from the watermark cache (missing cells fold lazily over the in-memory log). This is the write side of the persisted projection cache: the returned rows are the `(key → {ver, seq, val})` part of the durable `(sessionId, key, ver, seq, val)` rows. Every `val` is a DETACHED structured clone — never the live cell reference: the watermark cache is this registry\'s authoritative mutable state, and a caller reaching the live reference could corrupt every subsequent snapshot and frame through it (plain JSON by the unit contract, so the clone is total).', + parameters: [{ name: 'session', description: 'the session whose unit states are checkpointed.' }], + returns: 'one row per registered key; empty when no unit is registered.', }, { signature: 'restoreFloor(checkpoint: ProjectionCheckpoint): number | undefined', - jsDoc: '/**\n * The stored seq a {@link restore} tail read over `checkpoint` must start\n * at: one event BELOW the lowest usable watermark (a row is usable when\n * its `ver` matches the live unit\'s `stateVersion`; an absent or mismatched row\n * pulls the floor to `0` — that key must refold the full log). The\n * one-below anchor is load-bearing: the tail then proves how far the\n * stored log still extends, so {@link restore} can detect a log that\n * shrank below a row\'s watermark (crash-repair truncation) instead of\n * serving the stale row as current — an empty tail read from the anchor\n * yields an end below every watermark and the restore rejects for a full\n * re-read.\n * @param checkpoint - persisted rows for one session (possibly stale or empty).\n * @returns the seq to hand the persistence `readFrom`, or `undefined`\n * when no unit is registered (no read needed — {@link restore} would\n * serve empty values regardless).\n */', + description: 'The stored seq a restore tail read over `checkpoint` must start at: one event BELOW the lowest usable watermark (a row is usable when its `ver` matches the live unit\'s `stateVersion`; an absent or mismatched row pulls the floor to `0` — that key must refold the full log). The one-below anchor is load-bearing: the tail then proves how far the stored log still extends, so restore can detect a log that shrank below a row\'s watermark (crash-repair truncation) instead of serving the stale row as current — an empty tail read from the anchor yields an end below every watermark and the restore rejects for a full re-read.', + parameters: [{ name: 'checkpoint', description: 'persisted rows for one session (possibly stale or empty).' }], + returns: 'the seq to hand the persistence `readFrom`, or `undefined` when no unit is registered (no read needed — {@link restore} would serve empty values regardless).', }, { signature: 'viewCheckpoint(checkpoint: ProjectionCheckpoint): Partial', - jsDoc: '/**\n * View a checkpoint\'s rows without any log read: for every registered\n * unit whose row\'s `ver` matches, serve the schema-validated\n * `view` of the stored state; mismatched or absent rows leave their key\n * absent (a cold or listing consumer treats it as not-yet-available and a\n * fuller read path refolds it). The zero-I/O rung of the read ladder —\n * values are as stale as their rows, never wrong.\n * @param checkpoint - persisted rows for one session (possibly stale or empty).\n * @returns whole values per key with a usable row; empty when none.\n */', + description: 'View a checkpoint\'s rows without any log read: for every registered unit whose row\'s `ver` matches, serve the schema-validated `view` of the stored state; mismatched or absent rows leave their key absent (a cold or listing consumer treats it as not-yet-available and a fuller read path refolds it). The zero-I/O rung of the read ladder — values are as stale as their rows, never wrong.', + parameters: [{ name: 'checkpoint', description: 'persisted rows for one session (possibly stale or empty).' }], + returns: 'whole values per key with a usable row; empty when none.', }, { signature: 'restore(checkpoint: ProjectionCheckpoint, events: readonly SessionEvent[], baseSeq: number): { snapshot: ProjectionSnapshot; checkpoint: ProjectionCheckpoint }', - jsDoc: '/**\n * Cold read: fold every registered unit over a stored log suffix, seeding\n * each from its checkpoint row when usable — the one read recipe (cached\n * state + forward tail replay + `view`) applied without a live `Session`.\n * Call with the events returned by a persistence\n * `readFrom(id, restoreFloor(checkpoint))` and that same floor as\n * `baseSeq`; the floor\'s one-below anchor makes the supplied end honest,\n * so a shrunk log is detected here. A row is usable iff its\n * `ver` matches the live unit\'s `stateVersion`, it does not predate `baseSeq`\n * (`seq >= baseSeq - 1`), and it does not claim events past the\n * supplied end (`seq <= endSeq`); an unusable row is discarded\n * and its key refolds from `init` — which is only sound over the full\n * log, so a discarded row with `baseSeq > 0` throws (the caller re-reads\n * from seq 0, e.g. after a crash-repair truncation shrank the log below\n * a row\'s watermark).\n * @param checkpoint - persisted rows for one session (possibly stale or empty).\n * @param events - the stored events with `seq >= baseSeq`, in seq order.\n * @param baseSeq - the seq `events` starts at (its first event\'s seq when non-empty).\n * @returns the snapshot cut at the supplied log end (`asOfSeq` is the last\n * supplied event\'s seq, `baseSeq - 1` for an empty tail) plus the\n * refreshed checkpoint rows at that cut, ready for a durable write-back.\n */', + description: 'Cold read: fold every registered unit over a stored log suffix, seeding each from its checkpoint row when usable — the one read recipe (cached state + forward tail replay + `view`) applied without a live `Session`. Call with the events returned by a persistence `readFrom(id, restoreFloor(checkpoint))` and that same floor as `baseSeq`; the floor\'s one-below anchor makes the supplied end honest, so a shrunk log is detected here. A row is usable iff its `ver` matches the live unit\'s `stateVersion`, it does not predate `baseSeq` (`seq >= baseSeq - 1`), and it does not claim events past the supplied end (`seq <= endSeq`); an unusable row is discarded and its key refolds from `init` — which is only sound over the full log, so a discarded row with `baseSeq > 0` throws (the caller re-reads from seq 0, e.g. after a crash-repair truncation shrank the log below a row\'s watermark).', + parameters: [{ name: 'checkpoint', description: 'persisted rows for one session (possibly stale or empty).' }, { name: 'events', description: 'the stored events with `seq >= baseSeq`, in seq order.' }, { name: 'baseSeq', description: 'the seq `events` starts at (its first event\'s seq when non-empty).' }], + returns: 'the snapshot cut at the supplied log end (`asOfSeq` is the last supplied event\'s seq, `baseSeq - 1` for an empty tail) plus the refreshed checkpoint rows at that cut, ready for a durable write-back.', }, ], }, { key: 'sessionQuery', summary: 'Unified live-preferred session query service.', + description: 'Unified live-preferred session query service.\n\nExact reads, filters, and traces are backend-independent concrete behavior. A backend implements full-text observation, reconciliation, ranking, cursor generations, and query execution on the same `ctx.sessionQuery` service.', methods: [ { signature: 'abstract searchSessions( request: SessionSearchRequest, exec?: SessionSearchExecContext, ): Promise>', - jsDoc: '/**\n * Search the live-preferred logical corpus and group by session.\n * @param request - query text, metadata filters, page size, and cursor.\n * @param exec - optional cancellation control.\n * @returns session hits ranked by their strongest matching event.\n */', + description: 'Search the live-preferred logical corpus and group by session.', + parameters: [{ name: 'request', description: 'query text, metadata filters, page size, and cursor.' }, { name: 'exec', description: 'optional cancellation control.' }], + returns: 'session hits ranked by their strongest matching event.', }, { signature: 'abstract searchEvents( request: SessionEventSearchRequest, exec?: SessionSearchExecContext, ): Promise', - jsDoc: '/**\n * Search events within one live-preferred logical session.\n * @param request - target session, query text, filters, page size, and cursor.\n * @param exec - optional cancellation control.\n * @returns matching event hits and their target header from one indexed generation.\n */', + description: 'Search events within one live-preferred logical session.', + parameters: [{ name: 'request', description: 'target session, query text, filters, page size, and cursor.' }, { name: 'exec', description: 'optional cancellation control.' }], + returns: 'matching event hits and their target header from one indexed generation.', }, { signature: 'listSessions(signal?: AbortSignal): Promise', - jsDoc: '/**\n * List the complete logical corpus using live-preferred records.\n * @param signal - optional cancellation for persistence listing.\n * @returns deterministic newest-first cloned session records.\n */', + description: 'List the complete logical corpus using live-preferred records.', + parameters: [{ name: 'signal', description: 'optional cancellation for persistence listing.' }], + returns: 'deterministic newest-first cloned session records.', }, { signature: 'async readSession(sessionId: SessionId): Promise', - jsDoc: '/**\n * Read and replay-validate one complete logical session log without making it live.\n * @param sessionId - live or persisted session id to read.\n * @returns cloned header and complete raw event log from one observation.\n * @throws when persistence, header compatibility, or replay validation fails.\n */', + description: 'Read and replay-validate one complete logical session log without making it live.', + parameters: [{ name: 'sessionId', description: 'live or persisted session id to read.' }], + returns: 'cloned header and complete raw event log from one observation.', + throws: ['when persistence, header compatibility, or replay validation fails.'], }, { signature: 'async filterSessions( filters: readonly SessionResultFilter[], signal?: AbortSignal, ): Promise', - jsDoc: '/**\n * Filter the complete logical corpus with provider-independent predicates.\n * @param filters - ANDed session metadata and availability clauses.\n * @param signal - optional cancellation for persistence listing.\n * @returns matching cloned records in deterministic newest-first order.\n */', + description: 'Filter the complete logical corpus with provider-independent predicates.', + parameters: [{ name: 'filters', description: 'ANDed session metadata and availability clauses.' }, { name: 'signal', description: 'optional cancellation for persistence listing.' }], + returns: 'matching cloned records in deterministic newest-first order.', }, { signature: 'async readTitle( sessionId: SessionId, signal?: AbortSignal, ): Promise', - jsDoc: '/**\n * Fold the latest log-backed title from one live-preferred logical session.\n * @param sessionId - live or persisted session id to read.\n * @param signal - optional cancellation for source resolution and title folding.\n * @returns latest title snapshot, or `undefined` when the log has no title event.\n */', + description: 'Fold the latest log-backed title from one live-preferred logical session.', + parameters: [{ name: 'sessionId', description: 'live or persisted session id to read.' }, { name: 'signal', description: 'optional cancellation for source resolution and title folding.' }], + returns: 'latest title snapshot, or `undefined` when the log has no title event.', }, { signature: 'async readTitleSnapshot( sessionId: SessionId, signal?: AbortSignal, ): Promise', - jsDoc: '/**\n * Fold the latest title and return its source header from one corpus observation.\n * @param sessionId - live or persisted session id to read.\n * @param signal - optional cancellation for source resolution and title folding.\n * @returns cloned source header and optional latest title snapshot.\n */', + description: 'Fold the latest title and return its source header from one corpus observation.', + parameters: [{ name: 'sessionId', description: 'live or persisted session id to read.' }, { name: 'signal', description: 'optional cancellation for source resolution and title folding.' }], + returns: 'cloned source header and optional latest title snapshot.', }, { signature: 'async readTitleSnapshots( sessionIds: readonly SessionId[], signal?: AbortSignal, ): Promise', - jsDoc: '/**\n * Fold titles for unique sessions from one cancellable corpus observation.\n *\n * Results preserve first-occurrence input order. Operational failures stay\n * isolated per session, while cancellation rejects the complete operation.\n * @param sessionIds - live or persisted session ids to observe.\n * @param signal - optional cancellation shared by all source reads.\n * @returns one fulfilled or rejected result per unique requested id.\n */', + description: 'Fold titles for unique sessions from one cancellable corpus observation.\n\nResults preserve first-occurrence input order. Operational failures stay isolated per session, while cancellation rejects the complete operation.', + parameters: [{ name: 'sessionIds', description: 'live or persisted session ids to observe.' }, { name: 'signal', description: 'optional cancellation shared by all source reads.' }], + returns: 'one fulfilled or rejected result per unique requested id.', }, { signature: 'async listEvents(sessionId: SessionId): Promise', - jsDoc: '/**\n * List lightweight raw-log event records for one logical session.\n * @param sessionId - live-preferred session id to read.\n * @returns event records in ascending seq order.\n */', + description: 'List lightweight raw-log event records for one logical session.', + parameters: [{ name: 'sessionId', description: 'live-preferred session id to read.' }], + returns: 'event records in ascending seq order.', }, { signature: 'async filterEvents( sessionId: SessionId, filters: readonly SessionEventResultFilter[], ): Promise', - jsDoc: '/**\n * Scan first-party semantic event documents with provider-independent filters.\n * @param sessionId - live-preferred session id to scan.\n * @param filters - ANDed metadata and literal-text predicates.\n * @returns matching semantic documents in ascending seq order.\n */', + description: 'Scan first-party semantic event documents with provider-independent filters.', + parameters: [{ name: 'sessionId', description: 'live-preferred session id to scan.' }, { name: 'filters', description: 'ANDed metadata and literal-text predicates.' }], + returns: 'matching semantic documents in ascending seq order.', }, { signature: 'async readSurface(sessionId: SessionId): Promise', - jsDoc: '/**\n * Read one session\'s complete current model surface from one corpus observation.\n * @param sessionId - live-preferred session id to read.\n * @returns cloned header, current surface, and the last sequence number included in the raw-log capture.\n * @throws when source resolution fails or the session surface is invalid.\n */', + description: 'Read one session\'s complete current model surface from one corpus observation.', + parameters: [{ name: 'sessionId', description: 'live-preferred session id to read.' }], + returns: 'cloned header, current surface, and the last sequence number included in the raw-log capture.', + throws: ['when source resolution fails or the session surface is invalid.'], }, { signature: 'async traceSession(sessionId: SessionId, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Trace known ancestry and descendants from one corpus observation.\n * @param sessionId - logical session id to trace.\n * @param signal - optional cancellation for persistence listing.\n * @returns a complete lineage or the first parent that could not be resolved.\n * @throws when corpus resolution fails, the target is absent, or its known ancestry cycles.\n */', + description: 'Trace known ancestry and descendants from one corpus observation.', + parameters: [{ name: 'sessionId', description: 'logical session id to trace.' }, { name: 'signal', description: 'optional cancellation for persistence listing.' }], + returns: 'a complete lineage or the first parent that could not be resolved.', + throws: ['when corpus resolution fails, the target is absent, or its known ancestry cycles.'], }, { signature: 'async traceEvent(request: SessionEventTraceRequest, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Trace one event\'s direct positional replacements and cited source events.\n * @param request - target session id and event seq.\n * @param signal - optional cancellation for persisted source resolution.\n * @returns source header, direct links, and the target\'s positional replacement chain.\n * @throws when source resolution fails, the target is absent, or surface/source-event validation fails.\n */', + description: 'Trace one event\'s direct positional replacements and cited source events.', + parameters: [{ name: 'request', description: 'target session id and event seq.' }, { name: 'signal', description: 'optional cancellation for persisted source resolution.' }], + returns: 'source header, direct links, and the target\'s positional replacement chain.', + throws: ['when source resolution fails, the target is absent, or surface/source-event validation fails.'], }, { signature: 'async readEvent(request: SessionEventReadRequest, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Read one full event plus a bounded raw-log context window.\n * @param request - target session/seq and context sizes.\n * @param signal - optional cancellation for persisted source resolution.\n * @returns cloned target and neighboring events.\n */', + description: 'Read one full event plus a bounded raw-log context window.', + parameters: [{ name: 'request', description: 'target session/seq and context sizes.' }, { name: 'signal', description: 'optional cancellation for persisted source resolution.' }], + returns: 'cloned target and neighboring events.', }, ], }, { key: 'sessionReferenceResolver', summary: 'Exact-read consumer that prepares immutable cross-session message context.', + description: 'Exact-read consumer that prepares immutable cross-session message context.', methods: [ { signature: 'async listCandidates( agent: Agent, query: string = \'\', limit: number = this.config.candidateLimit, signal?: AbortSignal, ): Promise', - 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 */', + description: 'List reference candidates, ranked by working-directory affinity.', + parameters: [{ name: 'agent', description: 'target agent; self is excluded and its cwd drives ranking.' }, { name: 'query', description: 'optional case-insensitive session-id/cwd/title substring.' }, { name: 'limit', description: 'optional positive result cap.' }, { name: 'signal', description: 'optional cancellation boundary for host autocomplete teardown.' }], + returns: 'candidates labeled by latest title or, when absent, session id.', }, { signature: 'async prepare( agent: Agent, content: ContentBlock[], references: SessionReferenceInput[], signal?: AbortSignal, ): Promise', - jsDoc: '/**\n * Snapshot all references before enqueue and return one aggregated durable context.\n * @param agent - target agent; references to it are rejected.\n * @param content - already host-normalized readable message content.\n * @param references - structured source sessions in mention order.\n * @param signal - optional cancellation boundary for host request teardown.\n * @returns detached content and optional referenced-session context.\n */', + description: 'Snapshot all references before enqueue and return one aggregated durable context.', + parameters: [{ name: 'agent', description: 'target agent; references to it are rejected.' }, { name: 'content', description: 'already host-normalized readable message content.' }, { name: 'references', description: 'structured source sessions in mention order.' }, { name: 'signal', description: 'optional cancellation boundary for host request teardown.' }], + returns: 'detached content and optional referenced-session context.', }, ], }, { key: 'sessions', summary: 'In-memory session store (`ctx.sessions`).', + description: 'In-memory session store (`ctx.sessions`).\n\nPersistence is intentionally not implemented here — persistence plugins subscribe to `session/event` and flush on `session/flush` / dispose.', methods: [ { signature: 'create(id?: SessionId, options?: CreateSessionOptions): Session', - jsDoc: '/**\n * Create a session owned by the calling fiber: disposing that fiber stops\n * event notification and removes the session from the store. `options.seed`\n * populates the session with a copy of those events (replay/fork);\n * `options.meta` attaches creation metadata (validated absolute `cwd`, seed\n * and parent lineage, and delegation depth) as the immutable\n * {@link SessionHeader} (the store fills `version`/`id`/`createdAt`).\n *\n * For an agent whose session must be torn down IN ORDER with its loop (so the\n * loop\'s final events are published before the store attachment ends), do NOT use this\n * — fold the session lifecycle into the agent\'s own effect via\n * {@link prepare} + {@link enter} + {@link announce} (see\n * `dsh-agent-loop`\'s creation transaction).\n *\n * @param id - the session id; omitted, the store mints `session-`.\n * @param options - seed events and/or creation metadata for the header.\n * @returns the live session, already entered and announced.\n * @throws if a session with `id` already exists, metadata is not a plain\n * lossless-JSON record with valid scalar fields, or `meta.cwd` is a\n * non-absolute path (storage backends key directories off it).\n */', + description: 'Create a session owned by the calling fiber: disposing that fiber stops event notification and removes the session from the store. `options.seed` populates the session with a copy of those events (replay/fork); `options.meta` attaches creation metadata (validated absolute `cwd`, seed and parent lineage, and delegation depth) as the immutable SessionHeader (the store fills `version`/`id`/`createdAt`).\n\nFor an agent whose session must be torn down IN ORDER with its loop (so the loop\'s final events are published before the store attachment ends), do NOT use this — fold the session lifecycle into the agent\'s own effect via prepare + enter + announce (see `dsh-agent-loop`\'s creation transaction).', + parameters: [{ name: 'id', description: 'the session id; omitted, the store mints `session-`.' }, { name: 'options', description: 'seed events and/or creation metadata for the header.' }], + returns: 'the live session, already entered and announced.', + throws: ['if a session with `id` already exists, metadata is not a plain lossless-JSON record with valid scalar fields, or `meta.cwd` is a non-absolute path (storage backends key directories off it).'], }, { signature: 'prepare(id?: SessionId, options?: PrepareSessionOptions): Session', - jsDoc: '/**\n * Build a session WITHOUT entering it into the store — validate the id/cwd and\n * construct the {@link Session} (with its immutable {@link SessionHeader}).\n * Pairs with {@link enter} + {@link announce}: a caller that owns a composite\n * `ctx.effect` (the agent factory) folds the session lifecycle into that ONE\n * effect so a fiber unload tears the session + agent down as a single ORDERED\n * chain rather than as racing sibling effects — which would remove the publication hooks\n * before the driver\'s closing events commit, dropping them.\n *\n * @param id - the session id; omitted, the store mints `session-`.\n * @param options - seed events and/or creation metadata for the header. With\n * `seedSource: \'persistence\'`, metadata and events must be fresh detached\n * graphs whose ownership transfers to this call: they are validated and\n * frozen in place through {@link Session.fromRestore}, so the caller must\n * retain no mutable aliases.\n * @returns the constructed session, NOT yet in the store.\n * @throws if a session with `id` already exists, metadata is not a plain\n * lossless-JSON record with valid scalar fields, or `meta.cwd` is a\n * non-absolute path.\n */', + description: 'Build a session WITHOUT entering it into the store — validate the id/cwd and construct the Session (with its immutable SessionHeader). Pairs with enter + announce: a caller that owns a composite `ctx.effect` (the agent factory) folds the session lifecycle into that ONE effect so a fiber unload tears the session + agent down as a single ORDERED chain rather than as racing sibling effects — which would remove the publication hooks before the driver\'s closing events commit, dropping them.', + parameters: [{ name: 'id', description: 'the session id; omitted, the store mints `session-`.' }, { name: 'options', description: 'seed events and/or creation metadata for the header. With `seedSource: \'persistence\'`, metadata and events must be fresh detached graphs whose ownership transfers to this call: they are validated and frozen in place through {@link Session.fromRestore}, so the caller must retain no mutable aliases.' }], + returns: 'the constructed session, NOT yet in the store.', + throws: ['if a session with `id` already exists, metadata is not a plain lossless-JSON record with valid scalar fields, or `meta.cwd` is a non-absolute path.'], }, { signature: 'enter(session: Session): () => void', - jsDoc: '/**\n * Enter a {@link prepare}d session into the store: install the module-private\n * append publication hooks and add it to the store. Returns the DETACH\n * disposer (hooks + store removal). Does NOT emit `session/created` —\n * the caller yields this disposer inside its effect and THEN calls\n * {@link announce}, so a throwing `session/created` listener rolls the attach\n * back instead of leaking it.\n *\n * Re-checks the id for a duplicate: `prepare` and `enter` are public\n * cross-package primitives and a caller may interleave arbitrary work (or\n * another create) between them, so a stale prepared session must NOT overwrite\n * a live store entry of the same id — its detach disposer would later delete\n * the REAL session. The {@link create} convenience and the agent factory call\n * the two back-to-back so they never trip this, but the public API cannot\n * assume that.\n *\n * @param session - a {@link prepare}d session not yet in the store.\n * @returns the detach disposer (publication hooks + store removal). When called from\n * a synchronous `session/created` listener, removal and disposal wait until\n * that creation dispatch unwinds.\n * @throws if a session with this id is already in the store.\n */', + description: 'Enter a prepared session into the store: install the module-private append publication hooks and add it to the store. Returns the DETACH disposer (hooks + store removal). Does NOT emit `session/created` — the caller yields this disposer inside its effect and THEN calls announce, so a throwing `session/created` listener rolls the attach back instead of leaking it.\n\nRe-checks the id for a duplicate: `prepare` and `enter` are public cross-package primitives and a caller may interleave arbitrary work (or another create) between them, so a stale prepared session must NOT overwrite a live store entry of the same id — its detach disposer would later delete the REAL session. The create convenience and the agent factory call the two back-to-back so they never trip this, but the public API cannot assume that.', + parameters: [{ name: 'session', description: 'a {@link prepare}d session not yet in the store.' }], + returns: 'the detach disposer (publication hooks + store removal). When called from a synchronous `session/created` listener, removal and disposal wait until that creation dispatch unwinds.', + throws: ['if a session with this id is already in the store.'], }, { signature: 'announce(session: Session): void', - jsDoc: '/** Emit `session/created` exactly once for an {@link enter}ed session (with\n * the carrier {@link enter} captured). Separate from {@link enter} so the\n * caller can yield the detach disposer first (rollback safety — see\n * {@link enter}).\n * @param session - the entered session to announce to listeners.\n * @throws if the session is not live or its announcement already began,\n * including a reentrant call from a creation listener. */', + description: 'Emit `session/created` exactly once for an entered session (with the carrier enter captured). Separate from enter so the caller can yield the detach disposer first (rollback safety — see enter).', + parameters: [{ name: 'session', description: 'the entered session to announce to listeners.' }], + throws: ['if the session is not live or its announcement already began, including a reentrant call from a creation listener.'], }, { signature: 'async flush(session: Session): Promise', - jsDoc: '/**\n * Dispatch the awaited `session/flush` durability checkpoint for `session`,\n * with the carrier captured at {@link enter}. THE flush entry point: the\n * store owns the carrier, so callers (the checkpoint policy\'s per-request\n * barrier, goal-round-driver\'s idle checkpoint, teardown drains, and consumers\n * that flush themselves before reading storage) must come through here\n * rather than dispatch a raw `ctx.parallel(\'session/flush\', …)` — one owner,\n * one spelling, and the scoped-dispatch invariant can pin it.\n * @param session - the session whose buffered events must reach durable storage.\n * @returns whether at least one durability listener participated, after every\n * listener has settled successfully.\n * @throws the first registered listener failure after every listener settles.\n */', + description: 'Dispatch the awaited `session/flush` durability checkpoint for `session`, with the carrier captured at enter. THE flush entry point: the store owns the carrier, so callers (the checkpoint policy\'s per-request barrier, goal-round-driver\'s idle checkpoint, teardown drains, and consumers that flush themselves before reading storage) must come through here rather than dispatch a raw `ctx.parallel(\'session/flush\', …)` — one owner, one spelling, and the scoped-dispatch invariant can pin it.', + parameters: [{ name: 'session', description: 'the session whose buffered events must reach durable storage.' }], + returns: 'whether at least one durability listener participated, after every listener has settled successfully.', + throws: ['the first registered listener failure after every listener settles.'], }, { signature: 'get(id: SessionId): Session | undefined', - jsDoc: '/**\n * Look up a live session.\n * @param id - the session id to look up.\n * @returns the session, or undefined when no live session has that id.\n */', + description: 'Look up a live session.', + parameters: [{ name: 'id', description: 'the session id to look up.' }], + returns: 'the session, or undefined when no live session has that id.', }, { signature: 'list(): Session[]', - jsDoc: '/**\n * All live sessions, in creation order.\n * @returns a fresh array; mutating it does not affect the store.\n */', + description: 'All live sessions, in creation order.', + parameters: [], + returns: 'a fresh array; mutating it does not affect the store.', }, { signature: 'fork(source: SessionForkSource, boundary?: number, childSessionId?: SessionId): Session', - jsDoc: '/**\n * Create a live child session from a stable prefix of a live source.\n * `boundary` is an inclusive source event seq; omitted means the source\'s\n * current last event. The selected slice may end with a between-turn event\n * but must not end inside an open turn.\n *\n * @param source - Live source session object or id.\n * @param boundary - Inclusive source event seq to fork through; omitted means\n * the source\'s current last event, and omitted on an empty source forks an\n * empty child.\n * @param childSessionId - Optional child session id; omitted delegates to\n * `SessionStore`\'s id policy.\n * @returns The created live child session.\n */', + description: 'Create a live child session from a stable prefix of a live source. `boundary` is an inclusive source event seq; omitted means the source\'s current last event. The selected slice may end with a between-turn event but must not end inside an open turn.', + parameters: [{ name: 'source', description: 'Live source session object or id.' }, { name: 'boundary', description: 'Inclusive source event seq to fork through; omitted means the source\'s current last event, and omitted on an empty source forks an empty child.' }, { name: 'childSessionId', description: 'Optional child session id; omitted delegates to `SessionStore`\'s id policy.' }], + returns: 'The created live child session.', }, ], }, { key: 'sessionTelemetry', summary: 'Loadable form of the backend contract: one implementation per context — the cordis `Service` registration under the `telemetry` key throws on a duplicate, cordis\' standard behavior.', + description: 'Loadable form of the backend contract: one implementation per context — the cordis `Service` registration under the `telemetry` key throws on a duplicate, cordis\' standard behavior. A backend composes a SessionTelemetryCoordinator in its constructor to install the capture side.', methods: [ + { + signature: 'abstract readonly sharing: SessionTelemetrySharingStatus', + description: 'Deployment-selected session-sharing policy, disclosed for acknowledgement surfaces that report whether recorded feedback leaves the process. Every backend must disclose its policy; a consumer renders "not configured" only when no telemetry service is mounted. The seam owns this vocabulary so the disclosure is backend-independent.', + parameters: [], + }, { signature: 'abstract emit(record: SessionTelemetryRecord): void', - jsDoc: '/**\n * See {@link SessionTelemetrySink.emit} — that declaration is the contract\'s one home.\n * @param record - the logical record to report; owned by the backend after the call.\n */', + description: 'See SessionTelemetrySink.emit — that declaration is the contract\'s one home.', + parameters: [{ name: 'record', description: 'the logical record to report; owned by the backend after the call.' }], }, { signature: 'flush?(): void', - jsDoc: '/** See {@link SessionTelemetrySink.flush}. */', + description: 'See SessionTelemetrySink.flush.', + parameters: [], }, { signature: 'abstract shutdown(): Promise', - jsDoc: '/**\n * See {@link SessionTelemetrySink.shutdown}.\n * @returns resolves when the backend\'s pipeline has quiesced.\n */', + description: 'See SessionTelemetrySink.shutdown.', + parameters: [], + returns: 'resolves when the backend\'s pipeline has quiesced.', }, ], }, { key: 'sessionTitle', summary: 'Log-backed title fold plus asynchronous fallback generation.', + description: 'Log-backed title fold plus asynchronous fallback generation.', methods: [ { 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 */', + description: 'Read the latest folded title from one live or replayed session.', + parameters: [{ name: 'session', description: 'session whose log is the title source of truth.' }], + returns: 'latest title snapshot, or `undefined` before eligible input.', }, { 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 */', + description: 'Accept an explicit user title. Appends a `session/title` event with the `user` source, which pins the title: in-flight automatic generation is superseded and later user messages schedule none (an explicit SessionTitleService.refresh remains the deliberate unpin).', + parameters: [{ name: 'session', description: 'exact live session to rename.' }, { name: 'title', description: 'raw user input; normalized before acceptance.' }], + returns: 'the accepted title snapshot.', + throws: ['{SessionTitleInvalidError} when the title normalizes to empty.', '{Error} when the session is not live or the service is disposed.'], }, { signature: 'async refresh(session: Session, signal?: AbortSignal): Promise', - 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 */', + description: 'Explicitly retry the registered provider, or materialize the built-in fallback when no provider is registered.', + parameters: [{ name: 'session', description: 'exact live session to refresh.' }, { name: 'signal', description: 'optional caller cancellation.' }], + returns: 'latest accepted title, or `undefined` when no eligible text exists.', }, { signature: 'register(provider: SessionTitleProvider): () => Promise', - jsDoc: '/**\n * Register the sole optional title provider. Disposal aborts its pending and\n * active work before another provider may register.\n * @param provider - provider identity, cadence, and generation function.\n * @returns exact Cordis effect disposer, which settles after active calls quiesce.\n */', + description: 'Register the sole optional title provider. Disposal aborts its pending and active work before another provider may register.', + parameters: [{ name: 'provider', description: 'provider identity, cadence, and generation function.' }], + returns: 'exact Cordis effect disposer, which settles after active calls quiesce.', }, ], }, { key: 'settings', summary: 'Abstract settings service.', + description: 'Abstract settings service. Providers implement raw-document storage (`load`/`persist`) and push external changes through Settings.publish; the base class owns namespace registration, resolution, validation, change detection, and the `settings/updated` commit event.', methods: [ + { + signature: 'abstract readonly writable: boolean', + description: 'Whether update may persist through this provider.', + parameters: [], + }, { signature: 'prepareDocument(): Promise', - jsDoc: '/**\n * Prepare the provider\'s user-editable document for a native editor. File\n * providers may materialize an absent document before returning its path;\n * non-file providers return undefined.\n * @returns the absolute local document path, or undefined for non-file storage.\n */', + description: 'Prepare the provider\'s user-editable document for a native editor. File providers may materialize an absent document before returning its path; non-file providers return undefined.', + parameters: [], + returns: 'the absolute local document path, or undefined for non-file storage.', }, { signature: 'register(ns: SettingsNamespace, schema: z, options?: SettingsRegisterOptions): SettingsScope', - jsDoc: '/**\n * Register a namespace schema and receive its owner scope. The registration\n * is an effect on the calling plugin\'s fiber: disposing that fiber removes\n * the namespace and its observers. An invalid stored section fails the\n * registration itself — the earliest point where the schema can judge it.\n * @param ns - unique namespace; duplicate registration fails loud.\n * @param schema - schemastery schema resolving this namespace\'s value.\n * @param options - composition `base` layer and effect timing.\n * @returns the owner scope for reads, observation, and updates.\n */', + description: 'Register a namespace schema and receive its owner scope. The registration is an effect on the calling plugin\'s fiber: disposing that fiber removes the namespace and its observers. An invalid stored section fails the registration itself — the earliest point where the schema can judge it.', + parameters: [{ name: 'ns', description: 'unique namespace; duplicate registration fails loud.' }, { name: 'schema', description: 'schemastery schema resolving this namespace\'s value.' }, { name: 'options', description: 'composition `base` layer and effect timing.' }], + returns: 'the owner scope for reads, observation, and updates.', }, { signature: 'describe(options?: SettingsDescribeOptions): SettingsDescriptor[]', - jsDoc: '/**\n * Describe every registered namespace for configuration surfaces, including\n * the composition `base` and raw user layers so a form can mark which fields\n * the user overrode (presence in `user`) and what a reset returns to.\n * @param options - redaction switch; wire surfaces must redact.\n * @returns one descriptor per registered namespace, in registration order.\n */', + description: 'Describe every registered namespace for configuration surfaces, including the composition `base` and raw user layers so a form can mark which fields the user overrode (presence in `user`) and what a reset returns to.', + parameters: [{ name: 'options', description: 'redaction switch; wire surfaces must redact.' }], + returns: 'one descriptor per registered namespace, in registration order.', }, { signature: 'get(ns: SettingsNamespace): unknown', - jsDoc: '/**\n * Read one registered namespace\'s resolved value.\n * @param ns - the namespace to read.\n * @returns the resolved value, or `undefined` while unregistered.\n */', + description: 'Read one registered namespace\'s resolved value.', + parameters: [{ name: 'ns', description: 'the namespace to read.' }], + returns: 'the resolved value, or `undefined` while unregistered.', }, { signature: 'async update(ns: SettingsNamespace, patch: object, expectedRevision?: number): Promise', - jsDoc: '/**\n * Merge a patch into one registered namespace\'s user layer, validate the\n * resolved candidate, persist through the provider, then commit and emit.\n * A validation failure rejects before anything is persisted. Writes to one\n * namespace are serialized: concurrent updates apply in call order, each\n * merging over the previous write\'s committed section.\n * @param ns - the registered namespace to update.\n * @param patch - plain-object patch over the user section.\n * @param expectedRevision - the descriptor `revision` the caller read; a\n * namespace that moved past it rejects with {@link SettingsConflictError}.\n */', + description: 'Merge a patch into one registered namespace\'s user layer, validate the resolved candidate, persist through the provider, then commit and emit. A validation failure rejects before anything is persisted. Writes to one namespace are serialized: concurrent updates apply in call order, each merging over the previous write\'s committed section.', + parameters: [{ name: 'ns', description: 'the registered namespace to update.' }, { name: 'patch', description: 'plain-object patch over the user section.' }, { name: 'expectedRevision', description: 'the descriptor `revision` the caller read; a namespace that moved past it rejects with {@link SettingsConflictError}.' }], }, { signature: 'async replace(ns: SettingsNamespace, section: object, expectedRevision?: number): Promise', - jsDoc: '/**\n * Replace one registered namespace\'s user section wholesale, validate,\n * persist, then commit and emit. Keys absent from `section` fall back to the\n * composition `base` and schema defaults — this is the removal/reset path a\n * merge-only patch cannot express (`replace({})` re-inherits everything).\n * @param ns - the registered namespace to replace.\n * @param section - the complete next user section.\n * @param expectedRevision - the descriptor `revision` the caller read; a\n * namespace that moved past it rejects with {@link SettingsConflictError}.\n */', + description: 'Replace one registered namespace\'s user section wholesale, validate, persist, then commit and emit. Keys absent from `section` fall back to the composition `base` and schema defaults — this is the removal/reset path a merge-only patch cannot express (`replace({})` re-inherits everything).', + parameters: [{ name: 'ns', description: 'the registered namespace to replace.' }, { name: 'section', description: 'the complete next user section.' }, { name: 'expectedRevision', description: 'the descriptor `revision` the caller read; a namespace that moved past it rejects with {@link SettingsConflictError}.' }], }, { signature: 'async mutate(ns: SettingsNamespace, ops: readonly SettingsPathOp[], expectedRevision?: number): Promise', - jsDoc: '/**\n * Apply path-addressed edits to one registered namespace\'s user section,\n * validate, persist, then commit and emit. The ops are applied to the\n * section as it stands when the write reaches the front of the queue, so a\n * caller never has to restate fields it did not touch — and, crucially,\n * cannot delete fields it never saw. This is the write path for any caller\n * holding a redacted view; `replace` remains the wholesale reset.\n * @param ns - the registered namespace to edit.\n * @param ops - ordered path edits; later ops observe earlier ones.\n * @param expectedRevision - the descriptor `revision` the caller read; a\n * namespace that moved past it rejects with {@link SettingsConflictError}.\n */', + description: 'Apply path-addressed edits to one registered namespace\'s user section, validate, persist, then commit and emit. The ops are applied to the section as it stands when the write reaches the front of the queue, so a caller never has to restate fields it did not touch — and, crucially, cannot delete fields it never saw. This is the write path for any caller holding a redacted view; `replace` remains the wholesale reset.', + parameters: [{ name: 'ns', description: 'the registered namespace to edit.' }, { name: 'ops', description: 'ordered path edits; later ops observe earlier ones.' }, { name: 'expectedRevision', description: 'the descriptor `revision` the caller read; a namespace that moved past it rejects with {@link SettingsConflictError}.' }], }, ], }, { key: 'shell', summary: 'Abstract bash execution service.', + description: 'Abstract bash execution service. Subclass, implement the abstract methods, and load the subclass as a plugin — it registers as `ctx.shell` (one implementation per context; loading a second throws, which is cordis\' standard duplicate-service behavior).\n\nImplementations must honor these semantics:\n\n- run rejects only for infrastructure failures. Nonzero exits, timeout kills, and abort kills resolve with a ShellRunResult.\n- start returns immediately; no timeout applies to background processes. `done` settles at process close and never rejects; spawn failures settle as `killed` with the error on stderr.\n- ShellProcess.readOutput is incremental: consecutive reads never repeat output. Lossy reads report truncation and available spill files.\n- A still-running background process is stopped and awaited when its owning composition tears down. With the subprocess seam that boundary is `ctx.subprocess` disposal, so a background process survives an executor-only reload.', methods: [ { signature: 'abstract resolve(request: ShellExecRequest): ShellExecSpec', - jsDoc: '/**\n * Apply implementation-owned defaults and caps to a request before execution.\n * @param request - the caller\'s request; omitted fields get this\n * implementation\'s defaults, capped fields are clamped.\n * @returns the fully-specified spec to hand to {@link run}/{@link start}.\n */', + description: 'Apply implementation-owned defaults and caps to a request before execution.', + parameters: [{ name: 'request', description: 'the caller\'s request; omitted fields get this implementation\'s defaults, capped fields are clamped.' }], + returns: 'the fully-specified spec to hand to {@link run}/{@link start}.', }, { signature: 'abstract run(spec: ShellExecSpec): Promise', - jsDoc: '/**\n * Run a command in the foreground; resolves when it finishes.\n * @param spec - a resolved spec from {@link resolve}, never a raw request.\n * @returns the outcome; nonzero exits, timeout kills, and abort kills\n * resolve with a descriptive result rather than reject.\n */', + description: 'Run a command in the foreground; resolves when it finishes.', + parameters: [{ name: 'spec', description: 'a resolved spec from {@link resolve}, never a raw request.' }], + returns: 'the outcome; nonzero exits, timeout kills, and abort kills resolve with a descriptive result rather than reject.', }, { signature: 'abstract start(spec: ShellExecSpec): ShellProcess', - jsDoc: '/**\n * Start a background process and return its handle immediately.\n * @param spec - a resolved spec from {@link resolve}, never a raw request.\n * @returns the live process handle (reads, kill, quiescence promise).\n */', + description: 'Start a background process and return its handle immediately.', + parameters: [{ name: 'spec', description: 'a resolved spec from {@link resolve}, never a raw request.' }], + returns: 'the live process handle (reads, kill, quiescence promise).', }, ], }, { key: 'shellEnv', summary: 'Registry (`ctx.shellEnv`) for trusted, per-execution `DSH_*` variables.', + description: 'Registry (`ctx.shellEnv`) for trusted, per-execution `DSH_*` variables. The namespace is rebuilt for every model shell call: ambient `DSH_*` values are discarded by the executor, then the registry\'s current snapshot is injected. Built-in shell facts remain owned by the registry itself while plugins can register additional, enumerable facts with effect-scoped disposal.', methods: [ { signature: 'register(contributor: BashEnvContributor): () => void', - jsDoc: '/**\n * Register one environment contributor. Names and keys are unique; built-in\n * keys are reserved. Registration is disposed with the calling plugin fiber.\n * @param contributor - declared key ownership and per-execution resolver.\n * @returns the disposer that unregisters the contribution.\n */', + description: 'Register one environment contributor. Names and keys are unique; built-in keys are reserved. Registration is disposed with the calling plugin fiber.', + parameters: [{ name: 'contributor', description: 'declared key ownership and per-execution resolver.' }], + returns: 'the disposer that unregisters the contribution.', }, { signature: 'collect(execution: ToolExecution): DshEnvironment', - jsDoc: '/**\n * Build the trusted `DSH_*` snapshot for one shell tool execution.\n * @param execution - the current tool execution.\n * @returns an immutable environment overlay containing built-ins and current contributions.\n */', + description: 'Build the trusted `DSH_*` snapshot for one shell tool execution.', + parameters: [{ name: 'execution', description: 'the current tool execution.' }], + returns: 'an immutable environment overlay containing built-ins and current contributions.', }, { signature: 'list(): BashEnvVariableInfo[]', - jsDoc: '/**\n * Enumerate plugin-contributed variables without executing their resolvers.\n * @returns declarations sorted by environment variable name.\n */', + description: 'Enumerate plugin-contributed variables without executing their resolvers.', + parameters: [], + returns: 'declarations sorted by environment variable name.', }, ], }, { key: 'skills', summary: 'Layered registry of skill providers, the host+per-scope shape the tools registry established.', + description: 'Layered registry of skill providers, the host+per-scope shape the tools registry established. A registration files into the layer of its calling context\'s scope (scopeOf): host rows and repository plugins land in the global layer, while a plugin mounted by an agent preset\'s standing composition lands in that preset\'s layer. A read merges the global layer with the viewing scope\'s chain — the nearest layer\'s entry wins a duplicate name outright, and the rank order decides duplicates only within one layer. It exposes sorted invocation-neutral summaries and loads full skill bodies on demand.', methods: [ { signature: 'registerProvider(create: (control: SkillProviderControl) => SkillProvider): () => void', - jsDoc: '/**\n * Register a borrowed same-process provider synchronously during plugin\n * apply, into the calling context\'s layer: a scoped context (an agent\n * preset\'s standing mount) registers for that scope alone, an unscoped\n * context registers globally. Duplicate names within one layer and reserved\n * names throw; remote initialization belongs in `list()`. Fiber disposal\n * unregisters 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 */', + description: 'Register a borrowed same-process provider synchronously during plugin apply, into the calling context\'s layer: a scoped context (an agent preset\'s standing mount) registers for that scope alone, an unscoped context registers globally. Duplicate names within one layer and reserved names throw; remote initialization belongs in `list()`. Fiber disposal unregisters the provider and invalidates catalog caches.', + parameters: [{ name: 'create', description: 'synchronous factory receiving this registration\'s lifecycle and invalidation control.' }], + returns: 'the exact Cordis effect disposer that unregisters this provider; composite effects may yield it directly to preserve teardown ordering.', }, { signature: 'register(skill: SkillRegistration): () => void', - jsDoc: '/**\n * Register a borrowed readonly runtime skill into the calling context\'s\n * layer. Project entries outrank runtime entries, which outrank user\n * entries, within one layer. Same-name runtime entries in one layer are\n * first-wins; a duplicate logs a warning and receives a no-op disposer so\n * 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 */', + description: 'Register a borrowed readonly runtime skill into the calling context\'s layer. Project entries outrank runtime entries, which outrank user entries, within one layer. Same-name runtime entries in one layer are first-wins; a duplicate logs a warning and receives a no-op disposer so it cannot remove the winner.', + parameters: [{ name: 'skill', description: 'the skill definition input; omitted invocation and provider fields receive defaults.' }], + returns: 'the exact Cordis effect disposer, preserving composite teardown order and invalidating caches.', }, { signature: 'async list(options: SkillViewOptions = {}): Promise', - 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 - view options; `scope` selects the viewing agent\'s layers, `cwd` selects project roots, and `signal` cancels discovery.\n * @returns all sorted winning summaries.\n */', + description: 'List invocation-neutral skill summaries for a workspace. Consumers apply model or user invocation policy at their operational boundary. Lookup options and provider candidates are readonly same-process values borrowed throughout discovery.', + parameters: [{ name: 'options', description: 'view options; `scope` selects the viewing agent\'s layers, `cwd` selects project roots, and `signal` cancels discovery.' }], + returns: 'all sorted winning summaries.', }, { signature: 'async snapshot(options: SkillViewOptions = {}): Promise', - 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 - view options; `scope` selects the viewing agent\'s layers, `cwd` selects project roots, and `signal` cancels discovery.\n * @returns sorted summaries plus discovery-completeness state.\n */', + description: 'Observe the current invocation-neutral catalog and whether discovery completed within a stable revision. Incomplete observations are never cached, allowing consumers to retain last-good state and retry on their next request boundary.', + parameters: [{ name: 'options', description: 'view options; `scope` selects the viewing agent\'s layers, `cwd` selects project roots, and `signal` cancels discovery.' }], + returns: 'sorted summaries plus discovery-completeness state.', }, { signature: 'async get(name: string, options: SkillViewOptions = {}): Promise', - jsDoc: '/**\n * Load and validate the winning candidate, passing its opaque discovery locator back to the\n * provider. Cancellation is rechecked after selection, including cache hits, and raced against\n * loading so an uncooperative provider cannot hang the caller.\n * @param name - kebab-case skill name.\n * @param options - view options; `scope` selects the viewing agent\'s layers,\n * `cwd` selects workspace-sensitive skills, and `signal` cancels work.\n * @returns the full skill, including body content, or `undefined`.\n */', + description: 'Load and validate the winning candidate, passing its opaque discovery locator back to the provider. Cancellation is rechecked after selection, including cache hits, and raced against loading so an uncooperative provider cannot hang the caller.', + parameters: [{ name: 'name', description: 'kebab-case skill name.' }, { name: 'options', description: 'view options; `scope` selects the viewing agent\'s layers, `cwd` selects workspace-sensitive skills, and `signal` cancels work.' }], + returns: 'the full skill, including body content, or `undefined`.', }, ], }, { key: 'spillStore', summary: 'Abstract spill storage service.', + description: 'Abstract spill storage service. Subclass, implement saveText, and load the subclass as a plugin — it registers as `ctx.spillStore` (one implementation per context; loading a second throws, cordis\' standard duplicate-service behavior).\n\nSemantics every implementation must honor:\n\n- saveText persists the FULL `content` verbatim and returns an opaque locator, exact byte length, and model-facing retrieval guidance.\n- Storage is scoped by the request\'s SaveTextSpill.owner session; the backend chooses a private (not world-readable) location and a collision-free name derived from — never equal to — the caller\'s `suggestedName`.\n- `saveText` REJECTS on a real storage failure (permissions, ENOSPC, backend unavailable); the caller decides how to degrade (the spill policy treats a rejection as best-effort and keeps the inline result).', methods: [ { signature: 'abstract saveText(input: SaveTextSpill): Promise', - jsDoc: '/**\n * Persist `input.content` to a session-scoped spill artifact.\n * @param input - the owner, caller-supplied source fields, suggested name, and full text to save.\n * @returns the saved artifact\'s {@link SpillRef}; rejects on a storage failure.\n */', + description: 'Persist `input.content` to a session-scoped spill artifact.', + parameters: [{ name: 'input', description: 'the owner, caller-supplied source fields, suggested name, and full text to save.' }], + returns: 'the saved artifact\'s {@link SpillRef}; rejects on a storage failure.', }, ], }, { key: 'storage', summary: 'The storage hub service.', + description: 'The storage hub service. Backends register under `backend`; data forms mount under their `StorageForms` key and are reached as `ctx.storage.
`.', methods: [ + { + signature: 'readonly backend: BackendRegistry = new BackendRegistry()', + description: 'Named backend table; multiple backends stay mounted side by side.', + parameters: [], + }, { signature: 'mount(form: K, facility: StorageForms[K]): () => void', - jsDoc: '/**\n * Mount a data-form facility on the hub. Mounting is an effect: the\n * returned disposer unmounts the form.\n * @param form - Form key declared in {@link StorageForms}.\n * @param facility - The facility instance to expose.\n * @returns the disposer that unmounts the form.\n */', + description: 'Mount a data-form facility on the hub. Mounting is an effect: the returned disposer unmounts the form.', + parameters: [{ name: 'form', description: 'Form key declared in {@link StorageForms}.' }, { name: 'facility', description: 'The facility instance to expose.' }], + returns: 'the disposer that unmounts the form.', }, { signature: 'form(form: K): StorageForms[K]', - jsDoc: '/**\n * Resolve a mounted data form.\n * @param form - Form key declared in {@link StorageForms}.\n * @returns the mounted facility.\n */', + description: 'Resolve a mounted data form.', + parameters: [{ name: 'form', description: 'Form key declared in {@link StorageForms}.' }], + returns: 'the mounted facility.', }, ], }, { key: 'storageDomain', summary: 'The mounted domain facility.', + description: 'The mounted domain facility. Opens declared domains over routed backends; one facility instance owns the open-domain table and enforces single-open per domain name.', methods: [ { signature: 'async open(spec: S): Promise>', - jsDoc: '/**\n * Open one declared domain. Steps, each failing the whole call: reject a\n * name that is already open (`already-open`); resolve the backend route\n * (`backend-not-found` passes through from the hub); require its `kv` facet\n * (`facet-unsupported`); open the unit projected from the spec (backend\n * `version-mismatch`/`malformed-medium` pass through); load and validate\n * every stored record against the spec\'s zod schemas (`invalid-record`\n * with the offending table and key); construct the domain.\n *\n * Lifecycle: the CALLER owns the returned handle and closes it via\n * `Domain.close()` (typically as its own `ctx.effect` disposer) — the\n * facility does not tie the domain to any consumer fiber. Domains still\n * open when the facility unmounts are closed by the plugin disposer.\n * @param spec - The domain declaration, typically from `defineDomain`.\n * @returns the opened domain handle, typed by the spec.\n */', + description: 'Open one declared domain. Steps, each failing the whole call: reject a name that is already open (`already-open`); resolve the backend route (`backend-not-found` passes through from the hub); require its `kv` facet (`facet-unsupported`); open the unit projected from the spec (backend `version-mismatch`/`malformed-medium` pass through); load and validate every stored record against the spec\'s zod schemas (`invalid-record` with the offending table and key); construct the domain.\n\nLifecycle: the CALLER owns the returned handle and closes it via `Domain.close()` (typically as its own `ctx.effect` disposer) — the facility does not tie the domain to any consumer fiber. Domains still open when the facility unmounts are closed by the plugin disposer.', + parameters: [{ name: 'spec', description: 'The domain declaration, typically from `defineDomain`.' }], + returns: 'the opened domain handle, typed by the spec.', }, { signature: 'get(name: string): DomainImpl | undefined', - jsDoc: '/**\n * Look up an open domain by name, untyped. Diagnostic surface (the package\n * invariant cross-checks change events against live domain state); typed\n * consumers hold the handle returned by {@link open}.\n * @param name - Domain name.\n * @returns the open domain runtime, or `undefined` when not open.\n */', + description: 'Look up an open domain by name, untyped. Diagnostic surface (the package invariant cross-checks change events against live domain state); typed consumers hold the handle returned by open.', + parameters: [{ name: 'name', description: 'Domain name.' }], + returns: 'the open domain runtime, or `undefined` when not open.', }, { signature: 'async closeAll(): Promise', - jsDoc: '/**\n * Close every domain still open on this facility. The unmount path for\n * consumers that never called `Domain.close()` themselves; closing is\n * idempotent, so double-closing an already-closed domain is harmless.\n * @returns resolution after every unit is released.\n */', + description: 'Close every domain still open on this facility. The unmount path for consumers that never called `Domain.close()` themselves; closing is idempotent, so double-closing an already-closed domain is harmless.', + parameters: [], + returns: 'resolution after every unit is released.', }, ], }, { key: 'subagents', summary: 'Named provider registry with one-shot runs, durable discovery, and continuable-child operations.', + description: 'Named provider registry with one-shot runs, durable discovery, and continuable-child operations.', methods: [ { signature: 'async startContinuable(spec: ContinuableStartSpec): Promise', - jsDoc: '/**\n * Establish one durable continuable child and deliver its initial prompt.\n * Resolves when the child\'s inbox accepts that prompt, without waiting for the\n * turn to start or for the message to reach the Session log; any earlier\n * failure rejects with no ids and rolls back the child entirely.\n * @param spec - provider, delegation request, and caller cancellation.\n * @returns the durable child id and the accepted prompt\'s message id.\n * @throws when continuation services are unavailable or materialization fails.\n */', + description: 'Establish one durable continuable child and deliver its initial prompt. Resolves when the child\'s inbox accepts that prompt, without waiting for the turn to start or for the message to reach the Session log; any earlier failure rejects with no ids and rolls back the child entirely.', + parameters: [{ name: 'spec', description: 'provider, delegation request, and caller cancellation.' }], + returns: 'the durable child id and the accepted prompt\'s message id.', + throws: ['when continuation services are unavailable or materialization fails.'], }, { signature: 'async followup( parent: Agent, childId: SessionId, content: ContentBlock[], options: SubagentFollowupOptions, ): Promise', - jsDoc: '/**\n * Deliver one later message to a continuable child as its next FIFO turn. A\n * resident child\'s Agent inbox accepts it directly (waking a `waiting`\n * Activation), while an absent one is cold-resumed from its persisted\n * Session. The Agent inbox is the only queue, so every accepted message has\n * one observable order.\n * @param parent - the exact live direct parent authorizing this delivery.\n * @param childId - durable child session id.\n * @param content - user-role content to deliver.\n * @param options - the message source fields and caller cancellation, which stops the\n * operation only before inbox acceptance.\n * @returns the accepted message\'s inbox id.\n * @throws when continuation services are unavailable, parent authority is\n * rejected, or the message was not admitted.\n */', + description: 'Deliver one later message to a continuable child as its next FIFO turn. A resident child\'s Agent inbox accepts it directly (waking a `waiting` Activation), while an absent one is cold-resumed from its persisted Session. The Agent inbox is the only queue, so every accepted message has one observable order.', + parameters: [{ name: 'parent', description: 'the exact live direct parent authorizing this delivery.' }, { name: 'childId', description: 'durable child session id.' }, { name: 'content', description: 'user-role content to deliver.' }, { name: 'options', description: 'the message source fields and caller cancellation, which stops the operation only before inbox acceptance.' }], + returns: 'the accepted message\'s inbox id.', + throws: ['when continuation services are unavailable, parent authority is rejected, or the message was not admitted.'], }, { signature: 'interrupt(targetSessionId: SessionId, authority: SubagentInterruptAuthority): void', - jsDoc: '/**\n * Interrupt one live continuable child\'s current turn under a human parent\n * address or an exact live ancestor Agent. Fire-and-return: the cancel\n * signal is issued before this returns, but the target may keep running\n * until it observes the signal. Unclaimed pending inbox work, the Activation,\n * and published descendants are preserved; claimed work is not requeued.\n * Once the interrupted driver is idle, a waking send resumes the parked FIFO\n * queue. An absent target — including a one-shot or unknown id —\n * is an accepted no-op, as is a manager-less composition, which cannot own a\n * live Activation.\n * @param targetSessionId - the durable child session id to interrupt.\n * @param authority - the human parent address or exact live ancestor Agent.\n * @throws {SubagentError} `UNAUTHORIZED` when the authority does not own the\n * live target.\n */', + description: 'Interrupt one live continuable child\'s current turn under a human parent address or an exact live ancestor Agent. Fire-and-return: the cancel signal is issued before this returns, but the target may keep running until it observes the signal. Unclaimed pending inbox work, the Activation, and published descendants are preserved; claimed work is not requeued. Once the interrupted driver is idle, a waking send resumes the parked FIFO queue. An absent target — including a one-shot or unknown id — is an accepted no-op, as is a manager-less composition, which cannot own a live Activation.', + parameters: [{ name: 'targetSessionId', description: 'the durable child session id to interrupt.' }, { name: 'authority', description: 'the human parent address or exact live ancestor Agent.' }], + throws: ['{SubagentError} `UNAUTHORIZED` when the authority does not own the live target.'], }, { signature: 'async reportFrom( child: Agent, content: ContentBlock[], options: SubagentReportOptions, ): Promise', - jsDoc: '/**\n * Deliver selected content from one live continuable child to its durable\n * direct parent. The child is the authority credential; callers cannot name a\n * recipient. Reporting does not conclude the child\'s turn or Activation.\n * @param child - exact live reporting child.\n * @param content - selected model-facing content.\n * @param options - parent scheduling and pre-acceptance cancellation.\n * @returns the stable identity of the parent-accepted message.\n * @throws when continuation services are unavailable, sender authorization\n * fails, or the direct parent is not live.\n */', + description: 'Deliver selected content from one live continuable child to its durable direct parent. The child is the authority credential; callers cannot name a recipient. Reporting does not conclude the child\'s turn or Activation.', + parameters: [{ name: 'child', description: 'exact live reporting child.' }, { name: 'content', description: 'selected model-facing content.' }, { name: 'options', description: 'parent scheduling and pre-acceptance cancellation.' }], + returns: 'the stable identity of the parent-accepted message.', + throws: ['when continuation services are unavailable, sender authorization fails, or the direct parent is not live.'], }, { signature: 'registerContinuableSetup(contribution: ContinuableSetupContribution): () => void', - jsDoc: '/**\n * Compose one deployment capability into every continuable child\'s\n * unpublished creation context on fresh creation and cold resume. Grants wait\n * for the next Activation; removing the contribution revokes every resident\n * installation immediately.\n * @param contribution - synchronous child-scope installer.\n * @returns the exact Cordis effect disposer.\n */', + description: 'Compose one deployment capability into every continuable child\'s unpublished creation context on fresh creation and cold resume. Grants wait for the next Activation; removing the contribution revokes every resident installation immediately.', + parameters: [{ name: 'contribution', description: 'synchronous child-scope installer.' }], + returns: 'the exact Cordis effect disposer.', }, { signature: 'async drainContinuableDescendants(parents: readonly Agent[]): Promise', - jsDoc: '/**\n * Close continuable admission below exact live parent Agents, stop only their\n * visible descendant Activations synchronously, then await admitted scoped\n * materializations and release those forests child-first. The scoped cutoff\n * lasts until each exact parent leaves the registry; unrelated parent trees\n * remain live.\n * @param parents - exact host-owned parent Agents entering teardown.\n * @returns once every retained descendant Activation released its `AgentHandle`.\n * @throws an aggregate error after all branches settle when any failed.\n */', + description: 'Close continuable admission below exact live parent Agents, stop only their visible descendant Activations synchronously, then await admitted scoped materializations and release those forests child-first. The scoped cutoff lasts until each exact parent leaves the registry; unrelated parent trees remain live.', + parameters: [{ name: 'parents', description: 'exact host-owned parent Agents entering teardown.' }], + returns: 'once every retained descendant Activation released its `AgentHandle`.', + throws: ['an aggregate error after all branches settle when any failed.'], }, { signature: 'listChildren(parentSessionId: SessionId, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Enumerate the parent\'s direct session-backed subagents without loading or\n * resuming an Agent and without any query service: the listing merges the live\n * session store with optional session persistence (live-preferred) and\n * serves each child\'s durable mode/label from the registered `subagent`\n * projection unit down a three-rung ladder — the registry\'s watermark\n * snapshot for a live child; for a cold one, a durable projection-cache\n * row when the optional cache serves an own-suffix identity (its `seq`\n * gate proves the value postdates the fork seed, where a child\'s own\n * descriptor is immutable once appended), else one persistence inspection\n * folded through the registry. The\n * projection fold is the single classification authority; per-child\n * diagnostics relay a fold that served no identity or a failed inspection,\n * never a list-time descriptor parse. Absent persistence, enumeration is\n * live-only (a cold child cannot be resumed then either, so its absence is\n * capability absence, not an error). This service consults no Agent\n * registrations, Activations, or providers.\n *\n * Every persistence read receives `signal`, and the listing rechecks\n * cancellation around each of those awaits. Read rejections that settle\n * after an abort become a stable `SubagentError` with code `CANCELLED`.\n * @param parentSessionId - parent session whose direct children are listed.\n * @param signal - caller-owned cancellation forwarded to persistence reads\n * and observed around every read await.\n * @returns children and per-child diagnostics ordered by `createdAt`, then id.\n * @throws {@link SubagentError} when the projection registry or the session\n * store is not mounted, or the caller cancels the listing.\n */', + description: 'Enumerate the parent\'s direct session-backed subagents without loading or resuming an Agent and without any query service: the listing merges the live session store with optional session persistence (live-preferred) and serves each child\'s durable mode/label from the registered `subagent` projection unit down a three-rung ladder — the registry\'s watermark snapshot for a live child; for a cold one, a durable projection-cache row when the optional cache serves an own-suffix identity (its `seq` gate proves the value postdates the fork seed, where a child\'s own descriptor is immutable once appended), else one persistence inspection folded through the registry. The projection fold is the single classification authority; per-child diagnostics relay a fold that served no identity or a failed inspection, never a list-time descriptor parse. Absent persistence, enumeration is live-only (a cold child cannot be resumed then either, so its absence is capability absence, not an error). This service consults no Agent registrations, Activations, or providers.\n\nEvery persistence read receives `signal`, and the listing rechecks cancellation around each of those awaits. Read rejections that settle after an abort become a stable `SubagentError` with code `CANCELLED`.', + parameters: [{ name: 'parentSessionId', description: 'parent session whose direct children are listed.' }, { name: 'signal', description: 'caller-owned cancellation forwarded to persistence reads and observed around every read await.' }], + returns: 'children and per-child diagnostics ordered by `createdAt`, then id.', + throws: ['{@link SubagentError} when the projection registry or the session store is not mounted, or the caller cancels the listing.'], }, { signature: 'listDescendants(rootSessionId: SessionId, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Enumerate the root\'s complete session-backed subagent tree in stable\n * pre-order from one live-preferred corpus, without loading or resuming an\n * Agent. Ordinary sessions and one-shot children remain traversal nodes so\n * continuable descendants below them are discovered; each returned entry\n * adds its durable `parentId` and root-relative `depth`. Identity resolution,\n * diagnostics, optional persistence, and cancellation follow the same\n * projection-backed contract as {@link listChildren}.\n * @param rootSessionId - session whose complete descendant tree is listed.\n * @param signal - caller-owned cancellation forwarded to persistence reads\n * and observed around every read await.\n * @returns children and per-candidate diagnostics with tree position, in\n * stable pre-order.\n * @throws {@link SubagentError} under the same conditions as {@link listChildren}.\n */', + description: 'Enumerate the root\'s complete session-backed subagent tree in stable pre-order from one live-preferred corpus, without loading or resuming an Agent. Ordinary sessions and one-shot children remain traversal nodes so continuable descendants below them are discovered; each returned entry adds its durable `parentId` and root-relative `depth`. Identity resolution, diagnostics, optional persistence, and cancellation follow the same projection-backed contract as listChildren.', + parameters: [{ name: 'rootSessionId', description: 'session whose complete descendant tree is listed.' }, { name: 'signal', description: 'caller-owned cancellation forwarded to persistence reads and observed around every read await.' }], + returns: 'children and per-candidate diagnostics with tree position, in stable pre-order.', + throws: ['{@link SubagentError} under the same conditions as {@link listChildren}.'], }, { signature: 'registerProvider(provider: SubagentProvider): () => void', - jsDoc: '/**\n * Register a provider under its name. Registration is effect-scoped and HMR\n * safe; removing a provider blocks new starts but does not revoke runs that\n * were already returned to their holders.\n * @param provider - the trusted provider implementation.\n * @returns the exact Cordis effect disposer.\n */', + description: 'Register a provider under its name. Registration is effect-scoped and HMR safe; removing a provider blocks new starts but does not revoke runs that were already returned to their holders.', + parameters: [{ name: 'provider', description: 'the trusted provider implementation.' }], + returns: 'the exact Cordis effect disposer.', }, { signature: 'getProvider(name: string): SubagentProvider | undefined', - jsDoc: '/**\n * Look up a provider by name.\n * @param name - the provider name.\n * @returns the provider, or undefined when absent.\n */', + description: 'Look up a provider by name.', + parameters: [{ name: 'name', description: 'the provider name.' }], + returns: 'the provider, or undefined when absent.', }, { signature: 'list(): string[]', - jsDoc: '/**\n * List registered provider names in insertion order.\n * @returns the registered names.\n */', + description: 'List registered provider names in insertion order.', + parameters: [], + returns: 'the registered names.', }, { signature: 'async start(name: string, request: SubagentStartRequest): Promise', - jsDoc: '/**\n * Establish a published child on the named provider. Capability and semantic\n * checks run before delegation. Provider ownership lasts until its promise\n * fulfills; a rejection therefore has no run for the caller to dispose and\n * emits no run lifecycle events. Post-publication turn and infrastructure\n * failures settle through the returned run.\n * @param name - the provider to use.\n * @param request - child label, prompt, parent, signal, and optional capabilities.\n * @returns the published holder-owned run.\n */', + description: 'Establish a published child on the named provider. Capability and semantic checks run before delegation. Provider ownership lasts until its promise fulfills; a rejection therefore has no run for the caller to dispose and emits no run lifecycle events. Post-publication turn and infrastructure failures settle through the returned run.', + parameters: [{ name: 'name', description: 'the provider to use.' }, { name: 'request', description: 'child label, prompt, parent, signal, and optional capabilities.' }], + returns: 'the published holder-owned run.', }, ], }, { key: 'subprocess', summary: 'Abstract subprocess service.', + description: 'Abstract subprocess service. Subclass, implement spawn, and load the subclass as a plugin — it registers as `ctx.subprocess` (one implementation per context; loading a second throws, which is cordis\' standard duplicate-service behavior).\n\nImplementations must honor these semantics:\n\n- Executable paths belong to one execution world shared with the mounted filesystem provider.\n- spawn returns immediately with a live handle; `done` resolves at process close with exit facts and rejects only for spawn-level failures.\n- Collect-mode readers are offset-based and non-consuming, so independent readers never consume one another\'s output; lossy reads report truncation and the spill file holding the complete stream when one exists. Piped streams are handed to the caller raw and never buffered here.\n- SubprocessHandle.terminate (and the spec\'s abort signal) escalates SIGTERM→grace→SIGKILL — the only termination verb — tree-scoped on every platform. SubprocessHandle.waitForExit observes whole-tree liveness, so a consumer-owned teardown ladder can hold each tier on real quiescence.\n- Disposal of the service terminates all still-running managed processes and awaits their exit.\n- spawnTerminal owns terminal allocation, text transport, foreground groups, signalling, and whole-session quiescence behind one awaited termination method; readiness and persistent-shell policy stay in the PTY consumer. Its output stream ends after queued terminal output when the top-level process exits.', methods: [ { signature: 'abstract resolveExecutable( command: string, env?: Readonly>, signal?: AbortSignal, ): Promise', - jsDoc: '/**\n * Resolve one configured executable in this provider\'s execution world.\n * Absolute paths are verified; bare names use the provider\'s scrubbed PATH\n * plus explicit environment overrides. Relative paths containing separators\n * are rejected: the resolution base is undefined, so providers fail loud\n * instead of guessing.\n * @param command - absolute executable path or bare PATH name.\n * @param env - explicit environment entries used for lookup.\n * @param signal - aborts remote or local lookup.\n * @returns a canonical executable path.\n */', + description: 'Resolve one configured executable in this provider\'s execution world. Absolute paths are verified; bare names use the provider\'s scrubbed PATH plus explicit environment overrides. Relative paths containing separators are rejected: the resolution base is undefined, so providers fail loud instead of guessing.', + parameters: [{ name: 'command', description: 'absolute executable path or bare PATH name.' }, { name: 'env', description: 'explicit environment entries used for lookup.' }, { name: 'signal', description: 'aborts remote or local lookup.' }], + returns: 'a canonical executable path.', }, { signature: 'abstract spawn(spec: SubprocessSpawnSpec): SubprocessHandle', - jsDoc: '/**\n * Start one managed child process from a fully-specified spec; this seam\n * applies no defaults.\n * @param spec - argv, directory, stdio dispositions, grace, cancellation, and environment.\n * @returns the live process handle (streams/readers, signalling, outcome promise).\n */', + description: 'Start one managed child process from a fully-specified spec; this seam applies no defaults.', + parameters: [{ name: 'spec', description: 'argv, directory, stdio dispositions, grace, cancellation, and environment.' }], + returns: 'the live process handle (streams/readers, signalling, outcome promise).', }, { signature: 'abstract spawnTerminal(spec: SubprocessTerminalSpawnSpec): Promise', - jsDoc: '/**\n * Allocate a real terminal and start one owned process session. This is the\n * only non-pipe process primitive: implementations own terminal byte I/O,\n * foreground groups, signals, and complete session-tree cleanup.\n * @param spec - fully specified argv, cwd, environment, dimensions, grace, and allocation cancellation.\n * @returns the live terminal handle after allocation succeeds.\n */', + description: 'Allocate a real terminal and start one owned process session. This is the only non-pipe process primitive: implementations own terminal byte I/O, foreground groups, signals, and complete session-tree cleanup.', + parameters: [{ name: 'spec', description: 'fully specified argv, cwd, environment, dimensions, grace, and allocation cancellation.' }], + returns: 'the live terminal handle after allocation succeeds.', }, ], }, { key: 'systemPrompt', summary: 'Registry service for the prompt inputs assembled before each model step.', + description: 'Registry service for the prompt inputs assembled before each model step.', methods: [ { signature: 'section(section: PromptSection): () => void', - jsDoc: '/**\n * Register an ordered prompt section in the calling context\'s scope. A scoped\n * section shadows a global section with the same name; duplicates within one\n * layer and non-finite orders throw. Registration and disposal emit\n * `system-prompt/change`.\n * @param section - the section to register.\n * @returns the exact Cordis effect disposer.\n */', + description: 'Register an ordered prompt section in the calling context\'s scope. A scoped section shadows a global section with the same name; duplicates within one layer and non-finite orders throw. Registration and disposal emit `system-prompt/change`.', + parameters: [{ name: 'section', description: 'the section to register.' }], + returns: 'the exact Cordis effect disposer.', }, { signature: 'context(context: PromptContext): () => void', - jsDoc: '/**\n * Register ordered dynamic context in the calling context\'s scope. Scoped\n * entries shadow global entries with the same name.\n * @param context - the context contribution to register.\n * @returns the exact Cordis effect disposer.\n */', + description: 'Register ordered dynamic context in the calling context\'s scope. Scoped entries shadow global entries with the same name.', + parameters: [{ name: 'context', description: 'the context contribution to register.' }], + returns: 'the exact Cordis effect disposer.', }, { signature: 'tools(provider: (context: AssembleContext) => ToolProviderResult): () => void', - jsDoc: '/**\n * Register a tool-schema provider in the calling context\'s scope. Global and\n * matching scoped providers both contribute; returning the reserved\n * {@link TOOL_ORDER_REST} name makes assembly fail.\n * @param provider - evaluated for each assembly with its context.\n * @returns the exact Cordis effect disposer.\n */', + description: 'Register a tool-schema provider in the calling context\'s scope. Global and matching scoped providers both contribute; returning the reserved TOOL_ORDER_REST name makes assembly fail.', + parameters: [{ name: 'provider', description: 'evaluated for each assembly with its context.' }], + returns: 'the exact Cordis effect disposer.', }, { signature: 'variable(name: string, provider: (context: AssembleContext) => string | undefined): () => void', - jsDoc: '/**\n * Register a prompt variable in the calling context\'s scope. Scoped values\n * shadow globals; invalid or duplicate names throw. A provider may return\n * `undefined`, but rendering a section that references that value then fails.\n * @param name - the `[a-z][a-z0-9_]*` reference name.\n * @param provider - evaluated for each assembly.\n * @returns the exact Cordis effect disposer.\n */', + description: 'Register a prompt variable in the calling context\'s scope. Scoped values shadow globals; invalid or duplicate names throw. A provider may return `undefined`, but rendering a section that references that value then fails.', + parameters: [{ name: 'name', description: 'the `[a-z][a-z0-9_]*` reference name.' }, { name: 'provider', description: 'evaluated for each assembly.' }], + returns: 'the exact Cordis effect disposer.', }, { signature: 'async assemble(context: AssembleContext = {}): Promise', - jsDoc: '/**\n * Assemble global and scoped providers, detach tool parameters, apply\n * canonical ordering, then run the assembly waterfall. Scoped sections and\n * variables shadow globals. The returned waterfall value is authoritative\n * except that an effective complete section is restored afterwards as the\n * sole prompt section.\n * @param context - the optional scope and plugin-defined assembly fields.\n * @returns the post-waterfall assembly with any complete prompt enforced.\n */', + description: 'Assemble global and scoped providers, detach tool parameters, apply canonical ordering, then run the assembly waterfall. Scoped sections and variables shadow globals. The returned waterfall value is authoritative except that an effective complete section is restored afterwards as the sole prompt section.', + parameters: [{ name: 'context', description: 'the optional scope and plugin-defined assembly fields.' }], + returns: 'the post-waterfall assembly with any complete prompt enforced.', }, ], }, { key: 'terminals', summary: 'In-process registry for replaceable PTY backends and exact-Agent sessions.', + description: 'In-process registry for replaceable PTY backends and exact-Agent sessions.', methods: [ { signature: 'registerBackend(backend: TerminalBackend): () => void', - jsDoc: '/**\n * Register one backend type for this effect scope.\n * @param backend - provider with a non-empty unique type.\n * @returns disposer that removes exactly this contribution.\n */', + description: 'Register one backend type for this effect scope.', + parameters: [{ name: 'backend', description: 'provider with a non-empty unique type.' }], + returns: 'disposer that removes exactly this contribution.', }, { signature: 'listBackends(): string[]', - jsDoc: '/**\n * List registered backend types in registration order.\n * @returns fresh backend type names.\n */', + description: 'List registered backend types in registration order.', + parameters: [], + returns: 'fresh backend type names.', }, { signature: 'async spawn(owner: Agent, request: TerminalSpawnRequest, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Create and publish one owner-scoped session after backend setup succeeds.\n * @param owner - exact registered Agent that owns access and cleanup.\n * @param request - backend type plus optional owner-local name and cwd.\n * @param signal - cancellation of unpublished setup.\n * @returns published identity, metadata, status, and MOTD.\n */', + description: 'Create and publish one owner-scoped session after backend setup succeeds.', + parameters: [{ name: 'owner', description: 'exact registered Agent that owns access and cleanup.' }, { name: 'request', description: 'backend type plus optional owner-local name and cwd.' }, { name: 'signal', description: 'cancellation of unpublished setup.' }], + returns: 'published identity, metadata, status, and MOTD.', }, { signature: 'hasOwnerActivity(owner: Agent): boolean', - jsDoc: '/**\n * Test whether an exact owner has a published session or unpublished spawn.\n * @param owner - exact live owner to inspect.\n * @returns true across the entire spawn-to-close interval, with no publication gap.\n */', + description: 'Test whether an exact owner has a published session or unpublished spawn.', + parameters: [{ name: 'owner', description: 'exact live owner to inspect.' }], + returns: 'true across the entire spawn-to-close interval, with no publication gap.', }, { signature: 'startSend(owner: Agent, id: TerminalSessionId, request: TerminalSendRequest): TerminalSendOperation', - jsDoc: '/**\n * Start one exclusive interactive send.\n * @param owner - exact session owner.\n * @param id - target PTY identity.\n * @param request - explicit text, submit behavior, and cancellation.\n * @returns live operation handle for foreground await or task registration.\n */', + description: 'Start one exclusive interactive send.', + parameters: [{ name: 'owner', description: 'exact session owner.' }, { name: 'id', description: 'target PTY identity.' }, { name: 'request', description: 'explicit text, submit behavior, and cancellation.' }], + returns: 'live operation handle for foreground await or task registration.', }, { signature: 'read(owner: Agent, id: TerminalSessionId, request: TerminalReadRequest = {}): TerminalReadResult', - jsDoc: '/**\n * Read one bounded scrollback page from an owned session.\n * @param owner - exact session owner.\n * @param id - target PTY identity.\n * @param request - optional newest-relative offset and line count.\n * @returns bounded retained text and pagination metadata.\n */', + description: 'Read one bounded scrollback page from an owned session.', + parameters: [{ name: 'owner', description: 'exact session owner.' }, { name: 'id', description: 'target PTY identity.' }, { name: 'request', description: 'optional newest-relative offset and line count.' }], + returns: 'bounded retained text and pagination metadata.', }, { signature: 'signal(owner: Agent, id: TerminalSessionId, signal: TerminalSignal): Promise', - 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 */', + description: 'Deliver an allowed signal through an owned backend session.', + parameters: [{ name: 'owner', description: 'exact session owner.' }, { name: 'id', description: 'target PTY identity.' }, { name: 'signal', description: 'allowed POSIX signal name.' }], + returns: 'delivered foreground process-group identity.', }, { signature: 'async kill(owner: Agent, id: TerminalSessionId, reason: string = \'model request\'): Promise', - 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 */', + description: 'Close one owned session and remove it only after quiescent backend cleanup.', + parameters: [{ name: 'owner', description: 'exact session owner.' }, { name: 'id', description: 'target PTY identity.' }, { name: 'reason', description: 'diagnostic cleanup reason.' }], + returns: 'true for a newly closed session, false when the same close is already in flight.', }, { signature: 'list(owner: Agent): TerminalSessionSnapshot[]', - jsDoc: '/**\n * List fresh snapshots for exactly one owner.\n * @param owner - exact owner whose sessions are visible.\n * @returns owner-visible snapshots in publication order.\n */', + description: 'List fresh snapshots for exactly one owner.', + parameters: [{ name: 'owner', description: 'exact owner whose sessions are visible.' }], + returns: 'owner-visible snapshots in publication order.', + }, + ], + }, + { + key: 'timer', + summary: 'Disposable timer helpers mixed into Cordis contexts.', + description: 'Disposable timer helpers mixed into Cordis contexts.', + methods: [ + { + signature: 'timeout(callback: () => void, delay: number): () => void', + description: 'Run a callback once and return its disposer.', + parameters: [], + }, + { + signature: 'timeout(delay: number): Promise', + description: 'Resolve after a delay; disposal rejects the pending promise.', + parameters: [], + }, + { + signature: 'interval(callback: () => void, delay: number): () => void', + description: 'Run a callback repeatedly and return its disposer.', + parameters: [], + }, + { + signature: 'interval(delay: number): AsyncIterableIterator', + description: 'Return an async iterator of timer ticks.', + parameters: [], + }, + { + signature: 'throttle void>(callback: F, delay: number, noTrailing?: boolean): F & { dispose: () => void }', + description: 'Return a throttled function whose timer is disposed with the current fiber.', + parameters: [], + }, + { + signature: 'debounce void>(callback: F, delay: number): F & { dispose: () => void }', + description: 'Return a debounced function whose timer is disposed with the current fiber.', + parameters: [], }, ], }, { key: 'tokenMeter', summary: 'Replay owner for one service-wide estimator and isolated per-session folds.', + description: 'Replay owner for one service-wide estimator and isolated per-session folds.', methods: [ { signature: 'measure(session: Session, requestHeader?: EpochHeader): TokenMeasurement', - jsDoc: '/**\n * Measure current request pressure and surface through the durable tail.\n *\n * Provider usage is reused only when the latest successful call\'s canonical\n * request envelope matches `requestHeader` and its total is no lower than\n * that call\'s full heuristic anchor; otherwise the complete envelope and\n * surface are heuristically repriced.\n *\n * `requestHeader` affects request pressure only; surface fields always\n * describe the current session surface. Every call clones those positional\n * nodes, so measurement is O(surface).\n *\n * @param session - session to replay through its current durable tail.\n * @param requestHeader - optional effective request envelope replacing the latest logged header.\n * @returns a detached deeply immutable pressure and surface measurement.\n */', + description: 'Measure current request pressure and surface through the durable tail.\n\nProvider usage is reused only when the latest successful call\'s canonical request envelope matches `requestHeader` and its total is no lower than that call\'s full heuristic anchor; otherwise the complete envelope and surface are heuristically repriced.\n\n`requestHeader` affects request pressure only; surface fields always describe the current session surface. Every call clones those positional nodes, so measurement is O(surface).', + parameters: [{ name: 'session', description: 'session to replay through its current durable tail.' }, { name: 'requestHeader', description: 'optional effective request envelope replacing the latest logged header.' }], + returns: 'a detached deeply immutable pressure and surface measurement.', }, { signature: 'estimateMessage(message: Message): number', - jsDoc: '/**\n * Heuristically price one model-visible message (instance face of the pure\n * `estimateMessage` export from `estimate.ts`).\n * @param message - message to price without mutation.\n * @returns content and role-framing tokens under the fixed service heuristic.\n */', + description: 'Heuristically price one model-visible message (instance face of the pure `estimateMessage` export from `estimate.ts`).', + parameters: [{ name: 'message', description: 'message to price without mutation.' }], + returns: 'content and role-framing tokens under the fixed service heuristic.', }, ], }, { key: 'toolResultPruner', summary: 'Deterministic head/middle/tail pruning for current tool-result surface nodes.', + description: 'Deterministic head/middle/tail pruning for current tool-result surface nodes.', methods: [ + { + signature: 'readonly config: ResolvedConfig', + description: 'Resolved and immutable character budgets.', + parameters: [], + }, { signature: 'measureContent(blocks: readonly ContentBlock[]): number', - jsDoc: '/**\n * Measure text content in Unicode code points; non-text blocks cost zero.\n * @param blocks - tool-result content to measure.\n * @returns total Unicode code points across text blocks.\n */', + description: 'Measure text content in Unicode code points; non-text blocks cost zero.', + parameters: [{ name: 'blocks', description: 'tool-result content to measure.' }], + returns: 'total Unicode code points across text blocks.', }, { signature: 'pruneContent(blocks: readonly ContentBlock[]): ContentBlock[] | null', - jsDoc: '/**\n * Replace an over-budget text middle while retaining rich-block order.\n * Text slicing is by Unicode code point, not UTF-16 code unit, so a retained\n * boundary cannot split a surrogate pair. Grapheme clusters may still split.\n * @param blocks - original tool-result content.\n * @returns pruned content, or `null` when the text is within budget.\n */', + description: 'Replace an over-budget text middle while retaining rich-block order. Text slicing is by Unicode code point, not UTF-16 code unit, so a retained boundary cannot split a surrogate pair. Grapheme clusters may still split.', + parameters: [{ name: 'blocks', description: 'original tool-result content.' }], + returns: 'pruned content, or `null` when the text is within budget.', }, { signature: 'pruneSession(session: Session): PruneResult', - jsDoc: '/**\n * Prune every over-budget tool result from one stable current-surface snapshot.\n * Each replacement preserves the complete event data except for `content`,\n * cites the shadowed node so replay can recover the replacement input, and is\n * immediately preceded by a `compaction/prune` shadow-price event pricing the\n * shadowed node through the injected token meter, so pure consumers can\n * subtract it without per-node state.\n * @param session - session whose current surface is rewritten.\n * @returns landed replacements and aggregate Unicode-code-point savings.\n * @throws when the session rejects a replacement; replacements committed\n * earlier in the pass remain durable.\n */', + description: 'Prune every over-budget tool result from one stable current-surface snapshot. Each replacement preserves the complete event data except for `content`, cites the shadowed node so replay can recover the replacement input, and is immediately preceded by a `compaction/prune` shadow-price event pricing the shadowed node through the injected token meter, so pure consumers can subtract it without per-node state.', + parameters: [{ name: 'session', description: 'session whose current surface is rewritten.' }], + returns: 'landed replacements and aggregate Unicode-code-point savings.', + throws: ['when the session rejects a replacement; replacements committed earlier in the pass remain durable.'], }, ], }, { key: 'tools', summary: 'Tool registry and execution pipeline.', + description: 'Tool registry and execution pipeline. Scoped registrations shadow globals; one visibility resolver feeds presentation, lookup, and dispatch.', methods: [ { signature: 'presentAs(mode: ToolPresentationMode): () => void', - jsDoc: '/**\n * Present the calling scope\'s tools in `mode` instead of the deployment\n * default. Nearest scope on the chain wins, so a preset\'s standing\n * declaration covers every agent joined under it.\n *\n * Scoped only, and one declaration per scope: this is how an agent preset\n * composes Code Mode agents beside native ones in the same process, and a\n * process-global override would be the `mode` config field instead.\n * @param mode - the presentation the covered agents\' models see.\n * @returns the exact disposer that restores the deployment default.\n */', + description: 'Present the calling scope\'s tools in `mode` instead of the deployment default. Nearest scope on the chain wins, so a preset\'s standing declaration covers every agent joined under it.\n\nScoped only, and one declaration per scope: this is how an agent preset composes Code Mode agents beside native ones in the same process, and a process-global override would be the `mode` config field instead.', + parameters: [{ name: 'mode', description: 'the presentation the covered agents\' models see.' }], + returns: 'the exact disposer that restores the deployment default.', }, { signature: 'register(definition: ToolDefinition): () => void', - jsDoc: '/**\n * Register globally or in the calling agent scope. Scoped tools shadow\n * globals; duplicates within one layer and the reserved `run_code` name fail.\n * @param definition - tool schema, execution, and optional finalization/presentation callbacks.\n * @returns the exact disposer that unregisters the tool.\n */', + description: 'Register globally or in the calling agent scope. Scoped tools shadow globals; duplicates within one layer and the reserved `run_code` name fail.', + parameters: [{ name: 'definition', description: 'tool schema, execution, and optional finalization/presentation callbacks.' }], + returns: 'the exact disposer that unregisters the tool.', }, { signature: 'restrict(filter: ToolRestriction): () => void', - jsDoc: '/**\n * Restrict global tools for the calling agent scope. Empty filters, unknown\n * names, scope-local names, and reserved transport names fail. Restrictions\n * intersect; scoped registrations remain visible.\n * @param filter - global-tool mask: `allow` (keep only) and/or `deny` (remove).\n * @returns the exact disposer that lifts this restriction.\n */', + description: 'Restrict global tools for the calling agent scope. Empty filters, unknown names, scope-local names, and reserved transport names fail. Restrictions intersect; scoped registrations remain visible.', + parameters: [{ name: 'filter', description: 'global-tool mask: `allow` (keep only) and/or `deny` (remove).' }], + returns: 'the exact disposer that lifts this restriction.', }, { signature: 'guard(guard: ToolGuard): () => void', - jsDoc: '/**\n * Register a monotonic guard after the extensible `tools/pre-execute`\n * waterfall. A plain-context guard applies globally; one registered through\n * `agent.ctx` applies only to that agent. Any matching guard may deny by\n * returning a reason, while no guard can force-allow a call another guard\n * denied. The exact effect disposer is returned for ordered ownership and\n * HMR cleanup.\n * @param guard - synchronous check; a returned string denies the execution.\n * @returns the exact disposer that unregisters the guard.\n */', + description: 'Register a monotonic guard after the extensible `tools/pre-execute` waterfall. A plain-context guard applies globally; one registered through `agent.ctx` applies only to that agent. Any matching guard may deny by returning a reason, while no guard can force-allow a call another guard denied. The exact effect disposer is returned for ordered ownership and HMR cleanup.', + parameters: [{ name: 'guard', description: 'synchronous check; a returned string denies the execution.' }], + returns: 'the exact disposer that unregisters the guard.', }, { signature: 'get(name: string, scope?: ScopeKey): ToolDefinition | undefined', - jsDoc: '/**\n * Look up a tool as one scope sees it (scoped\n * shadows global; a restricted-away global reads as absent). Presenters pass\n * the calling agent so the rendered card matches the definition that\n * actually executed.\n * @param name - the tool name as registered.\n * @param scope - the viewing scope (the agent); omitted = the global view.\n * @returns the definition the scope resolves, or undefined when none is visible.\n */', + description: 'Look up a tool as one scope sees it (scoped shadows global; a restricted-away global reads as absent). Presenters pass the calling agent so the rendered card matches the definition that actually executed.', + parameters: [{ name: 'name', description: 'the tool name as registered.' }, { name: 'scope', description: 'the viewing scope (the agent); omitted = the global view.' }], + returns: 'the definition the scope resolves, or undefined when none is visible.', }, { signature: 'schemas(scope?: ScopeKey): ToolSchema[]', - jsDoc: '/**\n * Project visible definitions onto the allowlisted model-facing schema fields,\n * excluding execution and presentation callbacks.\n * @param scope - the viewing scope (the agent); omitted = the global view.\n * @returns one deep-cloned schema per visible tool.\n */', + description: 'Project visible definitions onto the allowlisted model-facing schema fields, excluding execution and presentation callbacks.', + parameters: [{ name: 'scope', description: 'the viewing scope (the agent); omitted = the global view.' }], + returns: 'one deep-cloned schema per visible tool.', }, { signature: 'executionMode(exec: ToolExecutionInput): ToolExecutionMode', - jsDoc: '/**\n * Classify a pending call through the caller\'s visible tool definition. Only\n * an exact `true` is parallel; unknown, hidden, undeclared, invalid, or\n * throwing classifiers are exclusive.\n * @param exec - call name, parsed arguments, and optional agent scope.\n * @returns the fail-closed scheduling mode.\n */', + description: 'Classify a pending call through the caller\'s visible tool definition. Only an exact `true` is parallel; unknown, hidden, undeclared, invalid, or throwing classifiers are exclusive.', + parameters: [{ name: 'exec', description: 'call name, parsed arguments, and optional agent scope.' }], + returns: 'the fail-closed scheduling mode.', }, { signature: 'async execute(exec: ToolExecutionInput): Promise', - jsDoc: '/**\n * Execute through pre-policy, guards, around-dispatch, post-policy,\n * definition-owned content finalization, and final notification. Tool and\n * listener failures resolve as materialized error results; an invisible tool\n * reports `UNKNOWN_TOOL`. The returned outcome is the same lossless, frozen\n * snapshot final observers receive. Cancellation\n * arriving after entry and before final result materialization skips a\n * not-yet-started body with `ABORTED_BEFORE_DISPATCH` or replaces a\n * successful started outcome with `ABORTED`; already-started work is still\n * drained and may retain a tool-owned structured error.\n * @param exec - the typed same-process call input. The registry assigns its\n * correlation token before policy begins.\n * @returns the materialized final result.\n */', + description: 'Execute through pre-policy, guards, around-dispatch, post-policy, definition-owned content finalization, and final notification. Tool and listener failures resolve as materialized error results; an invisible tool reports `UNKNOWN_TOOL`. The returned outcome is the same lossless, frozen snapshot final observers receive. Cancellation arriving after entry and before final result materialization skips a not-yet-started body with `ABORTED_BEFORE_DISPATCH` or replaces a successful started outcome with `ABORTED`; already-started work is still drained and may retain a tool-owned structured error.', + parameters: [{ name: 'exec', description: 'the typed same-process call input. The registry assigns its correlation token before policy begins.' }], + returns: 'the materialized final result.', }, ], }, { key: 'typert', summary: 'Registry of generated schemas, package reflection, invocations, and Remote dependency providers.', + description: 'Registry of generated schemas, package reflection, invocations, and Remote dependency providers.', methods: [ { signature: 'register(contribution: TypertContribution): TypertDisposer', - jsDoc: '/**\n * Register one generated contribution atomically for the calling fiber.\n * Duplicate package-face identities, schemas, invocation ids, or endpoints\n * reject the whole batch.\n * @param contribution - generated schemas, reflection, and Host invocations.\n * @returns the exact effect disposer that removes this contribution.\n */', + description: 'Register one generated contribution atomically for the calling fiber. Duplicate package-face identities, schemas, invocation ids, or endpoints reject the whole batch.', + parameters: [{ name: 'contribution', description: 'generated schemas, reflection, and Host invocations.' }], + returns: 'the exact effect disposer that removes this contribution.', }, { signature: 'get(key: string): TypertSchemaRecord | undefined', - jsDoc: '/**\n * Look up one schema by `#`.\n * @param key - global schema key.\n * @returns the live schema record, or `undefined` when absent.\n */', + description: 'Look up one schema by `#`.', + parameters: [{ name: 'key', description: 'global schema key.' }], + returns: 'the live schema record, or `undefined` when absent.', }, { 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 */', + description: 'Resolve one required schema.', + parameters: [{ name: 'key', description: 'global schema key.' }], + returns: 'the live schema record.', + throws: ['when the key is malformed, the package face is absent, or the schema is not contributed.'], }, { 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 */', + description: 'Enumerate live schemas in registration order.', + parameters: [{ name: 'filter', description: 'optional package and face restriction.' }], + returns: 'matching schema records.', }, { 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 */', + description: 'Look up generated reflection for one package face.', + parameters: [{ name: 'packageName', description: 'exact npm package name.' }, { name: 'face', description: 'face to query; defaults to the host runtime.' }], + returns: 'the live package record, or `undefined` when absent.', }, { 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 */', + description: 'Enumerate generated package reflection in registration order.', + parameters: [{ name: 'filter', description: 'optional package and face restriction.' }], + returns: 'matching package records.', }, { 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 */', + description: 'Project a live Zod schema to JSON Schema without caching the result.', + parameters: [{ name: 'key', description: 'global schema key.' }, { name: 'params', description: 'Zod projection parameters.' }], + returns: 'a fresh JSON Schema document.', }, ], }, { key: 'typertGateway', summary: 'Resolve strict generated definitions or conservative SRC markers against current Cordis Services and Typert providers.', + description: 'Resolve strict generated definitions or conservative SRC markers against current Cordis Services and Typert providers.', methods: [ { signature: 'async invoke(request: InvokeRemoteRequest): Promise', - jsDoc: '/**\n * Invoke one live Remote method through strict generated reflection or SRC markers.\n * @param request - decoded endpoint and exact named wire arguments.\n * @returns the validated business result.\n * @throws {@link TypertGatewayError} for dispatch, provider, or boundary failures; lookup-policy and business errors retain identity.\n */', + description: 'Invoke one live Remote method through strict generated reflection or SRC markers.', + parameters: [{ name: 'request', description: 'decoded endpoint and exact named wire arguments.' }], + returns: 'the validated business result.', + throws: ['{@link TypertGatewayError} for dispatch, provider, or boundary failures; lookup-policy and business errors retain identity.'], }, ], }, { key: 'userQuestions', summary: '`ctx.userQuestions`: one active UI provider plus an `ask()` API.', + description: '`ctx.userQuestions`: one active UI provider plus an `ask()` API.', methods: [ { signature: 'registerProvider(provider: UserQuestionProvider): () => void', - jsDoc: '/**\n * Register the UI provider. Only one provider may be active in a context.\n *\n * @param provider UI-side implementation that collects answers.\n * @returns Disposer that unregisters this provider.\n */', + description: 'Register the UI provider. Only one provider may be active in a context.', + parameters: [{ name: 'provider', description: 'UI-side implementation that collects answers.' }], + returns: 'Disposer that unregisters this provider.', }, { signature: 'async ask(request: AskUserQuestionRequest): Promise', - jsDoc: '/**\n * Ask the active UI provider and wait for the user\'s answer.\n *\n * When a caller supplies an agent, human interaction is valid only for the\n * exact live runtime root. Runtime ownership, not durable session lineage,\n * decides this boundary: an owned child has no human answerer and would\n * block forever, while a lineage-bearing session resumed as a new runtime\n * root may ask normally.\n *\n * @param request Questions, owner agent, and abort signal.\n * @returns The answer chosen or typed by the human.\n * @throws {UserQuestionError} code `CALLER_NOT_LIVE` when a supplied\n * agent is not the registry\'s exact live instance, or `DELEGATED_CALLER`\n * when that live agent is owned by another agent.\n */', + description: 'Ask the active UI provider and wait for the user\'s answer.\n\nWhen a caller supplies an agent, human interaction is valid only for the exact live runtime root. Runtime ownership, not durable session lineage, decides this boundary: an owned child has no human answerer and would block forever, while a lineage-bearing session resumed as a new runtime root may ask normally.', + parameters: [{ name: 'request', description: 'Questions, owner agent, and abort signal.' }], + returns: 'The answer chosen or typed by the human.', + throws: ['{UserQuestionError} code `CALLER_NOT_LIVE` when a supplied agent is not the registry\'s exact live instance, or `DELEGATED_CALLER` when that live agent is owned by another agent.'], }, ], }, { key: 'web', summary: 'The web access service.', + description: 'The web access service. Registered as `ctx.web` (one instance per context).\n\nSelection semantics (resolved at execution time, never order-dependent):\n\n- A configured id that is registered and `available()` → that provider.\n- A configured id not registered → `WEB_PROVIDER_CONFIGURED_MISSING`.\n- A configured id registered but unavailable → `WEB_PROVIDER_CONFIGURED_UNAVAILABLE`.\n- No id configured, exactly one registered usable provider → that provider.\n- No id configured, multiple usable providers → `WEB_PROVIDER_AMBIGUOUS`.\n- No id configured, no usable provider → `WEB_PROVIDER_UNAVAILABLE`.', methods: [ { signature: 'registerSearchProvider(provider: WebSearchProvider): () => void', - jsDoc: '/**\n * Register a search provider. Throws {@link WebError} `WEB_DUPLICATE_PROVIDER`\n * if its id is already registered for search. Returns a disposer; disposed\n * with the calling fiber.\n * @param provider - the provider; its `id` is the registry key.\n * @returns the disposer that unregisters the provider.\n */', + description: 'Register a search provider. Throws WebError `WEB_DUPLICATE_PROVIDER` if its id is already registered for search. Returns a disposer; disposed with the calling fiber.', + parameters: [{ name: 'provider', description: 'the provider; its `id` is the registry key.' }], + returns: 'the disposer that unregisters the provider.', }, { signature: 'registerFetchProvider(provider: WebFetchProvider): () => void', - jsDoc: '/**\n * Register a fetch provider. Throws {@link WebError} `WEB_DUPLICATE_PROVIDER`\n * if its id is already registered for fetch. Returns a disposer; disposed\n * with the calling fiber.\n * @param provider - the provider; its `id` is the registry key.\n * @returns the disposer that unregisters the provider.\n */', + description: 'Register a fetch provider. Throws WebError `WEB_DUPLICATE_PROVIDER` if its id is already registered for fetch. Returns a disposer; disposed with the calling fiber.', + parameters: [{ name: 'provider', description: 'the provider; its `id` is the registry key.' }], + returns: 'the disposer that unregisters the provider.', }, { signature: 'async search(request: WebSearchRequest, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Run one search through the selected provider. Resolves the provider at call\n * time with the selection rules above; throws {@link WebError} when the\n * capability cannot run. The seam enforces `request.maxResults` on the result:\n * if the provider over-returns, `sources[]` is truncated and `truncated` set.\n * @param request - the query and optional result limit.\n * @param signal - optional cancellation signal forwarded to the provider.\n * @returns the provider\'s results, capped to `request.maxResults`.\n */', + description: 'Run one search through the selected provider. Resolves the provider at call time with the selection rules above; throws WebError when the capability cannot run. The seam enforces `request.maxResults` on the result: if the provider over-returns, `sources[]` is truncated and `truncated` set.', + parameters: [{ name: 'request', description: 'the query and optional result limit.' }, { name: 'signal', description: 'optional cancellation signal forwarded to the provider.' }], + returns: 'the provider\'s results, capped to `request.maxResults`.', }, { signature: 'async fetch(request: WebFetchRequest, signal?: AbortSignal): Promise', - jsDoc: '/**\n * Retrieve one URL through the selected provider. Resolves the provider at\n * call time with the selection rules above; throws {@link WebError} when the\n * capability cannot run. A non-2xx response is a result, not a throw.\n * @param request - the URL plus retrieval options.\n * @param signal - optional cancellation signal forwarded to the provider.\n * @returns the retrieval outcome; non-2xx responses resolve descriptively.\n */', + description: 'Retrieve one URL through the selected provider. Resolves the provider at call time with the selection rules above; throws WebError when the capability cannot run. A non-2xx response is a result, not a throw.', + parameters: [{ name: 'request', description: 'the URL plus retrieval options.' }, { name: 'signal', description: 'optional cancellation signal forwarded to the provider.' }], + returns: 'the retrieval outcome; non-2xx responses resolve descriptively.', }, ], }, { key: 'webServer', summary: 'The browser HTTP carrier service.', + description: 'The browser HTTP carrier service. Activation listens immediately. Route registration order does not affect requests because configured named routes must be distinct, and the fallback handler answers anything not yet claimed during startup with 404 until its owner registers. A listen failure rejects initialization, and the boot process reports the failed fiber.', methods: [ { signature: 'register(route: WebRoute): () => void', - jsDoc: '/**\n * Register a named route. Duplicate (kind, path) throws — route patterns are\n * a composition-level contract, so a collision is a misconfiguration.\n * @param route - kind, path, and the owning handler.\n * @returns the disposer removing the route.\n */', + description: 'Register a named route. Duplicate (kind, path) throws — route patterns are a composition-level contract, so a collision is a misconfiguration.', + parameters: [{ name: 'route', description: 'kind, path, and the owning handler.' }], + returns: 'the disposer removing the route.', }, { signature: 'registerUpgrade(route: WebUpgradeRoute): () => void', - jsDoc: '/**\n * Register an exact-path HTTP upgrade route. Duplicate paths throw because\n * one socket can have only one protocol owner.\n * @param route - pathname and handler owning negotiation plus socket use.\n * @returns the disposer removing the route.\n */', + description: 'Register an exact-path HTTP upgrade route. Duplicate paths throw because one socket can have only one protocol owner.', + parameters: [{ name: 'route', description: 'pathname and handler owning negotiation plus socket use.' }], + returns: 'the disposer removing the route.', }, { signature: 'registerFallback(handler: WebRoute[\'handler\']): () => void', - jsDoc: '/**\n * Claim the fallback seat: the handler answering every request no named\n * route matches (the SPA dist server in the shipped Web composition). One\n * owner only — a second registration throws, because two fallbacks cannot\n * compose.\n * @param handler - owns the full response lifecycle of unmatched requests.\n * @returns the disposer releasing the seat.\n */', + description: 'Claim the fallback seat: the handler answering every request no named route matches (the SPA dist server in the shipped Web composition). One owner only — a second registration throws, because two fallbacks cannot compose.', + parameters: [{ name: 'handler', description: 'owns the full response lifecycle of unmatched requests.' }], + returns: 'the disposer releasing the seat.', }, { signature: 'tapIndex(transform: (html: string) => string): () => void', - jsDoc: '/**\n * Register an index.html transform, applied by the fallback owner to every\n * index response ({@link applyIndexTaps}) in registration order.\n * @param transform - pure html-to-html function.\n * @returns the disposer removing the transform.\n */', + description: 'Register an index.html transform, applied by the fallback owner to every index response (applyIndexTaps) in registration order.', + parameters: [{ name: 'transform', description: 'pure html-to-html function.' }], + returns: 'the disposer removing the transform.', }, { signature: 'applyIndexTaps(html: string): string', - jsDoc: '/**\n * Run an index.html body through the registered taps in registration order\n * — called by the fallback owner on every index response it renders.\n * @param html - the raw index.html body.\n * @returns the transformed body.\n */', + description: 'Run an index.html body through the registered taps in registration order — called by the fallback owner on every index response it renders.', + parameters: [{ name: 'html', description: 'the raw index.html body.' }], + returns: 'the transformed body.', }, ], }, { key: 'workflowEngine', summary: 'Workflow Service Definition contract.', + description: 'Workflow Service Definition contract. Invalid requests throw before publication; a live run is holder-owned, its result never rejects, cancellation and disposal are bounded, and disposal waits for child cleanup within that bound. Lifecycle listener failures are contained, and `workflow/end` fires exactly once as the result settles.', methods: [ { signature: 'abstract start(request: WorkflowStartRequest): WorkflowRun', - jsDoc: '/**\n * Parse and execute a workflow script.\n * @param request - the script, its `args`, the parent agent, and an\n * optional cancel signal.\n * @returns the live run; its `result` resolves when the script settles.\n */', + description: 'Parse and execute a workflow script.', + parameters: [{ name: 'request', description: 'the script, its `args`, the parent agent, and an optional cancel signal.' }], + returns: 'the live run; its `result` resolves when the script settles.', }, ], }, { key: 'workspaceRegistry', summary: 'Durable workspace registry.', + description: 'Durable workspace registry. Startup waits for `sessionPersistence`, builds one canonical-cwd header index, and completes the one-time history bootstrap before the service becomes active. The persistence dependency is mandatory so an unavailable peer can never be mistaken for an empty history and commit the initialized marker.', methods: [ { signature: 'async create(path: string, title?: string): Promise', - jsDoc: '/**\n * Create or reuse a workspace for an existing directory. The path is\n * canonicalized through `fs.realpath`; a nonexistent path rejects with the\n * original error and a non-directory rejects. Repeated calls for the same\n * canonical path return the existing entity without changing its title.\n * A newly created workspace is prepended to the durable registry order.\n * Different canonical paths may share a display title.\n * @param path - Existing directory to own, in any path spelling.\n * @param title - Display title used only when a new record is created.\n * @returns the existing or newly durable workspace.\n */', + description: 'Create or reuse a workspace for an existing directory. The path is canonicalized through `fs.realpath`; a nonexistent path rejects with the original error and a non-directory rejects. Repeated calls for the same canonical path return the existing entity without changing its title. A newly created workspace is prepended to the durable registry order. Different canonical paths may share a display title.', + parameters: [{ name: 'path', description: 'Existing directory to own, in any path spelling.' }, { name: 'title', description: 'Display title used only when a new record is created.' }], + returns: 'the existing or newly durable workspace.', }, { signature: 'get(id: WorkspaceId): Workspace | undefined', - jsDoc: '/**\n * Look up a workspace by id.\n * @param id - Workspace id.\n * @returns the workspace, or `undefined` when unknown.\n */', + description: 'Look up a workspace by id.', + parameters: [{ name: 'id', description: 'Workspace id.' }], + returns: 'the workspace, or `undefined` when unknown.', }, { signature: 'list(): Workspace[]', - jsDoc: '/**\n * Synchronous workspace projection in durable registry order. Every\n * entity\'s `sessionIds` getter is already filtered by the startup/live\n * canonical-cwd header index; this method performs no persistence reads.\n * @returns a fresh ordered array of workspace entities.\n */', + description: 'Synchronous workspace projection in durable registry order. Every entity\'s `sessionIds` getter is already filtered by the startup/live canonical-cwd header index; this method performs no persistence reads.', + parameters: [], + returns: 'a fresh ordered array of workspace entities.', }, { signature: 'delete(id: WorkspaceId): Promise', - jsDoc: '/**\n * Delete one workspace registration while retaining its directory and every\n * session log. The durable order is updated before the table deletion; a\n * failed table write restores the prior order and keeps the entity\n * published. Unknown ids are an idempotent no-op for domain callers.\n * @param id - Workspace registration to remove.\n * @returns `true` when a record was deleted, `false` when it was unknown.\n */', + description: 'Delete one workspace registration while retaining its directory and every session log. The durable order is updated before the table deletion; a failed table write restores the prior order and keeps the entity published. Unknown ids are an idempotent no-op for domain callers.', + parameters: [{ name: 'id', description: 'Workspace registration to remove.' }], + returns: '`true` when a record was deleted, `false` when it was unknown.', }, { signature: 'insertBefore(id: WorkspaceId, beforeId?: WorkspaceId): Promise', - jsDoc: '/**\n * Move one workspace within the durable display order, DOM-insertBefore-like.\n * With an anchor it lands before that workspace; without one it appends.\n * @param id - Workspace to move.\n * @param beforeId - Workspace anchor; omitted appends.\n * @returns the complete committed workspace order.\n */', + description: 'Move one workspace within the durable display order, DOM-insertBefore-like. With an anchor it lands before that workspace; without one it appends.', + parameters: [{ name: 'id', description: 'Workspace to move.' }, { name: 'beforeId', description: 'Workspace anchor; omitted appends.' }], + returns: 'the complete committed workspace order.', }, { signature: 'archiveSession(sessionId: SessionId): Promise', - jsDoc: '/**\n * Archive one session durably. The session must exist (live or in session\n * persistence); its workspace accounting — or lack of one — is irrelevant.\n * An already archived id resolves without writing.\n * @param sessionId - The session to archive.\n * @returns resolution after durability.\n */', + description: 'Archive one session durably. The session must exist (live or in session persistence); its workspace accounting — or lack of one — is irrelevant. An already archived id resolves without writing.', + parameters: [{ name: 'sessionId', description: 'The session to archive.' }], + returns: 'resolution after durability.', }, { signature: 'async resolveByPath(path: string): Promise', - jsDoc: '/**\n * Resolve by canonical directory path without creating or mutating a\n * workspace. A missing path rejects during `realpath`; an existing unowned\n * directory returns `undefined`.\n * @param path - Existing directory path in any spelling.\n * @returns the workspace owning the canonical path, when one exists.\n */', + description: 'Resolve by canonical directory path without creating or mutating a workspace. A missing path rejects during `realpath`; an existing unowned directory returns `undefined`.', + parameters: [{ name: 'path', description: 'Existing directory path in any spelling.' }], + returns: 'the workspace owning the canonical path, when one exists.', }, ], }, @@ -1406,355 +2155,453 @@ export const EVENT_API: readonly EventApiEntry[] = [ name: 'agent-loop/config-start-failed', mode: 'emit', signature: '\'agent-loop/config-start-failed\'(payload: { sessionId: SessionId; error: unknown }): void', - jsDoc: '/**\n * A declarative agent entry failed before it could publish a live agent.\n * Consumers that buffer work for the configured identity use this\n * transient signal to reject that work instead of waiting forever. Normal\n * factory teardown suppresses failures from the cancelled startup attempt.\n * @param payload.sessionId - exact shared agent/session identity that failed startup.\n * @param payload.error - persistence, setup, or publication failure.\n * @mode emit\n */', summary: 'A declarative agent entry failed before it could publish a live agent.', + description: 'A declarative agent entry failed before it could publish a live agent. Consumers that buffer work for the configured identity use this transient signal to reject that work instead of waiting forever. Normal factory teardown suppresses failures from the cancelled startup attempt.', + parameters: [{ name: 'payload', description: '.error - persistence, setup, or publication failure.' }], }, { name: 'agent-preset/selected', mode: 'emit', signature: '\'agent-preset/selected\'(sessionId: SessionId, agentPreset: string): void', - jsDoc: '/**\n * One session committed a different agent preset to its durable log.\n * Consumers invalidate only state derived from that session\'s composition.\n * @mode emit\n * @param sessionId - the session whose composition changed.\n * @param agentPreset - the preset recorded by the committed selection.\n */', summary: 'One session committed a different agent preset to its durable log.', + description: 'One session committed a different agent preset to its durable log. Consumers invalidate only state derived from that session\'s composition.', + parameters: [{ name: 'sessionId', description: 'the session whose composition changed.' }, { name: 'agentPreset', description: 'the preset recorded by the committed selection.' }], }, { name: 'agent/created', mode: 'emit', signature: '\'agent/created\'(this: Scoped, payload: { agent: Agent }): void', - jsDoc: '/**\n * A fully configured agent and live session were published. Setup is\n * composition-only; `agent/session-start` is the first startup-driving extension point.\n * Synchronous listener failure vetoes publication, while returned-promise\n * rejection is reported. Detach requested during dispatch waits until every\n * creation listener has observed the stable entry.\n * @param payload.agent - the newly registered agent with its live session and completed setup.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode emit\n */', summary: 'A fully configured agent and live session were published.', + description: 'A fully configured agent and live session were published. Setup is composition-only; `agent/session-start` is the first startup-driving extension point. Synchronous listener failure vetoes publication, while returned-promise rejection is reported. Detach requested during dispatch waits until every creation listener has observed the stable entry.', + parameters: [{ name: 'payload', description: '.agent - the newly registered agent with its live session and completed setup. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.' }], }, { name: 'agent/disposed', mode: 'emit', signature: '\'agent/disposed\'(this: Scoped, payload: { agent: Agent }): void', - jsDoc: '/**\n * An agent left the registry; AgentLoop emits this after driver quiescence\n * and scoped-registration unwind, but before session detachment. Custom\n * registry users own their driver-ordering contract.\n * @param payload.agent - the exact agent removed from the registry.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode emit\n */', summary: 'An agent left the registry; AgentLoop emits this after driver quiescence and scoped-registration unwind, but before session detachment.', + description: 'An agent left the registry; AgentLoop emits this after driver quiescence and scoped-registration unwind, but before session detachment. Custom registry users own their driver-ordering contract.', + parameters: [{ name: 'payload', description: '.agent - the exact agent removed from the registry. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.' }], }, { name: 'agent/error', mode: 'emit', signature: '\'agent/error\'(this: Scoped, payload: { agent: Agent; turn: number; step: number; error: unknown }): void', - jsDoc: '/**\n * A step or turn errored. The machine reports a failure here even when\n * the error has no in-turn position for a durable record.\n * @param payload.agent - the agent whose turn errored.\n * @param payload.turn - the turn in which the failure surfaced.\n * @param payload.step - the step at which the failure surfaced.\n * @param payload.error - the failure, verbatim.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode emit\n */', summary: 'A step or turn errored.', + description: 'A step or turn errored. The machine reports a failure here even when the error has no in-turn position for a durable record.', + parameters: [{ name: 'payload', description: '.error - the failure, verbatim. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.' }], }, { name: 'agent/inbox/claimed', mode: 'emit', signature: '\'agent/inbox/claimed\'(this: Scoped, payload: { agent: Agent; message: UserMessage; turn: number }): void', - jsDoc: '/**\n * One message left the inbox inside its open turn. If the proposed step\n * is rejected, the claimed message ends here: it is neither discarded nor\n * re-emitted as a user/message, and the turn closes without a step.\n * @param payload.agent - the agent whose inbox changed.\n * @param payload.message - the claimed message.\n * @param payload.turn - the owning turn.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode emit\n */', summary: 'One message left the inbox inside its open turn.', + description: 'One message left the inbox inside its open turn. If the proposed step is rejected, the claimed message ends here: it is neither discarded nor re-emitted as a user/message, and the turn closes without a step.', + parameters: [{ name: 'payload', description: '.turn - the owning turn. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.' }], }, { name: 'agent/inbox/discarded', mode: 'emit', signature: '\'agent/inbox/discarded\'(this: Scoped, payload: { agent: Agent; message: UserMessage }): void', - jsDoc: '/**\n * One message was discarded from the live inbox.\n * @param payload.agent - the agent whose inbox changed.\n * @param payload.message - the discarded message.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode emit\n */', summary: 'One message was discarded from the live inbox.', + description: 'One message was discarded from the live inbox.', + parameters: [{ name: 'payload', description: '.message - the discarded message. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.' }], }, { name: 'agent/inbox/inserted', mode: 'emit', signature: '\'agent/inbox/inserted\'(this: Scoped, payload: { agent: Agent; message: UserMessage }): void', - jsDoc: '/**\n * One message entered the live inbox.\n * @param payload.agent - the agent whose inbox changed.\n * @param payload.message - the inserted message.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode emit\n */', summary: 'One message entered the live inbox.', + description: 'One message entered the live inbox.', + parameters: [{ name: 'payload', description: '.message - the inserted message. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.' }], }, { name: 'agent/pre-step', mode: 'waterfall', signature: '\'agent/pre-step\'(this: Scoped, payload: { agent: Agent; messages: UserMessage[]; turn: number; step: number; signal: AbortSignal }, next: () => Promise): Promise', - jsDoc: '/**\n * Reject a proposed step or replace the messages that enter it. Calling\n * `next()` preserves the current messages.\n * @param payload.agent - the agent proposing the step.\n * @param payload.messages - messages removed from the inbox for this step.\n * @param payload.turn - the turn that will own the step.\n * @param payload.step - the step proposed by the loop.\n * @param payload.signal - the current turn\'s cancellation signal.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode waterfall\n */', summary: 'Reject a proposed step or replace the messages that enter it.', + description: 'Reject a proposed step or replace the messages that enter it. Calling `next()` preserves the current messages.', + parameters: [{ name: 'payload', description: '.signal - the current turn\'s cancellation signal. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.' }], }, { name: 'agent/request', mode: 'waterfall', signature: '\'agent/request\'(this: Scoped, payload: { agent: Agent; turn: number; step: number; signal: AbortSignal }, next: () => Promise): Promise', - jsDoc: '/**\n * Replace the frozen call configuration. `await next()` yields the config\n * the machine would use (agent options on the first request, the logged\n * header afterwards); return a replacement to switch. Model-visible\n * content must use logged channels; this waterfall cannot mutate messages.\n * @param payload.agent - the agent making the model call.\n * @param payload.turn - the open turn number.\n * @param payload.step - the step whose request this is.\n * @param payload.signal - the current turn\'s explicit abort signal.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode waterfall\n*/', summary: 'Replace the frozen call configuration.', + description: 'Replace the frozen call configuration. `await next()` yields the config the machine would use (agent options on the first request, the logged header afterwards); return a replacement to switch. Model-visible content must use logged channels; this waterfall cannot mutate messages.', + parameters: [{ name: 'payload', description: '.signal - the current turn\'s explicit abort signal. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.' }], }, { name: 'agent/request-error', mode: 'waterfall', signature: '\'agent/request-error\'(this: Scoped, payload: { agent: Agent; turn: number; step: number; provider: string; failure: LlmFailure; retryPolicy: ResolvedRetryPolicy | undefined; signal: AbortSignal }, next: () => Promise): Promise', - jsDoc: '/**\n * Handle one failed model-request attempt before the loop retries or closes\n * its step. A listener returns `{ kind: \'retry\' }` without calling `next()`\n * when it owns recovery, or calls `next()` to delegate. The default\n * `undefined` leaves the failure terminal.\n * @param payload.agent - the agent whose request failed.\n * @param payload.turn - the turn containing the failed request.\n * @param payload.step - the step containing the failed request attempt.\n * @param payload.provider - the provider selected for the failed request.\n * @param payload.failure - serializable facts normalized at the final adapter boundary.\n * @param payload.retryPolicy - the policy of the adapter registration that served the failed request.\n * @param payload.signal - the turn abort signal.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode waterfall\n */', summary: 'Handle one failed model-request attempt before the loop retries or closes its step.', + description: 'Handle one failed model-request attempt before the loop retries or closes its step. A listener returns `{ kind: \'retry\' }` without calling `next()` when it owns recovery, or calls `next()` to delegate. The default `undefined` leaves the failure terminal.', + parameters: [{ name: 'payload', description: '.signal - the turn abort signal. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.' }], }, { name: 'agent/session-start', mode: 'emit', signature: '\'agent/session-start\'(this: Scoped, payload: { agent: Agent; source: SessionStartSource }): void', - jsDoc: '/**\n * The session lifecycle began, once before the first turn. Use\n * `agent.inject()` to seed model-facing context. This is a notification, not\n * a veto; disposal requested by a lifecycle owner is rechecked before the\n * driver starts.\n * @param payload.agent - the agent whose session lifecycle began.\n * @param payload.source - why the session started (fresh startup, resume, …).\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode emit\n */', summary: 'The session lifecycle began, once before the first turn.', + description: 'The session lifecycle began, once before the first turn. Use `agent.inject()` to seed model-facing context. This is a notification, not a veto; disposal requested by a lifecycle owner is rechecked before the driver starts.', + parameters: [{ name: 'payload', description: '.source - why the session started (fresh startup, resume, …). Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.' }], }, { name: 'agent/status', mode: 'emit', signature: '\'agent/status\'(this: Scoped, payload: { agent: Agent; status: AgentStatus }): void', - jsDoc: '/**\n * Agent status changed (`idle` ⇄ `running`). A waking delivery enters\n * `running` synchronously after reserving cancellation; `idle` means no\n * driver remains scheduled or active.\n * @param payload.agent - the agent whose status flipped.\n * @param payload.status - the status just entered (the transition\'s destination).\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode emit\n */', summary: 'Agent status changed (`idle` ⇄ `running`).', + description: 'Agent status changed (`idle` ⇄ `running`). A waking delivery enters `running` synchronously after reserving cancellation; `idle` means no driver remains scheduled or active.', + parameters: [{ name: 'payload', description: '.status - the status just entered (the transition\'s destination). Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.' }], }, { name: 'agent/turn-stopping', mode: 'serial', signature: '\'agent/turn-stopping\'(this: Scoped, payload: { agent: Agent; turn: number; signal: AbortSignal }): Promise | void', - jsDoc: '/**\n * The turn is about to close: the model owes no response (no live tool\n * calls, no fresh steering). Awaited before the boundary commits — a\n * listener that objects steers (`agent.steer(...)`) and the machine\n * re-reads its inbox: fresh steering runs another step, none closes the\n * turn. Data decides, so listener order cannot change the outcome. The\n * inverse control (stop a tool loop early) is data too: a tool result\n * carrying `concludesTurn` ends the turn at its step. The conclusion\n * never short-circuits already-submitted next-step work: same-step\n * `additionalContexts` or racing steering still runs, and the turn\n * closes only when that inbox drains.\n * @param payload.agent - the agent whose turn is at its stop boundary.\n * @param payload.turn - the turn about to close.\n * @param payload.signal - the current turn\'s explicit abort signal.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @mode serial\n */', summary: 'The turn is about to close: the model owes no response (no live tool calls, no fresh steering).', + description: 'The turn is about to close: the model owes no response (no live tool calls, no fresh steering). Awaited before the boundary commits — a listener that objects steers (`agent.steer(...)`) and the machine re-reads its inbox: fresh steering runs another step, none closes the turn. Data decides, so listener order cannot change the outcome. The inverse control (stop a tool loop early) is data too: a tool result carrying `concludesTurn` ends the turn at its step. The conclusion never short-circuits already-submitted next-step work: same-step `additionalContexts` or racing steering still runs, and the turn closes only when that inbox drains.', + parameters: [{ name: 'payload', description: '.signal - the current turn\'s explicit abort signal. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.' }], }, { name: 'approval/request', mode: 'waterfall', signature: '\'approval/request\'(this: Scoped, req: ApprovalRequest, next: () => Promise): Promise', - jsDoc: '/**\n * Ask composed answerers for one decision. Return an outcome to claim the\n * request or call `next()`; failure yields the fail-closed default.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @param req - the pending decision (agent, tool identity, reason, signal).\n * @mode waterfall\n */', summary: 'Ask composed answerers for one decision.', + description: 'Ask composed answerers for one decision. Return an outcome to claim the request or call `next()`; failure yields the fail-closed default. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.', + parameters: [{ name: 'req', description: 'the pending decision (agent, tool identity, reason, signal).' }], }, { name: 'commands/change', mode: 'emit', signature: '\'commands/change\'(): void', - jsDoc: '/**\n * A command was registered or unregistered. This is an unfiltered registry\n * notification because a global or scoped change may affect any UI view.\n * Observer failures are contained and cannot veto the registry mutation.\n * @mode emit\n */', summary: 'A command was registered or unregistered.', + description: 'A command was registered or unregistered. This is an unfiltered registry notification because a global or scoped change may affect any UI view. Observer failures are contained and cannot veto the registry mutation.', + parameters: [], + }, + { + name: 'cordis/dynamic-package', + mode: 'emit', + signature: '\'cordis/dynamic-package\'(pkg: DynamicCordisPackage): void', + summary: 'One exact Plugin/Package activation is now live in the Host.', + description: 'One exact Plugin/Package activation is now live in the Host.', + parameters: [{ name: 'pkg', description: 'stable plugin, immutable package, run identity, and label.' }], + }, + { + name: 'cordis/dynamic-retract', + mode: 'emit', + signature: '\'cordis/dynamic-retract\'(retracted: DynamicCordisRetracted): void', + summary: 'One exact activation was withdrawn.', + description: 'One exact activation was withdrawn.', + parameters: [{ name: 'retracted', description: 'plugin, package, and run identity.' }], + }, + { + name: 'cordis/inspect-query', + mode: 'emit', + signature: '\'cordis/inspect-query\'(request: CordisInspectQueryRequest): void', + summary: 'Request a live read-only query from the Client inspect registry.', + description: 'Request a live read-only query from the Client inspect registry.', + parameters: [{ name: 'request', description: 'correlation, Session, provider, method, and JSON input.' }], + }, + { + name: 'cordis/inspect-query-resolved', + mode: 'emit', + signature: '\'cordis/inspect-query-resolved\'(resolved: CordisInspectQueryResolved): void', + summary: 'Notify every Client that an inspect query has settled or been cancelled.', + description: 'Notify every Client that an inspect query has settled or been cancelled.', + parameters: [{ name: 'resolved', description: 'exact query identity that is no longer answerable.' }], + }, + { + name: 'cordis/request-run', + mode: 'emit', + signature: '\'cordis/request-run\'(request: DynamicCordisRunRequest): void', + summary: 'A Client-bearing activation needs a browser page, and may require a user decision.', + description: 'A Client-bearing activation needs a browser page, and may require a user decision.', + parameters: [{ name: 'request', description: 'correlation identity, owner, target version, mode, and approval requirement.' }], + }, + { + name: 'cordis/request-run-resolved', + mode: 'emit', + signature: '\'cordis/request-run-resolved\'(resolved: DynamicCordisRequestResolved): void', + summary: 'A pending Client activation request left the answerable state.', + description: 'A pending Client activation request left the answerable state.', + parameters: [{ name: 'resolved', description: 'request identity and outcome.' }], }, { name: 'credentials/updated', mode: 'emit', signature: '\'credentials/updated\'(ref: CredentialRef): void', - jsDoc: '/**\n * Committed change to a provider-managed credential source: a `set`, an\n * `unset`, or an external edit observed in storage. Ambient\n * process-environment changes are not observable and never emit. Listener\n * failures are contained and logged — a sync throw and an async rejection\n * alike — without changing the committed operation\'s outcome, except\n * `INVARIANT`-coded failures, which rethrow after every listener ran;\n * that rethrow reaches the emitter only from synchronous listeners, so\n * invariant checks on this event must not be async functions.\n * @param ref - the reference whose stored value changed.\n * @mode emit\n */', summary: 'Committed change to a provider-managed credential source: a `set`, an `unset`, or an external edit observed in storage.', + description: 'Committed change to a provider-managed credential source: a `set`, an `unset`, or an external edit observed in storage. Ambient process-environment changes are not observable and never emit. Listener failures are contained and logged — a sync throw and an async rejection alike — without changing the committed operation\'s outcome, except `INVARIANT`-coded failures, which rethrow after every listener ran; that rethrow reaches the emitter only from synchronous listeners, so invariant checks on this event must not be async functions.', + parameters: [{ name: 'ref', description: 'the reference whose stored value changed.' }], }, { name: 'domain/changed', mode: 'emit', signature: '\'domain/changed\'(change: DomainChanged): void', - jsDoc: '/**\n * A domain record or the global singleton changed, emitted once per write\n * strictly after the backend acknowledged durability. Events of one\n * domain arrive in its write-chain order.\n * @param change - domain, table (`\'\'` for global), key (`\'\'` for global),\n * operation discriminant, and on `put` the new snapshot.\n * @mode emit\n */', summary: 'A domain record or the global singleton changed, emitted once per write strictly after the backend acknowledged durability.', + description: 'A domain record or the global singleton changed, emitted once per write strictly after the backend acknowledged durability. Events of one domain arrive in its write-chain order.', + parameters: [{ name: 'change', description: 'domain, table (`\'\'` for global), key (`\'\'` for global), operation discriminant, and on `put` the new snapshot.' }], }, { name: 'fs/edit-intent', mode: 'waterfall', signature: '\'fs/edit-intent\'(target: FsTarget, actor: object | undefined, next: () => { version: FsVersion } | undefined | Promise<{ version: FsVersion } | undefined>): Promise<{ version: FsVersion } | undefined>', - jsDoc: '/**\n * Single-slot decision for the next {@link FileSystem.editText}. Calling\n * `next()` yields an unconditional edit; the first returned guard wins.\n * @param target - the resolved target about to be edited.\n * @param actor - the opaque tool-execution context the decider keys off.\n * @mode waterfall\n */', summary: 'Single-slot decision for the next FileSystem.editText.', + description: 'Single-slot decision for the next FileSystem.editText. Calling `next()` yields an unconditional edit; the first returned guard wins.', + parameters: [{ name: 'target', description: 'the resolved target about to be edited.' }, { name: 'actor', description: 'the opaque tool-execution context the decider keys off.' }], }, { name: 'fs/observed', mode: 'emit', signature: '\'fs/observed\'(target: FsTarget, observation: FsObservation, actor: object | undefined): void', - jsDoc: '/**\n * Record an authoritative positive or negative observation. Listeners must\n * be synchronous recorders: throws fail the tool call and returned promises\n * are not awaited.\n * @param target - the target whose presence or absence was observed.\n * @param observation - present with its version, or confirmed absent.\n * @param actor - the observing tool-execution context; undefined records nothing useful.\n * @mode emit\n */', summary: 'Record an authoritative positive or negative observation.', + description: 'Record an authoritative positive or negative observation. Listeners must be synchronous recorders: throws fail the tool call and returned promises are not awaited.', + parameters: [{ name: 'target', description: 'the target whose presence or absence was observed.' }, { name: 'observation', description: 'present with its version, or confirmed absent.' }, { name: 'actor', description: 'the observing tool-execution context; undefined records nothing useful.' }], }, { name: 'fs/write-intent', mode: 'waterfall', signature: '\'fs/write-intent\'(target: FsTarget, actor: object | undefined, next: () => FsWriteIntent | undefined | Promise): Promise', - jsDoc: '/**\n * Single-slot decision for the next {@link FileSystem.writeText}. Calling\n * `next()` yields the bare provider\'s unconditional write; the first listener\n * that returns an intent owns the decision rather than composing with peers.\n * @param target - the resolved target about to be written.\n * @param actor - the opaque tool-execution context the decider keys off.\n * @mode waterfall\n */', summary: 'Single-slot decision for the next FileSystem.writeText.', + description: 'Single-slot decision for the next FileSystem.writeText. Calling `next()` yields the bare provider\'s unconditional write; the first listener that returns an intent owns the decision rather than composing with peers.', + parameters: [{ name: 'target', description: 'the resolved target about to be written.' }, { name: 'actor', description: 'the opaque tool-execution context the decider keys off.' }], }, { name: 'goal/changed', mode: 'emit', signature: '\'goal/changed\'(this: import(\'@deepseek-ai/dsh-scope\').Scoped, payload: { agent: Agent; change: GoalChanged }): void', - jsDoc: '/**\n * Goal mutation accepted by one live agent. The matching `goal/change`\n * session event has already committed. Listener failures are contained.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.\n * @param payload.agent - agent whose session owns the goal.\n * @param payload.change - fresh current projection or clear tombstone.\n * @mode emit\n */', summary: 'Goal mutation accepted by one live agent.', + description: 'Goal mutation accepted by one live agent. The matching `goal/change` session event has already committed. Listener failures are contained. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.', + parameters: [{ name: 'payload', description: '.change - fresh current projection or clear tombstone.' }], }, { name: 'llm/adapters-updated', mode: 'emit', signature: '\'llm/adapters-updated\'(): void', - jsDoc: '/**\n * The provider topology changed: an adapter registered or unregistered\n * routes, or the configurable-provider directory gained or lost entries.\n * This payload-free registry notification fires at each commit point\n * (including registration disposal); consumers re-read `listProviders()`,\n * `listModels()`, or `listConfigurableProviders()` for the new state.\n * Observer failures are contained and cannot veto the registry mutation.\n * @mode emit\n */', summary: 'The provider topology changed: an adapter registered or unregistered routes, or the configurable-provider directory gained or lost entries.', + description: 'The provider topology changed: an adapter registered or unregistered routes, or the configurable-provider directory gained or lost entries. This payload-free registry notification fires at each commit point (including registration disposal); consumers re-read `listProviders()`, `listModels()`, or `listConfigurableProviders()` for the new state. Observer failures are contained and cannot veto the registry mutation.', + parameters: [], }, { name: 'llm/stream', mode: 'waterfall', signature: '\'llm/stream\'(this: LlmRuntime, options: GenerateOptions, next: () => AsyncIterable): AsyncIterable', - jsDoc: '/**\n * Waterfall around every streaming model call (retry, replay, routing).\n * Bound to the {@link LlmRuntime}; call `next()` to reach the resolved\n * adapter\'s stream, or yield your own chunks to short-circuit.\n * @param options - the full request. A LOOP-built request carries the\n * process-local {@link markAgentLoopRequest} identity and arrives deep-frozen\n * (mutation throws): its content is a pure function of the session log (the\n * reconstructability Agent Note), so listeners read it, never rewrite it.\n * Hand-built calls do not carry that marker; their messages already obey\n * the immutable creation contract.\n * @mode waterfall\n */', summary: 'Waterfall around every streaming model call (retry, replay, routing).', + description: 'Waterfall around every streaming model call (retry, replay, routing). Bound to the LlmRuntime; call `next()` to reach the resolved adapter\'s stream, or yield your own chunks to short-circuit.', + parameters: [{ name: 'options', description: 'the full request. A LOOP-built request carries the process-local {@link markAgentLoopRequest} identity and arrives deep-frozen (mutation throws): its content is a pure function of the session log (the reconstructability Agent Note), so listeners read it, never rewrite it. Hand-built calls do not carry that marker; their messages already obey the immutable creation contract.' }], }, { name: 'session-telemetry/record', mode: 'waterfall', signature: '\'session-telemetry/record\'(record: SessionTelemetryRecord, next: () => SessionTelemetryRecord): SessionTelemetryRecord', - jsDoc: '/**\n * Transform one outbound record before it reaches the backend. This\n * waterfall is the Service Definition\'s redaction extension point. It ships NO rules\n * of its own: the\n * innermost `next()` passes the record through unchanged, and with no\n * listener mounted records reach the backend as captured, so exported\n * data is exactly as clean as the rules a deployment mounts. Listeners\n * stack by transforming `next()`\'s return value; returning without\n * `next()` replaces everything beneath. Dispatched synchronously on the\n * capture hot path inside the coordinator\'s containment: a throwing\n * listener withholds that one record (fail-closed) and never reaches the\n * agent loop. Live capture dispatches at append time; on-demand capture\n * dispatches while reading the canonical log. Redaction applies to the\n * exported copy only; the canonical session log is never rewritten.\n * @param record - the candidate record, already the coordinator\'s own deep\n * copy; listeners return a (possibly new) record and must not mutate it.\n * @mode waterfall\n */', summary: 'Transform one outbound record before it reaches the backend.', + description: 'Transform one outbound record before it reaches the backend. This waterfall is the Service Definition\'s redaction extension point. It ships NO rules of its own: the innermost `next()` passes the record through unchanged, and with no listener mounted records reach the backend as captured, so exported data is exactly as clean as the rules a deployment mounts. Listeners stack by transforming `next()`\'s return value; returning without `next()` replaces everything beneath. Dispatched synchronously on the capture hot path inside the coordinator\'s containment: a throwing listener withholds that one record (fail-closed) and never reaches the agent loop. Live capture dispatches at append time; on-demand capture dispatches while reading the canonical log. Redaction applies to the exported copy only; the canonical session log is never rewritten.', + parameters: [{ name: 'record', description: 'the candidate record, already the coordinator\'s own deep copy; listeners return a (possibly new) record and must not mutate it.' }], }, { name: 'session/created', mode: 'emit', signature: '\'session/created\'(this: Scoped, session: Session): void', - jsDoc: '/**\n * Creation announcement during session publication. A synchronous throw vetoes and rolls\n * back with a paired disposal; detach requested during dispatch is deferred.\n * A returned-promise rejection is logged but cannot retroactively veto this\n * synchronous boundary.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners\n * receive only sessions entered through that agent\'s context.\n * @param session - the session just entered and announced.\n * @dshScopeScan unsupported\n * @mode emit\n */', summary: 'Creation announcement during session publication.', + description: 'Creation announcement during session publication. A synchronous throw vetoes and rolls back with a paired disposal; detach requested during dispatch is deferred. A returned-promise rejection is logged but cannot retroactively veto this synchronous boundary. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only sessions entered through that agent\'s context.', + parameters: [{ name: 'session', description: 'the session just entered and announced.' }], }, { name: 'session/disposed', mode: 'emit', signature: '\'session/disposed\'(this: Scoped, session: Session): void', - jsDoc: '/**\n * Emitted once when an announced session leaves the store, including\n * publication rollback, but never for an entry whose creation announcement\n * did not begin. Listener failures are logged and contained.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`) reuses the owner scope.\n * @param session - the session that is no longer live in the store.\n * @dshScopeScan unsupported\n * @mode emit\n */', summary: 'Emitted once when an announced session leaves the store, including publication rollback, but never for an entry whose creation announcement did not begin.', + description: 'Emitted once when an announced session leaves the store, including publication rollback, but never for an entry whose creation announcement did not begin. Listener failures are logged and contained. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`) reuses the owner scope.', + parameters: [{ name: 'session', description: 'the session that is no longer live in the store.' }], }, { name: 'session/event', mode: 'emit', signature: '\'session/event\'(this: Scoped, session: Session, event: SessionEvent): void', - jsDoc: '/**\n * Post-commit, fire-and-forget append feed. The listener snapshot resolves\n * before the log push, but callbacks run after it; observer failures are\n * logged and contained without making the committed append fail.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners\n * receive only events from sessions entered through that agent\'s context.\n * @param session - the session whose log grew.\n * @param event - the appended event, exactly as recorded.\n * @dshScopeScan unsupported\n * @mode emit\n */', summary: 'Post-commit, fire-and-forget append feed.', + description: 'Post-commit, fire-and-forget append feed. The listener snapshot resolves before the log push, but callbacks run after it; observer failures are logged and contained without making the committed append fail. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only events from sessions entered through that agent\'s context.', + parameters: [{ name: 'session', description: 'the session whose log grew.' }, { name: 'event', description: 'the appended event, exactly as recorded.' }], }, { name: 'session/flush', mode: 'parallel', signature: '\'session/flush\'(this: Scoped, session: Session): Promise | void', - jsDoc: '/**\n * Awaited parallel durability checkpoint: every listener runs and the\n * caller awaits all of them, with no waterfall veto. Scope-filtered dispatch\n * (`@deepseek-ai/dsh-scope`) reuses the session\'s owner scope.\n * @param session - the session whose buffered events must reach durable storage.\n * @dshScopeScan unsupported\n * @mode parallel\n */', summary: 'Awaited parallel durability checkpoint: every listener runs and the caller awaits all of them, with no waterfall veto.', + description: 'Awaited parallel durability checkpoint: every listener runs and the caller awaits all of them, with no waterfall veto. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`) reuses the session\'s owner scope.', + parameters: [{ name: 'session', description: 'the session whose buffered events must reach durable storage.' }], }, { name: 'settings/document-updated', mode: 'emit', signature: '\'settings/document-updated\'(ns: SettingsNamespace, revision: number): void', - jsDoc: '/**\n * One registered namespace\'s RAW user section changed, whether or not the\n * resolved value did. `settings/updated` is the consumer-facing event and\n * stays deep-equal-gated; this one exists for configuration surfaces,\n * which must learn that a field went from inherited to overridden (same\n * resolved value, different meaning) and that their held revision is\n * stale. Listener containment matches `settings/updated`.\n * @param ns - the namespace whose stored section changed.\n * @param revision - the namespace\'s new revision.\n * @mode emit\n */', summary: 'One registered namespace\'s RAW user section changed, whether or not the resolved value did.', + description: 'One registered namespace\'s RAW user section changed, whether or not the resolved value did. `settings/updated` is the consumer-facing event and stays deep-equal-gated; this one exists for configuration surfaces, which must learn that a field went from inherited to overridden (same resolved value, different meaning) and that their held revision is stale. Listener containment matches `settings/updated`.', + parameters: [{ name: 'ns', description: 'the namespace whose stored section changed.' }, { name: 'revision', description: 'the namespace\'s new revision.' }], }, { name: 'settings/updated', mode: 'emit', signature: '\'settings/updated\'(ns: SettingsNamespace, next: unknown, prev: unknown, source: SettingsUpdateSource): void', - jsDoc: '/**\n * Committed change to one registered namespace\'s resolved value. Emitted\n * after the provider persisted (for `update`) or published (`provider`)\n * the change; never emitted when the resolved value is deep-equal.\n * Listener failures are contained and logged — a sync throw and an async\n * rejection alike — except `INVARIANT`-coded failures, which rethrow\n * after every listener ran; that rethrow reaches the emitter only from\n * synchronous listeners, so invariant checks on this event must not be\n * async functions.\n * @param ns - the namespace whose resolved value changed.\n * @param next - the new resolved value.\n * @param prev - the previous resolved value.\n * @param source - whether the change entered through `update()` or the provider.\n * @mode emit\n */', summary: 'Committed change to one registered namespace\'s resolved value.', + description: 'Committed change to one registered namespace\'s resolved value. Emitted after the provider persisted (for `update`) or published (`provider`) the change; never emitted when the resolved value is deep-equal. Listener failures are contained and logged — a sync throw and an async rejection alike — except `INVARIANT`-coded failures, which rethrow after every listener ran; that rethrow reaches the emitter only from synchronous listeners, so invariant checks on this event must not be async functions.', + parameters: [{ name: 'ns', description: 'the namespace whose resolved value changed.' }, { name: 'next', description: 'the new resolved value.' }, { name: 'prev', description: 'the previous resolved value.' }, { name: 'source', description: 'whether the change entered through `update()` or the provider.' }], }, { 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.', + description: 'A skill provider, runtime contribution, or provider-backed catalog may have changed. This is an unfiltered invalidation notification; consumers refetch the catalog for their own lookup options. Listener failures are contained and cannot veto the registry mutation.', + parameters: [], }, { name: 'subagent/end', mode: 'emit', signature: '\'subagent/end\'(this: Scoped, info: SubagentRunEndInfo): void', - jsDoc: '/**\n * A published child settled. Scope-filtered dispatch uses the same delegating\n * parent carrier as `subagent/start`, so the lifecycle pair reaches the\n * same scoped audience.\n * @param info - the run identity and terminal outcome.\n * @dshScopeScan unsupported\n * @mode emit\n */', summary: 'A published child settled.', + description: 'A published child settled. Scope-filtered dispatch uses the same delegating parent carrier as `subagent/start`, so the lifecycle pair reaches the same scoped audience.', + parameters: [{ name: 'info', description: 'the run identity and terminal outcome.' }], }, { name: 'subagent/provider-added', mode: 'emit', signature: '\'subagent/provider-added\'(provider: SubagentProvider): void', - jsDoc: '/**\n * A provider became resolvable in the registry.\n * @param provider - the registered provider.\n * @mode emit\n */', summary: 'A provider became resolvable in the registry.', + description: 'A provider became resolvable in the registry.', + parameters: [{ name: 'provider', description: 'the registered provider.' }], }, { name: 'subagent/provider-removed', mode: 'emit', signature: '\'subagent/provider-removed\'(name: string): void', - jsDoc: '/**\n * A provider left the registry. Accepted runs remain holder-owned.\n * @param name - the provider name that no longer resolves.\n * @mode emit\n */', summary: 'A provider left the registry.', + description: 'A provider left the registry. Accepted runs remain holder-owned.', + parameters: [{ name: 'name', description: 'the provider name that no longer resolves.' }], }, { name: 'subagent/start', mode: 'emit', signature: '\'subagent/start\'(this: Scoped, info: SubagentRunInfo): void', - jsDoc: '/**\n * A provider established a published child. For in-process providers,\n * `ctx.agents.get(info.id)` resolves during this notification.\n * Scope-filtered dispatch keys the carrier by the delegating parent, so a\n * parent-scoped listener observes only its own delegations. Paired with\n * `subagent/end`.\n * @param info - the provider and published child identity.\n * @dshScopeScan unsupported\n * @mode emit\n */', summary: 'A provider established a published child.', + description: 'A provider established a published child. For in-process providers, `ctx.agents.get(info.id)` resolves during this notification. Scope-filtered dispatch keys the carrier by the delegating parent, so a parent-scoped listener observes only its own delegations. Paired with `subagent/end`.', + parameters: [{ name: 'info', description: 'the provider and published child identity.' }], }, { name: 'system-prompt/assemble', mode: 'waterfall', signature: '\'system-prompt/assemble\'(this: Scoped, assembly: PromptAssembly, context: AssembleContext, next: () => Promise): Promise', - jsDoc: '/**\n * Expert waterfall over the assembled sections, contexts, tools, and variables.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): scoped listeners\n * receive only that scope\'s assemblies. The returned value is authoritative.\n * A supplied signal controls only this explicit assembly request and must not\n * be retained to control later turns. A registered complete section is\n * restored after this waterfall, so listeners cannot add to or replace\n * that scope\'s system prompt.\n * @param assembly - the mutable assembly built from registered providers.\n * @param context - the caller\'s per-assembly context.\n * @mode waterfall\n */', summary: 'Expert waterfall over the assembled sections, contexts, tools, and variables.', + description: 'Expert waterfall over the assembled sections, contexts, tools, and variables. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): scoped listeners receive only that scope\'s assemblies. The returned value is authoritative. A supplied signal controls only this explicit assembly request and must not be retained to control later turns. A registered complete section is restored after this waterfall, so listeners cannot add to or replace that scope\'s system prompt.', + parameters: [{ name: 'assembly', description: 'the mutable assembly built from registered providers.' }, { name: 'context', description: 'the caller\'s per-assembly context.' }], }, { name: 'system-prompt/change', mode: 'emit', signature: '\'system-prompt/change\'(): void', - jsDoc: '/**\n * Emitted when any prompt provider changes. This registry notification is\n * unfiltered because a global change affects every scope.\n * @mode emit\n */', summary: 'Emitted when any prompt provider changes.', + description: 'Emitted when any prompt provider changes. This registry notification is unfiltered because a global change affects every scope.', + parameters: [], }, { name: 'tools/change', mode: 'emit', signature: '\'tools/change\'(): void', - jsDoc: '/**\n * A tool was registered or unregistered, or a scoped restriction changed\n * (the available tool set changed — possibly for one scope only). An\n * UNFILTERED registry-subject notification, deliberately not scope-filtered\n * dispatch: a global change concerns every agent\'s next assembly, so a\n * scoped listener subscribing here sees every change, not just its own\n * scope\'s.\n * @mode emit\n */', summary: 'A tool was registered or unregistered, or a scoped restriction changed (the available tool set changed — possibly for one scope only).', + description: 'A tool was registered or unregistered, or a scoped restriction changed (the available tool set changed — possibly for one scope only). An UNFILTERED registry-subject notification, deliberately not scope-filtered dispatch: a global change concerns every agent\'s next assembly, so a scoped listener subscribing here sees every change, not just its own scope\'s.', + parameters: [], }, { name: 'tools/code-dispatch-log', mode: 'waterfall', signature: '\'tools/code-dispatch-log\'(this: Scoped, dispatch: CodeDispatchLog, next: () => Promise): Promise', - jsDoc: '/**\n * Allow a listener to replace content in the DURABLE LOG COPY of one\n * `run_code` sub-dispatch outcome before the bridge appends its\n * `tool/code-dispatch` event. `next()` keeps the\n * content unchanged; a listener may return replacement blocks (e.g. the\n * spill policy\'s preview + locator for an oversized text result). Only the\n * logged copy is affected — the program already received the complete\n * value, and the model sees neither. A throwing listener is contained:\n * the bridge falls back to logging the original settled content.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent\'s dispatches.\n * @param dispatch - the parent execution, sub-call identity, and the settled content to log.\n * @mode waterfall\n */', summary: 'Allow a listener to replace content in the DURABLE LOG COPY of one `run_code` sub-dispatch outcome before the bridge appends its `tool/code-dispatch` event.', + description: 'Allow a listener to replace content in the DURABLE LOG COPY of one `run_code` sub-dispatch outcome before the bridge appends its `tool/code-dispatch` event. `next()` keeps the content unchanged; a listener may return replacement blocks (e.g. the spill policy\'s preview + locator for an oversized text result). Only the logged copy is affected — the program already received the complete value, and the model sees neither. A throwing listener is contained: the bridge falls back to logging the original settled content. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent\'s dispatches.', + parameters: [{ name: 'dispatch', description: 'the parent execution, sub-call identity, and the settled content to log.' }], }, { name: 'tools/execute', mode: 'waterfall', signature: '\'tools/execute\'(this: Scoped, exec: ToolDispatchExecution, next: () => Promise): Promise', - jsDoc: '/**\n * Around-dispatch waterfall for timeout, retry, or metrics. `next()` returns\n * a normalized result; wrappers may change only `exec.signal`, while call\n * identity remains immutable. The registry re-fuses the original caller\n * signal before the body, so replacement cannot detach caller cancellation;\n * wrappers must still restore their signal and reach quiescence.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent\'s calls.\n * @param exec - the allowed call about to dispatch (name, parsed arguments, caller agent, signal).\n * @mode waterfall\n */', summary: 'Around-dispatch waterfall for timeout, retry, or metrics.', + description: 'Around-dispatch waterfall for timeout, retry, or metrics. `next()` returns a normalized result; wrappers may change only `exec.signal`, while call identity remains immutable. The registry re-fuses the original caller signal before the body, so replacement cannot detach caller cancellation; wrappers must still restore their signal and reach quiescence. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent\'s calls.', + parameters: [{ name: 'exec', description: 'the allowed call about to dispatch (name, parsed arguments, caller agent, signal).' }], }, { name: 'tools/post-execute', mode: 'waterfall', signature: '\'tools/post-execute\'(this: Scoped, exec: ToolExecution, result: Readonly, next: () => Promise): Promise', - jsDoc: '/**\n * Accept, replace, enrich, or block a normalized dispatch result. `next()`\n * accepts it unchanged; thrown tools still reach this waterfall as errors. Async\n * listeners must observe `exec.signal`; after they settle, caller\n * cancellation replaces only a successful accepted outcome with the code\n * selected by whether the tool body was invoked.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent\'s calls.\n * @param exec - the call that just ran (name, parsed arguments, caller agent).\n * @param result - the dispatch outcome a listener may accept, replace, or block.\n * @mode waterfall\n */', summary: 'Accept, replace, enrich, or block a normalized dispatch result.', + description: 'Accept, replace, enrich, or block a normalized dispatch result. `next()` accepts it unchanged; thrown tools still reach this waterfall as errors. Async listeners must observe `exec.signal`; after they settle, caller cancellation replaces only a successful accepted outcome with the code selected by whether the tool body was invoked. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent\'s calls.', + parameters: [{ name: 'exec', description: 'the call that just ran (name, parsed arguments, caller agent).' }, { name: 'result', description: 'the dispatch outcome a listener may accept, replace, or block.' }], }, { name: 'tools/pre-execute', mode: 'waterfall', signature: '\'tools/pre-execute\'(this: Scoped, exec: ToolExecution, next: () => Promise): Promise', - jsDoc: '/**\n * Allow, deny, or ask before dispatch. `next()` delegates to allow; missing\n * approval support turns `ask` into denial. Async gates must observe\n * `exec.signal`; the registry rechecks cancellation after they settle but\n * never abandons their promise.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent\'s calls.\n * @param exec - the pending call (name, parsed arguments, caller agent).\n * @mode waterfall\n */', summary: 'Allow, deny, or ask before dispatch.', + description: 'Allow, deny, or ask before dispatch. `next()` delegates to allow; missing approval support turns `ask` into denial. Async gates must observe `exec.signal`; the registry rechecks cancellation after they settle but never abandons their promise. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent\'s calls.', + parameters: [{ name: 'exec', description: 'the pending call (name, parsed arguments, caller agent).' }], }, { name: 'tools/result', mode: 'emit', signature: '\'tools/result\'(this: Scoped, exec: Readonly, result: Readonly): undefined', - jsDoc: '/**\n * Observe the frozen, lossless-JSON final outcome. Listener failures are contained.\n * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): keyed by `exec.agent`.\n * @param exec - the execution object that traversed the pipeline.\n * @param result - a deep-frozen snapshot of the final returned result.\n * @mode emit\n */', summary: 'Observe the frozen, lossless-JSON final outcome.', + description: 'Observe the frozen, lossless-JSON final outcome. Listener failures are contained. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): keyed by `exec.agent`.', + parameters: [{ name: 'exec', description: 'the execution object that traversed the pipeline.' }, { name: 'result', description: 'a deep-frozen snapshot of the final returned result.' }], }, { name: 'workflow/agent-end', mode: 'emit', signature: '\'workflow/agent-end\'(info: WorkflowRunInfo, agent: WorkflowAgentEndInfo): void', - jsDoc: '/**\n * One `agent()` call settled (clean result, child failure, or run\n * cancellation). Paired with {@link Events[\'workflow/agent-start\']} by\n * `agent.seq`, exactly once per started call on every stop path — on an\n * engine termination path (a worker killed past its grace) the end is\n * engine-synthesized with outcome `\'cancelled\'`.\n * @param info - the run\'s identity snapshot.\n * @param agent - the call identity plus its outcome.\n * @mode emit\n */', summary: 'One `agent()` call settled (clean result, child failure, or run cancellation).', + description: 'One `agent()` call settled (clean result, child failure, or run cancellation). Paired with Events[\'workflow/agent-start\'] by `agent.seq`, exactly once per started call on every stop path — on an engine termination path (a worker killed past its grace) the end is engine-synthesized with outcome `\'cancelled\'`.', + parameters: [{ name: 'info', description: 'the run\'s identity snapshot.' }, { name: 'agent', description: 'the call identity plus its outcome.' }], }, { name: 'workflow/agent-start', mode: 'emit', signature: '\'workflow/agent-start\'(info: WorkflowRunInfo, agent: WorkflowAgentInfo): void', - jsDoc: '/**\n * One `agent()` call established a published child run. Paired with\n * {@link Events[\'workflow/agent-end\']} by `agent.seq`. A call that never\n * receives a published run from the provider emits neither\n * event in this pair.\n * @param info - the run\'s identity snapshot.\n * @param agent - the call\'s sequence number, label, phase, and child id.\n * @mode emit\n */', summary: 'One `agent()` call established a published child run.', + description: 'One `agent()` call established a published child run. Paired with Events[\'workflow/agent-end\'] by `agent.seq`. A call that never receives a published run from the provider emits neither event in this pair.', + parameters: [{ name: 'info', description: 'the run\'s identity snapshot.' }, { name: 'agent', description: 'the call\'s sequence number, label, phase, and child id.' }], }, { name: 'workflow/end', mode: 'emit', signature: '\'workflow/end\'(info: WorkflowRunInfo, result: WorkflowResultInfo): void', - jsDoc: '/**\n * A workflow run settled (any stop reason). Fired when\n * {@link WorkflowRun.result} resolves. Paired with\n * {@link Events[\'workflow/start\']}.\n * @param info - the run\'s identity snapshot.\n * @param result - the outcome data (stop reason, error, agent count) —\n * deliberately WITHOUT the result value (see {@link WorkflowResultInfo}).\n * @mode emit\n */', summary: 'A workflow run settled (any stop reason).', + description: 'A workflow run settled (any stop reason). Fired when WorkflowRun.result resolves. Paired with Events[\'workflow/start\'].', + parameters: [{ name: 'info', description: 'the run\'s identity snapshot.' }, { name: 'result', description: 'the outcome data (stop reason, error, agent count) — deliberately WITHOUT the result value (see {@link WorkflowResultInfo}).' }], }, { name: 'workflow/log', mode: 'emit', signature: '\'workflow/log\'(info: WorkflowRunInfo, message: string): void', - jsDoc: '/**\n * The script emitted a narration line (a `log(message)` call).\n * @param info - the run\'s identity snapshot.\n * @param message - the logged message, verbatim.\n * @mode emit\n */', summary: 'The script emitted a narration line (a `log(message)` call).', + description: 'The script emitted a narration line (a `log(message)` call).', + parameters: [{ name: 'info', description: 'the run\'s identity snapshot.' }, { name: 'message', description: 'the logged message, verbatim.' }], }, { name: 'workflow/phase', mode: 'emit', signature: '\'workflow/phase\'(info: WorkflowRunInfo, title: string): void', - jsDoc: '/**\n * The script entered a phase (a `phase(title)` call) — progress grouping\n * for observers; no execution semantics.\n * @param info - the run\'s identity snapshot.\n * @param title - the phase title, verbatim.\n * @mode emit\n */', summary: 'The script entered a phase (a `phase(title)` call) — progress grouping for observers; no execution semantics.', + description: 'The script entered a phase (a `phase(title)` call) — progress grouping for observers; no execution semantics.', + parameters: [{ name: 'info', description: 'the run\'s identity snapshot.' }, { name: 'title', description: 'the phase title, verbatim.' }], }, { name: 'workflow/start', mode: 'emit', signature: '\'workflow/start\'(info: WorkflowRunInfo): void', - jsDoc: '/**\n * A workflow run started — the script\'s meta block validated, the body\n * about to execute. Paired with {@link Events[\'workflow/end\']}.\n * @param info - the run\'s identity snapshot (id + meta).\n * @mode emit\n */', summary: 'A workflow run started — the script\'s meta block validated, the body about to execute.', + description: 'A workflow run started — the script\'s meta block validated, the body about to execute. Paired with Events[\'workflow/end\'].', + parameters: [{ name: 'info', description: 'the run\'s identity snapshot (id + meta).' }], }, ] -/** Shapes of every exported type the SERVICE_API signatures reference (transitively), sorted by name. */ +/** Shapes of every exported type the Service and Event signatures reference (transitively), sorted by name. */ export const TYPE_API: readonly TypeApiEntry[] = [ { name: 'AdapterRegistrationHandle', @@ -1808,6 +2655,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'ApprovalRequest', declaration: 'export interface ApprovalRequest {\n readonly agent: Agent;\n readonly toolName: string;\n readonly callId?: CallId;\n readonly reason?: string;\n readonly signal?: AbortSignal;\n}', }, + { + name: 'ApprovalService', + declaration: 'export class ApprovalService extends Service {\n static Config: z;\n constructor(ctx: Context, public config: Config);\n setPolicy(agent: Agent, policy: ApprovalPolicy): void;\n async request(req: ApprovalRequest): Promise;\n overrideOf(session: Session): ApprovalPolicy | undefined;\n}', + }, { name: 'AskUserQuestionAnswer', declaration: 'export interface AskUserQuestionAnswer {\n answers: AskUserQuestionAnswerItem[];\n}', @@ -1856,6 +2707,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'AttachmentId', declaration: 'export type AttachmentId = Branded<\'AttachmentId\'>;', }, + { + name: 'BackendRegistry', + declaration: 'export class BackendRegistry {\n register(name: string, backend: StorageBackend): () => void;\n get(name: string): StorageBackend;\n names(): string[];\n}', + }, { name: 'BashEnvContributor', declaration: 'export interface BashEnvContributor {\n name: string;\n variables: Readonly>;\n resolve(execution: ToolExecution): Readonly>>;\n}', @@ -1872,14 +2727,14 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'Branded', declaration: 'export type Branded = string & {\n readonly [BRAND]: B;\n};', }, - { - name: 'CallId', - declaration: 'export type CallId = Branded<\'CallId\'>;', - }, { name: 'CancelOptions', declaration: 'export interface CancelOptions {\n keepInbox?: boolean | undefined;\n}', }, + { + name: 'ClientResponse', + declaration: 'export interface ClientResponse {\n type: \'client-response\';\n rpcId: RpcId;\n result: RpcResult;\n}', + }, { name: 'CodeBindingErrorClass', declaration: 'export interface CodeBindingErrorClass {\n name: string;\n memberNameProperty: string;\n}', @@ -1892,6 +2747,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'CodeBindingNamespace', declaration: 'export interface CodeBindingNamespace {\n global: string;\n functions: Record;\n errorClass?: CodeBindingErrorClass;\n}', }, + { + name: 'CodeDispatchLog', + declaration: 'export interface CodeDispatchLog {\n readonly exec: ToolExecution;\n readonly agent?: Agent;\n readonly subCallId: CallId;\n readonly name: string;\n readonly isError: boolean;\n readonly content: ContentBlock[];\n}', + }, { name: 'CodeJsonValue', declaration: 'export type CodeJsonValue = null | boolean | number | string | CodeJsonValue[] | {\n [key: string]: CodeJsonValue;\n};', @@ -2004,6 +2863,34 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'ContinuableSubagentDescriptorData', declaration: 'export interface ContinuableSubagentDescriptorData extends SubagentDescriptorBase {\n readonly mode: \'continuable\';\n readonly label: string;\n readonly agentProvider?: string;\n readonly agentModel?: string;\n readonly persona?: string;\n readonly toolFilter?: ToolRestriction;\n}', }, + { + name: 'CordisDynamicPackageId', + declaration: 'export type CordisDynamicPackageId = Branded<\'CordisDynamicPackageId\'>;', + }, + { + name: 'CordisDynamicPluginId', + declaration: 'export type CordisDynamicPluginId = Branded<\'CordisDynamicPluginId\'>;', + }, + { + name: 'CordisDynamicPluginRunId', + declaration: 'export type CordisDynamicPluginRunId = Branded<\'CordisDynamicPluginRunId\'>;', + }, + { + name: 'CordisDynamicRunMode', + declaration: 'export type CordisDynamicRunMode = \'run\' | \'update\';', + }, + { + name: 'CordisInspectQueryRequest', + declaration: 'export interface CordisInspectQueryRequest {\n requestId: CordisInspectRequestId;\n agentId: SessionId;\n provider: string;\n method: string;\n input?: JsonValue;\n}', + }, + { + name: 'CordisInspectQueryResolved', + declaration: 'export interface CordisInspectQueryResolved {\n requestId: CordisInspectRequestId;\n}', + }, + { + name: 'CordisInspectRequestId', + declaration: 'export type CordisInspectRequestId = Branded<\'CordisInspectRequestId\'>;', + }, { name: 'CreateAgentOptions', declaration: 'export interface CreateAgentOptions {\n readonly sessionId: SessionId;\n readonly meta?: {\n readonly cwd?: string;\n readonly parentSession?: SessionId;\n readonly seedLength?: number;\n readonly origin?: \'subagent\';\n readonly delegationDepth?: number;\n readonly agentPreset?: string;\n };\n readonly seed?: readonly SessionEvent[];\n readonly agentOptions?: AgentOptions;\n readonly signal?: AbortSignal;\n readonly setup?: AgentSetup;\n}', @@ -2036,14 +2923,6 @@ 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;\n createDirectory(path: string, name: string): Promise;\n}', @@ -2068,6 +2947,22 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'Domain', declaration: 'export interface Domain {\n readonly name: string;\n readonly global: DomainGlobalHandleOf;\n table(name: N): KvTable, TableValueOf>;\n close(): Promise;\n}', }, + { + name: 'DomainChanged', + declaration: 'export type DomainChanged = DomainChangedPut | DomainChangedDeleted;', + }, + { + name: 'DomainChangedBase', + declaration: 'export interface DomainChangedBase {\n readonly domain: string;\n readonly table: string;\n readonly key: string;\n}', + }, + { + name: 'DomainChangedDeleted', + declaration: 'export interface DomainChangedDeleted extends DomainChangedBase {\n readonly operation: \'deleted\';\n readonly value?: never;\n}', + }, + { + name: 'DomainChangedPut', + declaration: 'export interface DomainChangedPut extends DomainChangedBase {\n readonly operation: \'put\';\n readonly value: unknown;\n}', + }, { name: 'DomainGlobal', declaration: 'export interface DomainGlobal {\n get(): G;\n set(value: G): Promise;\n}', @@ -2092,6 +2987,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'DomainTableSpec', declaration: 'export interface DomainTableSpec {\n readonly valueSchema: ZodType;\n readonly __key?: K;\n}', }, + { + name: 'DownloadsApi', + declaration: 'export interface DownloadsApi {\n sessionLog(request: {\n sessionId: SessionId;\n includeDescendants?: boolean;\n }, signal: AbortSignal): Promise;\n}', + }, { name: 'DshEnvironment', declaration: 'export type DshEnvironment = Readonly>;', @@ -2100,6 +2999,22 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'DshEnvironmentKey', declaration: 'export type DshEnvironmentKey = `${typeof DSH_ENV_PREFIX}${string}`;', }, + { + name: 'DynamicCordisPackage', + declaration: 'export interface DynamicCordisPackage {\n pluginId: CordisDynamicPluginId;\n packageId: CordisDynamicPackageId;\n pluginRunId: CordisDynamicPluginRunId;\n name: string;\n}', + }, + { + name: 'DynamicCordisRequestResolved', + declaration: 'export interface DynamicCordisRequestResolved {\n requestId: ApprovalRequestId;\n outcome: RequestRunOutcome;\n}', + }, + { + name: 'DynamicCordisRetracted', + declaration: 'export interface DynamicCordisRetracted {\n pluginId: CordisDynamicPluginId;\n packageId: CordisDynamicPackageId;\n pluginRunId: CordisDynamicPluginRunId;\n}', + }, + { + name: 'DynamicCordisRunRequest', + declaration: 'export interface DynamicCordisRunRequest {\n requestId: ApprovalRequestId;\n agentId: SessionId;\n pluginId: CordisDynamicPluginId;\n packageId: CordisDynamicPackageId;\n mode: CordisDynamicRunMode;\n name: string;\n purpose: string;\n requiresApproval: boolean;\n}', + }, { name: 'EditGoalRequest', declaration: 'export interface EditGoalRequest {\n readonly objective?: string;\n readonly maxGoalRounds?: number;\n}', @@ -2140,6 +3055,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'FsInfo', declaration: 'export interface FsInfo {\n version: FsVersion;\n type: \'file\' | \'directory\' | \'other\';\n size?: number;\n}', }, + { + name: 'FsObservation', + declaration: 'export type FsObservation = {\n readonly kind: \'present\';\n readonly version: FsVersion;\n} | {\n readonly kind: \'absent\';\n};', + }, { name: 'FsPathInfo', declaration: 'export interface FsPathInfo {\n version: FsVersion;\n type: \'file\' | \'directory\' | \'symlink\' | \'other\';\n size?: number;\n}', @@ -2185,17 +3104,17 @@ export const TYPE_API: readonly TypeApiEntry[] = [ declaration: 'export interface GoalBlockReason {\n readonly code: string;\n readonly message: string;\n}', }, { - name: 'GoalId', - declaration: 'export type GoalId = Branded<\'GoalId\'>;', + name: 'GoalChanged', + declaration: 'export interface GoalChanged {\n readonly operation: GoalOperation;\n readonly ref: GoalRef;\n readonly goal?: GoalView;\n}', + }, + { + name: 'GoalOperation', + declaration: 'export type GoalOperation = \'create\' | \'edit\' | \'pause\' | \'resume\' | \'complete\' | \'block\' | \'clear\';', }, { name: 'GoalPhase', declaration: 'export type GoalPhase = \'active\' | \'paused\' | \'blocked\' | \'complete\';', }, - { - name: 'GoalRef', - declaration: 'export interface GoalRef {\n readonly id: GoalId;\n readonly revision: number;\n}', - }, { name: 'GoalSnapshot', declaration: 'export interface GoalSnapshot extends GoalRef {\n readonly objective: string;\n readonly phase: GoalPhase;\n readonly blockedReason?: GoalBlockReason;\n readonly maxGoalRounds: number;\n}', @@ -2204,6 +3123,10 @@ 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: 'ImageAttachmentLimits', + declaration: 'export interface ImageAttachmentLimits {\n maxImageBytes: number;\n maxImagesPerMessage: number;\n maxMessageImageBytes: number;\n maxImagePixels: number;\n mediaTypes: readonly ImageMediaType[];\n}', + }, { name: 'ImageAttachmentRef', declaration: 'export interface ImageAttachmentRef {\n attachmentId: AttachmentId;\n mediaType: ImageMediaType;\n bytes: number;\n width: number;\n height: number;\n name?: string;\n}', @@ -2316,6 +3239,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'KnobState', declaration: 'export interface KnobState {\n preset: string | null;\n sandbox: SandboxMode | null;\n approval: ApprovalPolicy | null;\n}', }, + { + name: 'KvFacet', + declaration: 'export interface KvFacet {\n open(descriptor: KvUnitDescriptor): Promise;\n}', + }, { name: 'KvTable', declaration: 'export interface KvTable {\n get(key: K): V | undefined;\n entries(): IterableIterator<[\n K,\n V\n ]>;\n keys(): IterableIterator;\n readonly size: number;\n put(key: K, value: V): Promise;\n delete(key: K): Promise;\n update(key: K, fn: (current: V) => V): Promise;\n}', @@ -2324,6 +3251,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'KvUnit', declaration: 'export interface KvUnit {\n loadAll(): Promise<{\n tables: Record>;\n global: unknown;\n }>;\n putRecord(table: string, key: string, value: unknown): Promise;\n deleteRecord(table: string, key: string): Promise;\n setGlobal(value: unknown): Promise;\n close(): Promise;\n}', }, + { + name: 'KvUnitDescriptor', + declaration: 'export interface KvUnitDescriptor {\n readonly name: string;\n readonly version: number;\n readonly tables: readonly string[];\n readonly hasGlobal: boolean;\n}', + }, { name: 'LlmAdapter', declaration: 'export abstract class LlmAdapter {\n providerInfo(provider: string): LlmProviderInfo;\n providerRetryPolicy(_provider: string): ResolvedRetryPolicy | undefined;\n listModels(_provider: string): Promise;\n resolveModel(provider: string, model: string, _signal?: AbortSignal): Promise;\n abstract stream(options: GenerateOptions): AsyncIterable;\n}', @@ -2376,6 +3307,50 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'LlmResolvedModelInfo', declaration: 'export interface LlmResolvedModelInfo extends LlmModelInfo {\n context?: LlmModelContext;\n defaultMaxTokens?: number;\n reasoning?: LlmModelReasoningInfo;\n}', }, + { + name: 'LlmRuntime', + declaration: 'export class LlmRuntime extends Service {\n constructor(ctx: Context);\n registerAdapter(providers: string[], adapter: LlmAdapter): AdapterRegistrationHandle;\n listProviders(): LlmProviderInfo[];\n registerConfigurableProviders(entries: readonly LlmConfigurableProvider[]): DirectoryRegistrationHandle;\n listConfigurableProviders(): LlmConfigurableProvider[];\n registerModelDiscovery(settingsNs: string, discover: (request: LlmModelDiscoveryRequest) => Promise): () => void;\n async discoverModels(settingsNs: string, request: LlmModelDiscoveryRequest): Promise;\n providerRetryPolicy(provider: string): ResolvedRetryPolicy;\n async listModels(provider: string): Promise;\n async resolveModelInfo(provider: string, model: string, signal?: AbortSignal): Promise;\n async resolveCallConfig(config: LlmCallConfig, signal?: AbortSignal): Promise;\n async prepareCall(config: LlmCallConfig, signal?: AbortSignal): Promise;\n stream(options: GenerateOptions): AsyncIterable;\n}', + }, + { + name: 'LspHover', + declaration: 'export interface LspHover {\n readonly contents: string;\n readonly range?: LspRange;\n}', + }, + { + name: 'LspLocation', + declaration: 'export interface LspLocation {\n readonly uri: string;\n readonly range: LspRange;\n}', + }, + { + name: 'LspOperation', + declaration: 'export type LspOperation = \'goToDefinition\' | \'findReferences\' | \'goToImplementation\' | \'hover\';', + }, + { + name: 'LspPosition', + declaration: 'export interface LspPosition {\n readonly line: number;\n readonly character: number;\n}', + }, + { + name: 'LspProvider', + declaration: 'export interface LspProvider {\n readonly id: LspProviderId;\n readonly extensionToLanguage: Readonly>;\n query(request: LspProviderQuery, signal?: AbortSignal): Promise;\n}', + }, + { + name: 'LspProviderId', + declaration: 'export type LspProviderId = Branded<\'LspProviderId\'>;', + }, + { + name: 'LspProviderQuery', + declaration: 'export interface LspProviderQuery extends LspQueryRequest {\n readonly languageId: string;\n}', + }, + { + name: 'LspQueryRequest', + declaration: 'export interface LspQueryRequest {\n readonly operation: LspOperation;\n readonly filePath: string;\n readonly position: LspPosition;\n readonly workspaceRoot: string;\n}', + }, + { + name: 'LspQueryResult', + declaration: 'export type LspQueryResult = {\n readonly kind: \'locations\';\n readonly locations: readonly LspLocation[];\n readonly resolvedWorkspaceUri: string;\n} | {\n readonly kind: \'hover\';\n readonly hover: LspHover | null;\n};', + }, + { + name: 'LspRange', + declaration: 'export interface LspRange {\n readonly start: LspPosition;\n readonly end: LspPosition;\n}', + }, { name: 'ManualCompactAgentContext', declaration: 'export interface ManualCompactAgentContext extends CompactionAgentContext {\n runMaintenance(task: (signal: AbortSignal) => Promise): Promise;\n}', @@ -2484,10 +3459,6 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'ModelModalityMap', declaration: 'export interface ModelModalityMap {\n text: \'text\';\n image: \'image\';\n}', }, - { - name: 'ModelSelection', - declaration: 'export interface ModelSelection {\n provider: string;\n model: string;\n reasoningEffort?: ReasoningEffortId;\n}', - }, { name: 'ObjectJsonSchema', declaration: 'export type ObjectJsonSchema = JsonSchemaNode & {\n type: \'object\';\n};', @@ -2500,6 +3471,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'PermissionSelect', declaration: 'export interface PermissionSelect {\n options: PresetOption[];\n currentValue: string;\n}', }, + { + name: 'PostToolDecision', + declaration: 'export type PostToolDecision = {\n kind: \'accept\';\n content?: ContentBlock[];\n value?: never;\n additionalContexts?: UserMessage[];\n} | {\n kind: \'accept\';\n value: JsonValue;\n content?: never;\n additionalContexts?: UserMessage[];\n} | {\n kind: \'block\';\n feedback: ContentBlock[];\n additionalContexts?: UserMessage[];\n};', + }, { name: 'PreparedLlmCall', declaration: 'export interface PreparedLlmCall {\n readonly config: LlmCallConfig;\n readonly retryPolicy: ResolvedRetryPolicy;\n readonly context?: LlmModelContext;\n readonly adapterDefaults: LlmCallConfigAdapterDefaults;\n stream(options: GenerateOptions): AsyncIterable;\n}', @@ -2524,6 +3499,14 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'PresetTrust', declaration: 'export type PresetTrust = \'system\' | \'user\';', }, + { + name: 'PreStepDecision', + declaration: 'export type PreStepDecision = {\n kind: \'reject\';\n} | {\n kind: \'enter\';\n messages: UserMessage[];\n};', + }, + { + name: 'PreToolDecision', + declaration: 'export type PreToolDecision = {\n kind: \'allow\';\n} | {\n kind: \'deny\';\n reason: string;\n} | {\n kind: \'ask\';\n reason?: string;\n};', + }, { name: 'ProjectionChangeListener', declaration: 'export type ProjectionChangeListener = (session: Session, key: Extract, value: unknown, seq: number) => void;', @@ -2592,10 +3575,18 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'RequestContext', declaration: 'export interface RequestContext {\n provider: string;\n model: string;\n contextWindow?: number;\n}', }, + { + name: 'RequestErrorAction', + declaration: 'export type RequestErrorAction = {\n kind: \'retry\';\n} | undefined;', + }, { name: 'RequestHeaderReason', declaration: 'export type RequestHeaderReason = \'initial\' | \'resume\' | \'change\';', }, + { + name: 'RequestRunOutcome', + declaration: 'export type RequestRunOutcome = \'approved\' | \'completed\' | \'rejected\' | \'cancelled\' | \'failed\';', + }, { name: 'ResolvedAlwaysRetryPolicy', declaration: 'export interface ResolvedAlwaysRetryPolicy extends ResolvedRetryBackoff {\n readonly mode: \'always\';\n}', @@ -2628,6 +3619,30 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'ResumeAgentOptions', declaration: 'export interface ResumeAgentOptions {\n readonly resumeSessionId: SessionId;\n readonly agentOptions?: AgentOptions;\n readonly signal?: AbortSignal;\n readonly setup?: AgentSetup;\n}', }, + { + name: 'RpcError', + declaration: 'export type RpcError = {\n [C in RpcErrorCode]: {\n code: C;\n message: string;\n details: RpcErrorDetailsMap[C];\n };\n}[RpcErrorCode];', + }, + { + name: 'RpcErrorCode', + declaration: 'export type RpcErrorCode = keyof RpcErrorDetailsMap;', + }, + { + name: 'RpcErrorDetailsMap', + declaration: 'export interface RpcErrorDetailsMap {\n \'bad-request\': {\n issues: ZodIssue[];\n };\n \'cancelled\': {};\n \'session-not-found\': {\n sessionId: SessionId;\n };\n \'model-unavailable\': {\n provider: string;\n model: string;\n };\n \'session-conflict\': {\n sessionId: SessionId;\n requestedCwd: string;\n existingCwd?: string;\n };\n \'invalid-time-zone\': {\n value: string;\n };\n \'workspace-attach-failed\': {\n sessionId: SessionId;\n workspaceId: string;\n };\n \'workspace-not-found\': {\n workspaceId: string;\n };\n \'workspace-invalid-path\': {\n path: string;\n };\n \'workspace-name-conflict\': {\n name: string;\n };\n \'workspace-move-invalid\': {\n workspaceId: string;\n sessionId: SessionId;\n beforeSessionId?: SessionId;\n };\n \'directory-unreadable\': {\n path: string;\n };\n \'directory-exists\': {\n path: string;\n };\n \'directory-create-failed\': {\n path: string;\n };\n \'directory-picker-unavailable\': {\n capability: string;\n };\n \'agent-preset-read-only\': {\n agentPreset: string;\n reason: string;\n };\n \'agent-preset-locked\': {\n sessionId: SessionId;\n agentPreset: string;\n };\n \'agent-preset-conflict\': {\n sessionId: SessionId;\n requestedPreset: string;\n existingPreset?: string;\n };\n \'agent-preset-not-found\': {\n agentPreset: string;\n /* …truncated — full shape in source */', + }, + { + name: 'RpcId', + declaration: 'export type RpcId = Branded<\'rpc-id\'>;', + }, + { + name: 'RpcReceipt', + declaration: 'export type RpcReceipt = {\n accepted: true;\n} | {\n accepted: false;\n reason: \'not-pending\' | \'bad-response\';\n};', + }, + { + name: 'RpcResult', + declaration: 'export type RpcResult = {\n ok: true;\n value: T;\n} | {\n ok: false;\n error: RpcError;\n};', + }, { name: 'RunnerFailureRule', declaration: 'export interface RunnerFailureRule {\n allowedExitCodes?: readonly number[];\n fatalSignatures: readonly string[];\n informationalLines?: readonly string[];\n}', @@ -2660,6 +3675,18 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'SaveTextSpill', declaration: 'export interface SaveTextSpill {\n owner: SpillOwner;\n source: SpillSource;\n suggestedName: string;\n content: string;\n}', }, + { + name: 'ScheduledToolDispatch', + declaration: 'export type ScheduledToolDispatch = {\n kind: \'post-result\';\n result: ToolExecutionResult;\n} | {\n kind: \'final-result\';\n result: ToolExecutionResult;\n};', + }, + { + name: 'ScheduledToolPreparation', + declaration: 'export type ScheduledToolPreparation = {\n kind: \'dispatch\';\n exec: ToolRunContext;\n} | {\n kind: \'post-result\';\n exec: ToolRunContext;\n result: ToolExecutionResult;\n} | {\n kind: \'final-result\';\n exec: ToolRunContext;\n result: ToolExecutionResult;\n};', + }, + { + name: 'Scoped', + declaration: 'export type Scoped = object & {\n readonly [ScopedBrand]: T;\n};', + }, { name: 'ScopeKey', declaration: 'export type ScopeKey = object;', @@ -2685,8 +3712,8 @@ export const TYPE_API: readonly TypeApiEntry[] = [ declaration: 'export type SearchResultView = SearchMatchesResultView | SearchPathsResultView;', }, { - name: 'Session', - declaration: 'export class Session {\n get surface(): SessionSurface;\n readonly header: SessionHeader;\n get id(): SessionId;\n readonly firstLiveSeq: number;\n static create(id: SessionId, seed?: readonly SessionEvent[], header?: SessionHeader): Session;\n static fromRestore(id: SessionId, seed: readonly SessionEvent[], header: SessionHeader): Session;\n get events(): readonly SessionEvent[];\n get seq(): number;\n append(type: T, data: SessionEventMap[T], ...opts: T extends SurfaceEventType ? [\n opts: SurfaceIntent\n ] : [\n ]): SessionEvent;\n requestHeader(): EpochHeader | undefined;\n requestContext(): RequestContext | undefined;\n deriveMessages(): Message[];\n deriveEventMessage(event: SessionEvent): Message | null;\n}', + name: 'ServerResponse', + declaration: 'export interface ServerResponse {\n type: \'server-response\';\n rpcId: RpcId;\n result: RpcResult;\n}', }, { name: 'SessionAvailability', @@ -2853,8 +3880,8 @@ export const TYPE_API: readonly TypeApiEntry[] = [ declaration: 'export interface SessionSearchRequest {\n query: string;\n sessionFilters?: readonly SessionResultFilter[];\n eventFilters?: readonly SessionEventMetadataFilter[];\n limit?: number;\n cursor?: SessionSearchCursor;\n}', }, { - name: 'SessionSurface', - declaration: 'export interface SessionSurface {\n readonly nodes: readonly number[];\n readonly replaceGeneration: number;\n}', + name: 'SessionStartSource', + declaration: 'export type SessionStartSource = \'startup\' | \'resume\' | \'clear\' | \'compact\';', }, { name: 'SessionSurfaceSnapshot', @@ -2868,6 +3895,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'SessionTelemetrySeverity', declaration: 'export type SessionTelemetrySeverity = \'info\' | \'warn\' | \'error\';', }, + { + name: 'SessionTelemetrySharingStatus', + declaration: 'export type SessionTelemetrySharingStatus = \'full\' | \'feedback-only\' | \'disabled\';', + }, { name: 'SessionTitleAutomaticMode', declaration: 'export type SessionTitleAutomaticMode = \'first-prompt\' | \'all-prompts\';', @@ -2941,8 +3972,8 @@ export const TYPE_API: readonly TypeApiEntry[] = [ declaration: 'export interface SettingsRegisterOptions {\n base?: Partial;\n applies?: SettingsApplies;\n validate?: (value: T) => void;\n}', }, { - name: 'SettingsScope', - declaration: 'export interface SettingsScope {\n get(): T;\n watch(callback: (next: T, prev: T) => void | Promise): () => void;\n update(patch: object): Promise;\n replace(section: object): Promise;\n}', + name: 'SettingsUpdateSource', + declaration: 'export type SettingsUpdateSource = \'update\' | \'provider\';', }, { name: 'ShellExecRequest', @@ -3040,6 +4071,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'SpillSource', declaration: 'export interface SpillSource {\n toolName: string;\n callId: CallId;\n label: string;\n}', }, + { + name: 'StorageBackend', + declaration: 'export interface StorageBackend {\n readonly kv?: KvFacet;\n close(): Promise;\n}', + }, { name: 'StorageForms', declaration: 'export interface StorageForms {\n}', @@ -3072,10 +4107,6 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'SubagentInterruptAuthority', declaration: 'export type SubagentInterruptAuthority = {\n readonly kind: \'user\';\n readonly parentSessionId: SessionId;\n} | {\n readonly kind: \'ancestor\';\n readonly agent: Agent;\n};', }, - { - name: 'SubagentListEntry', - declaration: 'export type SubagentListEntry = {\n readonly kind: \'child\';\n readonly id: SessionId;\n readonly activity: \'running\' | \'inactive\';\n readonly hasChildren: boolean;\n} & ({\n readonly mode: \'one-shot\';\n readonly label?: string;\n} | {\n readonly mode: \'continuable\';\n readonly label: string;\n}) | {\n readonly kind: \'diagnostic\';\n readonly id: SessionId;\n readonly reason: \'corrupt\' | \'unsupported\' | \'unavailable\';\n};', - }, { name: 'SubagentProvider', declaration: 'export interface SubagentProvider {\n readonly name: string;\n readonly capabilities: SubagentCapabilities;\n readonly inheritsParentContext: boolean;\n start(request: ResolvedSubagentStartRequest): Promise;\n prepareContinuable?(request: ContinuableCreateRequest): Promise;\n}', @@ -3096,6 +4127,22 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'SubagentRun', declaration: 'export interface SubagentRun {\n readonly id: SessionId;\n readonly localAgent: Agent | undefined;\n readonly result: Promise;\n dispose(): Promise;\n}', }, + { + name: 'SubagentRunEndInfo', + declaration: 'export interface SubagentRunEndInfo {\n readonly runId: SubagentRunId;\n readonly provider: string;\n readonly id: SessionId;\n readonly local: boolean;\n readonly stopReason: SubagentResult[\'stopReason\'];\n readonly lastAssistantMessage?: ContentBlock[];\n}', + }, + { + name: 'SubagentRunId', + declaration: 'export type SubagentRunId = Branded<\'SubagentRunId\'>;', + }, + { + name: 'SubagentRunInfo', + declaration: 'export interface SubagentRunInfo {\n readonly runId: SubagentRunId;\n readonly provider: string;\n readonly id: SessionId;\n readonly local: boolean;\n}', + }, + { + name: 'SubagentRuntime', + declaration: 'export class SubagentRuntime extends Service {\n constructor(ctx: Context);\n async startContinuable(spec: ContinuableStartSpec): Promise;\n async followup(parent: Agent, childId: SessionId, content: ContentBlock[], options: SubagentFollowupOptions): Promise;\n interrupt(targetSessionId: SessionId, authority: SubagentInterruptAuthority): void;\n async reportFrom(child: Agent, content: ContentBlock[], options: SubagentReportOptions): Promise;\n registerContinuableSetup(contribution: ContinuableSetupContribution): () => void;\n async drainContinuableDescendants(parents: readonly Agent[]): Promise;\n listChildren(parentSessionId: SessionId, signal?: AbortSignal): Promise;\n listDescendants(rootSessionId: SessionId, signal?: AbortSignal): Promise;\n registerProvider(provider: SubagentProvider): () => void;\n getProvider(name: string): SubagentProvider | undefined;\n list(): string[];\n async start(name: string, request: SubagentStartRequest): Promise;\n}', + }, { name: 'SubagentStartRequest', declaration: 'export interface SubagentStartRequest {\n readonly label?: string;\n readonly prompt: ContentBlock[];\n readonly parent: Agent;\n readonly signal: AbortSignal;\n readonly agentOptions?: AgentOptions;\n readonly outputSchema?: ObjectJsonSchema;\n readonly maxDepth?: number;\n readonly toolFilter?: ToolRestriction;\n readonly persona?: string;\n}', @@ -3172,14 +4219,14 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'SurfaceEventType', declaration: 'export type SurfaceEventType = \'user/message\' | \'assistant/message\' | \'tool/result\';', }, - { - name: 'SurfaceIntent', - declaration: 'export interface SurfaceIntent {\n surfaceOp: SurfaceOp;\n sourceEventSeqs?: number[];\n}', - }, { name: 'SurfaceOp', declaration: 'export type SurfaceOp = \'append\' | {\n op: \'replace\';\n start: number;\n end: number;\n};', }, + { + name: 'SystemPrompt', + declaration: 'export class SystemPrompt extends Service {\n static Config: z;\n constructor(ctx: Context, config: Config);\n section(section: PromptSection): () => void;\n context(context: PromptContext): () => void;\n tools(provider: (context: AssembleContext) => ToolProviderResult): () => void;\n variable(name: string, provider: (context: AssembleContext) => string | undefined): () => void;\n async assemble(context: AssembleContext = {}): Promise;\n}', + }, { name: 'TableKeyOf', declaration: 'export type TableKeyOf = S[\'tables\'][N] extends DomainTableSpec ? K : never;', @@ -3288,10 +4335,6 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'TokenUsage', declaration: 'export interface TokenUsage {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n reasoningTokens?: number;\n}', }, - { - name: 'ToolCallBlock', - declaration: 'export interface ToolCallBlock {\n type: \'tool-call\';\n id: CallId;\n name: string;\n arguments: string;\n}', - }, { name: 'ToolCallKind', declaration: 'export type ToolCallKind = \'read\' | \'edit\' | \'delete\' | \'move\' | \'search\' | \'execute\' | \'fetch\' | \'other\';', @@ -3304,6 +4347,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'ToolDefinition', declaration: 'export interface ToolDefinition extends ToolSchema {\n readonly output: ToolOutputDefinition;\n execute(args: unknown, exec: ToolRunContext): Promise;\n finalizeContent?(exec: Readonly, result: Readonly): ContentBlock[] | undefined;\n timeoutMs?: number;\n isConcurrencySafe?(args: unknown): boolean;\n presentCall?(args: unknown): ToolCallView | undefined;\n presentResult?(args: unknown, result: ToolResult): ToolResultView | undefined;\n}', }, + { + name: 'ToolDispatchExecution', + declaration: 'export interface ToolDispatchExecution extends Omit {\n signal: AbortSignal;\n}', + }, { name: 'ToolErrorInfo', declaration: 'export interface ToolErrorInfo {\n name: string;\n code: string;\n}', @@ -3384,6 +4431,14 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'ToolRunContext', declaration: 'export interface ToolRunContext extends ToolExecution {\n deferContext(context: UserMessage): void;\n concludeTurn(): void;\n}', }, + { + name: 'ToolRuntime', + declaration: 'export class ToolRuntime extends Service {\n static inject;\n static Config: z;\n readonly [TOOL_RUNTIME_SCHEDULER]: ToolRuntimeScheduler;\n constructor(ctx: Context, config: Config = {});\n presentAs(mode: ToolPresentationMode): () => void;\n register(definition: ToolDefinition): () => void;\n restrict(filter: ToolRestriction): () => void;\n guard(guard: ToolGuard): () => void;\n get(name: string, scope?: ScopeKey): ToolDefinition | undefined;\n schemas(scope?: ScopeKey): ToolSchema[];\n executionMode(exec: ToolExecutionInput): ToolExecutionMode;\n async execute(exec: ToolExecutionInput): Promise;\n}', + }, + { + name: 'ToolRuntimeScheduler', + declaration: 'export interface ToolRuntimeScheduler {\n prepare(exec: ToolExecutionInput): Promise;\n dispatch(exec: ToolRunContext): Promise;\n finalize(exec: ToolRunContext, result: ToolExecutionResult): Promise;\n finish(exec: ToolRunContext, result: ToolExecutionResult): ToolExecutionResult;\n}', + }, { name: 'ToolSchema', declaration: 'export interface ToolSchema {\n name: string;\n description: string;\n parameters: Record;\n}', @@ -3468,6 +4523,14 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'UserQuestionProvider', declaration: 'export interface UserQuestionProvider {\n ask(request: AskUserQuestionRequest): Promise;\n}', }, + { + name: 'WebBootEntry', + declaration: 'export interface WebBootEntry {\n id: string;\n url: string;\n rev: string;\n inject?: string[];\n immediately?: boolean;\n}', + }, + { + name: 'WebBootGraph', + declaration: 'export interface WebBootGraph {\n rev: string;\n entries: WebBootEntry[];\n}', + }, { name: 'WebFetchBody', declaration: 'export type WebFetchBody = {\n readonly kind: \'html\';\n readonly content: string;\n} | {\n readonly kind: \'text\';\n readonly content: string;\n};', @@ -3528,6 +4591,18 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'WebUpgradeRoute', declaration: 'export interface WebUpgradeRoute {\n path: string;\n handler: (req: IncomingMessage, socket: Duplex, head: Buffer) => void | Promise;\n}', }, + { + name: 'WorkflowAgentEndInfo', + declaration: 'export interface WorkflowAgentEndInfo extends WorkflowAgentInfo {\n outcome: WorkflowAgentOutcome;\n}', + }, + { + name: 'WorkflowAgentInfo', + declaration: 'export interface WorkflowAgentInfo {\n seq: number;\n label: string;\n phase?: string;\n childId: SessionId;\n}', + }, + { + name: 'WorkflowAgentOutcome', + declaration: 'export type WorkflowAgentOutcome = \'completed\' | \'failed\' | \'cancelled\';', + }, { name: 'WorkflowMeta', declaration: 'export interface WorkflowMeta {\n name: string;\n description: string;\n whenToUse?: string;\n phases?: WorkflowPhase[];\n}', @@ -3540,6 +4615,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'WorkflowResult', declaration: 'export interface WorkflowResult {\n value: unknown;\n stopReason: WorkflowStopReason;\n error?: string;\n agentsStarted: number;\n}', }, + { + name: 'WorkflowResultInfo', + declaration: 'export interface WorkflowResultInfo {\n stopReason: WorkflowStopReason;\n error?: string;\n agentsStarted: number;\n}', + }, { name: 'WorkflowRun', declaration: 'export interface WorkflowRun {\n readonly id: WorkflowRunId;\n readonly meta: WorkflowMeta;\n readonly result: Promise;\n cancel(reason?: string): void;\n dispose(): Promise;\n}', @@ -3548,6 +4627,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'WorkflowRunId', declaration: 'export type WorkflowRunId = Branded<\'WorkflowRunId\'>;', }, + { + name: 'WorkflowRunInfo', + declaration: 'export interface WorkflowRunInfo {\n id: WorkflowRunId;\n meta: WorkflowMeta;\n}', + }, { name: 'WorkflowStartRequest', declaration: 'export interface WorkflowStartRequest {\n script: string;\n meta: WorkflowMeta;\n args?: unknown;\n subagentProvider?: string;\n maxTotalAgents?: number;\n parent: Agent;\n signal?: AbortSignal;\n}', @@ -3556,10 +4639,6 @@ export const TYPE_API: readonly TypeApiEntry[] = [ name: 'WorkflowStopReason', declaration: 'export type WorkflowStopReason = \'completed\' | \'cancelled\' | \'error\';', }, - { - name: 'Workspace', - declaration: 'export interface Workspace {\n readonly id: WorkspaceId;\n readonly path: string;\n readonly title: string;\n readonly createdAt: string;\n readonly updatedAt: string;\n readonly sessionIds: readonly SessionId[];\n setTitle(title: string): Promise;\n attachSession(sessionId: SessionId): Promise;\n insertSessionBefore(sessionId: SessionId, beforeSessionId?: SessionId): Promise;\n detachSession(sessionId: SessionId): Promise;\n status(): Promise<\'ok\' | \'missing-dir\'>;\n}', - }, ] /** The inherited `ctx` API (cordis core + loader/hmr/timer), in curated order. */ @@ -3571,7 +4650,96 @@ export const INHERITED_CTX_API: readonly InheritedApiEntry[] = [ { name: 'ctx.get / ctx.set / ctx.provide / ctx.accessor / ctx.mixin', summary: 'Low-level service-store access and binding.' }, { name: 'ctx.extend / ctx.isolate / ctx.intercept', summary: 'Derive a child context (scoped services / isolation / interception).' }, { name: 'ctx.root / ctx.scope / ctx.fiber / ctx.registry / ctx.reflect / ctx.events / ctx.logger', summary: 'Ambient handles onto the running context graph.' }, - { name: 'ctx.timer (+ interval / timeout / throttle / debounce / setTimeout / setInterval)', summary: 'Disposable timer helpers. The `timer` key is provided at runtime; the six helpers are mixed onto ctx directly (declared via Pick).' }, + { name: 'ctx.timer (+ interval / timeout / throttle / debounce)', summary: 'Disposable timer helpers. The `timer` key is provided at runtime; the four supported helpers are mixed onto ctx directly (declared via Pick).' }, { name: 'ctx.loader', summary: 'The config Loader that booted the app (present under the loader).' }, { name: 'ctx.hmr', summary: 'The hot-module-reload watcher (present under the hmr plugin).' }, ] + +function referencedTypeClosure(seeds: readonly string[]): TypeApiEntry[] { + const included = new Set() + let frontier = [...seeds] + while (frontier.length > 0) { + const next: string[] = [] + for (const entry of TYPE_API) { + if (included.has(entry.name)) continue + const pattern = new RegExp(`\b${entry.name}\b`) + if (!frontier.some(text => pattern.test(text))) continue + included.add(entry.name) + next.push(entry.declaration) + } + frontier = next + } + return TYPE_API.filter(entry => included.has(entry.name)) +} + +function contextProperty(key: string): string { + return /^[A-Za-z_$][\w$]*$/.test(key) ? `ctx.${key}` : `ctx[${JSON.stringify(key)}]` +} + +/** + * Project the Service Catalog as a compact directory or one exact coding contract. + * @param key - exact Service key; omit it to list all Services and method signatures. + * @param services - platform-specific visible Service entries. + * @returns compact navigation data or one detailed Service with its referenced type closure. + */ +export function queryServiceApi(key?: string, services: readonly ServiceApiEntry[] = SERVICE_API): object { + if (key === undefined) { + return { + mode: 'catalog', + services: services.map(service => ({ + key: service.key, + description: service.summary, + methods: service.methods.map(method => ({ signature: method.signature })), + })), + } + } + const service = services.find(candidate => candidate.key === key) + if (service === undefined) throw new Error(`no catalogued Service named "${key}"`) + return { + mode: 'service', + service: { + key: service.key, + description: service.description, + access: { + optional: { expression: `ctx.get(${JSON.stringify(service.key)})`, requiresUndefinedCheck: true }, + hardDependency: { inject: [service.key], expression: contextProperty(service.key) }, + }, + methods: service.methods, + }, + referencedTypes: referencedTypeClosure(service.methods.map(method => method.signature)), + } +} + +/** + * Project the Event Catalog as a compact directory or one exact listener contract. + * @param name - exact Event name; omit it to list all Events and listener signatures. + * @param events - platform-specific visible Event entries. + * @returns compact navigation data or one detailed Event with its referenced type closure. + */ +export function queryEventApi(name?: string, events: readonly EventApiEntry[] = EVENT_API): object { + if (name === undefined) { + return { + mode: 'catalog', + events: events.map(event => ({ + name: event.name, + description: event.summary, + mode: event.mode, + signature: event.signature, + })), + } + } + const event = events.find(candidate => candidate.name === name) + if (event === undefined) throw new Error(`no catalogued Event named "${name}"`) + return { + mode: 'event', + event: { + name: event.name, + description: event.description, + mode: event.mode, + signature: event.signature, + parameters: event.parameters, + }, + referencedTypes: referencedTypeClosure([event.signature]), + } +} +/* jscpd:ignore-end */ diff --git a/packages/extensions/tool-cordis/tsconfig.json b/packages/extensions/tool-cordis/tsconfig.json index f6fd714e16..85557e1893 100644 --- a/packages/extensions/tool-cordis/tsconfig.json +++ b/packages/extensions/tool-cordis/tsconfig.json @@ -39,7 +39,7 @@ "path": "../cordis-host-runner" }, { - "path": "../../support/invariants" + "path": "../../runtime-diagnostics/invariants" } ] } diff --git a/packages/extensions/ui-cordis/package.json b/packages/extensions/ui-cordis/package.json index 8eed78ebc0..4131006b4c 100644 --- a/packages/extensions/ui-cordis/package.json +++ b/packages/extensions/ui-cordis/package.json @@ -37,7 +37,7 @@ "@deepseek-ai/dsh-cordis-client-runner", "@deepseek-ai/dsh-api-remotes", "@deepseek-ai/dsh-client-locale", - "@deepseek-ai/dsh-client-ui-slash", + "@deepseek-ai/dsh-client-ui-input-trigger", "@deepseek-ai/dsh-client-ui-tool", "@deepseek-ai/dsh-client-ui-sidebar" ], @@ -57,7 +57,7 @@ "@deepseek-ai/dsh-client-runtime": "workspace:^", "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", "@deepseek-ai/dsh-client-ui-sidebar": "workspace:^", - "@deepseek-ai/dsh-client-ui-slash": "workspace:^", + "@deepseek-ai/dsh-client-ui-input-trigger": "workspace:^", "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-client-ui-tool": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", @@ -72,7 +72,7 @@ "@deepseek-ai/dsh-client-runtime": "workspace:^", "@deepseek-ai/dsh-client-ui-primitives": "workspace:^", "@deepseek-ai/dsh-client-ui-sidebar": "workspace:^", - "@deepseek-ai/dsh-client-ui-slash": "workspace:^", + "@deepseek-ai/dsh-client-ui-input-trigger": "workspace:^", "@deepseek-ai/dsh-client-ui-slots": "workspace:^", "@deepseek-ai/dsh-client-ui-tool": "workspace:^", "@deepseek-ai/dsh-invariants": "workspace:^", diff --git a/packages/extensions/ui-cordis/src/client/index.ts b/packages/extensions/ui-cordis/src/client/index.ts index 719c804b2c..3e314be593 100644 --- a/packages/extensions/ui-cordis/src/client/index.ts +++ b/packages/extensions/ui-cordis/src/client/index.ts @@ -5,7 +5,7 @@ import type {} from '@deepseek-ai/dsh-client-ui-tool/client' import type {} from '@deepseek-ai/dsh-client-locale/client' import type {} from '@deepseek-ai/dsh-client-ui-sidebar/client' import type {} from '@deepseek-ai/dsh-api-remotes/client' -import type { SlashServiceContract, SlashSource } from '@deepseek-ai/dsh-client-ui-slash/client' +import type { InputTriggerService, InputTriggerSource } from '@deepseek-ai/dsh-client-ui-input-trigger/client' import type {} from './events.ts' import { CordisDefineRow } from './CordisDefineRow.tsx' import { CordisRunRow } from './CordisRunRow.tsx' @@ -133,7 +133,7 @@ export function apply(ctx: ClientContext): void { const rowsOf = (sessionId: SessionId, query: string) => inventory.getSnapshot().rows .filter(row => row.agentId === sessionId && String(row.pluginId).includes(query)) - const source: SlashSource = { + const source: InputTriggerSource = { trigger: '@', name: 'cordis', order: 1, @@ -153,7 +153,7 @@ export function apply(ctx: ClientContext): void { subscribeLexicon(_session, listener) { return inventory.subscribe(listener) }, onPick({ candidate }) { return { text: `@${candidate.name} ` } }, } - const slash = ctx.get('slash') as SlashServiceContract + const slash = ctx.get('slash') as InputTriggerService ctx.effect(() => slash.registerSource(source), 'ui-cordis: @pluginId source') inventory.refresh() diff --git a/packages/extensions/ui-cordis/tsconfig.json b/packages/extensions/ui-cordis/tsconfig.json index c738ddf2dc..049ad3185e 100644 --- a/packages/extensions/ui-cordis/tsconfig.json +++ b/packages/extensions/ui-cordis/tsconfig.json @@ -27,7 +27,7 @@ "path": "../../client/ui-sidebar" }, { - "path": "../../client/ui-slash" + "path": "../../client/ui-input-trigger" }, { "path": "../../client/ui-primitives" @@ -39,7 +39,7 @@ "path": "../../client/ui-tool" }, { - "path": "../../support/invariants" + "path": "../../runtime-diagnostics/invariants" } ] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b21718dde1..decdfef22f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -141,6 +141,9 @@ importers: '@deepseek-ai/cordis-plugin-timer': specifier: workspace:^ version: link:../../vendor/timer + '@deepseek-ai/dsh-agent-instructions': + specifier: workspace:^ + version: link:../../packages/context/agent-instructions '@deepseek-ai/dsh-agent-tool-presentation': specifier: workspace:^ version: link:../../packages/core/agent-tool-presentation @@ -150,6 +153,12 @@ importers: '@deepseek-ai/dsh-base': specifier: workspace:^ version: link:../../packages/bundle/base + '@deepseek-ai/dsh-client-ui-agent-preset': + specifier: workspace:^ + version: link:../../packages/client/ui-agent-preset + '@deepseek-ai/dsh-client-ui-cordis': + specifier: workspace:^ + version: link:../../packages/extensions/ui-cordis '@deepseek-ai/dsh-cmdline': specifier: workspace:^ version: link:../../packages/boot/cmdline @@ -165,9 +174,9 @@ importers: '@deepseek-ai/dsh-compaction-tool-result-pruner': specifier: workspace:^ version: link:../../packages/compaction/compaction-tool-result-pruner - '@deepseek-ai/dsh-launch-environment': + '@deepseek-ai/dsh-cordis-client-runner': specifier: workspace:^ - version: link:../../packages/util/launch-environment + version: link:../../packages/extensions/cordis-client-runner '@deepseek-ai/dsh-fs-local': specifier: workspace:^ version: link:../../packages/fs/fs-local @@ -180,30 +189,33 @@ importers: '@deepseek-ai/dsh-headless': specifier: workspace:^ version: link:../../packages/bundle/headless - '@deepseek-ai/dsh-mcp-client': - specifier: workspace:^ - version: link:../../packages/mcp/mcp-client '@deepseek-ai/dsh-home-paths': specifier: workspace:^ version: link:../../packages/util/home-paths + '@deepseek-ai/dsh-jobs-local': + specifier: workspace:^ + version: link:../../packages/jobs/jobs-local + '@deepseek-ai/dsh-launch-environment': + specifier: workspace:^ + version: link:../../packages/util/launch-environment + '@deepseek-ai/dsh-mcp-client': + specifier: workspace:^ + version: link:../../packages/mcp/mcp-client '@deepseek-ai/dsh-persona': specifier: workspace:^ version: link:../../packages/preset/persona '@deepseek-ai/dsh-plan-mode': specifier: workspace:^ version: link:../../packages/plan/plan-mode - '@deepseek-ai/dsh-terminal': - specifier: workspace:^ - version: link:../../packages/terminal/terminal - '@deepseek-ai/dsh-terminal-bash': - specifier: workspace:^ - version: link:../../packages/terminal/terminal-bash '@deepseek-ai/dsh-pwsh-local': specifier: workspace:^ version: link:../../packages/shell/pwsh-local '@deepseek-ai/dsh-pwsh-sandbox': specifier: workspace:^ version: link:../../packages/shell/pwsh-sandbox + '@deepseek-ai/dsh-schedule': + specifier: workspace:^ + version: link:../../packages/schedule/schedule '@deepseek-ai/dsh-session-projection': specifier: workspace:^ version: link:../../packages/session/session-projection @@ -216,9 +228,12 @@ importers: '@deepseek-ai/dsh-skill-filesystem': specifier: workspace:^ version: link:../../packages/skill/skill-filesystem - '@deepseek-ai/dsh-jobs-local': + '@deepseek-ai/dsh-terminal': specifier: workspace:^ - version: link:../../packages/jobs/jobs-local + version: link:../../packages/terminal/terminal + '@deepseek-ai/dsh-terminal-bash': + specifier: workspace:^ + version: link:../../packages/terminal/terminal-bash '@deepseek-ai/dsh-time-context': specifier: workspace:^ version: link:../../packages/context/time-context @@ -249,15 +264,15 @@ importers: '@deepseek-ai/dsh-tool-goal': specifier: workspace:^ version: link:../../packages/goal/tool-goal + '@deepseek-ai/dsh-tool-jobs': + specifier: workspace:^ + version: link:../../packages/jobs/tool-jobs '@deepseek-ai/dsh-tool-pwsh': specifier: workspace:^ version: link:../../packages/shell/tool-pwsh '@deepseek-ai/dsh-tool-ralph': specifier: workspace:^ version: link:../../packages/workflow/tool-ralph - '@deepseek-ai/dsh-schedule': - specifier: workspace:^ - version: link:../../packages/schedule/schedule '@deepseek-ai/dsh-tool-skill': specifier: workspace:^ version: link:../../packages/skill/tool-skill @@ -270,9 +285,6 @@ importers: '@deepseek-ai/dsh-tool-subagent-control': specifier: workspace:^ version: link:../../packages/subagent/tool-subagent-control - '@deepseek-ai/dsh-tool-jobs': - specifier: workspace:^ - version: link:../../packages/jobs/tool-jobs '@deepseek-ai/dsh-tool-todo': specifier: workspace:^ version: link:../../packages/todo/tool-todo @@ -288,9 +300,6 @@ importers: '@deepseek-ai/dsh-workflow-worker-thread': specifier: workspace:^ version: link:../../packages/workflow/workflow-worker-thread - '@deepseek-ai/dsh-agent-instructions': - specifier: workspace:^ - version: link:../../packages/context/agent-instructions commander: specifier: ^15.0.0 version: 15.0.0 @@ -304,12 +313,12 @@ importers: '@deepseek-ai/dsh-agent': specifier: workspace:^ version: link:../../packages/core/agent - '@deepseek-ai/dsh-host-frontend-static': - specifier: workspace:^ - version: link:../../packages/host/frontend-static '@deepseek-ai/dsh-host-apiproxy': specifier: workspace:^ version: link:../../packages/host/apiproxy + '@deepseek-ai/dsh-host-frontend-static': + specifier: workspace:^ + version: link:../../packages/host/frontend-static '@deepseek-ai/dsh-host-webserver': specifier: workspace:^ version: link:../../packages/host/webserver @@ -425,6 +434,9 @@ importers: '@deepseek-ai/dsh-agent': specifier: workspace:* version: link:../packages/core/agent + '@deepseek-ai/dsh-agent-instructions': + specifier: workspace:* + version: link:../packages/context/agent-instructions '@deepseek-ai/dsh-agent-loop': specifier: workspace:* version: link:../packages/core/agent-loop @@ -437,12 +449,6 @@ importers: '@deepseek-ai/dsh-attachment-local': specifier: workspace:* version: link:../packages/attachment/attachment-local - '@deepseek-ai/dsh-shell': - specifier: workspace:* - version: link:../packages/shell/shell - '@deepseek-ai/dsh-shell-env': - specifier: workspace:* - version: link:../packages/shell/shell-env '@deepseek-ai/dsh-bash-local': specifier: workspace:* version: link:../packages/shell/bash-local @@ -470,6 +476,9 @@ importers: '@deepseek-ai/dsh-compaction-tool-result-pruner': specifier: workspace:* version: link:../packages/compaction/compaction-tool-result-pruner + '@deepseek-ai/dsh-cordis-host-runner': + specifier: workspace:* + version: link:../packages/extensions/cordis-host-runner '@deepseek-ai/dsh-credentials-local': specifier: workspace:* version: link:../packages/credentials/credentials-local @@ -503,9 +512,9 @@ importers: '@deepseek-ai/dsh-invariants': specifier: workspace:* version: link:../packages/runtime-diagnostics/invariants - '@deepseek-ai/dsh-sdk-jsonrpc-server': + '@deepseek-ai/dsh-jobs-local': specifier: workspace:* - version: link:../packages/sdk/server + version: link:../packages/jobs/jobs-local '@deepseek-ai/dsh-llm': specifier: workspace:* version: link:../packages/llm/llm @@ -533,12 +542,6 @@ importers: '@deepseek-ai/dsh-plan-mode': specifier: workspace:* version: link:../packages/plan/plan-mode - '@deepseek-ai/dsh-terminal': - specifier: workspace:* - version: link:../packages/terminal/terminal - '@deepseek-ai/dsh-terminal-bash': - specifier: workspace:* - version: link:../packages/terminal/terminal-bash '@deepseek-ai/dsh-pwsh-local': specifier: workspace:* version: link:../packages/shell/pwsh-local @@ -557,6 +560,9 @@ importers: '@deepseek-ai/dsh-scope': specifier: workspace:* version: link:../packages/core/scope + '@deepseek-ai/dsh-sdk-jsonrpc-server': + specifier: workspace:* + version: link:../packages/sdk/server '@deepseek-ai/dsh-session': specifier: workspace:* version: link:../packages/core/session @@ -590,6 +596,12 @@ importers: '@deepseek-ai/dsh-settings-file': specifier: workspace:* version: link:../packages/settings/settings-file + '@deepseek-ai/dsh-shell': + specifier: workspace:* + version: link:../packages/shell/shell + '@deepseek-ai/dsh-shell-env': + specifier: workspace:* + version: link:../packages/shell/shell-env '@deepseek-ai/dsh-skill': specifier: workspace:* version: link:../packages/skill/skill @@ -632,15 +644,15 @@ importers: '@deepseek-ai/dsh-system-prompt': specifier: workspace:* version: link:../packages/core/system-prompt - '@deepseek-ai/dsh-jobs-local': + '@deepseek-ai/dsh-terminal': specifier: workspace:* - version: link:../packages/jobs/jobs-local + version: link:../packages/terminal/terminal + '@deepseek-ai/dsh-terminal-bash': + specifier: workspace:* + version: link:../packages/terminal/terminal-bash '@deepseek-ai/dsh-time-context': specifier: workspace:* version: link:../packages/context/time-context - '@deepseek-ai/dsh-tool-call-timeout-policy': - specifier: workspace:* - version: link:../packages/guard/timeout-policy '@deepseek-ai/dsh-token-meter': specifier: workspace:* version: link:../packages/llm/token-meter @@ -653,6 +665,9 @@ importers: '@deepseek-ai/dsh-tool-bash-persistent': specifier: workspace:* version: link:../packages/shell/tool-bash-persistent + '@deepseek-ai/dsh-tool-call-timeout-policy': + specifier: workspace:* + version: link:../packages/guard/timeout-policy '@deepseek-ai/dsh-tool-cordis': specifier: workspace:* version: link:../packages/extensions/tool-cordis @@ -665,12 +680,12 @@ importers: '@deepseek-ai/dsh-tool-goal': specifier: workspace:* version: link:../packages/goal/tool-goal + '@deepseek-ai/dsh-tool-jobs': + specifier: workspace:* + version: link:../packages/jobs/tool-jobs '@deepseek-ai/dsh-tool-lsp': specifier: workspace:* version: link:../packages/lsp/tool-lsp - '@deepseek-ai/dsh-tool-terminal': - specifier: workspace:* - version: link:../packages/terminal/tool-terminal '@deepseek-ai/dsh-tool-pwsh': specifier: workspace:* version: link:../packages/shell/tool-pwsh @@ -695,9 +710,9 @@ importers: '@deepseek-ai/dsh-tool-subagent-report': specifier: workspace:* version: link:../packages/subagent/tool-subagent-report - '@deepseek-ai/dsh-tool-jobs': + '@deepseek-ai/dsh-tool-terminal': specifier: workspace:* - version: link:../packages/jobs/tool-jobs + version: link:../packages/terminal/tool-terminal '@deepseek-ai/dsh-tool-todo': specifier: workspace:* version: link:../packages/todo/tool-todo @@ -725,9 +740,6 @@ importers: '@deepseek-ai/dsh-workflow-worker-thread': specifier: workspace:* version: link:../packages/workflow/workflow-worker-thread - '@deepseek-ai/dsh-agent-instructions': - specifier: workspace:* - version: link:../packages/context/agent-instructions native/landlock-run: devDependencies: @@ -840,6 +852,9 @@ importers: '@deepseek-ai/dsh-commands': specifier: workspace:^ version: link:../../interaction/commands + '@deepseek-ai/dsh-cordis-host-runner': + specifier: workspace:^ + version: link:../../extensions/cordis-host-runner '@deepseek-ai/dsh-credentials': specifier: workspace:^ version: link:../../credentials/credentials @@ -898,299 +913,12 @@ importers: '@deepseek-ai/dsh-attachment': specifier: workspace:^ version: link:../attachment - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants '@deepseek-ai/dsh-home-paths': specifier: workspace:^ version: link:../../util/home-paths - - packages/shell/shell: - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-sandbox': - specifier: workspace:^ - version: link:../../sandbox/sandbox - '@deepseek-ai/dsh-settings': - specifier: workspace:^ - version: link:../../settings/settings - '@deepseek-ai/dsh-subprocess': - specifier: workspace:^ - version: link:../../subprocess/subprocess - - packages/shell/shell-env: - dependencies: - '@deepseek-ai/schemastery': - specifier: link:../../../vendor/schemastery - version: link:../../../vendor/schemastery - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-agent': - specifier: workspace:^ - version: link:../../core/agent - '@deepseek-ai/dsh-shell': - specifier: workspace:^ - version: link:../shell - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-llm': - specifier: workspace:^ - version: link:../../llm/llm - '@deepseek-ai/dsh-home-paths': - specifier: workspace:^ - version: link:../../util/home-paths - '@deepseek-ai/dsh-session-persistence': - specifier: workspace:^ - version: link:../../session/session-persistence - '@deepseek-ai/dsh-tools': - specifier: workspace:^ - version: link:../../core/tools - - packages/shell/bash-local: - dependencies: - '@deepseek-ai/schemastery': - specifier: link:../../../vendor/schemastery - version: link:../../../vendor/schemastery - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-shell': - specifier: workspace:^ - version: link:../shell - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-settings': - specifier: workspace:^ - version: link:../../settings/settings - '@deepseek-ai/dsh-subprocess': - specifier: workspace:^ - version: link:../../subprocess/subprocess - '@deepseek-ai/dsh-subprocess-local': - specifier: workspace:^ - version: link:../../subprocess/subprocess-local - '@deepseek-ai/dsh-timeout': - specifier: workspace:^ - version: link:../../util/timeout - - packages/shell/bash-sandbox: - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-shell': - specifier: workspace:^ - version: link:../shell - '@deepseek-ai/dsh-bash-local': - specifier: workspace:^ - version: link:../bash-local - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-sandbox': - specifier: workspace:^ - version: link:../../sandbox/sandbox - '@deepseek-ai/dsh-sandbox-local': - specifier: workspace:^ - version: link:../../sandbox/sandbox-local - '@deepseek-ai/dsh-sandbox-policy': - specifier: workspace:^ - version: link:../../sandbox/sandbox-policy - '@deepseek-ai/dsh-subprocess-local': - specifier: workspace:^ - version: link:../../subprocess/subprocess-local - '@deepseek-ai/node-addon-landlock-run': - specifier: workspace:* - version: link:../../../native/landlock-run/packages/entry - - packages/shell/pwsh-local: - dependencies: - '@deepseek-ai/schemastery': - specifier: link:../../../vendor/schemastery - version: link:../../../vendor/schemastery - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-shell': - specifier: workspace:^ - version: link:../shell - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-settings': - specifier: workspace:^ - version: link:../../settings/settings - '@deepseek-ai/dsh-subprocess': - specifier: workspace:^ - version: link:../../subprocess/subprocess - '@deepseek-ai/dsh-subprocess-local': - specifier: workspace:^ - version: link:../../subprocess/subprocess-local - '@deepseek-ai/dsh-timeout': - specifier: workspace:^ - version: link:../../util/timeout - - packages/shell/pwsh-sandbox: - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-shell': - specifier: workspace:^ - version: link:../shell - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-pwsh-local': - specifier: workspace:^ - version: link:../pwsh-local - '@deepseek-ai/dsh-sandbox': - specifier: workspace:^ - version: link:../../sandbox/sandbox - '@deepseek-ai/dsh-sandbox-local': - specifier: workspace:^ - version: link:../../sandbox/sandbox-local - '@deepseek-ai/dsh-sandbox-policy': - specifier: workspace:^ - version: link:../../sandbox/sandbox-policy - '@deepseek-ai/dsh-subprocess-local': - specifier: workspace:^ - version: link:../../subprocess/subprocess-local - - packages/shell/tool-bash: - dependencies: - '@deepseek-ai/schemastery': - specifier: link:../../../vendor/schemastery - version: link:../../../vendor/schemastery - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-agent': - specifier: workspace:^ - version: link:../../core/agent - '@deepseek-ai/dsh-agent-loop': - specifier: workspace:^ - version: link:../../core/agent-loop - '@deepseek-ai/dsh-agent-loop-testkit': - specifier: workspace:^ - version: link:../../test-support/agent-loop-testkit - '@deepseek-ai/dsh-shell': - specifier: workspace:^ - version: link:../shell - '@deepseek-ai/dsh-shell-env': - specifier: workspace:^ - version: link:../shell-env - '@deepseek-ai/dsh-bash-local': - specifier: workspace:^ - version: link:../bash-local - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-llm': - specifier: workspace:^ - version: link:../../llm/llm - '@deepseek-ai/dsh-sandbox': - specifier: workspace:^ - version: link:../../sandbox/sandbox - '@deepseek-ai/dsh-sandbox-policy': - specifier: workspace:^ - version: link:../../sandbox/sandbox-policy - '@deepseek-ai/dsh-session': - specifier: workspace:^ - version: link:../../core/session - '@deepseek-ai/dsh-session-persistence-jsonl': - specifier: workspace:^ - version: link:../../session/session-persistence-jsonl - '@deepseek-ai/dsh-subprocess-local': - specifier: workspace:^ - version: link:../../subprocess/subprocess-local - '@deepseek-ai/dsh-system-prompt': - specifier: workspace:^ - version: link:../../core/system-prompt - '@deepseek-ai/dsh-jobs': - specifier: workspace:^ - version: link:../../jobs/jobs - '@deepseek-ai/dsh-jobs-local': - specifier: workspace:^ - version: link:../../jobs/jobs-local - '@deepseek-ai/dsh-tool-jobs': - specifier: workspace:^ - version: link:../../jobs/tool-jobs - '@deepseek-ai/dsh-tools': - specifier: workspace:^ - version: link:../../core/tools - '@deepseek-ai/dsh-user-approval': - specifier: workspace:^ - version: link:../../interaction/user-approval - - packages/shell/tool-pwsh: - dependencies: - '@deepseek-ai/schemastery': - specifier: link:../../../vendor/schemastery - version: link:../../../vendor/schemastery - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-agent': - specifier: workspace:^ - version: link:../../core/agent - '@deepseek-ai/dsh-shell': - specifier: workspace:^ - version: link:../shell - '@deepseek-ai/dsh-shell-env': - specifier: workspace:^ - version: link:../shell-env - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-llm': - specifier: workspace:^ - version: link:../../llm/llm - '@deepseek-ai/dsh-loader-smoke': - specifier: workspace:^ - version: link:../../test-support/loader-smoke - '@deepseek-ai/dsh-pwsh-local': - specifier: workspace:^ - version: link:../pwsh-local - '@deepseek-ai/dsh-sandbox': - specifier: workspace:^ - version: link:../../sandbox/sandbox - '@deepseek-ai/dsh-sandbox-policy': - specifier: workspace:^ - version: link:../../sandbox/sandbox-policy - '@deepseek-ai/dsh-subprocess-local': - specifier: workspace:^ - version: link:../../subprocess/subprocess-local - '@deepseek-ai/dsh-system-prompt': - specifier: workspace:^ - version: link:../../core/system-prompt - '@deepseek-ai/dsh-jobs': - specifier: workspace:^ - version: link:../../jobs/jobs - '@deepseek-ai/dsh-jobs-local': - specifier: workspace:^ - version: link:../../jobs/jobs-local - '@deepseek-ai/dsh-tool-jobs': - specifier: workspace:^ - version: link:../../jobs/tool-jobs - '@deepseek-ai/dsh-tools': - specifier: workspace:^ - version: link:../../core/tools - '@deepseek-ai/dsh-user-approval': - specifier: workspace:^ - version: link:../../interaction/user-approval packages/boot/app-boot: dependencies: @@ -1216,15 +944,15 @@ importers: '@deepseek-ai/cordis-plugin-timer': specifier: workspace:^ version: link:../../../vendor/timer - '@deepseek-ai/dsh-launch-environment': - specifier: workspace:^ - version: link:../../util/launch-environment - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants '@deepseek-ai/dsh-home-paths': specifier: workspace:^ version: link:../../util/home-paths + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-launch-environment': + specifier: workspace:^ + version: link:../../util/launch-environment '@deepseek-ai/dsh-system-prompt': specifier: workspace:^ version: link:../../core/system-prompt @@ -1264,6 +992,9 @@ importers: '@deepseek-ai/dsh-agent-default-model': specifier: workspace:^ version: link:../../core/agent-default-model + '@deepseek-ai/dsh-agent-instructions': + specifier: workspace:^ + version: link:../../context/agent-instructions '@deepseek-ai/dsh-agent-loop': specifier: workspace:^ version: link:../../core/agent-loop @@ -1273,9 +1004,6 @@ importers: '@deepseek-ai/dsh-attachment-local': specifier: workspace:^ version: link:../../attachment/attachment-local - '@deepseek-ai/dsh-shell-env': - specifier: workspace:^ - version: link:../../shell/shell-env '@deepseek-ai/dsh-bash-sandbox': specifier: workspace:^ version: link:../../shell/bash-sandbox @@ -1315,6 +1043,9 @@ importers: '@deepseek-ai/dsh-goal-round-driver': specifier: workspace:^ version: link:../../goal/goal-round-driver + '@deepseek-ai/dsh-jobs-local': + specifier: workspace:^ + version: link:../../jobs/jobs-local '@deepseek-ai/dsh-llm': specifier: workspace:^ version: link:../../llm/llm @@ -1372,6 +1103,9 @@ importers: '@deepseek-ai/dsh-settings-file': specifier: workspace:^ version: link:../../settings/settings-file + '@deepseek-ai/dsh-shell-env': + specifier: workspace:^ + version: link:../../shell/shell-env '@deepseek-ai/dsh-skill': specifier: workspace:^ version: link:../../skill/skill @@ -1408,18 +1142,15 @@ importers: '@deepseek-ai/dsh-system-prompt': specifier: workspace:^ version: link:../../core/system-prompt - '@deepseek-ai/dsh-jobs-local': - specifier: workspace:^ - version: link:../../jobs/jobs-local - '@deepseek-ai/dsh-tool-call-timeout-policy': - specifier: workspace:^ - version: link:../../guard/timeout-policy '@deepseek-ai/dsh-token-meter': specifier: workspace:^ version: link:../../llm/token-meter '@deepseek-ai/dsh-tool-bash': specifier: workspace:^ version: link:../../shell/tool-bash + '@deepseek-ai/dsh-tool-call-timeout-policy': + specifier: workspace:^ + version: link:../../guard/timeout-policy '@deepseek-ai/dsh-tool-fs': specifier: workspace:^ version: link:../../fs/tool-fs @@ -1429,6 +1160,9 @@ importers: '@deepseek-ai/dsh-tool-goal': specifier: workspace:^ version: link:../../goal/tool-goal + '@deepseek-ai/dsh-tool-jobs': + specifier: workspace:^ + version: link:../../jobs/tool-jobs '@deepseek-ai/dsh-tool-pwsh': specifier: workspace:^ version: link:../../shell/tool-pwsh @@ -1450,9 +1184,6 @@ importers: '@deepseek-ai/dsh-tool-subagent-report': specifier: workspace:^ version: link:../../subagent/tool-subagent-report - '@deepseek-ai/dsh-tool-jobs': - specifier: workspace:^ - version: link:../../jobs/tool-jobs '@deepseek-ai/dsh-tool-todo': specifier: workspace:^ version: link:../../todo/tool-todo @@ -1486,9 +1217,6 @@ importers: '@deepseek-ai/dsh-workflow-worker-thread': specifier: workspace:^ version: link:../../workflow/workflow-worker-thread - '@deepseek-ai/dsh-agent-instructions': - specifier: workspace:^ - version: link:../../context/agent-instructions devDependencies: '@deepseek-ai/cordis': specifier: workspace:^ @@ -1569,6 +1297,9 @@ importers: '@deepseek-ai/dsh-client-ui-conversation': specifier: workspace:^ version: link:../../client/ui-conversation + '@deepseek-ai/dsh-client-ui-cordis': + specifier: workspace:^ + version: link:../../extensions/ui-cordis '@deepseek-ai/dsh-client-ui-deliverables': specifier: workspace:^ version: link:../../client/ui-deliverables @@ -1578,57 +1309,54 @@ importers: '@deepseek-ai/dsh-client-ui-directory-picker-native': specifier: workspace:^ version: link:../../client/ui-directory-picker-native - '@deepseek-ai/dsh-client-ui-message-feedback': - specifier: workspace:^ - version: link:../../client/ui-message-feedback '@deepseek-ai/dsh-client-ui-goal': specifier: workspace:^ version: link:../../client/ui-goal + '@deepseek-ai/dsh-client-ui-input-trigger': + specifier: workspace:^ + version: link:../../client/ui-input-trigger + '@deepseek-ai/dsh-client-ui-jobs': + specifier: workspace:^ + version: link:../../client/ui-jobs '@deepseek-ai/dsh-client-ui-layout': specifier: workspace:^ version: link:../../client/ui-layout + '@deepseek-ai/dsh-client-ui-message-feedback': + specifier: workspace:^ + version: link:../../client/ui-message-feedback '@deepseek-ai/dsh-client-ui-model-selection': specifier: workspace:^ version: link:../../client/ui-model-selection - '@deepseek-ai/dsh-client-ui-settings-models': - specifier: workspace:^ - version: link:../../client/ui-settings-models '@deepseek-ai/dsh-client-ui-permission-presets': specifier: workspace:^ version: link:../../client/ui-permission-presets '@deepseek-ai/dsh-client-ui-plan': specifier: workspace:^ version: link:../../client/ui-plan - '@deepseek-ai/dsh-client-ui-settings-plugins': - specifier: workspace:^ - version: link:../../client/ui-settings-plugins - '@deepseek-ai/dsh-client-ui-settings-plugin-inventory': - specifier: workspace:^ - version: link:../../client/ui-settings-plugin-inventory - '@deepseek-ai/dsh-client-ui-user-questions': - specifier: workspace:^ - version: link:../../client/ui-user-questions '@deepseek-ai/dsh-client-ui-settings': specifier: workspace:^ version: link:../../client/ui-settings '@deepseek-ai/dsh-client-ui-settings-general': specifier: workspace:^ version: link:../../client/ui-settings-general + '@deepseek-ai/dsh-client-ui-settings-models': + specifier: workspace:^ + version: link:../../client/ui-settings-models + '@deepseek-ai/dsh-client-ui-settings-plugin-inventory': + specifier: workspace:^ + version: link:../../client/ui-settings-plugin-inventory + '@deepseek-ai/dsh-client-ui-settings-plugins': + specifier: workspace:^ + version: link:../../client/ui-settings-plugins '@deepseek-ai/dsh-client-ui-sidebar': specifier: workspace:^ version: link:../../client/ui-sidebar '@deepseek-ai/dsh-client-ui-skill': specifier: workspace:^ version: link:../../client/ui-skill - '@deepseek-ai/dsh-client-ui-input-trigger': - specifier: workspace:^ - version: link:../../client/ui-input-trigger '@deepseek-ai/dsh-client-ui-subagent': specifier: workspace:^ version: link:../../client/ui-subagent - '@deepseek-ai/dsh-client-ui-jobs': - specifier: workspace:^ - version: link:../../client/ui-jobs '@deepseek-ai/dsh-client-ui-theme': specifier: workspace:^ version: link:../../client/ui-theme @@ -1638,6 +1366,9 @@ importers: '@deepseek-ai/dsh-client-ui-trajectory': specifier: workspace:^ version: link:../../client/ui-trajectory + '@deepseek-ai/dsh-client-ui-user-questions': + specifier: workspace:^ + version: link:../../client/ui-user-questions '@deepseek-ai/dsh-client-ui-workflow-run': specifier: workspace:^ version: link:../../client/ui-workflow-run @@ -1650,12 +1381,12 @@ importers: '@deepseek-ai/dsh-code-runtime-worker-thread': specifier: workspace:^ version: link:../../code-runtime/code-runtime-worker-thread - '@deepseek-ai/dsh-web-frontend': + '@deepseek-ai/dsh-cordis-client-runner': specifier: workspace:^ - version: link:../../../apps/web - '@deepseek-ai/dsh-host-frontend-static': + version: link:../../extensions/cordis-client-runner + '@deepseek-ai/dsh-cordis-host-runner': specifier: workspace:^ - version: link:../../host/frontend-static + version: link:../../extensions/cordis-host-runner '@deepseek-ai/dsh-host-apiproxy': specifier: workspace:^ version: link:../../host/apiproxy @@ -1668,6 +1399,9 @@ importers: '@deepseek-ai/dsh-host-directory-picker-native': specifier: workspace:^ version: link:../../host/directory-picker-native + '@deepseek-ai/dsh-host-frontend-static': + specifier: workspace:^ + version: link:../../host/frontend-static '@deepseek-ai/dsh-host-plugin-inventory': specifier: workspace:^ version: link:../../host/plugin-inventory @@ -1695,6 +1429,9 @@ importers: '@deepseek-ai/dsh-storage-json': specifier: workspace:^ version: link:../../storage/storage-json + '@deepseek-ai/dsh-web-frontend': + specifier: workspace:^ + version: link:../../../apps/web '@deepseek-ai/dsh-workspace': specifier: workspace:^ version: link:../../workspace/workspace @@ -1711,12 +1448,12 @@ importers: '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ version: link:../../../vendor/loader - '@deepseek-ai/dsh-shell-env': - specifier: workspace:^ - version: link:../../shell/shell-env '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-shell-env': + specifier: workspace:^ + version: link:../../shell/shell-env '@deepseek-ai/dsh-system-prompt': specifier: workspace:^ version: link:../../core/system-prompt @@ -1921,49 +1658,6 @@ importers: specifier: workspace:^ version: link:../../runtime-diagnostics/invariants - packages/test-support/client-runtime: - dependencies: - '@testing-library/dom': - specifier: ^10.4.1 - version: 10.4.1 - '@testing-library/react': - specifier: ^16.3.2 - version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - vitest: - specifier: ^4.1.8 - version: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@25.9.3)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-client-runtime': - specifier: workspace:^ - version: link:../../client/runtime - '@deepseek-ai/dsh-client-ui-slots': - specifier: workspace:^ - version: link:../../client/ui-slots - '@deepseek-ai/dsh-client-web-react': - specifier: workspace:^ - version: link:../../client/web-react - '@deepseek-ai/dsh-host-apiproxy': - specifier: workspace:^ - version: link:../../host/apiproxy - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@types/react': - specifier: ~18.3.1 - version: 18.3.31 - '@types/react-dom': - specifier: ~18.3.0 - version: 18.3.7(@types/react@18.3.31) - react: - specifier: ^18.2.0 - version: 18.3.1 - react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) - packages/client/ui-agent-preset: devDependencies: '@deepseek-ai/cordis': @@ -2067,12 +1761,12 @@ importers: '@deepseek-ai/dsh-client-ui-conversation': specifier: workspace:^ version: link:../ui-conversation - '@deepseek-ai/dsh-client-ui-primitives': - specifier: workspace:^ - version: link:../ui-primitives '@deepseek-ai/dsh-client-ui-input-trigger': specifier: workspace:^ version: link:../ui-input-trigger + '@deepseek-ai/dsh-client-ui-primitives': + specifier: workspace:^ + version: link:../ui-primitives '@deepseek-ai/dsh-client-ui-slots': specifier: workspace:^ version: link:../ui-slots @@ -2131,6 +1825,9 @@ importers: '@deepseek-ai/dsh-client-ui-attachment': specifier: workspace:^ version: link:../ui-attachment + '@deepseek-ai/dsh-client-ui-input-trigger': + specifier: workspace:^ + version: link:../ui-input-trigger '@deepseek-ai/dsh-client-ui-layout': specifier: workspace:^ version: link:../ui-layout @@ -2140,9 +1837,6 @@ importers: '@deepseek-ai/dsh-client-ui-settings': specifier: workspace:^ version: link:../ui-settings - '@deepseek-ai/dsh-client-ui-input-trigger': - specifier: workspace:^ - version: link:../ui-input-trigger '@deepseek-ai/dsh-client-ui-slots': specifier: workspace:^ version: link:../ui-slots @@ -2299,6 +1993,149 @@ importers: specifier: ^18.2.0 version: 18.3.1(react@18.3.1) + packages/client/ui-goal: + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-api-remotes': + specifier: workspace:^ + version: link:../../api/remotes + '@deepseek-ai/dsh-client-locale': + specifier: workspace:^ + version: link:../locale + '@deepseek-ai/dsh-client-runtime': + specifier: workspace:^ + version: link:../runtime + '@deepseek-ai/dsh-client-test-runtime': + specifier: workspace:^ + version: link:../../test-support/client-runtime + '@deepseek-ai/dsh-client-ui-conversation': + specifier: workspace:^ + version: link:../ui-conversation + '@deepseek-ai/dsh-client-ui-primitives': + specifier: workspace:^ + version: link:../ui-primitives + '@deepseek-ai/dsh-client-ui-slots': + specifier: workspace:^ + version: link:../ui-slots + '@deepseek-ai/dsh-commands': + specifier: workspace:^ + version: link:../../interaction/commands + '@deepseek-ai/dsh-goal': + specifier: workspace:^ + version: link:../../goal/goal + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@testing-library/react': + specifier: ^16.1.0 + version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@types/react': + specifier: ~18.3.1 + version: 18.3.31 + react: + specifier: ^18.2.0 + version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) + + packages/client/ui-input-trigger: + dependencies: + clsx: + specifier: ^2.0.0 + version: 2.1.1 + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-client-locale': + specifier: workspace:^ + version: link:../locale + '@deepseek-ai/dsh-client-runtime': + specifier: workspace:^ + version: link:../runtime + '@deepseek-ai/dsh-client-test-runtime': + specifier: workspace:^ + version: link:../../test-support/client-runtime + '@deepseek-ai/dsh-client-ui-primitives': + specifier: workspace:^ + version: link:../ui-primitives + '@deepseek-ai/dsh-client-ui-slots': + specifier: workspace:^ + version: link:../ui-slots + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@types/react': + specifier: ~18.3.1 + version: 18.3.31 + react: + specifier: ^18.2.0 + version: 18.3.1 + + packages/client/ui-jobs: + dependencies: + react: + specifier: ^18.2.0 + version: 18.3.1 + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-client-locale': + specifier: workspace:^ + version: link:../locale + '@deepseek-ai/dsh-client-runtime': + specifier: workspace:^ + version: link:../runtime + '@deepseek-ai/dsh-client-test-runtime': + specifier: workspace:^ + version: link:../../test-support/client-runtime + '@deepseek-ai/dsh-client-ui-conversation': + specifier: workspace:^ + version: link:../ui-conversation + '@deepseek-ai/dsh-client-ui-primitives': + specifier: workspace:^ + version: link:../ui-primitives + '@deepseek-ai/dsh-client-ui-slots': + specifier: workspace:^ + version: link:../ui-slots + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@types/react': + specifier: ~18.3.1 + version: 18.3.31 + + packages/client/ui-layout: + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-client-locale': + specifier: workspace:^ + version: link:../locale + '@deepseek-ai/dsh-client-runtime': + specifier: workspace:^ + version: link:../runtime + '@deepseek-ai/dsh-client-ui-slots': + specifier: workspace:^ + version: link:../ui-slots + '@deepseek-ai/dsh-client-ui-theme': + specifier: workspace:^ + version: link:../ui-theme + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@types/react': + specifier: ~18.3.1 + version: 18.3.31 + react: + specifier: ^18.2.0 + version: 18.3.1 + packages/client/ui-message-feedback: devDependencies: '@deepseek-ai/cordis': @@ -2350,81 +2187,6 @@ importers: specifier: ^18.2.0 version: 18.3.1(react@18.3.1) - packages/client/ui-goal: - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-api-remotes': - specifier: workspace:^ - version: link:../../api/remotes - '@deepseek-ai/dsh-client-locale': - specifier: workspace:^ - version: link:../locale - '@deepseek-ai/dsh-client-runtime': - specifier: workspace:^ - version: link:../runtime - '@deepseek-ai/dsh-client-test-runtime': - specifier: workspace:^ - version: link:../../test-support/client-runtime - '@deepseek-ai/dsh-client-ui-conversation': - specifier: workspace:^ - version: link:../ui-conversation - '@deepseek-ai/dsh-client-ui-primitives': - specifier: workspace:^ - version: link:../ui-primitives - '@deepseek-ai/dsh-client-ui-slots': - specifier: workspace:^ - version: link:../ui-slots - '@deepseek-ai/dsh-commands': - specifier: workspace:^ - version: link:../../interaction/commands - '@deepseek-ai/dsh-goal': - specifier: workspace:^ - version: link:../../goal/goal - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@testing-library/react': - specifier: ^16.1.0 - version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@types/react': - specifier: ~18.3.1 - version: 18.3.31 - react: - specifier: ^18.2.0 - version: 18.3.1 - react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) - - packages/client/ui-layout: - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-client-locale': - specifier: workspace:^ - version: link:../locale - '@deepseek-ai/dsh-client-runtime': - specifier: workspace:^ - version: link:../runtime - '@deepseek-ai/dsh-client-ui-slots': - specifier: workspace:^ - version: link:../ui-slots - '@deepseek-ai/dsh-client-ui-theme': - specifier: workspace:^ - version: link:../ui-theme - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@types/react': - specifier: ~18.3.1 - version: 18.3.31 - react: - specifier: ^18.2.0 - version: 18.3.1 - packages/client/ui-model-selection: devDependencies: '@deepseek-ai/cordis': @@ -2451,12 +2213,12 @@ importers: '@deepseek-ai/dsh-client-ui-conversation': specifier: workspace:^ version: link:../ui-conversation - '@deepseek-ai/dsh-client-ui-primitives': - specifier: workspace:^ - version: link:../ui-primitives '@deepseek-ai/dsh-client-ui-input-trigger': specifier: workspace:^ version: link:../ui-input-trigger + '@deepseek-ai/dsh-client-ui-primitives': + specifier: workspace:^ + version: link:../ui-primitives '@deepseek-ai/dsh-client-ui-slots': specifier: workspace:^ version: link:../ui-slots @@ -2473,51 +2235,6 @@ importers: specifier: ^18.2.0 version: 18.3.1 - packages/client/ui-settings-models: - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-api-remotes': - specifier: workspace:^ - version: link:../../api/remotes - '@deepseek-ai/dsh-client-connection': - specifier: workspace:^ - version: link:../connection - '@deepseek-ai/dsh-client-locale': - specifier: workspace:^ - version: link:../locale - '@deepseek-ai/dsh-client-runtime': - specifier: workspace:^ - version: link:../runtime - '@deepseek-ai/dsh-client-schema-form': - specifier: workspace:^ - version: link:../schema-form - '@deepseek-ai/dsh-client-test-runtime': - specifier: workspace:^ - version: link:../../test-support/client-runtime - '@deepseek-ai/dsh-client-ui-primitives': - specifier: workspace:^ - version: link:../ui-primitives - '@deepseek-ai/dsh-client-ui-settings': - specifier: workspace:^ - version: link:../ui-settings - '@deepseek-ai/dsh-client-ui-slots': - specifier: workspace:^ - version: link:../ui-slots - '@deepseek-ai/dsh-client-web-react': - specifier: workspace:^ - version: link:../web-react - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@types/react': - specifier: ~18.3.1 - version: 18.3.31 - react: - specifier: ^18.2.0 - version: 18.3.1 - packages/client/ui-permission-presets: devDependencies: '@deepseek-ai/cordis': @@ -2544,15 +2261,15 @@ importers: '@deepseek-ai/dsh-client-ui-commands': specifier: workspace:^ version: link:../ui-commands + '@deepseek-ai/dsh-client-ui-input-trigger': + specifier: workspace:^ + version: link:../ui-input-trigger '@deepseek-ai/dsh-client-ui-primitives': specifier: workspace:^ version: link:../ui-primitives '@deepseek-ai/dsh-client-ui-settings': specifier: workspace:^ version: link:../ui-settings - '@deepseek-ai/dsh-client-ui-input-trigger': - specifier: workspace:^ - version: link:../ui-input-trigger '@deepseek-ai/dsh-client-ui-slots': specifier: workspace:^ version: link:../ui-slots @@ -2614,94 +2331,6 @@ importers: specifier: ^18.2.0 version: 18.3.1 - packages/client/ui-settings-plugins: - dependencies: - clsx: - specifier: ^2.0.0 - version: 2.1.1 - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-api-remotes': - specifier: workspace:^ - version: link:../../api/remotes - '@deepseek-ai/dsh-client-connection': - specifier: workspace:^ - version: link:../connection - '@deepseek-ai/dsh-client-locale': - specifier: workspace:^ - version: link:../locale - '@deepseek-ai/dsh-client-runtime': - specifier: workspace:^ - version: link:../runtime - '@deepseek-ai/dsh-client-test-runtime': - specifier: workspace:^ - version: link:../../test-support/client-runtime - '@deepseek-ai/dsh-client-ui-primitives': - specifier: workspace:^ - version: link:../ui-primitives - '@deepseek-ai/dsh-client-ui-settings': - specifier: workspace:^ - version: link:../ui-settings - '@deepseek-ai/dsh-client-ui-slots': - specifier: workspace:^ - version: link:../ui-slots - '@deepseek-ai/dsh-client-web-react': - specifier: workspace:^ - version: link:../web-react - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@types/react': - specifier: ~18.3.1 - version: 18.3.31 - react: - specifier: ^18.2.0 - version: 18.3.1 - - packages/client/ui-settings-plugin-inventory: - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-api-remotes': - specifier: workspace:^ - version: link:../../api/remotes - '@deepseek-ai/dsh-client-locale': - specifier: workspace:^ - version: link:../locale - '@deepseek-ai/dsh-client-runtime': - specifier: workspace:^ - version: link:../runtime - '@deepseek-ai/dsh-client-test-runtime': - specifier: workspace:^ - version: link:../../test-support/client-runtime - '@deepseek-ai/dsh-client-ui-primitives': - specifier: workspace:^ - version: link:../ui-primitives - '@deepseek-ai/dsh-client-ui-settings': - specifier: workspace:^ - version: link:../ui-settings - '@deepseek-ai/dsh-client-ui-slots': - specifier: workspace:^ - version: link:../ui-slots - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@testing-library/react': - specifier: ^16.1.0 - version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@types/react': - specifier: ~18.3.1 - version: 18.3.31 - react: - specifier: ^18.2.0 - version: 18.3.1 - react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) - packages/client/ui-primitives: dependencies: '@shikijs/langs': @@ -2778,58 +2407,6 @@ importers: specifier: ~18.3.0 version: 18.3.7(@types/react@18.3.31) - packages/client/ui-user-questions: - dependencies: - '@deepseek-ai/dsh-client-connection': - specifier: workspace:^ - version: link:../connection - '@deepseek-ai/dsh-client-runtime': - specifier: workspace:^ - version: link:../runtime - '@deepseek-ai/dsh-client-ui-conversation': - specifier: workspace:^ - version: link:../ui-conversation - '@deepseek-ai/dsh-client-ui-primitives': - specifier: workspace:^ - version: link:../ui-primitives - '@deepseek-ai/dsh-client-ui-slots': - specifier: workspace:^ - version: link:../ui-slots - clsx: - specifier: ^2.0.0 - version: 2.1.1 - react: - specifier: ^18.2.0 - version: 18.3.1 - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-agent': - specifier: workspace:^ - version: link:../../core/agent - '@deepseek-ai/dsh-api-remotes': - specifier: workspace:^ - version: link:../../api/remotes - '@deepseek-ai/dsh-client-locale': - specifier: workspace:^ - version: link:../locale - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-system-prompt': - specifier: workspace:^ - version: link:../../core/system-prompt - '@deepseek-ai/dsh-tools': - specifier: workspace:^ - version: link:../../core/tools - '@deepseek-ai/dsh-user-questions': - specifier: workspace:^ - version: link:../../interaction/user-questions - '@types/react': - specifier: ~18.3.1 - version: 18.3.31 - packages/client/ui-settings: dependencies: '@deepseek-ai/dsh-client-connection': @@ -2922,6 +2499,139 @@ importers: specifier: ^18.2.0 version: 18.3.1 + packages/client/ui-settings-models: + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-api-remotes': + specifier: workspace:^ + version: link:../../api/remotes + '@deepseek-ai/dsh-client-connection': + specifier: workspace:^ + version: link:../connection + '@deepseek-ai/dsh-client-locale': + specifier: workspace:^ + version: link:../locale + '@deepseek-ai/dsh-client-runtime': + specifier: workspace:^ + version: link:../runtime + '@deepseek-ai/dsh-client-schema-form': + specifier: workspace:^ + version: link:../schema-form + '@deepseek-ai/dsh-client-test-runtime': + specifier: workspace:^ + version: link:../../test-support/client-runtime + '@deepseek-ai/dsh-client-ui-primitives': + specifier: workspace:^ + version: link:../ui-primitives + '@deepseek-ai/dsh-client-ui-settings': + specifier: workspace:^ + version: link:../ui-settings + '@deepseek-ai/dsh-client-ui-slots': + specifier: workspace:^ + version: link:../ui-slots + '@deepseek-ai/dsh-client-web-react': + specifier: workspace:^ + version: link:../web-react + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@types/react': + specifier: ~18.3.1 + version: 18.3.31 + react: + specifier: ^18.2.0 + version: 18.3.1 + + packages/client/ui-settings-plugin-inventory: + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-api-remotes': + specifier: workspace:^ + version: link:../../api/remotes + '@deepseek-ai/dsh-client-locale': + specifier: workspace:^ + version: link:../locale + '@deepseek-ai/dsh-client-runtime': + specifier: workspace:^ + version: link:../runtime + '@deepseek-ai/dsh-client-test-runtime': + specifier: workspace:^ + version: link:../../test-support/client-runtime + '@deepseek-ai/dsh-client-ui-primitives': + specifier: workspace:^ + version: link:../ui-primitives + '@deepseek-ai/dsh-client-ui-settings': + specifier: workspace:^ + version: link:../ui-settings + '@deepseek-ai/dsh-client-ui-slots': + specifier: workspace:^ + version: link:../ui-slots + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@testing-library/react': + specifier: ^16.1.0 + version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@types/react': + specifier: ~18.3.1 + version: 18.3.31 + react: + specifier: ^18.2.0 + version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) + + packages/client/ui-settings-plugins: + dependencies: + clsx: + specifier: ^2.0.0 + version: 2.1.1 + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-api-remotes': + specifier: workspace:^ + version: link:../../api/remotes + '@deepseek-ai/dsh-client-connection': + specifier: workspace:^ + version: link:../connection + '@deepseek-ai/dsh-client-locale': + specifier: workspace:^ + version: link:../locale + '@deepseek-ai/dsh-client-runtime': + specifier: workspace:^ + version: link:../runtime + '@deepseek-ai/dsh-client-test-runtime': + specifier: workspace:^ + version: link:../../test-support/client-runtime + '@deepseek-ai/dsh-client-ui-primitives': + specifier: workspace:^ + version: link:../ui-primitives + '@deepseek-ai/dsh-client-ui-settings': + specifier: workspace:^ + version: link:../ui-settings + '@deepseek-ai/dsh-client-ui-slots': + specifier: workspace:^ + version: link:../ui-slots + '@deepseek-ai/dsh-client-web-react': + specifier: workspace:^ + version: link:../web-react + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@types/react': + specifier: ~18.3.1 + version: 18.3.31 + react: + specifier: ^18.2.0 + version: 18.3.1 + packages/client/ui-sidebar: dependencies: clsx: @@ -2979,12 +2689,12 @@ importers: '@deepseek-ai/dsh-client-test-runtime': specifier: workspace:^ version: link:../../test-support/client-runtime - '@deepseek-ai/dsh-client-ui-primitives': - specifier: workspace:^ - version: link:../ui-primitives '@deepseek-ai/dsh-client-ui-input-trigger': specifier: workspace:^ version: link:../ui-input-trigger + '@deepseek-ai/dsh-client-ui-primitives': + specifier: workspace:^ + version: link:../ui-primitives '@deepseek-ai/dsh-client-ui-slots': specifier: workspace:^ version: link:../ui-slots @@ -3007,40 +2717,6 @@ importers: specifier: ^18.2.0 version: 18.3.1(react@18.3.1) - packages/client/ui-input-trigger: - dependencies: - clsx: - specifier: ^2.0.0 - version: 2.1.1 - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-client-locale': - specifier: workspace:^ - version: link:../locale - '@deepseek-ai/dsh-client-runtime': - specifier: workspace:^ - version: link:../runtime - '@deepseek-ai/dsh-client-test-runtime': - specifier: workspace:^ - version: link:../../test-support/client-runtime - '@deepseek-ai/dsh-client-ui-primitives': - specifier: workspace:^ - version: link:../ui-primitives - '@deepseek-ai/dsh-client-ui-slots': - specifier: workspace:^ - version: link:../ui-slots - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@types/react': - specifier: ~18.3.1 - version: 18.3.31 - react: - specifier: ^18.2.0 - version: 18.3.1 - packages/client/ui-slots: devDependencies: '@deepseek-ai/cordis': @@ -3074,12 +2750,12 @@ importers: '@deepseek-ai/dsh-client-ui-conversation': specifier: workspace:^ version: link:../ui-conversation - '@deepseek-ai/dsh-client-ui-primitives': - specifier: workspace:^ - version: link:../ui-primitives '@deepseek-ai/dsh-client-ui-input-trigger': specifier: workspace:^ version: link:../ui-input-trigger + '@deepseek-ai/dsh-client-ui-primitives': + specifier: workspace:^ + version: link:../ui-primitives '@deepseek-ai/dsh-client-ui-slots': specifier: workspace:^ version: link:../ui-slots @@ -3096,40 +2772,6 @@ importers: specifier: ~18.3.1 version: 18.3.31 - packages/client/ui-jobs: - dependencies: - react: - specifier: ^18.2.0 - version: 18.3.1 - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-client-locale': - specifier: workspace:^ - version: link:../locale - '@deepseek-ai/dsh-client-runtime': - specifier: workspace:^ - version: link:../runtime - '@deepseek-ai/dsh-client-test-runtime': - specifier: workspace:^ - version: link:../../test-support/client-runtime - '@deepseek-ai/dsh-client-ui-conversation': - specifier: workspace:^ - version: link:../ui-conversation - '@deepseek-ai/dsh-client-ui-primitives': - specifier: workspace:^ - version: link:../ui-primitives - '@deepseek-ai/dsh-client-ui-slots': - specifier: workspace:^ - version: link:../ui-slots - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@types/react': - specifier: ~18.3.1 - version: 18.3.31 - packages/client/ui-theme: dependencies: '@deepseek-ai/dsh-client-connection': @@ -3289,6 +2931,58 @@ importers: specifier: ^18.2.0 version: 18.3.1(react@18.3.1) + packages/client/ui-user-questions: + dependencies: + '@deepseek-ai/dsh-client-connection': + specifier: workspace:^ + version: link:../connection + '@deepseek-ai/dsh-client-runtime': + specifier: workspace:^ + version: link:../runtime + '@deepseek-ai/dsh-client-ui-conversation': + specifier: workspace:^ + version: link:../ui-conversation + '@deepseek-ai/dsh-client-ui-primitives': + specifier: workspace:^ + version: link:../ui-primitives + '@deepseek-ai/dsh-client-ui-slots': + specifier: workspace:^ + version: link:../ui-slots + clsx: + specifier: ^2.0.0 + version: 2.1.1 + react: + specifier: ^18.2.0 + version: 18.3.1 + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-agent': + specifier: workspace:^ + version: link:../../core/agent + '@deepseek-ai/dsh-api-remotes': + specifier: workspace:^ + version: link:../../api/remotes + '@deepseek-ai/dsh-client-locale': + specifier: workspace:^ + version: link:../locale + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-system-prompt': + specifier: workspace:^ + version: link:../../core/system-prompt + '@deepseek-ai/dsh-tools': + specifier: workspace:^ + version: link:../../core/tools + '@deepseek-ai/dsh-user-questions': + specifier: workspace:^ + version: link:../../interaction/user-questions + '@types/react': + specifier: ~18.3.1 + version: 18.3.31 + packages/client/ui-workflow-run: dependencies: react: @@ -3614,6 +3308,55 @@ importers: specifier: workspace:^ version: link:../../llm/token-meter + packages/context/agent-instructions: + dependencies: + '@deepseek-ai/schemastery': + specifier: link:../../../vendor/schemastery + version: link:../../../vendor/schemastery + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/cordis-plugin-loader': + specifier: workspace:^ + version: link:../../../vendor/loader + '@deepseek-ai/dsh-agent': + specifier: workspace:^ + version: link:../../core/agent + '@deepseek-ai/dsh-agent-loop': + specifier: workspace:^ + version: link:../../core/agent-loop + '@deepseek-ai/dsh-fs': + specifier: workspace:^ + version: link:../../fs/fs + '@deepseek-ai/dsh-fs-local': + specifier: workspace:^ + version: link:../../fs/fs-local + '@deepseek-ai/dsh-home-paths': + specifier: workspace:^ + version: link:../../util/home-paths + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-llm': + specifier: workspace:^ + version: link:../../llm/llm + '@deepseek-ai/dsh-llm-deepseek': + specifier: workspace:^ + version: link:../../llm/llm-deepseek + '@deepseek-ai/dsh-session': + specifier: workspace:^ + version: link:../../core/session + '@deepseek-ai/dsh-system-prompt': + specifier: workspace:^ + version: link:../../core/system-prompt + '@deepseek-ai/dsh-tool-fs': + specifier: workspace:^ + version: link:../../fs/tool-fs + '@deepseek-ai/dsh-tools': + specifier: workspace:^ + version: link:../../core/tools + packages/context/session-reference: dependencies: '@deepseek-ai/schemastery': @@ -3694,71 +3437,22 @@ importers: '@deepseek-ai/dsh-agent': specifier: workspace:^ version: link:../../core/agent + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-llm': + specifier: workspace:^ + version: link:../../llm/llm + '@deepseek-ai/dsh-session': + specifier: workspace:^ + version: link:../../core/session '@deepseek-ai/dsh-shell': specifier: workspace:^ version: link:../../shell/shell - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-llm': - specifier: workspace:^ - version: link:../../llm/llm - '@deepseek-ai/dsh-session': - specifier: workspace:^ - version: link:../../core/session '@deepseek-ai/dsh-system-prompt': specifier: workspace:^ version: link:../../core/system-prompt - packages/context/agent-instructions: - dependencies: - '@deepseek-ai/schemastery': - specifier: link:../../../vendor/schemastery - version: link:../../../vendor/schemastery - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ - version: link:../../../vendor/loader - '@deepseek-ai/dsh-agent': - specifier: workspace:^ - version: link:../../core/agent - '@deepseek-ai/dsh-agent-loop': - specifier: workspace:^ - version: link:../../core/agent-loop - '@deepseek-ai/dsh-fs': - specifier: workspace:^ - version: link:../../fs/fs - '@deepseek-ai/dsh-fs-local': - specifier: workspace:^ - version: link:../../fs/fs-local - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-llm': - specifier: workspace:^ - version: link:../../llm/llm - '@deepseek-ai/dsh-llm-deepseek': - specifier: workspace:^ - version: link:../../llm/llm-deepseek - '@deepseek-ai/dsh-home-paths': - specifier: workspace:^ - version: link:../../util/home-paths - '@deepseek-ai/dsh-session': - specifier: workspace:^ - version: link:../../core/session - '@deepseek-ai/dsh-system-prompt': - specifier: workspace:^ - version: link:../../core/system-prompt - '@deepseek-ai/dsh-tool-fs': - specifier: workspace:^ - version: link:../../fs/tool-fs - '@deepseek-ai/dsh-tools': - specifier: workspace:^ - version: link:../../core/tools - packages/core/agent: devDependencies: '@deepseek-ai/cordis': @@ -3998,15 +3692,15 @@ importers: '@deepseek-ai/dsh-credentials': specifier: workspace:^ version: link:../credentials - '@deepseek-ai/dsh-launch-environment': - specifier: workspace:^ - version: link:../../util/launch-environment - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants '@deepseek-ai/dsh-home-paths': specifier: workspace:^ version: link:../../util/home-paths + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-launch-environment': + specifier: workspace:^ + version: link:../../util/launch-environment packages/e2b/e2b: dependencies: @@ -4088,6 +3782,9 @@ importers: '@deepseek-ai/dsh-agent': specifier: workspace:^ version: link:../../core/agent + '@deepseek-ai/dsh-agent-instructions': + specifier: workspace:^ + version: link:../../context/agent-instructions '@deepseek-ai/dsh-agent-spine-demo': specifier: workspace:^ version: link:../agent-spine-demo @@ -4115,9 +3812,6 @@ importers: '@deepseek-ai/dsh-tools': specifier: workspace:^ version: link:../../core/tools - '@deepseek-ai/dsh-agent-instructions': - specifier: workspace:^ - version: link:../../context/agent-instructions packages/examples/agent-spine-demo: dependencies: @@ -4134,12 +3828,12 @@ importers: '@deepseek-ai/dsh-agent': specifier: workspace:^ version: link:../../core/agent + '@deepseek-ai/dsh-agent-instructions': + specifier: workspace:^ + version: link:../../context/agent-instructions '@deepseek-ai/dsh-agent-loop': specifier: workspace:^ version: link:../../core/agent-loop - '@deepseek-ai/dsh-shell-env': - specifier: workspace:^ - version: link:../../shell/shell-env '@deepseek-ai/dsh-bash-local': specifier: workspace:^ version: link:../../shell/bash-local @@ -4161,18 +3855,24 @@ importers: '@deepseek-ai/dsh-goal-round-driver': specifier: workspace:^ version: link:../../goal/goal-round-driver + '@deepseek-ai/dsh-home-paths': + specifier: workspace:^ + version: link:../../util/home-paths '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-jobs': + specifier: workspace:^ + version: link:../../jobs/jobs + '@deepseek-ai/dsh-jobs-local': + specifier: workspace:^ + version: link:../../jobs/jobs-local '@deepseek-ai/dsh-llm': specifier: workspace:^ version: link:../../llm/llm '@deepseek-ai/dsh-llm-retry': specifier: workspace:^ version: link:../../llm/llm-retry - '@deepseek-ai/dsh-home-paths': - specifier: workspace:^ - version: link:../../util/home-paths '@deepseek-ai/dsh-sandbox-local': specifier: workspace:^ version: link:../../sandbox/sandbox-local @@ -4188,6 +3888,9 @@ importers: '@deepseek-ai/dsh-session-title': specifier: workspace:^ version: link:../../session/session-title + '@deepseek-ai/dsh-shell-env': + specifier: workspace:^ + version: link:../../shell/shell-env '@deepseek-ai/dsh-skill': specifier: workspace:^ version: link:../../skill/skill @@ -4200,12 +3903,6 @@ importers: '@deepseek-ai/dsh-system-prompt': specifier: workspace:^ version: link:../../core/system-prompt - '@deepseek-ai/dsh-jobs': - specifier: workspace:^ - version: link:../../jobs/jobs - '@deepseek-ai/dsh-jobs-local': - specifier: workspace:^ - version: link:../../jobs/jobs-local '@deepseek-ai/dsh-tool-bash': specifier: workspace:^ version: link:../../shell/tool-bash @@ -4215,18 +3912,15 @@ importers: '@deepseek-ai/dsh-tool-goal': specifier: workspace:^ version: link:../../goal/tool-goal - '@deepseek-ai/dsh-tool-skill': - specifier: workspace:^ - version: link:../../skill/tool-skill '@deepseek-ai/dsh-tool-jobs': specifier: workspace:^ version: link:../../jobs/tool-jobs + '@deepseek-ai/dsh-tool-skill': + specifier: workspace:^ + version: link:../../skill/tool-skill '@deepseek-ai/dsh-tools': specifier: workspace:^ version: link:../../core/tools - '@deepseek-ai/dsh-agent-instructions': - specifier: workspace:^ - version: link:../../context/agent-instructions '@deepseek-ai/node-addon-landlock-run': specifier: workspace:* version: link:../../../native/landlock-run/packages/entry @@ -4244,6 +3938,160 @@ importers: specifier: workspace:^ version: link:../../runtime-diagnostics/invariants + packages/extensions/cordis-client-runner: + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/cordis-plugin-loader': + specifier: workspace:^ + version: link:../../../vendor/loader + '@deepseek-ai/dsh-api-remotes': + specifier: workspace:^ + version: link:../../api/remotes + '@deepseek-ai/dsh-client-connection': + specifier: workspace:^ + version: link:../../client/connection + '@deepseek-ai/dsh-client-modules': + specifier: workspace:^ + version: link:../../client/modules + '@deepseek-ai/dsh-client-runtime': + specifier: workspace:^ + version: link:../../client/runtime + '@deepseek-ai/dsh-client-ui-slots': + specifier: workspace:^ + version: link:../../client/ui-slots + '@deepseek-ai/dsh-client-ui-theme': + specifier: workspace:^ + version: link:../../client/ui-theme + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@types/react': + specifier: ~18.3.1 + version: 18.3.31 + react: + specifier: ^18.2.0 + version: 18.3.1 + + packages/extensions/cordis-host-runner: + dependencies: + '@deepseek-ai/schemastery': + specifier: link:../../../vendor/schemastery + version: link:../../../vendor/schemastery + zod: + specifier: ^4.4.3 + version: 4.4.3 + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/cordis-plugin-timer': + specifier: workspace:^ + version: link:../../../vendor/timer + '@deepseek-ai/dsh-agent': + specifier: workspace:^ + version: link:../../core/agent + '@deepseek-ai/dsh-brand': + specifier: workspace:^ + version: link:../../util/brand + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-llm': + specifier: workspace:^ + version: link:../../llm/llm + '@deepseek-ai/dsh-scope': + specifier: workspace:^ + version: link:../../core/scope + '@deepseek-ai/dsh-session': + specifier: workspace:^ + version: link:../../core/session + '@deepseek-ai/dsh-tools': + specifier: workspace:^ + version: link:../../core/tools + '@deepseek-ai/dsh-typert-protocol': + specifier: workspace:^ + version: link:../../typert/protocol + + packages/extensions/tool-cordis: + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/cordis-plugin-loader': + specifier: workspace:^ + version: link:../../../vendor/loader + '@deepseek-ai/dsh-agent': + specifier: workspace:^ + version: link:../../core/agent + '@deepseek-ai/dsh-cordis-host-runner': + specifier: workspace:^ + version: link:../cordis-host-runner + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-llm': + specifier: workspace:^ + version: link:../../llm/llm + '@deepseek-ai/dsh-scope': + specifier: workspace:^ + version: link:../../core/scope + '@deepseek-ai/dsh-session': + specifier: workspace:^ + version: link:../../core/session + '@deepseek-ai/dsh-system-prompt': + specifier: workspace:^ + version: link:../../core/system-prompt + '@deepseek-ai/dsh-tools': + specifier: workspace:^ + version: link:../../core/tools + + packages/extensions/ui-cordis: + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-api-remotes': + specifier: workspace:^ + version: link:../../api/remotes + '@deepseek-ai/dsh-client-connection': + specifier: workspace:^ + version: link:../../client/connection + '@deepseek-ai/dsh-client-locale': + specifier: workspace:^ + version: link:../../client/locale + '@deepseek-ai/dsh-client-runtime': + specifier: workspace:^ + version: link:../../client/runtime + '@deepseek-ai/dsh-client-ui-input-trigger': + specifier: workspace:^ + version: link:../../client/ui-input-trigger + '@deepseek-ai/dsh-client-ui-primitives': + specifier: workspace:^ + version: link:../../client/ui-primitives + '@deepseek-ai/dsh-client-ui-sidebar': + specifier: workspace:^ + version: link:../../client/ui-sidebar + '@deepseek-ai/dsh-client-ui-slots': + specifier: workspace:^ + version: link:../../client/ui-slots + '@deepseek-ai/dsh-client-ui-tool': + specifier: workspace:^ + version: link:../../client/ui-tool + '@deepseek-ai/dsh-cordis-client-runner': + specifier: workspace:^ + version: link:../cordis-client-runner + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@types/react': + specifier: ~18.3.1 + version: 18.3.31 + react: + specifier: ^18.2.0 + version: 18.3.1 + packages/feedback/command-feedback: devDependencies: '@deepseek-ai/cordis': @@ -4258,6 +4106,9 @@ importers: '@deepseek-ai/dsh-agent': specifier: workspace:^ version: link:../../core/agent + '@deepseek-ai/dsh-anonymous-user-id': + specifier: workspace:^ + version: link:../../identity/anonymous-user-id '@deepseek-ai/dsh-commands': specifier: workspace:^ version: link:../../interaction/commands @@ -4273,9 +4124,6 @@ importers: '@deepseek-ai/dsh-session-telemetry': specifier: workspace:^ version: link:../../session/session-telemetry - '@deepseek-ai/dsh-anonymous-user-id': - specifier: workspace:^ - version: link:../../identity/anonymous-user-id packages/feedback/message-feedback: dependencies: @@ -4743,15 +4591,15 @@ importers: '@deepseek-ai/cordis': specifier: workspace:^ version: link:../../../vendor/cordis - '@deepseek-ai/dsh-shell': - specifier: workspace:^ - version: link:../../shell/shell '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../runtime-diagnostics/invariants '@deepseek-ai/dsh-session': specifier: workspace:^ version: link:../../core/session + '@deepseek-ai/dsh-shell': + specifier: workspace:^ + version: link:../../shell/shell packages/hooks/hooks-claude-code: dependencies: @@ -4771,9 +4619,6 @@ importers: '@deepseek-ai/dsh-agent-loop-testkit': specifier: workspace:^ version: link:../../test-support/agent-loop-testkit - '@deepseek-ai/dsh-shell': - specifier: workspace:^ - version: link:../../shell/shell '@deepseek-ai/dsh-bash-local': specifier: workspace:^ version: link:../../shell/bash-local @@ -4795,6 +4640,9 @@ importers: '@deepseek-ai/dsh-session-persistence-jsonl': specifier: workspace:^ version: link:../../session/session-persistence-jsonl + '@deepseek-ai/dsh-shell': + specifier: workspace:^ + version: link:../../shell/shell '@deepseek-ai/dsh-subagent': specifier: workspace:^ version: link:../../subagent/subagent @@ -4823,9 +4671,6 @@ importers: '@deepseek-ai/dsh-agent-loop-testkit': specifier: workspace:^ version: link:../../test-support/agent-loop-testkit - '@deepseek-ai/dsh-shell': - specifier: workspace:^ - version: link:../../shell/shell '@deepseek-ai/dsh-bash-local': specifier: workspace:^ version: link:../../shell/bash-local @@ -4847,6 +4692,9 @@ importers: '@deepseek-ai/dsh-session-persistence-jsonl': specifier: workspace:^ version: link:../../session/session-persistence-jsonl + '@deepseek-ai/dsh-shell': + specifier: workspace:^ + version: link:../../shell/shell '@deepseek-ai/dsh-subprocess-local': specifier: workspace:^ version: link:../../subprocess/subprocess-local @@ -4883,6 +4731,9 @@ importers: '@deepseek-ai/dsh-host-directory-picker': specifier: workspace:^ version: link:../directory-picker + '@deepseek-ai/dsh-jobs': + specifier: workspace:^ + version: link:../../jobs/jobs '@deepseek-ai/dsh-llm': specifier: workspace:^ version: link:../../llm/llm @@ -4916,9 +4767,6 @@ importers: '@deepseek-ai/dsh-subagent': specifier: workspace:^ version: link:../../subagent/subagent - '@deepseek-ai/dsh-jobs': - specifier: workspace:^ - version: link:../../jobs/jobs '@deepseek-ai/dsh-tools': specifier: workspace:^ version: link:../../core/tools @@ -4947,6 +4795,9 @@ importers: '@deepseek-ai/dsh-agent-presets': specifier: workspace:^ version: link:../../preset/agent-presets + '@deepseek-ai/dsh-cordis-host-runner': + specifier: workspace:^ + version: link:../../extensions/cordis-host-runner '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../runtime-diagnostics/invariants @@ -5097,6 +4948,21 @@ importers: specifier: workspace:^ version: link:../../runtime-diagnostics/invariants + packages/identity/anonymous-user-id: + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-brand': + specifier: workspace:^ + version: link:../../util/brand + '@deepseek-ai/dsh-home-paths': + specifier: workspace:^ + version: link:../../util/home-paths + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + packages/interaction/commands: dependencies: zod: @@ -5137,9 +5003,6 @@ importers: '@deepseek-ai/cordis': specifier: workspace:^ version: link:../../../vendor/cordis - '@deepseek-ai/dsh-shell': - specifier: workspace:^ - version: link:../../shell/shell '@deepseek-ai/dsh-commands': specifier: workspace:^ version: link:../commands @@ -5161,6 +5024,9 @@ importers: '@deepseek-ai/dsh-settings': specifier: workspace:^ version: link:../../settings/settings + '@deepseek-ai/dsh-shell': + specifier: workspace:^ + version: link:../../shell/shell '@deepseek-ai/dsh-user-approval': specifier: workspace:^ version: link:../user-approval @@ -5235,6 +5101,98 @@ importers: specifier: workspace:^ version: link:../../llm/llm + packages/jobs/jobs: + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-agent': + specifier: workspace:^ + version: link:../../core/agent + '@deepseek-ai/dsh-brand': + specifier: workspace:^ + version: link:../../util/brand + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-session': + specifier: workspace:^ + version: link:../../core/session + + packages/jobs/jobs-local: + dependencies: + '@deepseek-ai/schemastery': + specifier: link:../../../vendor/schemastery + version: link:../../../vendor/schemastery + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/cordis-plugin-include': + specifier: workspace:^ + version: link:../../../vendor/include + '@deepseek-ai/cordis-plugin-loader': + specifier: workspace:^ + version: link:../../../vendor/loader + '@deepseek-ai/dsh-agent': + specifier: workspace:^ + version: link:../../core/agent + '@deepseek-ai/dsh-brand': + specifier: workspace:^ + version: link:../../util/brand + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-jobs': + specifier: workspace:^ + version: link:../jobs + '@deepseek-ai/dsh-scope': + specifier: workspace:^ + version: link:../../core/scope + '@deepseek-ai/dsh-session': + specifier: workspace:^ + version: link:../../core/session + '@deepseek-ai/dsh-timeout': + specifier: workspace:^ + version: link:../../util/timeout + + packages/jobs/tool-jobs: + dependencies: + '@deepseek-ai/schemastery': + specifier: link:../../../vendor/schemastery + version: link:../../../vendor/schemastery + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-agent': + specifier: workspace:^ + version: link:../../core/agent + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-jobs': + specifier: workspace:^ + version: link:../jobs + '@deepseek-ai/dsh-jobs-local': + specifier: workspace:^ + version: link:../jobs-local + '@deepseek-ai/dsh-llm': + specifier: workspace:^ + version: link:../../llm/llm + '@deepseek-ai/dsh-output-retention': + specifier: workspace:^ + version: link:../../util/output-retention + '@deepseek-ai/dsh-session': + specifier: workspace:^ + version: link:../../core/session + '@deepseek-ai/dsh-system-prompt': + specifier: workspace:^ + version: link:../../core/system-prompt + '@deepseek-ai/dsh-tools': + specifier: workspace:^ + version: link:../../core/tools + packages/llm/llm: dependencies: '@deepseek-ai/schemastery': @@ -5269,15 +5227,18 @@ importers: '@deepseek-ai/cordis': specifier: workspace:^ version: link:../../../vendor/cordis + '@deepseek-ai/dsh-anonymous-user-id': + specifier: workspace:^ + version: link:../../identity/anonymous-user-id '@deepseek-ai/dsh-credentials': specifier: workspace:^ version: link:../../credentials/credentials - '@deepseek-ai/dsh-launch-environment': - specifier: workspace:^ - version: link:../../util/launch-environment '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-launch-environment': + specifier: workspace:^ + version: link:../../util/launch-environment '@deepseek-ai/dsh-llm': specifier: workspace:^ version: link:../llm @@ -5287,9 +5248,6 @@ importers: '@deepseek-ai/dsh-timeout': specifier: workspace:^ version: link:../../util/timeout - '@deepseek-ai/dsh-anonymous-user-id': - specifier: workspace:^ - version: link:../../identity/anonymous-user-id packages/llm/llm-pi-ai: dependencies: @@ -5309,12 +5267,12 @@ importers: '@deepseek-ai/dsh-credentials': specifier: workspace:^ version: link:../../credentials/credentials - '@deepseek-ai/dsh-launch-environment': - specifier: workspace:^ - version: link:../../util/launch-environment '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-launch-environment': + specifier: workspace:^ + version: link:../../util/launch-environment '@deepseek-ai/dsh-llm': specifier: workspace:^ version: link:../llm @@ -5625,15 +5583,15 @@ importers: '@deepseek-ai/dsh-atomic-write': specifier: workspace:^ version: link:../../util/atomic-write + '@deepseek-ai/dsh-home-paths': + specifier: workspace:^ + version: link:../../util/home-paths '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../runtime-diagnostics/invariants '@deepseek-ai/dsh-llm': specifier: workspace:^ version: link:../../llm/llm - '@deepseek-ai/dsh-home-paths': - specifier: workspace:^ - version: link:../../util/home-paths '@deepseek-ai/dsh-scope': specifier: workspace:^ version: link:../../core/scope @@ -5672,25 +5630,7 @@ importers: specifier: workspace:^ version: link:../../core/system-prompt - packages/terminal/terminal: - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-agent': - specifier: workspace:^ - version: link:../../core/agent - '@deepseek-ai/dsh-brand': - specifier: workspace:^ - version: link:../../util/brand - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-session': - specifier: workspace:^ - version: link:../../core/session - - packages/terminal/terminal-bash: + packages/runtime-diagnostics/invariants: dependencies: '@deepseek-ai/schemastery': specifier: link:../../../vendor/schemastery @@ -5699,143 +5639,6 @@ importers: '@deepseek-ai/cordis': specifier: workspace:^ version: link:../../../vendor/cordis - '@deepseek-ai/dsh-agent': - specifier: workspace:^ - version: link:../../core/agent - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-terminal': - specifier: workspace:^ - version: link:../terminal - '@deepseek-ai/dsh-sandbox': - specifier: workspace:^ - version: link:../../sandbox/sandbox - '@deepseek-ai/dsh-sandbox-policy': - specifier: workspace:^ - version: link:../../sandbox/sandbox-policy - '@deepseek-ai/dsh-session': - specifier: workspace:^ - version: link:../../core/session - '@deepseek-ai/dsh-subprocess': - specifier: workspace:^ - version: link:../../subprocess/subprocess - '@deepseek-ai/dsh-subprocess-local': - specifier: workspace:^ - version: link:../../subprocess/subprocess-local - - packages/shell/tool-bash-persistent: - dependencies: - '@deepseek-ai/schemastery': - specifier: link:../../../vendor/schemastery - version: link:../../../vendor/schemastery - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/cordis-plugin-include': - specifier: workspace:^ - version: link:../../../vendor/include - '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ - version: link:../../../vendor/loader - '@deepseek-ai/dsh-agent': - specifier: workspace:^ - version: link:../../core/agent - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-llm': - specifier: workspace:^ - version: link:../../llm/llm - '@deepseek-ai/dsh-terminal': - specifier: workspace:^ - version: link:../../terminal/terminal - '@deepseek-ai/dsh-terminal-bash': - specifier: workspace:^ - version: link:../../terminal/terminal-bash - '@deepseek-ai/dsh-sandbox': - specifier: workspace:^ - version: link:../../sandbox/sandbox - '@deepseek-ai/dsh-sandbox-policy': - specifier: workspace:^ - version: link:../../sandbox/sandbox-policy - '@deepseek-ai/dsh-session': - specifier: workspace:^ - version: link:../../core/session - '@deepseek-ai/dsh-subprocess-local': - specifier: workspace:^ - version: link:../../subprocess/subprocess-local - '@deepseek-ai/dsh-system-prompt': - specifier: workspace:^ - version: link:../../core/system-prompt - '@deepseek-ai/dsh-timeout': - specifier: workspace:^ - version: link:../../util/timeout - '@deepseek-ai/dsh-tools': - specifier: workspace:^ - version: link:../../core/tools - - packages/terminal/tool-terminal: - dependencies: - '@deepseek-ai/schemastery': - specifier: link:../../../vendor/schemastery - version: link:../../../vendor/schemastery - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/cordis-plugin-include': - specifier: workspace:^ - version: link:../../../vendor/include - '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ - version: link:../../../vendor/loader - '@deepseek-ai/dsh-agent': - specifier: workspace:^ - version: link:../../core/agent - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-llm': - specifier: workspace:^ - version: link:../../llm/llm - '@deepseek-ai/dsh-terminal': - specifier: workspace:^ - version: link:../terminal - '@deepseek-ai/dsh-terminal-bash': - specifier: workspace:^ - version: link:../terminal-bash - '@deepseek-ai/dsh-output-retention': - specifier: workspace:^ - version: link:../../util/output-retention - '@deepseek-ai/dsh-sandbox': - specifier: workspace:^ - version: link:../../sandbox/sandbox - '@deepseek-ai/dsh-sandbox-policy': - specifier: workspace:^ - version: link:../../sandbox/sandbox-policy - '@deepseek-ai/dsh-session': - specifier: workspace:^ - version: link:../../core/session - '@deepseek-ai/dsh-subprocess-local': - specifier: workspace:^ - version: link:../../subprocess/subprocess-local - '@deepseek-ai/dsh-system-prompt': - specifier: workspace:^ - version: link:../../core/system-prompt - '@deepseek-ai/dsh-jobs': - specifier: workspace:^ - version: link:../../jobs/jobs - '@deepseek-ai/dsh-jobs-local': - specifier: workspace:^ - version: link:../../jobs/jobs-local - '@deepseek-ai/dsh-tool-jobs': - specifier: workspace:^ - version: link:../../jobs/tool-jobs - '@deepseek-ai/dsh-tools': - specifier: workspace:^ - version: link:../../core/tools packages/sandbox/sandbox: devDependencies: @@ -6045,49 +5848,6 @@ importers: specifier: workspace:^ version: link:../../subagent/subagent - packages/extensions/tool-cordis: - dependencies: - '@deepseek-ai/schemastery': - specifier: link:../../../vendor/schemastery - version: link:../../../vendor/schemastery - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ - version: link:../../../vendor/loader - '@deepseek-ai/cordis-plugin-timer': - specifier: workspace:^ - version: link:../../../vendor/timer - '@deepseek-ai/dsh-agent': - specifier: workspace:^ - version: link:../../core/agent - '@deepseek-ai/dsh-agent-loop': - specifier: workspace:^ - version: link:../../core/agent-loop - '@deepseek-ai/dsh-agent-loop-testkit': - specifier: workspace:^ - version: link:../../test-support/agent-loop-testkit - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-llm': - specifier: workspace:^ - version: link:../../llm/llm - '@deepseek-ai/dsh-scope': - specifier: workspace:^ - version: link:../../core/scope - '@deepseek-ai/dsh-session': - specifier: workspace:^ - version: link:../../core/session - '@deepseek-ai/dsh-system-prompt': - specifier: workspace:^ - version: link:../../core/system-prompt - '@deepseek-ai/dsh-tools': - specifier: workspace:^ - version: link:../../core/tools - packages/session-query/session-log-download: devDependencies: '@deepseek-ai/cordis': @@ -6455,6 +6215,9 @@ importers: '@deepseek-ai/cordis-plugin-loader': specifier: workspace:^ version: link:../../../vendor/loader + '@deepseek-ai/dsh-anonymous-user-id': + specifier: workspace:^ + version: link:../../identity/anonymous-user-id '@deepseek-ai/dsh-command-feedback': specifier: workspace:^ version: link:../../feedback/command-feedback @@ -6470,9 +6233,6 @@ importers: '@deepseek-ai/dsh-session-telemetry': specifier: workspace:^ version: link:../session-telemetry - '@deepseek-ai/dsh-anonymous-user-id': - specifier: workspace:^ - version: link:../../identity/anonymous-user-id packages/session/session-title: dependencies: @@ -6592,21 +6352,6 @@ importers: specifier: workspace:^ version: link:../../util/timeout - packages/identity/anonymous-user-id: - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-brand': - specifier: workspace:^ - version: link:../../util/brand - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-home-paths': - specifier: workspace:^ - version: link:../../util/home-paths - packages/settings/settings: dependencies: '@deepseek-ai/schemastery': @@ -6641,16 +6386,355 @@ importers: '@deepseek-ai/dsh-atomic-write': specifier: workspace:^ version: link:../../util/atomic-write - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants '@deepseek-ai/dsh-home-paths': specifier: workspace:^ version: link:../../util/home-paths + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants '@deepseek-ai/dsh-settings': specifier: workspace:^ version: link:../settings + packages/shell/bash-local: + dependencies: + '@deepseek-ai/schemastery': + specifier: link:../../../vendor/schemastery + version: link:../../../vendor/schemastery + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-settings': + specifier: workspace:^ + version: link:../../settings/settings + '@deepseek-ai/dsh-shell': + specifier: workspace:^ + version: link:../shell + '@deepseek-ai/dsh-subprocess': + specifier: workspace:^ + version: link:../../subprocess/subprocess + '@deepseek-ai/dsh-subprocess-local': + specifier: workspace:^ + version: link:../../subprocess/subprocess-local + '@deepseek-ai/dsh-timeout': + specifier: workspace:^ + version: link:../../util/timeout + + packages/shell/bash-sandbox: + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-bash-local': + specifier: workspace:^ + version: link:../bash-local + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-sandbox': + specifier: workspace:^ + version: link:../../sandbox/sandbox + '@deepseek-ai/dsh-sandbox-local': + specifier: workspace:^ + version: link:../../sandbox/sandbox-local + '@deepseek-ai/dsh-sandbox-policy': + specifier: workspace:^ + version: link:../../sandbox/sandbox-policy + '@deepseek-ai/dsh-shell': + specifier: workspace:^ + version: link:../shell + '@deepseek-ai/dsh-subprocess-local': + specifier: workspace:^ + version: link:../../subprocess/subprocess-local + '@deepseek-ai/node-addon-landlock-run': + specifier: workspace:* + version: link:../../../native/landlock-run/packages/entry + + packages/shell/pwsh-local: + dependencies: + '@deepseek-ai/schemastery': + specifier: link:../../../vendor/schemastery + version: link:../../../vendor/schemastery + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-settings': + specifier: workspace:^ + version: link:../../settings/settings + '@deepseek-ai/dsh-shell': + specifier: workspace:^ + version: link:../shell + '@deepseek-ai/dsh-subprocess': + specifier: workspace:^ + version: link:../../subprocess/subprocess + '@deepseek-ai/dsh-subprocess-local': + specifier: workspace:^ + version: link:../../subprocess/subprocess-local + '@deepseek-ai/dsh-timeout': + specifier: workspace:^ + version: link:../../util/timeout + + packages/shell/pwsh-sandbox: + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-pwsh-local': + specifier: workspace:^ + version: link:../pwsh-local + '@deepseek-ai/dsh-sandbox': + specifier: workspace:^ + version: link:../../sandbox/sandbox + '@deepseek-ai/dsh-sandbox-local': + specifier: workspace:^ + version: link:../../sandbox/sandbox-local + '@deepseek-ai/dsh-sandbox-policy': + specifier: workspace:^ + version: link:../../sandbox/sandbox-policy + '@deepseek-ai/dsh-shell': + specifier: workspace:^ + version: link:../shell + '@deepseek-ai/dsh-subprocess-local': + specifier: workspace:^ + version: link:../../subprocess/subprocess-local + + packages/shell/shell: + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-sandbox': + specifier: workspace:^ + version: link:../../sandbox/sandbox + '@deepseek-ai/dsh-settings': + specifier: workspace:^ + version: link:../../settings/settings + '@deepseek-ai/dsh-subprocess': + specifier: workspace:^ + version: link:../../subprocess/subprocess + + packages/shell/shell-env: + dependencies: + '@deepseek-ai/schemastery': + specifier: link:../../../vendor/schemastery + version: link:../../../vendor/schemastery + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-agent': + specifier: workspace:^ + version: link:../../core/agent + '@deepseek-ai/dsh-home-paths': + specifier: workspace:^ + version: link:../../util/home-paths + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-llm': + specifier: workspace:^ + version: link:../../llm/llm + '@deepseek-ai/dsh-session-persistence': + specifier: workspace:^ + version: link:../../session/session-persistence + '@deepseek-ai/dsh-shell': + specifier: workspace:^ + version: link:../shell + '@deepseek-ai/dsh-tools': + specifier: workspace:^ + version: link:../../core/tools + + packages/shell/tool-bash: + dependencies: + '@deepseek-ai/schemastery': + specifier: link:../../../vendor/schemastery + version: link:../../../vendor/schemastery + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-agent': + specifier: workspace:^ + version: link:../../core/agent + '@deepseek-ai/dsh-agent-loop': + specifier: workspace:^ + version: link:../../core/agent-loop + '@deepseek-ai/dsh-agent-loop-testkit': + specifier: workspace:^ + version: link:../../test-support/agent-loop-testkit + '@deepseek-ai/dsh-bash-local': + specifier: workspace:^ + version: link:../bash-local + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-jobs': + specifier: workspace:^ + version: link:../../jobs/jobs + '@deepseek-ai/dsh-jobs-local': + specifier: workspace:^ + version: link:../../jobs/jobs-local + '@deepseek-ai/dsh-llm': + specifier: workspace:^ + version: link:../../llm/llm + '@deepseek-ai/dsh-sandbox': + specifier: workspace:^ + version: link:../../sandbox/sandbox + '@deepseek-ai/dsh-sandbox-policy': + specifier: workspace:^ + version: link:../../sandbox/sandbox-policy + '@deepseek-ai/dsh-session': + specifier: workspace:^ + version: link:../../core/session + '@deepseek-ai/dsh-session-persistence-jsonl': + specifier: workspace:^ + version: link:../../session/session-persistence-jsonl + '@deepseek-ai/dsh-shell': + specifier: workspace:^ + version: link:../shell + '@deepseek-ai/dsh-shell-env': + specifier: workspace:^ + version: link:../shell-env + '@deepseek-ai/dsh-subprocess-local': + specifier: workspace:^ + version: link:../../subprocess/subprocess-local + '@deepseek-ai/dsh-system-prompt': + specifier: workspace:^ + version: link:../../core/system-prompt + '@deepseek-ai/dsh-tool-jobs': + specifier: workspace:^ + version: link:../../jobs/tool-jobs + '@deepseek-ai/dsh-tools': + specifier: workspace:^ + version: link:../../core/tools + '@deepseek-ai/dsh-user-approval': + specifier: workspace:^ + version: link:../../interaction/user-approval + + packages/shell/tool-bash-persistent: + dependencies: + '@deepseek-ai/schemastery': + specifier: link:../../../vendor/schemastery + version: link:../../../vendor/schemastery + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/cordis-plugin-include': + specifier: workspace:^ + version: link:../../../vendor/include + '@deepseek-ai/cordis-plugin-loader': + specifier: workspace:^ + version: link:../../../vendor/loader + '@deepseek-ai/dsh-agent': + specifier: workspace:^ + version: link:../../core/agent + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-llm': + specifier: workspace:^ + version: link:../../llm/llm + '@deepseek-ai/dsh-sandbox': + specifier: workspace:^ + version: link:../../sandbox/sandbox + '@deepseek-ai/dsh-sandbox-policy': + specifier: workspace:^ + version: link:../../sandbox/sandbox-policy + '@deepseek-ai/dsh-session': + specifier: workspace:^ + version: link:../../core/session + '@deepseek-ai/dsh-subprocess-local': + specifier: workspace:^ + version: link:../../subprocess/subprocess-local + '@deepseek-ai/dsh-system-prompt': + specifier: workspace:^ + version: link:../../core/system-prompt + '@deepseek-ai/dsh-terminal': + specifier: workspace:^ + version: link:../../terminal/terminal + '@deepseek-ai/dsh-terminal-bash': + specifier: workspace:^ + version: link:../../terminal/terminal-bash + '@deepseek-ai/dsh-timeout': + specifier: workspace:^ + version: link:../../util/timeout + '@deepseek-ai/dsh-tools': + specifier: workspace:^ + version: link:../../core/tools + + packages/shell/tool-pwsh: + dependencies: + '@deepseek-ai/schemastery': + specifier: link:../../../vendor/schemastery + version: link:../../../vendor/schemastery + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-agent': + specifier: workspace:^ + version: link:../../core/agent + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-jobs': + specifier: workspace:^ + version: link:../../jobs/jobs + '@deepseek-ai/dsh-jobs-local': + specifier: workspace:^ + version: link:../../jobs/jobs-local + '@deepseek-ai/dsh-llm': + specifier: workspace:^ + version: link:../../llm/llm + '@deepseek-ai/dsh-loader-smoke': + specifier: workspace:^ + version: link:../../test-support/loader-smoke + '@deepseek-ai/dsh-pwsh-local': + specifier: workspace:^ + version: link:../pwsh-local + '@deepseek-ai/dsh-sandbox': + specifier: workspace:^ + version: link:../../sandbox/sandbox + '@deepseek-ai/dsh-sandbox-policy': + specifier: workspace:^ + version: link:../../sandbox/sandbox-policy + '@deepseek-ai/dsh-shell': + specifier: workspace:^ + version: link:../shell + '@deepseek-ai/dsh-shell-env': + specifier: workspace:^ + version: link:../shell-env + '@deepseek-ai/dsh-subprocess-local': + specifier: workspace:^ + version: link:../../subprocess/subprocess-local + '@deepseek-ai/dsh-system-prompt': + specifier: workspace:^ + version: link:../../core/system-prompt + '@deepseek-ai/dsh-tool-jobs': + specifier: workspace:^ + version: link:../../jobs/tool-jobs + '@deepseek-ai/dsh-tools': + specifier: workspace:^ + version: link:../../core/tools + '@deepseek-ai/dsh-user-approval': + specifier: workspace:^ + version: link:../../interaction/user-approval + packages/skill/skill: dependencies: '@deepseek-ai/schemastery': @@ -6700,12 +6784,12 @@ importers: '@deepseek-ai/dsh-fs': specifier: workspace:^ version: link:../../fs/fs - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants '@deepseek-ai/dsh-home-paths': specifier: workspace:^ version: link:../../util/home-paths + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants '@deepseek-ai/dsh-skill': specifier: workspace:^ version: link:../skill @@ -6902,6 +6986,9 @@ importers: '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-jobs': + specifier: workspace:^ + version: link:../../jobs/jobs '@deepseek-ai/dsh-llm': specifier: workspace:^ version: link:../../llm/llm @@ -6932,9 +7019,6 @@ importers: '@deepseek-ai/dsh-storage-domain': specifier: workspace:^ version: link:../../storage/storage-domain - '@deepseek-ai/dsh-jobs': - specifier: workspace:^ - version: link:../../jobs/jobs '@deepseek-ai/dsh-tools': specifier: workspace:^ version: link:../../core/tools @@ -7278,6 +7362,12 @@ importers: '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-jobs': + specifier: workspace:^ + version: link:../../jobs/jobs + '@deepseek-ai/dsh-jobs-local': + specifier: workspace:^ + version: link:../../jobs/jobs-local '@deepseek-ai/dsh-llm': specifier: workspace:^ version: link:../../llm/llm @@ -7299,12 +7389,6 @@ importers: '@deepseek-ai/dsh-system-prompt': specifier: workspace:^ version: link:../../core/system-prompt - '@deepseek-ai/dsh-jobs': - specifier: workspace:^ - version: link:../../jobs/jobs - '@deepseek-ai/dsh-jobs-local': - specifier: workspace:^ - version: link:../../jobs/jobs-local '@deepseek-ai/dsh-tool-jobs': specifier: workspace:^ version: link:../../jobs/tool-jobs @@ -7434,6 +7518,119 @@ importers: specifier: workspace:^ version: link:../../util/timeout + packages/terminal/terminal: + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-agent': + specifier: workspace:^ + version: link:../../core/agent + '@deepseek-ai/dsh-brand': + specifier: workspace:^ + version: link:../../util/brand + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-session': + specifier: workspace:^ + version: link:../../core/session + + packages/terminal/terminal-bash: + dependencies: + '@deepseek-ai/schemastery': + specifier: link:../../../vendor/schemastery + version: link:../../../vendor/schemastery + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-agent': + specifier: workspace:^ + version: link:../../core/agent + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-sandbox': + specifier: workspace:^ + version: link:../../sandbox/sandbox + '@deepseek-ai/dsh-sandbox-policy': + specifier: workspace:^ + version: link:../../sandbox/sandbox-policy + '@deepseek-ai/dsh-session': + specifier: workspace:^ + version: link:../../core/session + '@deepseek-ai/dsh-subprocess': + specifier: workspace:^ + version: link:../../subprocess/subprocess + '@deepseek-ai/dsh-subprocess-local': + specifier: workspace:^ + version: link:../../subprocess/subprocess-local + '@deepseek-ai/dsh-terminal': + specifier: workspace:^ + version: link:../terminal + + packages/terminal/tool-terminal: + dependencies: + '@deepseek-ai/schemastery': + specifier: link:../../../vendor/schemastery + version: link:../../../vendor/schemastery + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/cordis-plugin-include': + specifier: workspace:^ + version: link:../../../vendor/include + '@deepseek-ai/cordis-plugin-loader': + specifier: workspace:^ + version: link:../../../vendor/loader + '@deepseek-ai/dsh-agent': + specifier: workspace:^ + version: link:../../core/agent + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-jobs': + specifier: workspace:^ + version: link:../../jobs/jobs + '@deepseek-ai/dsh-jobs-local': + specifier: workspace:^ + version: link:../../jobs/jobs-local + '@deepseek-ai/dsh-llm': + specifier: workspace:^ + version: link:../../llm/llm + '@deepseek-ai/dsh-output-retention': + specifier: workspace:^ + version: link:../../util/output-retention + '@deepseek-ai/dsh-sandbox': + specifier: workspace:^ + version: link:../../sandbox/sandbox + '@deepseek-ai/dsh-sandbox-policy': + specifier: workspace:^ + version: link:../../sandbox/sandbox-policy + '@deepseek-ai/dsh-session': + specifier: workspace:^ + version: link:../../core/session + '@deepseek-ai/dsh-subprocess-local': + specifier: workspace:^ + version: link:../../subprocess/subprocess-local + '@deepseek-ai/dsh-system-prompt': + specifier: workspace:^ + version: link:../../core/system-prompt + '@deepseek-ai/dsh-terminal': + specifier: workspace:^ + version: link:../terminal + '@deepseek-ai/dsh-terminal-bash': + specifier: workspace:^ + version: link:../terminal-bash + '@deepseek-ai/dsh-tool-jobs': + specifier: workspace:^ + version: link:../../jobs/tool-jobs + '@deepseek-ai/dsh-tools': + specifier: workspace:^ + version: link:../../core/tools + packages/test-support/acp-snapshot: dependencies: '@agentclientprotocol/sdk': @@ -7483,15 +7680,48 @@ importers: specifier: workspace:^ version: link:../../core/tools - packages/runtime-diagnostics/invariants: + packages/test-support/client-runtime: dependencies: - '@deepseek-ai/schemastery': - specifier: link:../../../vendor/schemastery - version: link:../../../vendor/schemastery + '@testing-library/dom': + specifier: ^10.4.1 + version: 10.4.1 + '@testing-library/react': + specifier: ^16.3.2 + version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + vitest: + specifier: ^4.1.8 + version: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@25.9.3)(@vitest/coverage-v8@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)) devDependencies: '@deepseek-ai/cordis': specifier: workspace:^ version: link:../../../vendor/cordis + '@deepseek-ai/dsh-client-runtime': + specifier: workspace:^ + version: link:../../client/runtime + '@deepseek-ai/dsh-client-ui-slots': + specifier: workspace:^ + version: link:../../client/ui-slots + '@deepseek-ai/dsh-client-web-react': + specifier: workspace:^ + version: link:../../client/web-react + '@deepseek-ai/dsh-host-apiproxy': + specifier: workspace:^ + version: link:../../host/apiproxy + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + '@types/react': + specifier: ~18.3.1 + version: 18.3.31 + '@types/react-dom': + specifier: ~18.3.0 + version: 18.3.7(@types/react@18.3.31) + react: + specifier: ^18.2.0 + version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) packages/test-support/llm-mock-server: devDependencies: @@ -7545,98 +7775,6 @@ importers: specifier: workspace:^ version: link:../../core/session - packages/jobs/jobs: - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-agent': - specifier: workspace:^ - version: link:../../core/agent - '@deepseek-ai/dsh-brand': - specifier: workspace:^ - version: link:../../util/brand - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-session': - specifier: workspace:^ - version: link:../../core/session - - packages/jobs/jobs-local: - dependencies: - '@deepseek-ai/schemastery': - specifier: link:../../../vendor/schemastery - version: link:../../../vendor/schemastery - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/cordis-plugin-include': - specifier: workspace:^ - version: link:../../../vendor/include - '@deepseek-ai/cordis-plugin-loader': - specifier: workspace:^ - version: link:../../../vendor/loader - '@deepseek-ai/dsh-agent': - specifier: workspace:^ - version: link:../../core/agent - '@deepseek-ai/dsh-brand': - specifier: workspace:^ - version: link:../../util/brand - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-scope': - specifier: workspace:^ - version: link:../../core/scope - '@deepseek-ai/dsh-session': - specifier: workspace:^ - version: link:../../core/session - '@deepseek-ai/dsh-jobs': - specifier: workspace:^ - version: link:../jobs - '@deepseek-ai/dsh-timeout': - specifier: workspace:^ - version: link:../../util/timeout - - packages/jobs/tool-jobs: - dependencies: - '@deepseek-ai/schemastery': - specifier: link:../../../vendor/schemastery - version: link:../../../vendor/schemastery - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-agent': - specifier: workspace:^ - version: link:../../core/agent - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - '@deepseek-ai/dsh-llm': - specifier: workspace:^ - version: link:../../llm/llm - '@deepseek-ai/dsh-output-retention': - specifier: workspace:^ - version: link:../../util/output-retention - '@deepseek-ai/dsh-session': - specifier: workspace:^ - version: link:../../core/session - '@deepseek-ai/dsh-system-prompt': - specifier: workspace:^ - version: link:../../core/system-prompt - '@deepseek-ai/dsh-jobs': - specifier: workspace:^ - version: link:../jobs - '@deepseek-ai/dsh-jobs-local': - specifier: workspace:^ - version: link:../jobs-local - '@deepseek-ai/dsh-tools': - specifier: workspace:^ - version: link:../../core/tools - packages/todo/tool-todo: dependencies: '@deepseek-ai/schemastery': @@ -7736,14 +7874,7 @@ importers: specifier: ^4.4.3 version: 4.4.3 - packages/typert/registry: - dependencies: - '@deepseek-ai/dsh-typert-protocol': - specifier: workspace:^ - version: link:../protocol - zod: - specifier: ^4.4.3 - version: 4.4.3 + packages/typert/protocol: devDependencies: '@deepseek-ai/cordis': specifier: workspace:^ @@ -7752,7 +7883,14 @@ importers: specifier: workspace:^ version: link:../../runtime-diagnostics/invariants - packages/typert/protocol: + packages/typert/registry: + dependencies: + '@deepseek-ai/dsh-typert-protocol': + specifier: workspace:^ + version: link:../protocol + zod: + specifier: ^4.4.3 + version: 4.4.3 devDependencies: '@deepseek-ai/cordis': specifier: workspace:^ @@ -7779,6 +7917,15 @@ importers: specifier: workspace:^ version: link:../../runtime-diagnostics/invariants + packages/util/home-paths: + devDependencies: + '@deepseek-ai/cordis': + specifier: workspace:^ + version: link:../../../vendor/cordis + '@deepseek-ai/dsh-invariants': + specifier: workspace:^ + version: link:../../runtime-diagnostics/invariants + packages/util/launch-environment: devDependencies: '@deepseek-ai/cordis': @@ -7797,15 +7944,6 @@ importers: specifier: workspace:^ version: link:../../runtime-diagnostics/invariants - packages/util/home-paths: - devDependencies: - '@deepseek-ai/cordis': - specifier: workspace:^ - version: link:../../../vendor/cordis - '@deepseek-ai/dsh-invariants': - specifier: workspace:^ - version: link:../../runtime-diagnostics/invariants - packages/util/output-retention: devDependencies: '@deepseek-ai/cordis': @@ -7932,12 +8070,12 @@ importers: '@deepseek-ai/dsh-credentials-local': specifier: workspace:^ version: link:../../credentials/credentials-local - '@deepseek-ai/dsh-launch-environment': - specifier: workspace:^ - version: link:../../util/launch-environment '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-launch-environment': + specifier: workspace:^ + version: link:../../util/launch-environment '@deepseek-ai/dsh-session': specifier: workspace:^ version: link:../../core/session @@ -7957,12 +8095,12 @@ importers: '@deepseek-ai/cordis': specifier: workspace:^ version: link:../../../vendor/cordis - '@deepseek-ai/dsh-launch-environment': - specifier: workspace:^ - version: link:../../util/launch-environment '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-launch-environment': + specifier: workspace:^ + version: link:../../util/launch-environment '@deepseek-ai/dsh-web': specifier: workspace:^ version: link:../web @@ -7976,12 +8114,12 @@ importers: '@deepseek-ai/cordis': specifier: workspace:^ version: link:../../../vendor/cordis - '@deepseek-ai/dsh-launch-environment': - specifier: workspace:^ - version: link:../../util/launch-environment '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../runtime-diagnostics/invariants + '@deepseek-ai/dsh-launch-environment': + specifier: workspace:^ + version: link:../../util/launch-environment '@deepseek-ai/dsh-web': specifier: workspace:^ version: link:../web @@ -8199,24 +8337,24 @@ importers: '@deepseek-ai/dsh-agent': specifier: workspace:^ version: link:../../packages/core/agent + '@deepseek-ai/dsh-agent-instructions': + specifier: workspace:^ + version: link:../../packages/context/agent-instructions '@deepseek-ai/dsh-agent-loop': specifier: workspace:^ version: link:../../packages/core/agent-loop '@deepseek-ai/dsh-agent-spine-demo': specifier: workspace:^ version: link:../../packages/examples/agent-spine-demo + '@deepseek-ai/dsh-anonymous-user-id': + specifier: workspace:^ + version: link:../../packages/identity/anonymous-user-id '@deepseek-ai/dsh-app-boot': specifier: workspace:^ version: link:../../packages/boot/app-boot '@deepseek-ai/dsh-attachment': specifier: workspace:^ version: link:../../packages/attachment/attachment - '@deepseek-ai/dsh-shell': - specifier: workspace:^ - version: link:../../packages/shell/shell - '@deepseek-ai/dsh-shell-env': - specifier: workspace:^ - version: link:../../packages/shell/shell-env '@deepseek-ai/dsh-bash-local': specifier: workspace:^ version: link:../../packages/shell/bash-local @@ -8244,12 +8382,12 @@ importers: '@deepseek-ai/dsh-compaction-tool-result-pruner': specifier: workspace:^ version: link:../../packages/compaction/compaction-tool-result-pruner + '@deepseek-ai/dsh-cordis-host-runner': + specifier: workspace:^ + version: link:../../packages/extensions/cordis-host-runner '@deepseek-ai/dsh-credentials': specifier: workspace:^ version: link:../../packages/credentials/credentials - '@deepseek-ai/dsh-launch-environment': - specifier: workspace:^ - version: link:../../packages/util/launch-environment '@deepseek-ai/dsh-fs': specifier: workspace:^ version: link:../../packages/fs/fs @@ -8268,6 +8406,9 @@ importers: '@deepseek-ai/dsh-goal-round-driver': specifier: workspace:^ version: link:../../packages/goal/goal-round-driver + '@deepseek-ai/dsh-home-paths': + specifier: workspace:^ + version: link:../../packages/util/home-paths '@deepseek-ai/dsh-hook-protocol': specifier: workspace:^ version: link:../../packages/hooks/hook-protocol @@ -8280,12 +8421,15 @@ importers: '@deepseek-ai/dsh-invariants': specifier: workspace:^ version: link:../../packages/runtime-diagnostics/invariants - '@deepseek-ai/dsh-sdk-jsonrpc-server': + '@deepseek-ai/dsh-jobs': specifier: workspace:^ - version: link:../../packages/sdk/server - '@deepseek-ai/dsh-sdk-jsonrpc-demo': + version: link:../../packages/jobs/jobs + '@deepseek-ai/dsh-jobs-local': specifier: workspace:^ - version: link:../../packages/examples/jsonrpc-demo + version: link:../../packages/jobs/jobs-local + '@deepseek-ai/dsh-launch-environment': + specifier: workspace:^ + version: link:../../packages/util/launch-environment '@deepseek-ai/dsh-llm': specifier: workspace:^ version: link:../../packages/llm/llm @@ -8298,27 +8442,18 @@ importers: '@deepseek-ai/dsh-llm-retry': specifier: workspace:^ version: link:../../packages/llm/llm-retry - '@deepseek-ai/dsh-home-paths': + '@deepseek-ai/dsh-output-retention': specifier: workspace:^ - version: link:../../packages/util/home-paths + version: link:../../packages/util/output-retention '@deepseek-ai/dsh-permission-presets': specifier: workspace:^ version: link:../../packages/interaction/permission-presets '@deepseek-ai/dsh-plan-mode': specifier: workspace:^ version: link:../../packages/plan/plan-mode - '@deepseek-ai/dsh-terminal': - specifier: workspace:^ - version: link:../../packages/terminal/terminal - '@deepseek-ai/dsh-terminal-bash': - specifier: workspace:^ - version: link:../../packages/terminal/terminal-bash '@deepseek-ai/dsh-repeat-tool-reminder': specifier: workspace:^ version: link:../../packages/guard/repeat-tool-reminder - '@deepseek-ai/dsh-output-retention': - specifier: workspace:^ - version: link:../../packages/util/output-retention '@deepseek-ai/dsh-sandbox': specifier: workspace:^ version: link:../../packages/sandbox/sandbox @@ -8331,6 +8466,12 @@ importers: '@deepseek-ai/dsh-scope': specifier: workspace:^ version: link:../../packages/core/scope + '@deepseek-ai/dsh-sdk-jsonrpc-demo': + specifier: workspace:^ + version: link:../../packages/examples/jsonrpc-demo + '@deepseek-ai/dsh-sdk-jsonrpc-server': + specifier: workspace:^ + version: link:../../packages/sdk/server '@deepseek-ai/dsh-sdk-protocol': specifier: workspace:^ version: link:../../packages/sdk/protocol @@ -8367,6 +8508,12 @@ importers: '@deepseek-ai/dsh-settings': specifier: workspace:^ version: link:../../packages/settings/settings + '@deepseek-ai/dsh-shell': + specifier: workspace:^ + version: link:../../packages/shell/shell + '@deepseek-ai/dsh-shell-env': + specifier: workspace:^ + version: link:../../packages/shell/shell-env '@deepseek-ai/dsh-skill': specifier: workspace:^ version: link:../../packages/skill/skill @@ -8397,18 +8544,15 @@ importers: '@deepseek-ai/dsh-system-prompt': specifier: workspace:^ version: link:../../packages/core/system-prompt - '@deepseek-ai/dsh-jobs': + '@deepseek-ai/dsh-terminal': specifier: workspace:^ - version: link:../../packages/jobs/jobs - '@deepseek-ai/dsh-jobs-local': + version: link:../../packages/terminal/terminal + '@deepseek-ai/dsh-terminal-bash': specifier: workspace:^ - version: link:../../packages/jobs/jobs-local + version: link:../../packages/terminal/terminal-bash '@deepseek-ai/dsh-timeout': specifier: workspace:^ version: link:../../packages/util/timeout - '@deepseek-ai/dsh-tool-call-timeout-policy': - specifier: workspace:^ - version: link:../../packages/guard/timeout-policy '@deepseek-ai/dsh-token-meter': specifier: workspace:^ version: link:../../packages/llm/token-meter @@ -8421,6 +8565,9 @@ importers: '@deepseek-ai/dsh-tool-bash-persistent': specifier: workspace:^ version: link:../../packages/shell/tool-bash-persistent + '@deepseek-ai/dsh-tool-call-timeout-policy': + specifier: workspace:^ + version: link:../../packages/guard/timeout-policy '@deepseek-ai/dsh-tool-cordis': specifier: workspace:^ version: link:../../packages/extensions/tool-cordis @@ -8430,6 +8577,9 @@ importers: '@deepseek-ai/dsh-tool-goal': specifier: workspace:^ version: link:../../packages/goal/tool-goal + '@deepseek-ai/dsh-tool-jobs': + specifier: workspace:^ + version: link:../../packages/jobs/tool-jobs '@deepseek-ai/dsh-tool-skill': specifier: workspace:^ version: link:../../packages/skill/tool-skill @@ -8442,9 +8592,6 @@ importers: '@deepseek-ai/dsh-tool-subagent-control': specifier: workspace:^ version: link:../../packages/subagent/tool-subagent-control - '@deepseek-ai/dsh-tool-jobs': - specifier: workspace:^ - version: link:../../packages/jobs/tool-jobs '@deepseek-ai/dsh-tool-todo': specifier: workspace:^ version: link:../../packages/todo/tool-todo @@ -8463,9 +8610,6 @@ importers: '@deepseek-ai/dsh-user-approval': specifier: workspace:^ version: link:../../packages/interaction/user-approval - '@deepseek-ai/dsh-anonymous-user-id': - specifier: workspace:^ - version: link:../../packages/identity/anonymous-user-id '@deepseek-ai/dsh-user-questions': specifier: workspace:^ version: link:../../packages/interaction/user-questions @@ -8490,9 +8634,6 @@ importers: '@deepseek-ai/dsh-workflow-worker-thread': specifier: workspace:^ version: link:../../packages/workflow/workflow-worker-thread - '@deepseek-ai/dsh-agent-instructions': - specifier: workspace:^ - version: link:../../packages/context/agent-instructions '@deepseek-ai/schemastery': specifier: link:../../vendor/schemastery version: link:../../vendor/schemastery diff --git a/scripts/gen-cordis-catalog.ts b/scripts/gen-cordis-catalog.ts index a69b4a4995..c037a97975 100644 --- a/scripts/gen-cordis-catalog.ts +++ b/scripts/gen-cordis-catalog.ts @@ -63,10 +63,10 @@ export const SERVICE_PAGE: Record = { codeRuntime: 'code-runtime.md', commands: 'commands.md', compaction: 'compaction.md', - cordisInspect: 'self-modification.md', + cordisInspect: 'extensions.md', credentials: 'credentials.md', directoryPicker: 'workspace.md', - dynamicCordisRunner: 'self-modification.md', + dynamicCordisRunner: 'extensions.md', e2b: 'subprocess.md', fs: 'filesystem.md', goals: 'goal.md', @@ -134,8 +134,7 @@ export const SERVICE_WALK_EXEMPTIONS: Record = { launcherSessionQueryPath: 'not a service: launcher-provided boot-context value (string | undefined) — packages/session-query/session-query-sqlite/README.md owns this launcher contract', dshHomePath: 'not a service: boot-provided root accessor function (typeof dshHomePath | undefined) for Loader !!js config expressions — packages/boot/app-boot/README.md owns the boot contract', launchEnvironment: 'not a service: launcher-provided root accessor value (LaunchEnvironmentSnapshot | undefined) — packages/util/launch-environment/README.md owns this launcher contract', - lsp: 'interface-typed (LspService); implementing class Lsp is not the declared type name — packages/lsp/lsp/README.md owns the API', - apiProxy: 'interface-typed (ApiProxy) with the class in api-proxy.ts, not index.ts — packages/host/apiproxy/README.md owns the API', + connection: 'interface-typed (HostConnectionHandle); implementing class HostConnectionService is declared in rpc-host.ts — packages/client/connection/README.md owns the API', appShell: 'client-side interface-typed browser service — packages/client/web/README.md owns the API', settingsScope: 'client-side settings-namespace transport service — packages/client/ui-settings/README.md owns the API', chatFileMentions: 'client-side slot-contract accessor (ChatFileMentions) — packages/client/ui-conversation/README.md owns the API', @@ -169,7 +168,7 @@ export const EVENT_SCOPE_PAGE: Record = { 'agent-preset': 'core.md', 'approval': 'approval.md', 'commands': 'commands.md', - 'cordis': 'self-modification.md', + 'cordis': 'extensions.md', 'credentials': 'credentials.md', 'domain': 'storage.md', 'fs': 'filesystem.md',