Merge remote-tracking branch 'origin/master' into feat/telemetry-otel-plugin

Resolutions: regenerate the conflicted generated docs (cordis services
catalog, event-producer-consumer, module-graph); take master's
packages/README pair and re-insert the telemetry row on both sides;
re-record the README and session-doc translation pairs.
This commit is contained in:
kingwl
2026-07-27 20:26:21 +08:00
1287 changed files with 40863 additions and 13931 deletions

View File

@@ -9,7 +9,7 @@ This file is GENERATED from source (`scripts/gen-cordis-catalog.ts`) and verifie
The **harness tier** below (the `@deepseek-ai/dsh-*` packages) is the vocabulary this repo owns, grouped by scope. The **inherited tier** at the end is the cordis-core + loader/hmr/timer event surface a plugin also sees — pinned vendor source, summarized tersely. The event-dispatch methods themselves are generated in the [Cordis core Events API](core/events.md).
Dispatch modes: **emit** (fire-and-forget), **waterfall** (each listener gets `next()` and may transform or veto — see [waterfall semantics](../cordis-primer.md#cordis-waterfall-semantics)), **parallel** (awaited fan-out; all listeners run), **serial** (awaited in registration order until one returns a bail value — anything other than `null`, `false`, or `undefined`).
Dispatch modes: **emit** (fire-and-forget), **waterfall** (each listener gets `next()` and may transform or veto — see [waterfall semantics](../cordis-primer.md#cordis-waterfall-semantics)), **parallel** (awaited fan-out; all listeners run), **serial** (awaited in registration order until one returns a bail value — anything other than `null`, `false`, or `undefined`), **bail** (synchronous in-order dispatch until one listener returns a bail value; the scoped input-mutation events use it for an applied/not-applied answer).
## `agent/*`
@@ -616,7 +616,7 @@ Waterfall around every streaming model call (retry, replay, routing). Bound to t
Types: [GenerateOptions](../core-data-structures/core.md) · [LlmService](../core-data-structures/llm-streaming.md) · [StreamChunk](../core-data-structures/llm-streaming.md)
Source: [`packages/llm/llm/src/index.ts:52`](../../packages/llm/llm/src/index.ts)
Source: [`packages/llm/llm/src/index.ts:53`](../../packages/llm/llm/src/index.ts)
## `session/*`
@@ -708,6 +708,75 @@ Types: [Scoped](../core-data-structures/scope.md) · [Session](../core-data-stru
Source: [`packages/core/session/src/index.ts:111`](../../packages/core/session/src/index.ts)
## `slash/*`
### `slash/input-begin-command` — bail
Applies one command claim to the scoped Input. Dispatched with the session's scope carrier; the owning session's input listener returns `true` only after the phase and span CAS checks pass and the machine actually mutated — producers treat anything else as "not applied".
```ts cordis-catalog
/**
* Applies one command claim to the scoped Input. Dispatched with the
* session's scope carrier; the owning session's input listener returns
* `true` only after the phase and span CAS checks pass and the machine
* actually mutated — producers treat anything else as "not applied".
* @param request - Claim and menu-time span CAS.
* @mode bail
*/
'slash/input-begin-command'(request: BeginCommandRequest): true | undefined
```
Source: [`packages/client/ui-slash/src/types.ts:220`](../../packages/client/ui-slash/src/types.ts)
### `slash/input-consume-token` — bail
Consumes one command token after business success (popup settle / menu-pick execute). Same carrier routing and applied-truth contract.
```ts cordis-catalog
/**
* Consumes one command token after business success (popup settle /
* menu-pick execute). Same carrier routing and applied-truth contract.
* @param request - Exact span or bare-token guard.
* @mode bail
*/
'slash/input-consume-token'(request: ConsumeTokenRequest): true | undefined
```
Source: [`packages/client/ui-slash/src/types.ts:234`](../../packages/client/ui-slash/src/types.ts)
### `slash/input-insert-reference` — bail
Inserts one reference into the scoped Input (same carrier routing and applied-truth contract as begin-command).
```ts cordis-catalog
/**
* Inserts one reference into the scoped Input (same carrier routing and
* applied-truth contract as begin-command).
* @param request - Reference and menu-time span CAS.
* @mode bail
*/
'slash/input-insert-reference'(request: InsertReferenceRequest): true | undefined
```
Source: [`packages/client/ui-slash/src/types.ts:227`](../../packages/client/ui-slash/src/types.ts)
### `slash/input-insert-text` — bail
Replaces the trigger token span with literal text — the plain-text reference path (decision 21). Same carrier routing and applied-truth contract; the draft gains ordinary characters, no occurrence entry.
```ts cordis-catalog
/**
* Replaces the trigger token span with literal text — the plain-text
* reference path (decision 21). Same carrier routing and applied-truth
* contract; the draft gains ordinary characters, no occurrence entry.
* @param request - Replacement text and menu-time span CAS.
* @mode bail
*/
'slash/input-insert-text'(request: InsertTextRequest): true | undefined
```
Source: [`packages/client/ui-slash/src/types.ts:242`](../../packages/client/ui-slash/src/types.ts)
## `subagent/*`
### `subagent/end` — emit
@@ -870,7 +939,31 @@ A tool was registered or unregistered, or a scoped restriction changed (the avai
'tools/change'(): void
```
Source: [`packages/core/tools/src/index.ts:143`](../../packages/core/tools/src/index.ts)
Source: [`packages/core/tools/src/index.ts:156`](../../packages/core/tools/src/index.ts)
### `tools/code-dispatch-log` — waterfall
Shape 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 unshaped content. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's dispatches.
```ts cordis-catalog
/**
* Shape 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 unshaped content.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's dispatches.
* @param dispatch - the parent execution, sub-call identity, and the settled content to log.
* @mode waterfall
*/
'tools/code-dispatch-log'(this: Scoped<ToolRegistry>, dispatch: CodeDispatchLog, next: () => Promise<ContentBlock[]>): Promise<ContentBlock[]>
```
Types: [CodeDispatchLog](../core-data-structures/tools.md) · [ContentBlock](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md) · [ToolRegistry](../core-data-structures/tools.md)
Source: [`packages/core/tools/src/index.ts:138`](../../packages/core/tools/src/index.ts)
### `tools/execute` — waterfall
@@ -955,7 +1048,7 @@ Observe the frozen, lossless-JSON final outcome. Listener failures are contained
Types: [Scoped](../core-data-structures/scope.md) · [ToolExecution](../core-data-structures/tools.md) · [ToolExecutionResult](../core-data-structures/tools.md) · [ToolRegistry](../core-data-structures/tools.md)
Source: [`packages/core/tools/src/index.ts:133`](../../packages/core/tools/src/index.ts)
Source: [`packages/core/tools/src/index.ts:146`](../../packages/core/tools/src/index.ts)
## `workflow/*`

View File

@@ -257,7 +257,7 @@ Implementations must honor these semantics:
- run rejects only for infrastructure failures. Nonzero exits, timeout kills, and abort kills resolve with a BashRunResult.
- 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.
- BashProcess.readOutput is incremental: consecutive reads never repeat output. Lossy reads report truncation and available spill files.
- Disposal kills all running background processes and awaits their exit.
- 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.
```ts cordis-catalog
/**
@@ -286,7 +286,7 @@ abstract start(spec: BashExecSpec): BashProcess
Types: [BashExecRequest](../core-data-structures/bash.md) · [BashExecSpec](../core-data-structures/bash.md) · [BashProcess](../core-data-structures/bash.md) · [BashRunResult](../core-data-structures/bash.md)
Source: [`packages/bash/bash/src/index.ts:48`](../../packages/bash/bash/src/index.ts)
Source: [`packages/bash/bash/src/index.ts:51`](../../packages/bash/bash/src/index.ts)
## `ctx.bashEnv` — `BashEnvRegistry`
@@ -315,7 +315,7 @@ collect(execution: ToolExecution): DshEnvironment
list(): BashEnvVariableInfo[]
```
Types: [DshEnvironment](../core-data-structures/bash.md) · [ToolExecution](../core-data-structures/tools.md)
Types: [DshEnvironment](../core-data-structures/subprocess.md) · [ToolExecution](../core-data-structures/tools.md)
Source: [`packages/bash/tool-bash/src/index.ts:104`](../../packages/bash/tool-bash/src/index.ts)
@@ -730,33 +730,57 @@ listProviders(): LlmProviderInfo[]
async listModels(provider: string): Promise<LlmModelInfo[]>
/**
* Resolve context capacity from the adapter that owns one exact route.
* This query is independent of the advisory model catalog: an unlisted model
* may return metadata, while `undefined` never rejects later routing.
* 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.
* @param provider - registered provider route to inspect.
* @param model - exact model id passed to the adapter.
* @returns detached context metadata, or `undefined` when the adapter has none.
* @param signal - optional cancellation for adapter-owned asynchronous lookup.
* @returns exact model identity plus available context and reasoning metadata.
*/
async resolveModelContext( provider: string, model: string, ): Promise<LlmModelContext | undefined>
async resolveModelInfo( provider: string, model: string, signal?: AbortSignal, ): Promise<LlmResolvedModelInfo>
/**
* Validate a conversation call config against its exact model capability and
* materialize an adapter-configured default. Unsupported explicit efforts
* reject before provider I/O; no clamping or aliasing is performed. This
* standalone query does not bind a later dispatch; use {@link prepareCall}
* when logging and streaming must share one adapter registration.
* @param config - provider/model route and optional request controls.
* @param signal - optional cancellation for adapter-owned capability lookup.
* @returns a detached config only when a default must be materialized.
*/
async resolveCallConfig(config: LlmCallConfig, signal?: AbortSignal): Promise<LlmCallConfig>
/**
* 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.
* @param config - provider/model route and optional request controls.
* @param signal - optional cancellation for adapter-owned capability lookup.
* @returns a prepared config and its registration-bound stream entry point.
*/
async prepareCall(config: LlmCallConfig, signal?: AbortSignal): Promise<PreparedLlmCall>
/**
* Stream one model call as raw chunks (token-level deltas). Throws
* `LlmError` with code `NO_ADAPTER` if no adapter is registered for
* `options.provider`. Replay state is retained only when the same adapter
* instance owns its historical provider and the target provider. Final
* adapter selection, dispatch, and iteration failures retain their original
* Error identity and are tagged in a call-local scope for narrow agent-loop
* request recovery; middleware and nested-call failures remain untagged for
* the outer call.
* adapter selection remains fixed through asynchronous exact-model resolution
* and dispatch. Selection, dispatch, and iteration failures retain their
* original Error identity and are tagged in a call-local scope for narrow
* agent-loop request recovery; middleware and nested-call failures remain
* untagged for the outer call.
* @param options - the full request; `options.provider` selects the adapter.
* @returns the chunk stream, possibly wrapped by `llm/stream` listeners.
*/
stream(options: GenerateOptions): AsyncIterable<StreamChunk>
```
Types: [GenerateOptions](../core-data-structures/core.md) · [LlmAdapter](../core-data-structures/llm-streaming.md) · [LlmModelContext](../core-data-structures/core.md) · [LlmModelInfo](../core-data-structures/core.md) · [LlmProviderInfo](../core-data-structures/core.md) · [StreamChunk](../core-data-structures/llm-streaming.md)
Types: [GenerateOptions](../core-data-structures/core.md) · [LlmAdapter](../core-data-structures/llm-streaming.md) · [LlmCallConfig](../core-data-structures/core.md) · [LlmModelInfo](../core-data-structures/core.md) · [LlmProviderInfo](../core-data-structures/core.md) · [LlmResolvedModelInfo](../core-data-structures/core.md) · [PreparedLlmCall](../core-data-structures/llm-streaming.md) · [StreamChunk](../core-data-structures/llm-streaming.md)
Source: [`packages/llm/llm/src/index.ts:159`](../../packages/llm/llm/src/index.ts)
Source: [`packages/llm/llm/src/index.ts:177`](../../packages/llm/llm/src/index.ts)
## `ctx.permission` — `PermissionService`
@@ -1342,7 +1366,7 @@ fork(source: SessionForkSource, boundary?: number, childSessionId?: SessionId):
Types: [CreateSessionOptions](../core-data-structures/persistence.md) · [OutOfBandSessionEventType](../core-data-structures/session.md) · [Session](../core-data-structures/session.md) · [SessionEvent](../core-data-structures/core.md) · [SessionEventMap](../core-data-structures/session.md) · [SessionId](../core-data-structures/core.md) · [TurnTrigger](../core-data-structures/session.md)
Source: [`packages/core/session/src/index.ts:620`](../../packages/core/session/src/index.ts)
Source: [`packages/core/session/src/index.ts:625`](../../packages/core/session/src/index.ts)
## `ctx.sessionTitle` — `SessionTitleService`
@@ -1559,6 +1583,31 @@ Types: [SubagentProvider](../core-data-structures/subagent.md) · [SubagentRun](
Source: [`packages/subagent/subagent/src/index.ts:180`](../../packages/subagent/subagent/src/index.ts)
## `ctx.subprocess` — `SubprocessService` (abstract seam)
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).
Implementations must honor these semantics:
- spawn returns immediately with a live handle; `done` resolves at process close with exit facts and rejects only for spawn-level failures.
- 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.
- 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.
- Disposal of the service terminates all still-running managed processes and awaits their exit.
```ts cordis-catalog
/**
* Start one managed child process from a fully-specified spec; this seam
* applies no defaults.
* @param spec - argv, directory, stdio dispositions, grace, cancellation, and environment.
* @returns the live process handle (streams/readers, signalling, outcome promise).
*/
abstract spawn(spec: SubprocessSpawnSpec): SubprocessHandle
```
Types: [SubprocessHandle](../core-data-structures/subprocess.md) · [SubprocessSpawnSpec](../core-data-structures/subprocess.md)
Source: [`packages/subprocess/subprocess/src/index.ts:88`](../../packages/subprocess/subprocess/src/index.ts)
## `ctx.systemPrompt` — `SystemPrompt`
Registry service for the prompt inputs assembled before each model step.
@@ -1607,9 +1656,16 @@ Types: [AssembleContext](../core-data-structures/system-prompt.md) · [PromptSec
Source: [`packages/core/system-prompt/src/index.ts:246`](../../packages/core/system-prompt/src/index.ts)
## `ctx.tasks` — `TaskService`
## `ctx.tasks` — `TaskService` (abstract seam)
The `tasks` service: the runtime-global background task registry. See the module doc for the ownership, isolation, and lifecycle contracts.
Abstract background task registry. Subclass, implement the abstract methods, and load the subclass as a plugin — it registers as `ctx.tasks` (one implementation per context; loading a second throws, which is cordis' standard duplicate-service behavior).
Implementations must honor these semantics:
- Registrations outlive producer and control-surface fibers. Owner and service disposal cancel live work and await compliant producers; a throwing teardown cancel force-fails only the record.
- Owned-task access is fenced by the owner's session id. Ids are predictable, so authorization — not secrecy — is the boundary.
- Settlement is first-wins: one terminal record, one round of contained listener notification, and released waiters, even against a late producer outcome.
- start refuses work while no control surface is attached, so a producer cannot start work that callers cannot collect or stop.
```ts cordis-catalog
/**
@@ -1620,7 +1676,7 @@ The `tasks` service: the runtime-global background task registry. See the module
* @param spec - task identity, owner, and synchronous starter.
* @returns the registry-issued `<kind>-N` id.
*/
start(spec: TaskStart): TaskId
abstract start(spec: TaskStart): TaskId
/**
* List caller-owned and unowned tasks in registration order without exposing
@@ -1628,7 +1684,7 @@ start(spec: TaskStart): TaskId
* @param caller - reading agent; a non-agent caller sees only unowned tasks.
* @returns fresh snapshots.
*/
list(caller?: Agent): TaskSnapshot[]
abstract list(caller?: Agent): TaskSnapshot[]
/**
* Return a non-consuming snapshot without changing its read cursor or notice
@@ -1637,7 +1693,7 @@ list(caller?: Agent): TaskSnapshot[]
* @param caller - reading agent checked against the owner.
* @returns a fresh snapshot.
*/
get(id: TaskId, caller?: Agent): TaskSnapshot
abstract get(id: TaskId, caller?: Agent): TaskSnapshot
/**
* Read the next stream delta, or the idempotent final output after settlement.
@@ -1647,7 +1703,7 @@ get(id: TaskId, caller?: Agent): TaskSnapshot
* @param caller - reading agent checked against the owner.
* @returns output text and the post-read snapshot.
*/
read(id: TaskId, caller?: Agent): TaskRead
abstract read(id: TaskId, caller?: Agent): TaskRead
/**
* Request cancellation, then mark the task stopping and reported. A producer
@@ -1658,21 +1714,20 @@ read(id: TaskId, caller?: Agent): TaskRead
* @param reason - logged reason forwarded to the producer.
* @returns `requested` for live work, otherwise `already-finished`.
*/
kill(id: TaskId, caller?: Agent, reason?: string): 'requested' | 'already-finished'
abstract kill(id: TaskId, caller?: Agent, reason?: string): 'requested' | 'already-finished'
/**
* Wait for settlement or timeout without cancelling the task. Caller abort
* rejects only while the task is live; after settlement it returns the
* terminal snapshot so a notice suppressed for this waiter is still delivered.
* Timed-out and aborted waits detach their resolvers. Throws for invalid,
* unknown, or foreign input.
* rejects only while the task 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.
* @param id - task to wait for.
* @param timeoutMs - positive finite wait bound in milliseconds.
* @param caller - waiting agent checked against the owner.
* @param signal - optional cancellation of the wait itself.
* @returns snapshot at settlement or timeout.
*/
async wait(id: TaskId, timeoutMs: number, caller?: Agent, signal?: AbortSignal): Promise<TaskSnapshot>
abstract wait(id: TaskId, timeoutMs: number, caller?: Agent, signal?: AbortSignal): Promise<TaskSnapshot>
/**
* Register an effect-scoped completion listener. Each listener is contained;
@@ -1681,7 +1736,7 @@ async wait(id: TaskId, timeoutMs: number, caller?: Agent, signal?: AbortSignal):
* @param listener - receives each terminal snapshot and its exact owner.
* @returns disposer that unregisters the listener.
*/
onTaskDone(listener: TaskDoneListener): () => void
abstract onTaskDone(listener: TaskDoneListener): () => void
/**
* Attach an effect-scoped surface that can read and stop tasks. {@link start}
@@ -1689,12 +1744,12 @@ onTaskDone(listener: TaskDoneListener): () => void
* @param name - diagnostic label; duplicate names remain independent.
* @returns disposer that detaches this surface.
*/
attachSurface(name: string): () => void
abstract attachSurface(name: string): () => void
```
Types: [Agent](../core-data-structures/core.md) · [TaskDoneListener](../core-data-structures/tasks.md) · [TaskId](../core-data-structures/tasks.md) · [TaskRead](../core-data-structures/tasks.md) · [TaskSnapshot](../core-data-structures/tasks.md) · [TaskStart](../core-data-structures/tasks.md)
Source: [`packages/tasks/tasks/src/index.ts:77`](../../packages/tasks/tasks/src/index.ts)
Source: [`packages/tasks/tasks/src/index.ts:50`](../../packages/tasks/tasks/src/index.ts)
## `ctx.telemetry` — `Telemetry` (abstract seam)
@@ -1872,7 +1927,7 @@ async execute(exec: ToolExecutionInput): Promise<ToolExecutionResult>
Types: [ScopeKey](../core-data-structures/scope.md) · [ToolDefinition](../core-data-structures/tools.md) · [ToolExecutionInput](../core-data-structures/tools.md) · [ToolExecutionMode](../core-data-structures/tools.md) · [ToolExecutionResult](../core-data-structures/tools.md) · [ToolGuard](../core-data-structures/tools.md) · [ToolRestriction](../core-data-structures/tools.md) · [ToolSchema](../core-data-structures/tools.md)
Source: [`packages/core/tools/src/index.ts:634`](../../packages/core/tools/src/index.ts)
Source: [`packages/core/tools/src/index.ts:688`](../../packages/core/tools/src/index.ts)
## `ctx.tui` — `TuiExtensionService` (abstract seam)
@@ -1895,7 +1950,7 @@ The concrete provider retains pi-tui, focus, and terminal lifecycle state. Plugi
abstract openOverlay(request: TuiOverlayRequest): TuiOverlaySession
```
Source: [`packages/ui/tui/src/index.ts:150`](../../packages/ui/tui/src/index.ts)
Source: [`packages/ui/tui/src/index.ts:153`](../../packages/ui/tui/src/index.ts)
## `ctx.userInteraction` — `UserInteractionService`
@@ -2032,6 +2087,16 @@ get(id: WorkspaceId): Workspace | undefined
*/
list(): Workspace[]
/**
* 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.
* @param id - Workspace registration to remove.
* @returns `true` when a record was deleted, `false` when it was unknown.
*/
delete(id: WorkspaceId): Promise<boolean>
/**
* Resolve by canonical directory path without creating or mutating a
* workspace. A missing path rejects during `realpath`; an existing unowned