deepseek-harness/docs/config-catalog.md

3379 lines
140 KiB
Markdown
Raw Normal View History

feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
<!-- Generated by scripts/gen-config-catalog.ts — do not edit by hand.
Run `pnpm run gen-config-catalog` to regenerate. -->
# Plugin Config Catalog
Every `config:` block a `cordis.yml` entry can set: for each loadable harness package, the verbatim config declaration (JSDoc included) its `apply` function or service constructor receives, with every referenced type pasted alongside (package-local types) or linked (everything else). The paste is the plugin's full declared config type — a field the runtime schema deliberately excludes is a runtime-only seam (its own JSDoc says so) and is not settable from `cordis.yml`. This is the **deployment**-axis reference — the wiring a plugin author works against is the generated Cordis API region on each [subsystem page](subsystems/core.md), the model-facing tool schemas are the [tool catalog](tool-catalog.md), and [subsystems/](subsystems/core.md) documents the types these declarations reference.
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
fix: extend the schema cross-check to nested key paths; scope the catalog framing Review findings on the config catalog: The schema-subset check compared only top-level z.object keys against top-level type members, so a nested loader-accepted key (agents[].id, agentOptions.model, capabilities.*) missing from the declared type would pass the gate unseen. The walk now collects nested object/array compositions as key paths and resolves each against the declared config type — through interfaces (heritage included), aliases, literals, intersections, unions, arrays, indexed access, Partial-style wrappers, and type references across package-local and workspace imports (re-export chains included). The check stays presence-only and one-directional, and only a definite miss is a violation: a path crossing a type the walk cannot enumerate (an external package's) is skipped, never mis-reported. The recursion guard applies at named declarations only — a structural first child shares its span start with its parent, so a span-keyed guard on every node mistakes ordinary descent for a cycle and silently turns definite misses into unknowns. The page and RFC framing also overstated the catalog as the exact cordis.yml-settable surface: the paste is the plugin's full declared config type, and a field the runtime schema deliberately excludes (the ACP bridge's test-injected stream) is a runtime-only seam its own JSDoc marks. Both now say so. Five spec cases pin the new behavior: nested hidden key, workspace intersection via star re-export, Partial wrapper, indexed-access composition, and the external-type unknown path.
2026-07-06 23:06:03 +08:00
This file is GENERATED from source (`scripts/gen-config-catalog.ts`) and verified fresh by `pnpm run verify-config-catalog` (part of `doc-sync`) — do not edit it by hand. Declaration blocks use a `ts config-catalog` fence (skipped by doc-typecheck, since a lone declaration referencing imports is not standalone-compilable). The generator also cross-checks the runtime schemastery schema against the pasted declaration — every schema-validated key, nested keys included, must be locatable on the declared config type — so the paste cannot hide a loader-accepted field.
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
A `Requires:` line lists the service keys the plugin `inject`s: its `cordis.yml` tree must also load providers for those services. Scope is the harness tier (`packages/`); the vendored cordis plugins a config tree may also load (`hmr`, the console logger, …) are pinned upstream source ([vendoring policy](../vendor/README.md)) and not catalogued here.
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-acp"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-acp`
Requires: `agents` · `llm` · `sessionPersistence` · `sessions`
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
```ts config-catalog
/** Plugin config: the provider/model selection used for each ACP-created agent. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
export interface AcpConfig {
2026-07-14 21:57:52 +08:00
/** Provider route for created agents. */
provider?: string
/** Model name for created agents. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
model?: string
/** Maximum summaries returned by one session/list page. */
sessionListPageSize?: number
2026-07-19 02:18:59 +08:00
/** Runtime-only transport override; production uses stdio. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
stream?: Stream
}
```
Depends on: `Stream` (`@agentclientprotocol/sdk`)
Source: [`packages/acp/acp/src/index.ts:74`](../packages/acp/acp/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-agent-default-model"></a>
## `@deepseek-ai/dsh-agent-default-model`
```ts config-catalog
/** Composition entry for the default model selection. */
export interface Config {
/** Registered provider route. */
provider: string
/** Provider-owned model id. */
model: string
}
```
Source: [`packages/core/agent-default-model/src/index.ts:41`](../packages/core/agent-default-model/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-agent-instructions"></a>
## `@deepseek-ai/dsh-agent-instructions`
```ts config-catalog
/** User-facing workspace instruction loader configuration. */
export interface Config {
/** Harness home containing the fixed user-global `AGENTS.md`; defaults to `$DSH_HOME` or `~/.dsh`. */
dshHome?: string
/** Directory entries that identify the project root while walking upward from the session cwd. */
projectRootMarkers?: string[]
/** UTF-8 byte cap for one rendered baseline or dynamic batch; non-positive or non-finite disables loading. */
maxBytes: number
/** Maximum UTF-8 bytes read from one instruction file; larger files are ignored. */
maxSourceBytes?: number
/**
* Ordered same-directory project candidates; every existing file loads, with
* per-directory trimmed-content duplicates collapsed to the earliest candidate.
*/
instructionFileCandidates?: string[]
/**
* Ordered same-directory local-overlay candidates loaded after the base files
* under the same per-directory trimmed-content dedup; empty disables the overlay.
*/
localInstructionFileCandidates?: string[]
}
```
Source: [`packages/context/agent-instructions/src/config.ts:18`](../packages/context/agent-instructions/src/config.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-agent-loop"></a>
## `@deepseek-ai/dsh-agent-loop`
Requires: `agents` · `sessions` · `llm` · `tools` · `systemPrompt`
```ts config-catalog
/** Agent-loop plugin configuration. */
export interface Config {
/**
2026-07-18 14:59:26 +08:00
* Maximum parallel-safe calls in flight per agent step. `1` is serial;
* omission defaults to {@link DEFAULT_MAX_PARALLEL_TOOL_CALLS}.
*/
maxParallelToolCalls?: number
/** Agents created or resumed at plugin startup. */
agents: (AgentOptions & {
/** Stable config label used in logs and as the fresh combined-id prefix. */
id: string
/** Optional stable identity; remounts resume its materialized history, while first use creates it fresh. */
sessionId?: SessionId
/** Optional workspace for a fresh session. */
cwd?: string
/** Persisted session to resume instead of creating a fresh session. */
resumeSessionId?: SessionId
})[]
}
```
Depends on: [`AgentOptions`](subsystems/core.md) · [`SessionId`](subsystems/core.md)
Source: [`packages/core/agent-loop/src/index.ts:255`](../packages/core/agent-loop/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-agent-presets"></a>
## `@deepseek-ai/dsh-agent-presets`
Requires: `loader`
```ts config-catalog
/** Plugin config: which preset is the default, and where presets live. */
export interface Config {
/** Preset id mounted when a caller names none. Missing at mount time fails loud. */
default: string
/** Scanned roots in precedence order; an earlier root wins a duplicate id. */
roots: PresetRoot[]
/**
* Append the harness home's `USER_PRESET_DIR` as a `user` root, after every
* configured root. False mounts a roster over `roots` alone.
*/
includeUserRoot: boolean
}
/** One directory scanned for preset subdirectories. */
export interface PresetRoot {
/** Directory holding one subdirectory per preset; a leading `~` expands. */
path: string
/** Trust recorded on every preset discovered under this root. */
trust: PresetTrust
}
/**
* Where a preset's composition came from. A `system` preset ships with the
* deployment; a `user` preset was authored locally, by a person or by an
* agent, and therefore carries the same trust as shell access.
*/
export type PresetTrust = 'system' | 'user'
```
Source: [`packages/preset/agent-presets/src/preset.ts:52`](../packages/preset/agent-presets/src/preset.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-agent-spine-demo"></a>
## `@deepseek-ai/dsh-agent-spine-demo`
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
```ts config-catalog
/**
* Bundle config: each field forwarded verbatim to the child that owns it —
* `agents` to the agent loop (an app that pre-creates no agents, like the ACP
* bridge, simply omits it), `includeHarnessIdentity`, `includeRuntimeContext`,
* `persona`, and `toolOrder` to the system-prompt plugin (the fixed opener,
* dynamic-context policy, deployment persona, and explicit model-facing tool
* order), the `tools` object to the tool registry (its presentation `mode`),
* `dshHome` to bash environment and local skill discovery, `sessionTitle` to
* the fallback title service, `skills` to the
* skill registry/local provider/tool consumer, `workspaceContext` to the
* agent-instructions loader, `jobs` to the process-local job provider, and
* `toolBash`/`toolJobs` to the model-facing tool plugins this bundle owns.
* Provider adapters own their `retryPolicy`; this bundle always mounts its
* executor.
* `goals` opts into and configures the persisted goal domain plus its model tool
* and same-session driver; `invariants` configures global and package-filtered
* relational checks. Owner schemas supply defaults for optional input;
* workspace context instead requires an explicit byte budget or `false` because
* it changes model-visible input. Producer opt-in stays producer-local:
* `toolBash` configures bash only; independently composed producers keep their
* own config. Set `toolBash: false` when another plugin owns the model-facing
* `bash` name.
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
*/
export interface Config {
/** The agent-loop `agents` list (see dsh-agent-loop's `Config`). */
agents?: AgentLoopConfig['agents']
2026-07-18 14:59:26 +08:00
/** Agent-loop concurrency cap; `1` is serial. */
maxParallelToolCalls?: AgentLoopConfig['maxParallelToolCalls']
/** Whether the system prompt includes the fixed Harness identity (default true). */
includeHarnessIdentity?: SystemPromptConfig['includeHarnessIdentity']
/** Whether model history includes dynamic runtime-context snapshots (default true). */
includeRuntimeContext?: SystemPromptConfig['includeRuntimeContext']
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
/** The deployment persona (see dsh-system-prompt's `Config`). */
persona?: SystemPromptConfig['persona']
/** The explicit model-facing tool order (see dsh-system-prompt's `Config`). */
toolOrder?: SystemPromptConfig['toolOrder']
feat: Code Mode — the registry's mode config, the SDK codegen, and the run_code bridge The dsh-tools half of the Code Mode RFC (its fourth, final change): the registry gains its first config — mode: native | code | both — and OWNS how its tools reach the model. 'code' contributes exactly one wire tool, run_code, plus a lazy tools:sdk prompt section declaring every other tool as a generated TypeScript API (jsonSchemaToTs: total over the defineTool subset, unknown degradation, lexicographic byte-identical rendering); 'both' ships both representations; 'native' is byte-for-byte the old behavior. Non-native modes fail every assembly loudly without a typescript-language ctx.codeRuntime. run_code's dispatch bridge: JSON-normalizes each binding argument before dispatch (what dispatches is what the tool/code-dispatch event logs — the append can never fail on payload shape; BigInt/circulars reject that one call), serializes all program tool calls through a per-run queue (even Promise.all — no concurrency-safety metadata yet), routes every sub-call through tools/pre-execute → tools/post-execute (a deny rejects the program-side promise), drops sub-call additionalContext (no safe outlet mid-run; pinned), owns a run-scoped abort that follows the outer signal in and fires on settlement (in-flight sub-dispatch aborted, queued abandoned, queue drained before returning), and converts a failed run into CodeRunFailedError → a structured isError carrying kind + captured logs. tool/code-dispatch joins SessionEventMap by declaration merging (log-only; deriveMessages ignores it). The composed surface: the tools config forwards through agent-core and both app packages; examples/code-agent + demo:code run the worker runtime under mode code (keyless boot smoke + a with-key e2e proving the collapsed [run_code] header, the dispatch events, and the file the program wrote); two new snapshot scenarios (code-mode-turn, both-mode-turn) record the SDK section, collapsed header, dispatch events, and result card — each its own header-pinning class (the harness gains per-scenario config overlays and per-class pins). Catalogs, graphs, cookbook, hooks-bridge notes, and the RFC (moved to implemented/, restructured to decision-era headings) updated in the same change.
2026-07-08 12:58:23 +08:00
/** The tool registry's config — its presentation `mode` (see dsh-tools' `Config`). */
tools?: ToolsConfig
/** DeepSeek Harness home directory shared by shell context and local skill discovery. */
dshHome?: string
/** Deterministic fallback and accepted-title limits; omission uses the bundle's example policy. */
sessionTitle?: SessionTitleConfig
/** Workspace-context loader controls with an explicit byte budget; set `false` for hermetic prompts. */
workspaceContext: workspaceContext.Config | false
/**
* Skill registry, local provider, and model-facing consumer config.
* Skills use `enabled` because one nested config controls a provider stack;
* single model-tool plugins use `Config | false` to disable that one consumer.
*/
skills?: SkillConfig
/** Model-facing bash tool config, or false when another plugin owns `bash`. */
toolBash?: toolBash.Config | false
/** Process-local background-job admission config. */
jobs?: JobsConfig
/** Generic background-job controls; set false to keep the job service without model-facing job tools. */
toolJobs?: toolJobs.Config | false
/** Global enablement and package-name filters for invariant companions. */
invariants?: InvariantConfig
2026-07-19 23:55:33 +08:00
/** Opt-in persisted same-session goal stack; set false or omit to leave it unmounted. */
goals?: GoalConfig | false
}
/** Skill bundle config forwarded to the registry, local provider, and model-facing consumer. */
export interface SkillConfig {
/** Mount the bundled local skill provider and model-facing skill tool (default true). */
enabled?: boolean
/** Registry-level discovery cache settings. */
registry?: SkillRegistryConfig
/** Local filesystem skill provider settings. */
filesystem?: SkillFileSystem.Config
/** Model-facing skill catalog and tool settings. */
tool?: toolSkill.Config
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
}
2026-07-19 23:55:33 +08:00
/** Persisted goal domain, model-tool policy, and same-session driver config. */
export interface GoalConfig {
/** Goal-domain creation defaults. */
domain?: GoalDomainConfig
/** Model-facing goal-tool authority policy. */
tool?: toolGoal.Config
}
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
```
Depends on: [`AgentLoopConfig`](#deepseek-aidsh-agent-loop) · [`GoalDomainConfig`](#deepseek-aidsh-goal) · [`InvariantConfig`](#deepseek-aidsh-invariants) · [`JobsConfig`](#deepseek-aidsh-jobs-local) · [`SessionTitleConfig`](#deepseek-aidsh-session-title) · [`SkillFileSystem`](../packages/skill/skill-filesystem/src/index.ts) · [`SkillRegistryConfig`](#deepseek-aidsh-skill) · [`SystemPromptConfig`](#deepseek-aidsh-system-prompt) · [`toolBash`](../packages/shell/tool-bash/src/index.ts) · [`toolGoal`](../packages/goal/tool-goal/src/index.ts) · [`toolJobs`](../packages/jobs/tool-jobs/src/index.ts) · [`ToolsConfig`](#deepseek-aidsh-tools) · [`toolSkill`](../packages/skill/tool-skill/src/index.ts) · [`workspaceContext`](../packages/context/agent-instructions/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
Source: [`packages/examples/agent-spine-demo/src/index.ts:92`](../packages/examples/agent-spine-demo/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-agent-tool-presentation"></a>
## `@deepseek-ai/dsh-agent-tool-presentation`
Requires: `tools`
```ts config-catalog
/** Plugin config. */
export interface Config {
/**
* The form this agent's model sees. `native` sends every visible schema,
* `code` sends only `run_code` plus a generated SDK, `both` sends both.
* Required rather than defaulted: the deployment default is what a preset
* without this row already gets, so an omitted value would mean the row was
* composed for nothing.
*/
mode: ToolPresentationMode
}
```
Depends on: [`ToolPresentationMode`](subsystems/tools.md)
Source: [`packages/core/agent-tool-presentation/src/index.ts:38`](../packages/core/agent-tool-presentation/src/index.ts)
<a id="deepseek-aidsh-api-session-controller"></a>
## `@deepseek-ai/dsh-api-session-controller`
Requires: `agentDefaultModel` · `agents` · `attachments` · `llm` · `sessions` · `sessionQuery` · `tools` · `typert` · `workspaceRegistry`
```ts config-catalog
/** Session Controller deployment policy. */
export interface Config {
/** Maximum cold Session artifact size read to determine blankness. */
readonly coldBlankProbeMaxBytes?: number
}
```
Source: [`packages/api/session-controller/src/index.ts:58`](../packages/api/session-controller/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-attachment-local"></a>
2026-07-23 15:20:47 +08:00
## `@deepseek-ai/dsh-attachment-local`
```ts config-catalog
/** Local attachment backend configuration. */
export interface Config {
/** Explicit harness home; omitted follows `DSH_HOME`, then `~/.dsh`. */
dshHome?: string
/** Maximum encoded bytes accepted for one submitted image. Default: 20 MiB. */
2026-07-23 15:20:47 +08:00
maxImageBytes?: number
/** Maximum image count accepted in one submitted message. Default: 20. */
maxImagesPerMessage?: number
/** Maximum aggregate encoded image bytes accepted in one submitted message. Default: 200 MiB. */
maxMessageImageBytes?: number
/** Maximum intrinsic width multiplied by height accepted for one submitted image. Default: 64,000,000. */
2026-07-23 15:20:47 +08:00
maxImagePixels?: number
/** Maximum intrinsic width and maximum intrinsic height accepted for one submitted image. Default: 8192px. */
maxImageDimension?: number
/** Long-edge pixel cap of the stored provider-independent normalized image. */
normalizedImageMaxDimension?: number
/** Encoded-byte safety cap of the stored provider-independent normalized image. */
normalizedImageMaxBytes?: number
/** Maximum simultaneous normalization or request-image transformations in this service instance. */
imageCompressionConcurrency?: number
2026-07-23 15:20:47 +08:00
}
```
Source: [`packages/attachment/attachment-local/src/index.ts:51`](../packages/attachment/attachment-local/src/index.ts)
2026-07-23 15:20:47 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-bash-local"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-bash-local`
Requires: `subprocess`
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
```ts config-catalog
/** Plugin config (all optional — `static Config` supplies the defaults). */
export interface Config {
/** Default working directory for commands (default: process.cwd()). */
cwd?: string
/** Default foreground timeout in milliseconds. */
timeoutMs?: number
/** Upper bound for per-call timeout overrides. */
maxTimeoutMs?: number
/** Per-stream in-memory output cap; overflow spills to a temp file. */
maxOutputBytes?: number
/** Per-stream spill-file cap; larger streams retain only their in-memory tail. */
maxSpillBytes?: number
/** Grace period for kill escalation and inherited pipes; at most `MAX_TIMER_DELAY_MS`. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
graceMs?: number
}
```
Source: [`packages/shell/bash-local/src/index.ts:41`](../packages/shell/bash-local/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-bash-sandbox"></a>
## `@deepseek-ai/dsh-bash-sandbox`
Requires: `subprocess` · `sandbox` · `sandboxPolicy`
```ts config-catalog
/**
feat(sandbox): cross-family file sandbox — one policy home, sandboxed fs provider, fs escalation parity Extend SandboxMode enforcement from bash to the filesystem tools, the sandbox RFC's deferred cross-family phase. - dsh-sandbox-policy (new, ctx.sandboxPolicy): the single home for the deployment default mode + workspaceRoot and the per-session override event, renamed bash/sandbox-mode -> sandbox/mode and moved here with its fold/setter. Decouples the bash seam from dsh-session. - dsh-fs-sandbox (new): SandboxedFileSystem extends LocalFileSystem and fences write/edit by the per-call mode (read-only denies, workspace-write contains to the workspace + temp roots via the shared writableRoots, danger passes through); reads pass through. Structured FS_SANDBOX_DENIED; in-lock parent re-canonicalization. A policy fence in trusted code, not a kernel boundary. - dsh-sandbox: the shared escalation kit (writableRoots, the strictly-wider ladder, denial/hint markers, approveEscalation) both tool families use; approveEscalation takes a structural approver so dsh-sandbox gains no approval/agent dependency, and both tools stay duplication-free. - tool-fs: write/edit advertise sandbox_permissions/justification under a confining ctx.fs, map FS_SANDBOX_DENIED to the shared [sandbox: ...] marker, and resolve the same one-approved-wider retry. - examples/acp-agent: composes sandbox-policy + fs-sandbox, drops the gating that disabled the fs stack under confined modes. RFC docs/rfc/implemented/feature/2026-07-14-cross-family-fs-sandbox.md; the old sandbox RFC's In-process/deferred/FAQ sections updated to shipped fact.
2026-07-14 20:05:57 +08:00
* Plugin config: the local executor's knobs, verbatim. The sandbox policy —
* the default mode and fallback `workspace-write` root — is NOT here: it lives
* on `ctx.sandboxPolicy` (`@deepseek-ai/dsh-sandbox-policy`), which resolves
* each calling session's mode and cwd for every enforcing capability. The runner
* choice is likewise the `ctx.sandbox` provider's config, not this executor's.
*/
feat(sandbox): cross-family file sandbox — one policy home, sandboxed fs provider, fs escalation parity Extend SandboxMode enforcement from bash to the filesystem tools, the sandbox RFC's deferred cross-family phase. - dsh-sandbox-policy (new, ctx.sandboxPolicy): the single home for the deployment default mode + workspaceRoot and the per-session override event, renamed bash/sandbox-mode -> sandbox/mode and moved here with its fold/setter. Decouples the bash seam from dsh-session. - dsh-fs-sandbox (new): SandboxedFileSystem extends LocalFileSystem and fences write/edit by the per-call mode (read-only denies, workspace-write contains to the workspace + temp roots via the shared writableRoots, danger passes through); reads pass through. Structured FS_SANDBOX_DENIED; in-lock parent re-canonicalization. A policy fence in trusted code, not a kernel boundary. - dsh-sandbox: the shared escalation kit (writableRoots, the strictly-wider ladder, denial/hint markers, approveEscalation) both tool families use; approveEscalation takes a structural approver so dsh-sandbox gains no approval/agent dependency, and both tools stay duplication-free. - tool-fs: write/edit advertise sandbox_permissions/justification under a confining ctx.fs, map FS_SANDBOX_DENIED to the shared [sandbox: ...] marker, and resolve the same one-approved-wider retry. - examples/acp-agent: composes sandbox-policy + fs-sandbox, drops the gating that disabled the fs stack under confined modes. RFC docs/rfc/implemented/feature/2026-07-14-cross-family-fs-sandbox.md; the old sandbox RFC's In-process/deferred/FAQ sections updated to shipped fact.
2026-07-14 20:05:57 +08:00
export type Config = LocalConfig
```
feat(sandbox): cross-family file sandbox — one policy home, sandboxed fs provider, fs escalation parity Extend SandboxMode enforcement from bash to the filesystem tools, the sandbox RFC's deferred cross-family phase. - dsh-sandbox-policy (new, ctx.sandboxPolicy): the single home for the deployment default mode + workspaceRoot and the per-session override event, renamed bash/sandbox-mode -> sandbox/mode and moved here with its fold/setter. Decouples the bash seam from dsh-session. - dsh-fs-sandbox (new): SandboxedFileSystem extends LocalFileSystem and fences write/edit by the per-call mode (read-only denies, workspace-write contains to the workspace + temp roots via the shared writableRoots, danger passes through); reads pass through. Structured FS_SANDBOX_DENIED; in-lock parent re-canonicalization. A policy fence in trusted code, not a kernel boundary. - dsh-sandbox: the shared escalation kit (writableRoots, the strictly-wider ladder, denial/hint markers, approveEscalation) both tool families use; approveEscalation takes a structural approver so dsh-sandbox gains no approval/agent dependency, and both tools stay duplication-free. - tool-fs: write/edit advertise sandbox_permissions/justification under a confining ctx.fs, map FS_SANDBOX_DENIED to the shared [sandbox: ...] marker, and resolve the same one-approved-wider retry. - examples/acp-agent: composes sandbox-policy + fs-sandbox, drops the gating that disabled the fs stack under confined modes. RFC docs/rfc/implemented/feature/2026-07-14-cross-family-fs-sandbox.md; the old sandbox RFC's In-process/deferred/FAQ sections updated to shipped fact.
2026-07-14 20:05:57 +08:00
Depends on: [`LocalConfig`](#deepseek-aidsh-bash-local)
Source: [`packages/shell/bash-sandbox/src/index.ts:35`](../packages/shell/bash-sandbox/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-client-connection"></a>
## `@deepseek-ai/dsh-client-connection`
Requires: `webServer`
```ts config-catalog
/** Plugin config: the deployment's non-loopback serving authorities. */
export interface ConnectionConfig {
/**
* Authorities this deployment serves beyond loopback: exact `host:port`, or
* port-less `host` matching any port. The /api trust fence refuses any
* request whose Host is neither loopback nor listed here, so a
* non-loopback (`0.0.0.0`) deployment must declare the names it is reached
* by (the dsh CLI derives the machine's LAN IP literals itself). An entry
* that is not a bare, canonical authority fails the plugin load.
*/
trustedHosts?: string[]
/** Maximum buffered JSON body for every `/api` request. Default: 300 MiB. */
maxRequestBodyBytes?: number
}
```
Source: [`packages/client/connection/src/index.ts:52`](../packages/client/connection/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-client-hmr"></a>
## `@deepseek-ai/dsh-client-hmr`
Requires: `clientModules` · `webServer`
```ts config-catalog
/** Plugin config, validated by the same-named schemastery schema. */
export interface Config {
/** Bundle stat-poll interval in milliseconds (default 500, the build-side watcher's polling default). */
pollIntervalMs?: number
}
```
Source: [`packages/client/hmr/src/index.ts:31`](../packages/client/hmr/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-code-runtime-worker-thread"></a>
## `@deepseek-ai/dsh-code-runtime-worker-thread`
```ts config-catalog
/** Plugin config: every execution cap, changeable from `cordis.yml` (no hardcoded tunables). */
export interface Config {
/**
* Busy-time budget in milliseconds: the run fails with kind `'timeout'`
* once the worker's MEASURED event-loop active time
* (`worker.performance.eventLoopUtilization()`) exceeds this. Metering
* measured busy time — not wall time, not host-side pending-call
* bookkeeping — is what makes the budget both fair (a program awaiting a
* slow tool accrues nothing) and ungameable (a hot loop accrues whether
* or not a decoy dispatch is in flight).
*/
computeMs?: number
/**
* Wall-clock ceiling in milliseconds; never pauses for anything. The
* backstop for what busy-time cannot see (a program awaiting a promise
* nobody will resolve). At most `2_147_483_647` (Node's maximum
* `setTimeout` delay, about 24.9 days): a longer value is rejected at load
* because `setTimeout` would clamp it to 1 ms.
*/
maxWallMs?: number
/**
* Hard cap for serialized log-array, completion-value, and failure-message payloads;
* fixed result-envelope syntax is excluded.
*/
maxOutputBytes?: number
/** The worker's max old-generation heap in MiB (`resourceLimits`); overflow kills the worker, surfacing as kind `'worker-exit'`. */
maxOldGenerationSizeMb?: number
}
```
Source: [`packages/code-runtime/code-runtime-worker-thread/src/index.ts:25`](../packages/code-runtime/code-runtime-worker-thread/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-compaction-basic"></a>
## `@deepseek-ai/dsh-compaction-basic`
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
Requires: `llm` · `tokenMeter` · `sessions`
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
```ts config-catalog
/** Basic compaction configuration with an optional exact-target policy table. */
export interface BasicCompactionConfig extends CompactionPolicyConfig {
/** Exact provider/model overrides; duplicate targets fail plugin load. */
modelPolicies?: ModelCompactPolicyConfig[]
/** Enable automatic step-boundary pressure and overflow-recovery listeners. Defaults to `true`. */
auto?: boolean
}
/** Policy fields shared by the default policy and exact model overrides. */
export interface CompactionPolicyConfig {
/** Compact at this fraction of the model's context window. Defaults to `0.8`. */
thresholdRatio?: number
/** Recent context retained as a fraction of the model's window. Defaults to `0.16`. */
retainRatio?: number
/** Absolute recent-context budget; mutually exclusive with `retainRatio`. */
retainTokens?: number
/** Summary provider; set together with `summarizationModel`, or inherit the conversation target. */
summarizationProvider?: string
/** Summary model; set together with `summarizationProvider`, or inherit the conversation target. */
summarizationModel?: string
/** Provider generation cap for summarization. Defaults to `8192`. */
maxTokens?: number
/** Extra attempts after the first compaction when pressure remains above threshold. Defaults to `1`. */
compactionRetries?: number
/** Maximum retries after canonical context overflow; `0` disables recovery. Defaults to `1`. */
maxOverflowRetries?: number
}
/** Exact provider/model override merged over the default compaction policy. */
export interface ModelCompactPolicyConfig extends CompactionPolicyConfig {
/** Registered provider route to match. */
provider: string
/** Exact routed model id to match within `provider`. */
model: string
}
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
```
Source: [`packages/compaction/compaction-basic/src/types.ts:38`](../packages/compaction/compaction-basic/src/types.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-compaction-tool-result-pruner"></a>
## `@deepseek-ai/dsh-compaction-tool-result-pruner`
Requires: `tokenMeter`
```ts config-catalog
/** Character-budget policy for deterministic tool-result pruning. */
export interface ToolResultPruneConfig {
/** Prune when total text exceeds this many Unicode code points. Defaults to `8192`. */
thresholdChars?: number
/** Maximum leading Unicode code points retained. Defaults to `4096`. */
headChars?: number
/** Maximum trailing Unicode code points retained. Defaults to `1024`. */
tailChars?: number
}
```
Source: [`packages/compaction/compaction-tool-result-pruner/src/types.ts:4`](../packages/compaction/compaction-tool-result-pruner/src/types.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-cordis-host-runner"></a>
2026-08-13 02:22:10 +08:00
## `@deepseek-ai/dsh-cordis-host-runner`
Requires: `tools`
```ts config-catalog
/** Runner configuration. */
export interface Config {
/** Maximum synchronous VM evaluation time in milliseconds. */
vmTimeoutMs?: number
}
```
Source: [`packages/extensions/cordis-host-runner/src/index.ts:88`](../packages/extensions/cordis-host-runner/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-credentials-local"></a>
## `@deepseek-ai/dsh-credentials-local`
```ts config-catalog
/** Plugin config: file location and hot-reload behavior. */
export interface Config {
feat(credentials): move the store to .credentials.yaml and layer $DSH_HOME/.env $DSH_HOME/.env carried two incompatible jobs. As credentials-local's writable secret store it could not be hoisted into process.env — hoisting makes every stored key read as a read-only launch override and blocks rotation from the TUI and the web page. But its name and dotenv format promise an environment file, so a DEEPSEEK_BASE_URL sitting beside a working DEEPSEEK_API_KEY in the same file was silently ignored: only the credential provider read the document, and it addresses credential references alone. Split the two jobs into two files. .credentials.yaml is the provider-managed store: a strict YAML mapping of CredentialRef to non-empty string, no version field, no wrapper level. Because it holds credentials and nothing else, a non-mapping root, a non-identifier key, a non-string value, an empty string, a duplicate key, and malformed YAML are all rejections rather than skipped entries — loud at boot and at a write, warn-and-keep-last-good on a live reload. The dotenv physical-line editor gives way to a patch of the parsed document, so comments and untouched entries keep their formatting and any string value round-trips, multi-line included. Writer lock, read-modify-write, atomic 0600 write under a 0700 directory, watcher, self-write suppression, and quiescent disposal are unchanged. $DSH_HOME/.env becomes the user's ordinary environment layer. app-boot's new loadLayeredEnv loads the invoking directory's .env then the Harness home's, giving user < project < inherited; the home resolves from the inherited environment first, so a project .env cannot redirect it. Credential precedence is unchanged: the live environment still wins read-only over the file, and shadowed writes still reject. Whether a provider-managed store should instead win over the environment is a separate decision. No migration: a key already in $DSH_HOME/.env keeps resolving through the new environment layer, as a read-only env source that shadows the stored one.
2026-08-04 14:50:38 +08:00
/** Credentials document path; defaults to `.credentials.yaml` under the harness home. */
path?: string
/** Harness home used when `path` is omitted; defaults to `$DSH_HOME` or `~/.dsh`. */
dshHome?: string
/** Watch the document and hot-publish external edits; defaults to true. */
watch?: boolean
/** Watcher write-settle window in milliseconds; defaults to 100. */
debounceMs?: number
}
```
fix(credentials,authorization,llm-pi-ai): harden the auth seams per review Review findings on #2509, all confirmed: - Every writer of .credentials.yaml now waits out the record-mutation lock (DOCUMENT_LOCK_WAIT_MS): refs and records share one file and one lock, so a reference write or record delete contending with an OAuth refresh must not fail at the 2s file-work default. - api-key records are admitted before they are rendered: an empty key, a non-POSIX env name, or an empty env value is refused at the write instead of persisting a document the next boot rejects wholesale. - llm-pi-ai no longer lets the credential-key grammar reject legal route ids: reads answer "nothing stored" via isCredentialKeySegment (new dsh-credentials export), deletes have nothing to remove, and only a write refuses, as LlmError UNSTORABLE_PROVIDER_ID; flow registration skips a future catalog id outside the grammar instead of failing the mount. - authorization/settled fans out with contained listener failures on the credentials seam's terms (INVARIANT still rethrows), so a broken watcher can never turn a finished attempt into a failure. - notify() is fire-and-forget at the seam: a surface that cannot render a notice loses the notice, never the attempt. - A declined prompt is an outcome: interactions reject with the new AuthorizationDeclinedError and the attempt settles cancelled instead of failed. - NOT_COMMITTED now confirms a commit observed during the attempt (credentials/record-updated for the flow's key), so a re-auth cannot pass a stale record off as fresh; a flow that deletes its record is refused on the same code. READMEs, the subsystem/event/config catalogs, and the Agent Note follow the shipped behavior; memory.ts carries the dedup TODO.
2026-08-17 13:46:13 +08:00
Source: [`packages/credentials/credentials-local/src/index.ts:64`](../packages/credentials/credentials-local/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-e2b"></a>
## `@deepseek-ai/dsh-e2b`
```ts config-catalog
/** Configuration for the shared E2B sandbox owner. */
export interface Config {
/** API key; omission reads `E2B_API_KEY`. It is never forwarded into the sandbox. */
apiKey?: string
/** Shared remote working directory, created before adapters receive the sandbox. */
cwd?: string
/** E2B sandbox lifetime in milliseconds; expiry always deletes the sandbox. */
timeoutMs?: number
}
```
Source: [`packages/e2b/e2b/src/index.ts:43`](../packages/e2b/e2b/src/index.ts)
2026-08-19 22:44:23 +08:00
<a id="deepseek-aidsh-experimental-agent-team"></a>
## `@deepseek-ai/dsh-experimental-agent-team`
Requires: `agents` · `sessions` · `sessionPersistence` · `subagents`
```ts config-catalog
/** Team-service deployment limits. */
export interface Config {
/** Maximum immutable teammate names retained by one Team. */
readonly maxMembers?: number
/** Maximum non-deleted tasks retained by one Team. */
readonly maxTasks?: number
/** Maximum queued-minus-delivered messages for one target member. */
readonly maxPendingMessagesPerMember?: number
/** Maximum UTF-8 bytes in one complete sender-framed delivery. */
readonly maxMessageBytes?: number
/** Maximum milliseconds allowed for Team-owned runtime disposal. */
readonly disposalTimeoutMs?: number
}
```
Source: [`packages/experimental/agent-team/src/types.ts:125`](../packages/experimental/agent-team/src/types.ts)
<a id="deepseek-aidsh-experimental-tool-agent-team"></a>
## `@deepseek-ai/dsh-experimental-tool-agent-team`
Requires: `agents` · `agentTeams` · `tools` · `systemPrompt`
```ts config-catalog
/** Tool routing configuration. */
export interface Config {
/** Continuable-subagent provider used for fresh teammates. */
readonly freshProvider?: string
/** Continuable-subagent provider used for completed-prefix fork teammates. */
readonly forkProvider?: string
}
```
Source: [`packages/experimental/tool-agent-team/src/index.ts:17`](../packages/experimental/tool-agent-team/src/index.ts)
Merge remote-tracking branch 'origin/master' into worktree/web-file-session-references # Conflicts: # .agents/notes/implemented/architecture/2026-07-25-web-command-surfaces-and-assembly.i18n.yaml # .agents/notes/implemented/architecture/2026-07-25-web-command-surfaces-and-assembly.md # .agents/notes/implemented/architecture/2026-07-25-web-command-surfaces-and-assembly.zh.md # .agents/notes/implemented/feature/2026-07-21-cross-session-references.i18n.yaml # .agents/notes/implemented/feature/2026-07-21-cross-session-references.md # .agents/notes/implemented/feature/2026-07-21-cross-session-references.zh.md # .agents/notes/implemented/feature/2026-07-27-web-subagent-conversations.i18n.yaml # apps/cli/config/web.cordis.yml # apps/cli/package.json # apps/web/tests/scaffold.ts # docs/capability-seams.md # docs/config-catalog.md # docs/cordis-catalog/services.md # docs/event-producer-consumer.md # docs/module-graph.md # packages/client/connection/src/client/api.ts # packages/client/connection/src/client/fixture.ts # packages/client/connection/src/client/index.ts # packages/client/runtime/src/client/contract/session.ts # packages/client/runtime/src/client/sessions/session.ts # packages/client/runtime/tests/session.client.spec.ts # packages/client/ui-conversation/README.i18n.yaml # packages/client/ui-conversation/README.md # packages/client/ui-conversation/README.zh.md # packages/client/ui-conversation/src/client/chat/ChatView.tsx # packages/client/ui-conversation/src/client/chat/MessageItem.tsx # packages/client/ui-conversation/src/client/chat/chat-flow.ts # packages/client/ui-conversation/src/client/input/facade.ts # packages/client/ui-conversation/src/client/input/hub.ts # packages/client/ui-conversation/tests/apply-inject.client.spec.tsx # packages/client/ui-conversation/tests/chat-branch-tails.client.spec.tsx # packages/client/ui-conversation/tests/chat-view.client.spec.tsx # packages/client/ui-conversation/tests/input-bar.client.spec.tsx # packages/client/ui-conversation/tests/input-matrix.client.spec.tsx # packages/client/ui-conversation/tests/input-scenarios.client.spec.tsx # packages/client/ui-conversation/tests/skeleton.client.spec.tsx # packages/client/ui-input-trigger/package.json # packages/client/ui-input-trigger/src/types.ts # packages/client/ui-jobs/README.i18n.yaml # packages/client/ui-slash/README.md # packages/client/ui-slash/README.zh.md # packages/client/ui-subagent/README.i18n.yaml # packages/client/ui-subagent/README.md # packages/client/ui-subagent/README.zh.md # packages/client/ui-subagent/package.json # packages/client/ui-subagent/src/client/index.ts # packages/client/ui-subagent/tests/browser-plugin.client.spec.ts # packages/client/ui-subagent/tsconfig.json # packages/context/session-reference/README.i18n.yaml # packages/context/session-reference/README.md # packages/context/session-reference/README.zh.md # packages/cordis/tool-cordis/src/api-catalog.ts # packages/core/session/README.i18n.yaml # packages/core/session/README.zh.md # packages/host/apiproxy/README.i18n.yaml # packages/host/apiproxy/README.md # packages/host/apiproxy/README.zh.md # packages/host/apiproxy/src/api-proxy.ts # packages/host/apiproxy/src/api/index.ts # packages/host/apiproxy/src/api/rpc-map.ts # packages/host/apiproxy/src/api/rpc.schema.ts # packages/host/apiproxy/src/api/rpc.ts # packages/host/apiproxy/src/api/sessions.ts # packages/host/apiproxy/src/fetch/client.ts # packages/host/apiproxy/src/fetch/handler.ts # packages/host/apiproxy/src/index.ts # packages/host/apiproxy/tests/client-handler.spec.ts # packages/host/apiproxy/tsconfig.json # pnpm-lock.yaml # scripts/gen-cordis-catalog.ts # scripts/gen-doc-graphs.ts # scripts/verify-package-readme-model-experience.ts # tsconfig.base.json # tsconfig.client.json # vitest.config.ts
2026-08-14 16:18:40 +08:00
<a id="deepseek-aidsh-file-reference-local"></a>
## `@deepseek-ai/dsh-file-reference-local`
Requires: `agents`
```ts config-catalog
/** Local file-reference discovery configuration. */
export interface Config {
/** Maximum ranked candidates returned for one query. */
maxResults?: number
/** Maximum indexed files and directories per agent workspace. */
maxEntries?: number
/** Directory basenames never traversed or offered. */
excludedDirectories?: string[]
}
```
Source: [`packages/context/file-reference-local/src/index.ts:35`](../packages/context/file-reference-local/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-fs-local"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-fs-local`
```ts config-catalog
/** Configuration for the local filesystem backend. */
export interface Config {
/** Base directory for relative paths. Defaults to `process.cwd()`. */
cwd?: string
/**
* Exclusive UTF-8 byte limit on each overwrite-diff side, capped by the
* runtime's safe allocation/decode maximum. Defaults to 10 MiB.
*/
diffBasisMaxBytes?: number
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
}
```
Source: [`packages/fs/fs-local/src/index.ts:41`](../packages/fs/fs-local/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-fs-sandbox"></a>
feat(sandbox): cross-family file sandbox — one policy home, sandboxed fs provider, fs escalation parity Extend SandboxMode enforcement from bash to the filesystem tools, the sandbox RFC's deferred cross-family phase. - dsh-sandbox-policy (new, ctx.sandboxPolicy): the single home for the deployment default mode + workspaceRoot and the per-session override event, renamed bash/sandbox-mode -> sandbox/mode and moved here with its fold/setter. Decouples the bash seam from dsh-session. - dsh-fs-sandbox (new): SandboxedFileSystem extends LocalFileSystem and fences write/edit by the per-call mode (read-only denies, workspace-write contains to the workspace + temp roots via the shared writableRoots, danger passes through); reads pass through. Structured FS_SANDBOX_DENIED; in-lock parent re-canonicalization. A policy fence in trusted code, not a kernel boundary. - dsh-sandbox: the shared escalation kit (writableRoots, the strictly-wider ladder, denial/hint markers, approveEscalation) both tool families use; approveEscalation takes a structural approver so dsh-sandbox gains no approval/agent dependency, and both tools stay duplication-free. - tool-fs: write/edit advertise sandbox_permissions/justification under a confining ctx.fs, map FS_SANDBOX_DENIED to the shared [sandbox: ...] marker, and resolve the same one-approved-wider retry. - examples/acp-agent: composes sandbox-policy + fs-sandbox, drops the gating that disabled the fs stack under confined modes. RFC docs/rfc/implemented/feature/2026-07-14-cross-family-fs-sandbox.md; the old sandbox RFC's In-process/deferred/FAQ sections updated to shipped fact.
2026-07-14 20:05:57 +08:00
## `@deepseek-ai/dsh-fs-sandbox`
Requires: `sandboxPolicy`
```ts config-catalog
/**
* Plugin config: the local backend's knobs verbatim (`cwd` resolution default
* and `diffBasisMaxBytes` overwrite-presentation bound). The sandbox default
* (mode + `workspace-write` fallback root) is NOT here — `ctx.sandboxPolicy`
* resolves each calling session for every enforcing capability.
feat(sandbox): cross-family file sandbox — one policy home, sandboxed fs provider, fs escalation parity Extend SandboxMode enforcement from bash to the filesystem tools, the sandbox RFC's deferred cross-family phase. - dsh-sandbox-policy (new, ctx.sandboxPolicy): the single home for the deployment default mode + workspaceRoot and the per-session override event, renamed bash/sandbox-mode -> sandbox/mode and moved here with its fold/setter. Decouples the bash seam from dsh-session. - dsh-fs-sandbox (new): SandboxedFileSystem extends LocalFileSystem and fences write/edit by the per-call mode (read-only denies, workspace-write contains to the workspace + temp roots via the shared writableRoots, danger passes through); reads pass through. Structured FS_SANDBOX_DENIED; in-lock parent re-canonicalization. A policy fence in trusted code, not a kernel boundary. - dsh-sandbox: the shared escalation kit (writableRoots, the strictly-wider ladder, denial/hint markers, approveEscalation) both tool families use; approveEscalation takes a structural approver so dsh-sandbox gains no approval/agent dependency, and both tools stay duplication-free. - tool-fs: write/edit advertise sandbox_permissions/justification under a confining ctx.fs, map FS_SANDBOX_DENIED to the shared [sandbox: ...] marker, and resolve the same one-approved-wider retry. - examples/acp-agent: composes sandbox-policy + fs-sandbox, drops the gating that disabled the fs stack under confined modes. RFC docs/rfc/implemented/feature/2026-07-14-cross-family-fs-sandbox.md; the old sandbox RFC's In-process/deferred/FAQ sections updated to shipped fact.
2026-07-14 20:05:57 +08:00
*/
export type Config = LocalConfig
```
Depends on: [`LocalConfig`](#deepseek-aidsh-fs-local)
Source: [`packages/fs/fs-sandbox/src/index.ts:45`](../packages/fs/fs-sandbox/src/index.ts)
feat(sandbox): cross-family file sandbox — one policy home, sandboxed fs provider, fs escalation parity Extend SandboxMode enforcement from bash to the filesystem tools, the sandbox RFC's deferred cross-family phase. - dsh-sandbox-policy (new, ctx.sandboxPolicy): the single home for the deployment default mode + workspaceRoot and the per-session override event, renamed bash/sandbox-mode -> sandbox/mode and moved here with its fold/setter. Decouples the bash seam from dsh-session. - dsh-fs-sandbox (new): SandboxedFileSystem extends LocalFileSystem and fences write/edit by the per-call mode (read-only denies, workspace-write contains to the workspace + temp roots via the shared writableRoots, danger passes through); reads pass through. Structured FS_SANDBOX_DENIED; in-lock parent re-canonicalization. A policy fence in trusted code, not a kernel boundary. - dsh-sandbox: the shared escalation kit (writableRoots, the strictly-wider ladder, denial/hint markers, approveEscalation) both tool families use; approveEscalation takes a structural approver so dsh-sandbox gains no approval/agent dependency, and both tools stay duplication-free. - tool-fs: write/edit advertise sandbox_permissions/justification under a confining ctx.fs, map FS_SANDBOX_DENIED to the shared [sandbox: ...] marker, and resolve the same one-approved-wider retry. - examples/acp-agent: composes sandbox-policy + fs-sandbox, drops the gating that disabled the fs stack under confined modes. RFC docs/rfc/implemented/feature/2026-07-14-cross-family-fs-sandbox.md; the old sandbox RFC's In-process/deferred/FAQ sections updated to shipped fact.
2026-07-14 20:05:57 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-goal"></a>
## `@deepseek-ai/dsh-goal`
Requires: `agents`
```ts config-catalog
/** Deployment defaults for goal creation. */
export interface Config {
/** Total rounds used when a create request omits its own cap. */
defaultMaxGoalRounds?: number
}
```
2026-08-06 15:28:54 +08:00
Source: [`packages/goal/goal/src/index.ts:116`](../packages/goal/goal/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-headless"></a>
## `@deepseek-ai/dsh-headless`
Requires: `agentDefaultModel` · `agents` · `sessions`
```ts config-catalog
/** Plugin config: the task resolved from this app's injected provider service. */
export interface Config {
/** The prompt text for the single run. */
task: string
}
```
Source: [`packages/bundle/headless/src/index.ts:31`](../packages/bundle/headless/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-hooks-claude-code"></a>
## `@deepseek-ai/dsh-hooks-claude-code`
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
Requires: `shell`
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
```ts config-catalog
/** Plugin config: where the CC hook config lives + substitution roots. */
export interface Config {
/**
* Path to a `hooks.json` or a settings file whose `hooks` key holds the config.
* Process-level: read once at load, a relative path resolves against the process
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
* launch cwd, so one config applies to the whole process.
* TODO(per-session-hook-config): per-session discovery of a project-local
* `hooks.json` from each `session/new.cwd`.
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
*/
configPath: string
/**
* Replaces `${CLAUDE_PLUGIN_ROOT}` in command strings (the plugin's root dir).
*/
pluginRoot?: string
/**
* Replaces `${CLAUDE_PROJECT_DIR}` in command strings AND is exported as the
* `CLAUDE_PROJECT_DIR` env var for hook processes. When omitted, the env var
* defaults per-run to the agent's session workspace (`session.header.cwd`, the
* same dir the hook runs in) — Claude Code always exports this var, and common
* unmodified hooks reference `$CLAUDE_PROJECT_DIR` for project-relative paths.
*/
projectDir?: string
/** Default per-hook timeout in ms when a hook sets none (CC default: 600000). */
defaultTimeoutMs?: number
/** Character cap for the `hook/result` event's persisted stderr summary. */
stderrSummaryMaxChars?: number
}
```
Source: [`packages/hooks/hooks-claude-code/src/index.ts:45`](../packages/hooks/hooks-claude-code/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-hooks-codex"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-hooks-codex`
Requires: `shell`
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
```ts config-catalog
/** Plugin config: where the Codex hooks.json lives + the model name for payloads. */
export interface Config {
/**
* Path to a Codex `hooks.json`. Process-level: read once at load, a relative
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
* path resolves against the process launch cwd.
* TODO(per-session-hook-config): per-session project-local discovery from each
* `session/new.cwd`.
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
*/
configPath: string
/** The model name stamped on every payload (Codex includes `model` on each event). */
model?: string
/** Default per-hook timeout in ms when a hook sets none (Codex default: 600000). */
defaultTimeoutMs?: number
/** Character cap for the `hook/result` event's persisted stderr summary. */
stderrSummaryMaxChars?: number
}
```
Source: [`packages/hooks/hooks-codex/src/index.ts:44`](../packages/hooks/hooks-codex/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-host-apiproxy"></a>
## `@deepseek-ai/dsh-host-apiproxy`
Requires: `agentDefaultModel` · `agents` · `attachments` · `directoryPicker` · `llm` · `sessions` · `subagents` · `sessionQuery` · `sessionController`
```ts config-catalog
/** Gateway plugin configuration. */
export interface Config {
refactor(agent-presets,web): copy-only preset authoring with a path to the files The web YAML editor is gone. agentPreset.write (arbitrary composition text) became agentPreset.copy { from, agentPreset, name? }: a host-side whole-directory copy of ids the host resolves itself — symlinks dereferenced, modes re-tightened to owner-only with owner-execute kept, metadata rewritten to keep the source's description but never its name or roster order. No composition text or path crosses the wire in either authoring direction, and the entryListSchema/!!js concern dissolves with assertComposition itself. The settings section becomes: a read-only viewer over shipped compositions, a copy dialog (id + optional display name) as the only create entry, delete for custom rows, and a location action leading into the preset's own files — agentPreset.openDocument { agentPreset } resolves the directory host-side and opens it natively, or answers { opened: false, path } for the row to show as text where the deployment has no desktop. agentPreset.list reports hasDocument beside authorable; the gateway's nativeOpen config pins the capability where canOpenNativePath platform detection would mislead. The privileged set is now read/copy/openDocument/remove. With files as the only composition editor, standing mounts grew stamp-keyed generations: ensureStanding compares the composition file's mtime+size and starts the next generation for later sessions, while every joined session keeps the generation it runs on. New keyless web lane (agent-preset-authoring, overlay pins nativeOpen: false so goldens render one branch on every platform) drives view/copy/reveal/delete end to end; the real-composition CLI e2e switches to copy semantics.
2026-08-08 22:35:26 +08:00
/**
* Whether this deployment can hand paths to a native desktop opener —
* the `hasDocument` capability the agent-preset roster reports. Absent,
* the platform is asked (macOS/Windows/WSL yes; Linux only with a display
* server); set it explicitly where detection misleads, e.g. `false` in a
* container whose DISPLAY points nowhere a user can see.
*/
nativeOpen?: boolean
/**
* DEFLATE level for every session-log ZIP entry: `0` stores without
* compression, `1` favors CPU/latency, and `9` favors archive size.
* @default 6
*/
sessionExportCompressionLevel?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
}
```
Source: [`packages/host/apiproxy/src/index.ts:41`](../packages/host/apiproxy/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-host-directory-picker-browse"></a>
## `@deepseek-ai/dsh-host-directory-picker-browse`
```ts config-catalog
/** Validated plugin configuration. */
export interface Config {
/** Complete-result bound of one listing level; see {@link BrowseDirectoryPicker.Config}. */
maxEntries: number
}
```
Source: [`packages/host/directory-picker-browse/src/index.ts:181`](../packages/host/directory-picker-browse/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-host-frontend-static"></a>
## `@deepseek-ai/dsh-host-frontend-static`
Requires: `webServer`
```ts config-catalog
/** Plugin config: the dist anchor. */
export interface Config {
/** Absolute path of index.html inside the dist root. */
distIndex: string
}
```
Source: [`packages/host/frontend-static/src/index.ts:28`](../packages/host/frontend-static/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-host-webserver"></a>
## `@deepseek-ai/dsh-host-webserver`
```ts config-catalog
/** Gateway config: the listen address. */
export interface Config {
/** Listen host; the two supported values are loopback and all-interfaces. */
host: '127.0.0.1' | '0.0.0.0'
/** Listen port; zero requests an OS-assigned port. */
port: number
}
```
Source: [`packages/host/webserver/src/index.ts:59`](../packages/host/webserver/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-invariants"></a>
## `@deepseek-ai/dsh-invariants`
```ts config-catalog
/** Runtime invariant selection configured on the service plugin. */
export interface Config {
/** Global switch; defaults to `true`. */
readonly enabled?: boolean
/** Case-sensitive JavaScript regex sources that admit package names; empty admits all. */
readonly package_allowlist?: string[]
/** Case-sensitive JavaScript regex sources that exclude package names after allowlist matching. */
readonly package_blocklist?: string[]
}
```
Source: [`packages/runtime-diagnostics/invariants/src/index.ts:15`](../packages/runtime-diagnostics/invariants/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-jobs-local"></a>
## `@deepseek-ai/dsh-jobs-local`
```ts config-catalog
/** Configuration for the process-local job registry. */
export interface Config {
/**
* Maximum `running` plus `stopping` jobs per exact owner or in the shared unowned bucket;
* omission defaults to 10.
*/
maxConcurrentJobsPerOwner?: number
}
```
Source: [`packages/jobs/jobs-local/src/index.ts:31`](../packages/jobs/jobs-local/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-llm-deepseek"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-llm-deepseek`
Requires: `llm`
```ts config-catalog
/**
* Plugin config, validated by the same-named schemastery schema and doubling
* as the `llm-deepseek` settings-section shape. Every field is optional in
* yml: a missing API key resolves through {@link Config.apiKeyEnv} at each
* request (a request without any key fails with `MISSING_CREDENTIAL`, not at
* plugin load), omitted thinking mode uses the provider default, and omitted
* reasoning effort resolves to `high`.
*/
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
export interface Config {
/** Credential reference (environment-variable name) resolved per request; defaults to `DEEPSEEK_API_KEY`. */
apiKeyEnv?: string
feat(config)!: one ordering for configuration sources, and a bootstrap deny rule $DSH_HOME/.env had just become an ordinary environment layer, which left the harness resolving user-facing values from a flattened process.env that could no longer say where a value came from. A key stored through the web page stayed shadowed by an older key in the user's own .env. An endpoint could be redirected by the project: the invoking directory's .env is materialized like every other layer, and a base URL decides where a resolved API key is sent, so a DEEPSEEK_BASE_URL written into a model-editable workspace would send the user's credential — and the prompts carrying their code — to whatever host that file named. Give every user-facing value one ordering, with four kinds of source: explicit for this run per-operation override, CLI argument > authored by deployment --config / --config-replace > this launch's shell inherited process environment > product-managed store settings.yaml, .credentials.yaml > discovered file $DSH_HOME/.env > defaults schema default, shipped base, public default The domains differ only in which tiers exist. The earlier split — credentials ranking the environment over the managed file while settings ranked over the environment — was inconsistent: the distinguishing fact is who authored the source, not the domain. packages/util/environment owns an immutable snapshot with per-layer provenance. getFrom(name, sources) searches only the layers a caller names, and omitting one is a refusal rather than a demotion: the adapters ask for ['process', 'user-env'], so no reordering can let a project file back into a decision it was excluded from. isBootstrapOnly rejects, before anything is materialized, any .env setting a variable that governs how a process launches (PATH, SHELL, NODE_OPTIONS, LD_PRELOAD), where code or model-visible instructions load from (the whole DSH_* namespace, HOME, XDG_*), or how the network is reached (proxy and CA variables). The namespace is denied wholesale so a switch added later cannot become settable by being forgotten, and there is no opt-out. verify-config-source-ownership keeps both rules: no unregistered process.env read under packages/*/*/src (26 allowlisted with reasons), and no apiKey, baseURL, or headers inlined from the environment in shipped Cordis config — removing those inlines is what makes the deployment tier meaningful.
2026-08-04 16:17:32 +08:00
/** Endpoint base; falls back to $DEEPSEEK_BASE_URL from a trusted environment layer, then the public API. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
baseURL?: string
/** Deployment thinking policy; `disabled` limits every conversation request to `off`. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
thinking?: 'enabled' | 'disabled'
/** Default thinking effort (default `high`); `off` disables thinking per request. */
reasoningEffort?: 'off' | 'low' | 'high' | 'max'
/** Default per-request output cap (default 256,000); a model's own cap and explicit request values win. */
maxTokens?: number
/** Positive context capacity used when the selected model has no exact value (default 1,000,000). */
defaultContextWindow?: number
/** Advisory models shown by discovery consumers; defaults to V4 Flash, V4 Pro, and V4 Flash Vision Exp. */
models?: DeepSeekCatalogModel[]
/** Maximum provider idle time while one stream read is outstanding (default five minutes). */
streamIdleTimeoutMs?: number
/** Maximum accumulated file-referenced image bytes per chat request (default 128 MiB). */
maxRequestFilesBytes?: number
/** Maximum accumulated base64 image payload after Files API fallback (default 20 MiB). */
maxInlineRequestImageBytes?: number
/** Maximum number of represented images per chat request (default 600). */
maxImagesPerRequest?: number
/** Raw-byte removal step after the request exceeds its file bound (default 64 MiB). */
imageOffloadByteQuantum?: number
/** Base64-byte removal step after inline fallback exceeds its bound (default 10 MiB). */
inlineImageOffloadByteQuantum?: number
/** Image-count removal step after the request exceeds its count bound (default 20). */
imageOffloadCountQuantum?: number
/** Maximum duration of one request-image Files API resolution (default one minute). */
filesApiTimeoutMs?: number
/** Explicit lifetime assigned to each uploaded image (default seven days). */
fileExpiresAfterSeconds?: number
/** Remaining lifetime below which an indexed file is replaced (default one hour). */
fileRefreshMarginSeconds?: number
/** Oldest harness-owned files deleted before one quota-recovery upload retry (default 100). */
fileQuotaCleanupBatch?: number
/** Provider-owned model-request retry policy; omission uses normal mode with five retries. */
retryPolicy?: RetryPolicyConfig
}
/** One optional model entry advertised by the direct-fetch adapter. */
export interface DeepSeekCatalogModel {
/** Wire model id accepted by the configured endpoint. */
id: string
/** Selector label; defaults to {@link id}. */
name?: string
/** Optional selector detail for deployments with similar model variants. */
description?: string
/** Known combined request/response context capacity; omitted when deployment metadata is unavailable. */
contextWindow?: number
/** Per-request output cap for this model; omission falls back to the profile's {@link DeepSeekConnectionOptions.maxTokens}. */
maxTokens?: number
/** Accepted request modalities; omission is text-only. */
inputModalities?: ModelModality[]
/** Total-pixel budget for one deterministic request preview. */
imagePixelBudget?: number
/** Encoded-byte cap for one deterministic request preview. */
imageMaxBytes?: number
/** Provider detail tier; `low` uses the 512-by-512 total-pixel default. */
imageDetail?: 'auto' | 'low'
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
}
```
Depends on: [`ModelModality`](../packages/llm/llm/src/index.ts) · [`RetryPolicyConfig`](../packages/llm/llm/src/index.ts)
Source: [`packages/llm/llm-deepseek/src/index.ts:106`](../packages/llm/llm-deepseek/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-llm-pi-ai"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-llm-pi-ai`
Requires: `llm`
```ts config-catalog
/** Plugin configuration: the provider routes this instance owns. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
export interface Config {
/**
* pi-ai provider routes, keyed by provider. An empty (or omitted) dict is
* the dormant settings-driven posture: the adapter mounts with no routes
* and registers them the moment a settings section supplies profiles.
*/
providers?: Record<string, PiAiProviderProfile>
2026-07-14 21:57:52 +08:00
}
/** Configuration for one pi-ai provider route; the `providers` dict key IS the route. */
2026-07-14 21:57:52 +08:00
export interface PiAiProviderProfile {
/** Credential reference (environment-variable name) resolved per request through `ctx.credentials`. */
apiKeyEnv?: string
/** Name shown by configuration surfaces; defaults to the route key. */
displayName?: string
/**
* Wire protocol every model on this route speaks. Omission keeps each
* installed catalog model's own protocol, which is why a catalog route needs
* no protocol at all; a route the catalog does not ship must name one.
*/
api?: string
/** Endpoint for this route's models; defaults to the installed catalog's endpoint. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
baseURL?: string
/**
* This route's model catalog. Omission serves the installed catalog for the
* route unchanged; an explicit list replaces it, each entry defaulting its
* unset fields from the installed model of the same id.
*/
models?: PiAiModelProfile[]
/**
* Installed-catalog customizations by model id: each entry reshapes that
* one model with the same fields a {@link models} entry takes, while the
* rest of the catalog keeps serving untouched. Only meaningful on a catalog
* route with no `models` list — `models` already replaces the catalog, so
* an override beside it, on a route the catalog does not ship, or naming a
* model the catalog does not describe is refused rather than skipped.
*/
modelOverrides?: Record<string, PiAiModelOverride>
/**
* pi-ai wire-compatibility switches defaulting every model on this route
* whose protocol declares them; each model's own `compat` overrides per
* field. What neither sets keeps the installed catalog entry's value, then
* pi-ai's own detection. A switch no model on the route could read is
* refused rather than left looking applied.
*/
compat?: PiAiCompatProfile
fix(llm): size unknown models and refuse a section that cannot be served Three defects surfaced while driving the Models page. A hand-declared model needed an explicit contextWindow and maxTokens, but a provider listing usually returns ids and nothing else — so the page happily wrote a profile the adapter then rejected, which took the whole namespace down silently. Capacities now fall back to the route's `defaultContextWindow` (262,144) and `defaultMaxTokens` (32,768). Both are guesses by construction, which is why they are route fields a deployment corrects once rather than constants buried in the adapter; the fallback sizes the model and never becomes a per-request cap. That silent failure was the second defect. A schema-valid profile the adapter could not serve was stored and only rejected later, disabling every route in the namespace with nothing said. `dsh-settings` gains an optional `validate` on registration — a check for what a schema cannot express — and `llm-pi-ai` refuses an unserviceable section at the write that produced it. A stored section that fails keeps the namespace's last good value, as a schema failure already did, so an externally edited document still cannot strand the owner. The plugin's own last-good fallback goes with it: nothing reaching it can fail any more. Third, a model with no reasoning metadata advertised the single level `off`, which pi-ai translates to *omitting* the reasoning option — the same request naming no effort produces. Selecting it disabled nothing, so a provider whose default is to think kept thinking with `off` shown as selected. Such a model now reports no reasoning capability at all, which is the seam's way of saying the control is unavailable, and the per-model `reasoning` flag is gone: without a thinkingLevelMap to spell levels it could only invent them. The protocol table narrows to the three a hand-declared route reaches today, most-reached first so a surface offering a choice defaults to the one gateways actually speak.
2026-08-04 13:32:56 +08:00
/**
* Context capacity for a model this route lists that neither the entry nor
* the installed catalog sizes (default 262,144). A guess by construction, so
* a deployment whose gateway serves smaller models corrects it here.
*/
defaultContextWindow?: number
/**
* Output capability for a model this route lists that neither the entry nor
* the installed catalog sizes (default 32,768). This sizes the model; it
* never becomes a per-request cap on its own.
*/
defaultMaxTokens?: number
/**
* Request modalities for a model this route lists that neither its entry's
* {@link PiAiModelProfile.input} nor the installed catalog declares (default
* `[text]`). A fallback like the capacities above, not an override: a
* catalog model keeps the modalities the catalog records for it, and this
* value never narrows one. A gateway serving vision models the catalog does
* not describe declares `[text, image]` once here instead of on every entry.
* Unlike an entry's list, this one may not be empty — nothing sits below it
* to answer instead.
*/
defaultInput?: PiAiModality[]
2026-07-14 21:57:52 +08:00
/** Provider request headers; Harness attribution wins reserved names. */
headers?: Record<string, string>
/** Provider-neutral pi-ai reasoning level. */
reasoning?: ModelThinkingLevel
2026-07-14 21:57:52 +08:00
/** Token budgets used by reasoning providers that support them. */
thinkingBudgets?: ThinkingBudgets
/** Prompt-cache retention preference. */
cacheRetention?: CacheRetention
/** Streaming transport preference. */
transport?: Transport
/** HTTP/provider SDK timeout in milliseconds. */
timeoutMs?: number
/** WebSocket connection timeout in milliseconds. */
websocketConnectTimeoutMs?: number
/** Maximum provider idle time while one stream read is outstanding. */
streamIdleTimeoutMs?: number
/**
* Maximum base64-encoded image payload per request. When a request's
* accumulated images exceed it, the oldest images are replaced by text
* placeholders until the request fits, so a long session keeps completing
* requests instead of being rejected by a request-size cap.
*/
maxRequestImageBytes?: number
/** Total-pixel budget for each deterministic inline request version. */
requestImagePixelBudget?: number
/** Raw encoded-byte cap for each deterministic inline request version. */
requestImageMaxBytes?: number
/** Provider-owned model-request retry policy; omission uses normal mode with five retries. */
retryPolicy?: RetryPolicyConfig
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
}
/** One configured model entry: an id plus the catalog fields it overrides. */
export interface PiAiModelProfile {
/** Model id sent to the provider and accepted by {@link GenerateOptions.model}. */
id: string
/** Display name for selectors; defaults to the catalog name, then the id. */
name?: string
/** Maximum combined request and response context in tokens. */
contextWindow?: number
fix(llm): capture an immutable snapshot per pi-ai operation Review found four defects in the declared-provider work. `PiAiAdapter` reused one `Models` collection and mutated it whenever the configuration changed. `Models.streamSimple()` resolves its provider lazily — when the stream is first consumed, which is after the adapter awaits the route's credential — so a configuration change landing in that window let an in-flight request finish under a configuration it never resolved against, or fail on a provider that no longer existed. Each resolution now produces an immutable snapshot and every operation captures one before its first await, which is what makes the seam's per-step freeze (`llm.prepareCall()`) hold end to end: switching models mid-reply takes effect on the next step, never inside the one in flight. `defaultMaxTokens` was materialized from the catalog's `Model.maxTokens`. The two answer different questions: pi-ai requires that field as the model's output capability, while the seam's is a cap the deployment chose to send on requests naming none, so every request had started carrying a number nobody picked. Only an explicitly configured cap reaches the seam now. The configurable-provider directory was refreshed by disposing its registration and making a new one. A candidate set the registry refuses — a profile keyed `deepseek-official`, which llm-deepseek declares — left the whole directory withdrawn and the Models page empty, silently, because the settings callback contains the failure. The seam's registration handle now carries `replace()` with the same validate-first atomicity `registerAdapter` has. The protocol table offered every pi-ai streaming API, including four whose authentication a profile cannot express: Bedrock signs with SigV4 over AWS credentials and a region, Vertex needs a project, a location, and ADC, Azure needs provider environment plus an api-version, and Codex uses OAuth. Offering them handed back routes that cannot authenticate. Catalog routes still reach them through their own provider.
2026-08-04 11:42:35 +08:00
/**
* Maximum output tokens. Configuring one also makes it this model's
fix(llm): size unknown models and refuse a section that cannot be served Three defects surfaced while driving the Models page. A hand-declared model needed an explicit contextWindow and maxTokens, but a provider listing usually returns ids and nothing else — so the page happily wrote a profile the adapter then rejected, which took the whole namespace down silently. Capacities now fall back to the route's `defaultContextWindow` (262,144) and `defaultMaxTokens` (32,768). Both are guesses by construction, which is why they are route fields a deployment corrects once rather than constants buried in the adapter; the fallback sizes the model and never becomes a per-request cap. That silent failure was the second defect. A schema-valid profile the adapter could not serve was stored and only rejected later, disabling every route in the namespace with nothing said. `dsh-settings` gains an optional `validate` on registration — a check for what a schema cannot express — and `llm-pi-ai` refuses an unserviceable section at the write that produced it. A stored section that fails keeps the namespace's last good value, as a schema failure already did, so an externally edited document still cannot strand the owner. The plugin's own last-good fallback goes with it: nothing reaching it can fail any more. Third, a model with no reasoning metadata advertised the single level `off`, which pi-ai translates to *omitting* the reasoning option — the same request naming no effort produces. Selecting it disabled nothing, so a provider whose default is to think kept thinking with `off` shown as selected. Such a model now reports no reasoning capability at all, which is the seam's way of saying the control is unavailable, and the per-model `reasoning` flag is gone: without a thinkingLevelMap to spell levels it could only invent them. The protocol table narrows to the three a hand-declared route reaches today, most-reached first so a surface offering a choice defaults to the one gateways actually speak.
2026-08-04 13:32:56 +08:00
* per-request default; a value inherited from the installed catalog, or the
* route's fallback, is the model's capability and never becomes a request
* default on its own.
fix(llm): capture an immutable snapshot per pi-ai operation Review found four defects in the declared-provider work. `PiAiAdapter` reused one `Models` collection and mutated it whenever the configuration changed. `Models.streamSimple()` resolves its provider lazily — when the stream is first consumed, which is after the adapter awaits the route's credential — so a configuration change landing in that window let an in-flight request finish under a configuration it never resolved against, or fail on a provider that no longer existed. Each resolution now produces an immutable snapshot and every operation captures one before its first await, which is what makes the seam's per-step freeze (`llm.prepareCall()`) hold end to end: switching models mid-reply takes effect on the next step, never inside the one in flight. `defaultMaxTokens` was materialized from the catalog's `Model.maxTokens`. The two answer different questions: pi-ai requires that field as the model's output capability, while the seam's is a cap the deployment chose to send on requests naming none, so every request had started carrying a number nobody picked. Only an explicitly configured cap reaches the seam now. The configurable-provider directory was refreshed by disposing its registration and making a new one. A candidate set the registry refuses — a profile keyed `deepseek-official`, which llm-deepseek declares — left the whole directory withdrawn and the Models page empty, silently, because the settings callback contains the failure. The seam's registration handle now carries `replace()` with the same validate-first atomicity `registerAdapter` has. The protocol table offered every pi-ai streaming API, including four whose authentication a profile cannot express: Bedrock signs with SigV4 over AWS credentials and a region, Vertex needs a project, a location, and ADC, Azure needs provider environment plus an api-version, and Codex uses OAuth. Offering them handed back routes that cannot authenticate. Catalog routes still reach them through their own provider.
2026-08-04 11:42:35 +08:00
*/
maxTokens?: number
/**
* Request modalities this model accepts. Absent — or empty, which describes
* a model that accepts nothing and so states no answer either — keeps the
* installed catalog entry's modalities, then the route's `defaultInput`.
* Declaring images is what makes a hand-declared vision model usable, and
* declaring text alone corrects a catalog model whose gateway does not serve
* what the catalog records. This is a claim about the endpoint, not a check
* of it: nothing interrogates a gateway for what it accepts, so a model
* claiming images its endpoint refuses is refused by the provider instead,
* mid-turn.
*/
input?: PiAiModality[]
/**
* Selectable reasoning efforts. Absent inherits the installed catalog
* entry's capability (a hand-declared model has none and does not reason);
* `false` declares a non-reasoning model, which is how a profile strips
* reasoning from a catalog model its gateway cannot serve; a non-empty dict
* declares the offered levels and their wire spellings.
*/
reasoningEfforts?: false | PiAiReasoningEfforts
/** pi-ai wire-compatibility switches for this model, winning over the route's per field; one its protocol does not declare is refused. */
compat?: PiAiCompatProfile
}
/**
* Customization of one installed catalog model, keyed by its id in the
* route's `modelOverrides` dict — the same fields a `models` entry may set,
* with the id living in the key. Unlike a `models` list, overrides leave the
* rest of the catalog serving untouched, which is what makes "correct one
* model, keep the other thirty-seven" a three-line edit.
*/
export type PiAiModelOverride = Omit<PiAiModelProfile, 'id'>
/**
* pi-ai wire-compatibility switches, set on the route (its models' default) or
* per model (winning over the route, field by field).
*
* pi-ai decides each of these from the provider id and baseURL when no layer
* sets it, and a private gateway's URL says nothing: for an endpoint it does
* not recognize the detection answers as though it were OpenAI itself, which
* is wrong for most OpenAI-compatible gateways. So every field here is one a
* deployment must be able to state because nothing can infer it, while the
* fields pi-ai's catalog sets for a named vendor stay withheld.
*
* A field belongs to the protocols whose upstream compat type declares it: a
* model-level switch its protocol does not take fails resolution, and a
* route-level one skips past models it cannot fit. "The three Responses
* protocols" below means `openai-responses`, `azure-openai-responses`, and
* `openai-codex-responses`, which pi-ai gives one shared compat type, so a
* switch settable on one is settable on all three.
*/
export interface PiAiCompatProfile {
/** Whether the endpoint accepts `store`; `openai-completions`. */
supportsStore?: boolean
/**
* Whether the endpoint accepts the `developer` role for the system prompt,
* which pi-ai sends only to a reasoning model; `false` keeps `system`.
* `openai-completions` and the three Responses protocols.
*/
supportsDeveloperRole?: boolean
/** Whether the endpoint accepts `reasoning_effort`; `openai-completions`. */
supportsReasoningEffort?: boolean
/** Whether the endpoint accepts `stream_options: {include_usage: true}`; `openai-completions`. */
supportsUsageInStreaming?: boolean
/** Which output-cap field the endpoint reads; `openai-completions`. */
fix(llm-pi-ai): refuse valueless compat and group gates by compat type Review found two live defects in the compat surface. A valueless key (`supportsDeveloperRole:`) survives schemastery as null, and resolution carried it forward as a configured value. It landed on `Model.compat` as null, which replaced the installed catalog entry's value and left pi-ai's `??` reaching for its baseURL detection — the catalog layer skipped entirely, and the switch written but not applied. The vocabulary check now refuses it where it is written, matching the `reasoningEfforts` precedent in the same file. The gates were keyed by protocol name, but pi-ai keys compat by type: `openai-responses`, `azure-openai-responses`, and `openai-codex-responses` share one `OpenAIResponsesCompat`, so two shipped catalog routes were refused the fields their own models declare. Gates now group by compat type, `bedrock-converse-stream` gains its own, and the protocol set is derived from `Model.compat`'s conditional so a release that gives a further protocol a compat type fails the gate list by name. Field types are derived from upstream rather than restated, with a proof pinning the profile assignable to the upstream types, so a widened value union cannot silently narrow what configuration accepts. The `undefined` filter stays removed: `exactOptionalPropertyTypes` keeps a typed caller from writing one, and schemastery never materializes one, so it was validation for a value the static interface already excludes. Refs #2646
2026-08-19 11:48:01 +08:00
maxTokensField?: NonNullable<OpenAICompletionsCompat['maxTokensField']>
/** Whether tool results must carry `name`; `openai-completions`. */
requiresToolResultName?: boolean
/** Whether a user message after tool results needs an assistant message between; `openai-completions`. */
requiresAssistantAfterToolResult?: boolean
/** Whether thinking blocks must travel as text in `<thinking>` delimiters; `openai-completions`. */
requiresThinkingAsText?: boolean
/** Whether replayed assistant messages need an empty `reasoning_content` while reasoning is on; `openai-completions`. */
requiresReasoningContentOnAssistantMessages?: boolean
/** Reasoning parameter format the endpoint expects; `openai-completions`. */
thinkingFormat?: PiAiThinkingFormat
fix(llm-pi-ai): refuse valueless compat and group gates by compat type Review found two live defects in the compat surface. A valueless key (`supportsDeveloperRole:`) survives schemastery as null, and resolution carried it forward as a configured value. It landed on `Model.compat` as null, which replaced the installed catalog entry's value and left pi-ai's `??` reaching for its baseURL detection — the catalog layer skipped entirely, and the switch written but not applied. The vocabulary check now refuses it where it is written, matching the `reasoningEfforts` precedent in the same file. The gates were keyed by protocol name, but pi-ai keys compat by type: `openai-responses`, `azure-openai-responses`, and `openai-codex-responses` share one `OpenAIResponsesCompat`, so two shipped catalog routes were refused the fields their own models declare. Gates now group by compat type, `bedrock-converse-stream` gains its own, and the protocol set is derived from `Model.compat`'s conditional so a release that gives a further protocol a compat type fails the gate list by name. Field types are derived from upstream rather than restated, with a proof pinning the profile assignable to the upstream types, so a widened value union cannot silently narrow what configuration accepts. The `undefined` filter stays removed: `exactOptionalPropertyTypes` keeps a typed caller from writing one, and schemastery never materializes one, so it was validation for a value the static interface already excludes. Refs #2646
2026-08-19 11:48:01 +08:00
/**
* Kwargs sent as `chat_template_kwargs`, which pi-ai reads only under the
* two `chat-template` thinking formats; `openai-completions`. Nothing checks
* that pairing: the format in force may come from the installed catalog
* entry or from pi-ai's own baseURL detection, neither of which resolution
* can read, so kwargs set beside another format are sent nowhere.
*/
chatTemplateKwargs?: NonNullable<OpenAICompletionsCompat['chatTemplateKwargs']>
/**
* Whether the endpoint accepts `strict` in tool definitions;
* `openai-completions`, the three Responses protocols, `bedrock-converse-stream`.
*/
supportsStrictMode?: boolean
/** Prompt-cache marker convention; `openai-completions`. */
fix(llm-pi-ai): refuse valueless compat and group gates by compat type Review found two live defects in the compat surface. A valueless key (`supportsDeveloperRole:`) survives schemastery as null, and resolution carried it forward as a configured value. It landed on `Model.compat` as null, which replaced the installed catalog entry's value and left pi-ai's `??` reaching for its baseURL detection — the catalog layer skipped entirely, and the switch written but not applied. The vocabulary check now refuses it where it is written, matching the `reasoningEfforts` precedent in the same file. The gates were keyed by protocol name, but pi-ai keys compat by type: `openai-responses`, `azure-openai-responses`, and `openai-codex-responses` share one `OpenAIResponsesCompat`, so two shipped catalog routes were refused the fields their own models declare. Gates now group by compat type, `bedrock-converse-stream` gains its own, and the protocol set is derived from `Model.compat`'s conditional so a release that gives a further protocol a compat type fails the gate list by name. Field types are derived from upstream rather than restated, with a proof pinning the profile assignable to the upstream types, so a widened value union cannot silently narrow what configuration accepts. The `undefined` filter stays removed: `exactOptionalPropertyTypes` keeps a typed caller from writing one, and schemastery never materializes one, so it was validation for a value the static interface already excludes. Refs #2646
2026-08-19 11:48:01 +08:00
cacheControlFormat?: NonNullable<OpenAICompletionsCompat['cacheControlFormat']>
/**
* Whether the endpoint accepts long prompt-cache retention;
* `openai-completions`, the three Responses protocols, `anthropic-messages`.
*/
supportsLongCacheRetention?: boolean
/** Whether the endpoint accepts per-tool `eager_input_streaming`; `anthropic-messages`. */
supportsEagerToolInputStreaming?: boolean
/** Whether the endpoint accepts `cache_control` on tool definitions; `anthropic-messages`. */
supportsCacheControlOnTools?: boolean
/** Whether the endpoint accepts the `temperature` request field; `anthropic-messages`. */
supportsTemperature?: boolean
/** Whether to force adaptive thinking regardless of model id; `anthropic-messages`. */
forceAdaptiveThinking?: boolean
/** Whether to replay an empty thinking signature instead of converting thinking to text; `anthropic-messages`. */
allowEmptySignature?: boolean
/** Whether the endpoint accepts Anthropic strict tool schemas; `anthropic-messages`. */
supportsStrictTools?: boolean
}
/** One request modality a pi-ai model may accept. */
export type PiAiModality = Model<Api>['input'][number]
/**
* Selectable reasoning efforts for one model: each key is a level the model
* offers (and selectors show), and its value is the wire spelling dispatch
* sends for it. `off` alone may leave its value empty — "supported, send
* nothing" — because for most providers not thinking is the parameter's
* absence; every other declared level must name a wire value. A level absent
* from the dict is not offered.
*/
export type PiAiReasoningEfforts = Partial<Record<ModelThinkingLevel, string | null>>
/** One reasoning-dispatch wire format a profile may name. */
export type PiAiThinkingFormat = NonNullable<OpenAICompletionsCompat['thinkingFormat']>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
```
Depends on: `Api` (`@earendil-works/pi-ai`) · `CacheRetention` (`@earendil-works/pi-ai`) · `Model` (`@earendil-works/pi-ai`) · `ModelThinkingLevel` (`@earendil-works/pi-ai`) · `OpenAICompletionsCompat` (`@earendil-works/pi-ai`) · [`RetryPolicyConfig`](../packages/llm/llm/src/index.ts) · `ThinkingBudgets` (`@earendil-works/pi-ai`) · `Transport` (`@earendil-works/pi-ai`)
2026-07-14 21:57:52 +08:00
Source: [`packages/llm/llm-pi-ai/src/config.ts:213`](../packages/llm/llm-pi-ai/src/config.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-llm-replay"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-llm-replay`
Requires: `llm`
```ts config-catalog
/** Plugin config: the {@link ReplayConfig} inputs, each defaulting to its `DSH_SNAPSHOT_*` env var in `apply`. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
export interface Config {
/** Override the fixture path; defaults to `$DSH_SNAPSHOT_FILE`. */
file?: string
/** Override the sidecar path; defaults to `$DSH_SNAPSHOT_OVERRIDE`. */
overrideFile?: string
/**
* Override the child-log paths; defaults to `$DSH_SNAPSHOT_CHILD_FILES` (a
* path-separator-delimited list). Each is a recorded subagent session log for
* a nested-agent scenario; absent/empty for a single-session scenario.
*/
childFiles?: string[]
/** Optional replay-only provider catalog; absent or empty selects catch-all waterfall replay. */
providers?: ReplayProviderConfig[]
/** Optional per-chunk pacing delay in ms (see {@link ReplayConfig.paceMs}); absent keeps burst yield. */
paceMs?: number
}
/** One provider route exposed by the replay adapter. */
export interface ReplayProviderConfig {
/** Provider route used for replay requests. */
id: string
/** Selector label; defaults to {@link id}. */
name?: string
/** Advisory models exposed to replay scenarios that exercise discovery. */
models?: ReplayModelConfig[]
/** Optional provider-owned retry policy used by assembled recovery snapshots. */
retryPolicy?: RetryPolicyConfig
}
/** One model exposed by a replay-only provider catalog. */
export interface ReplayModelConfig {
/** Model id used for replay requests. */
id: string
/** Selector label; defaults to {@link id}. */
name?: string
/** Optional selector description. */
description?: string
/** Optional positive integer context capacity published by the replay adapter. */
contextWindow?: number
/** Optional declared input modalities, so a scenario can exercise capability gates (e.g. image-capable `read_image`). */
inputModalities?: readonly ModelModality[]
/**
* Optional per-request output cap the replay route materializes when callers
* omit one, so replay reconstructs the request header a live catalog produced.
*/
defaultMaxTokens?: number
/** Optional reasoning-effort ids the replay route accepts, in display order. */
reasoningEfforts?: string[]
/**
* Optional effort materialized when callers omit one; must appear in
* {@link reasoningEfforts} or call resolution rejects the route.
*/
defaultReasoningEffort?: string
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
}
```
Depends on: [`ModelModality`](../packages/llm/llm/src/index.ts) · [`RetryPolicyConfig`](../packages/llm/llm/src/index.ts)
Source: [`packages/test-support/llm-replay/src/index.ts:847`](../packages/test-support/llm-replay/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-llm-retry"></a>
## `@deepseek-ai/dsh-llm-retry`
Requires: `agents`
```ts config-catalog
/** This policy executor has no config; providers own `retryPolicy`. */
export type Config = Readonly<Record<string, never>>
```
2026-08-09 18:56:34 +08:00
Source: [`packages/llm/llm-retry/src/index.ts:24`](../packages/llm/llm-retry/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-lsp-stdio"></a>
## `@deepseek-ai/dsh-lsp-stdio`
Requires: `fs` · `lsp` · `subprocess`
```ts config-catalog
/** Plugin configuration: provider id → local language-server configuration. */
export interface Config {
/** Non-empty table of stable provider ids to independent local server configurations. */
servers: Record<string, LspLocalServerConfig>
}
/** One configured local language server and its host bounds. */
export interface LspLocalServerConfig {
/** Executable to spawn (absolute, or resolved on PATH at load). */
command: string
/** Lowercase leading-dot extension → LSP language id (e.g. `{ '.ts': 'typescript' }`). */
extensionToLanguage: Record<string, string>
/** Arguments passed to the executable (no shell). Default `[]`. */
args?: string[]
/** Extra env vars merged on top of the scrubbed ambient env. Default `{}`. */
env?: Record<string, string>
/** Static `initialize` options forwarded to the server. Default `null`. */
initializationOptions?: unknown
/** Static answer to every `workspace/configuration` item. Default `null`. */
configuration?: unknown
/** Largest single framed message accepted from the server (bytes). Default 16000000. */
maxMessageBytes?: number
/** Largest stderr tail retained for diagnostics (bytes). Default 1000000. */
maxStderrBytes?: number
/** Largest source file this host will open (bytes). Default 4000000. */
maxDocumentBytes?: number
/** Graceful `shutdown`/`exit` budget before escalation (ms). Default 5000. */
shutdownTimeoutMs?: number
/** Request-cancel and SIGTERM→SIGKILL grace (ms). Default 2000. */
killGraceMs?: number
}
```
Source: [`packages/lsp/lsp-stdio/src/index.ts:82`](../packages/lsp/lsp-stdio/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-mcp-client"></a>
## `@deepseek-ai/dsh-mcp-client`
Requires: `tools`
```ts config-catalog
2026-07-25 13:02:37 +08:00
/** Configuration for one stdio or Streamable HTTP MCP server. */
export type Config = StdioConfig | StreamableHttpConfig
/** Config for connecting to an MCP server via a spawned child process over stdio. */
export interface StdioConfig {
2026-07-25 13:02:37 +08:00
/** Selects child-process stdio transport. */
transport: 'stdio'
/**
* Stable local namespace for this server's model-facing tool names
* (`mcp__<serverName>__<rawName>`). Must match `[A-Za-z0-9_-]{1,32}` and be
* unique across live mcp-client instances.
*/
serverName: string
2026-07-25 13:02:37 +08:00
/** Executable used to start the server. */
command: string
2026-07-25 13:02:37 +08:00
/** Arguments passed directly, without shell interpolation. */
args: string[]
/** Extra env vars merged on top of scrubbed ambient env. */
env: Record<string, string>
/** Working directory for the child process. */
cwd: string
2026-07-25 13:02:37 +08:00
/** Per-tool-call timeout in milliseconds. */
toolCallTimeoutMs: number
/** Fail plugin activation when the initial connection or tool synchronization fails. */
failOnStartupError: boolean
/** Automatic reconnect policy after a lost connection; omission uses the defaults. */
reconnect?: ReconnectConfig
}
/** Config for connecting to an MCP server over Streamable HTTP (SSE). */
export interface StreamableHttpConfig {
2026-07-25 13:02:37 +08:00
/** Selects Streamable HTTP transport. */
transport: 'streamable-http'
/**
* Stable local namespace for this server's model-facing tool names
* (`mcp__<serverName>__<rawName>`). Must match `[A-Za-z0-9_-]{1,32}` and be
* unique across live mcp-client instances.
*/
serverName: string
2026-07-25 13:02:37 +08:00
/** MCP endpoint URL. */
url: string
2026-07-25 13:02:37 +08:00
/** Additional headers attached to MCP requests. */
headers: Record<string, string>
2026-07-25 13:02:37 +08:00
/** Per-tool-call timeout in milliseconds. */
toolCallTimeoutMs: number
/** Fail plugin activation when the initial connection or tool synchronization fails. */
failOnStartupError: boolean
/** Automatic reconnect policy after a lost connection; omission uses the defaults. */
reconnect?: ReconnectConfig
}
/** Automatic reconnect policy for one MCP server connection. */
export interface ReconnectConfig {
/** Reconnect automatically after a lost connection (default true). */
enabled?: boolean
/** First reconnect delay in milliseconds; doubles per consecutive failed attempt (default 500). */
initialDelayMs?: number
/** Backoff ceiling in milliseconds; also the uptime after which the attempt budget resets (default 30000). */
maxDelayMs?: number
/** Consecutive failed attempts per outage before giving up for good (default 10). */
maxAttempts?: number
}
```
Source: [`packages/mcp/mcp-client/src/index.ts:98`](../packages/mcp/mcp-client/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-message-feedback"></a>
## `@deepseek-ai/dsh-message-feedback`
Requires: `storageDomain` · `sessionPersistence` · `sessions`
```ts config-catalog
/** Required deployment policy for optional notes. */
export interface Config {
/** Maximum UTF-8 byte length accepted for one note. */
readonly maxNoteBytes: number
}
```
Source: [`packages/feedback/message-feedback/src/index.ts:49`](../packages/feedback/message-feedback/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-permission-presets"></a>
## `@deepseek-ai/dsh-permission-presets`
feat(permission): user-facing permission presets — one Permissions select over the two knobs A preset names a bundle of the two mechanism knobs — request = workspace-write + ask, yolo = danger-full-access + never — so the editor shows ONE 'Permissions' select where the sandbox-mode and approval-policy tiers stay orthogonal capabilities (the Codex /approvals shape: presets over two dials). ctx.permission (dsh-permission) owns the config-defined table, validates the default preset's bundle against the composed knob defaults at load (fails loud), and writes a switch THROUGH: one log-only permission/preset event (the audit fact reverse-mapping cannot recover — the planned 'agent' preset shares request's knob values and differs only in composed policy) plus each knob event via its own setter, deduped — a net-zero switch appends nothing. Every knob consumer keeps reading its own fold, untouched. The current preset DERIVES from the effective knob values — the fold breaks bundle ties, a knob state outside the table is the reserved 'custom' value (a state, not an error: shown while it holds, switchable FROM, never a target), and defaultPreset disappears (zero-event state reverse-maps from the composition defaults). The ACP bridge drops the two per-knob selects for the one preset select (advertised only when ctx.permission is composed); pending/anchor/no-op semantics carry over unchanged, with the no-op echo acknowledged before vocabulary validation so a client re-pushing a derived 'custom' current never errors. The sandbox variant example composes the service with a workspace-write default; the permission-switching, escalation-approved and escalation-rejected scenarios are re-recorded under it (escalations now target an outside-workspace /tmp path under danger-full-access, self-cleaning) and config-options is re-authored on the single-select wire.
2026-07-12 21:03:41 +08:00
Requires: `shell` · `approval` · `sessions`
feat(permission): user-facing permission presets — one Permissions select over the two knobs A preset names a bundle of the two mechanism knobs — request = workspace-write + ask, yolo = danger-full-access + never — so the editor shows ONE 'Permissions' select where the sandbox-mode and approval-policy tiers stay orthogonal capabilities (the Codex /approvals shape: presets over two dials). ctx.permission (dsh-permission) owns the config-defined table, validates the default preset's bundle against the composed knob defaults at load (fails loud), and writes a switch THROUGH: one log-only permission/preset event (the audit fact reverse-mapping cannot recover — the planned 'agent' preset shares request's knob values and differs only in composed policy) plus each knob event via its own setter, deduped — a net-zero switch appends nothing. Every knob consumer keeps reading its own fold, untouched. The current preset DERIVES from the effective knob values — the fold breaks bundle ties, a knob state outside the table is the reserved 'custom' value (a state, not an error: shown while it holds, switchable FROM, never a target), and defaultPreset disappears (zero-event state reverse-maps from the composition defaults). The ACP bridge drops the two per-knob selects for the one preset select (advertised only when ctx.permission is composed); pending/anchor/no-op semantics carry over unchanged, with the no-op echo acknowledged before vocabulary validation so a client re-pushing a derived 'custom' current never errors. The sandbox variant example composes the service with a workspace-write default; the permission-switching, escalation-approved and escalation-rejected scenarios are re-recorded under it (escalations now target an outside-workspace /tmp path under danger-full-access, self-cleaning) and config-options is re-authored on the single-select wire.
2026-07-12 21:03:41 +08:00
```ts config-catalog
/** The {@link PermissionPresetService} config: preset table and composition default. */
feat(permission): user-facing permission presets — one Permissions select over the two knobs A preset names a bundle of the two mechanism knobs — request = workspace-write + ask, yolo = danger-full-access + never — so the editor shows ONE 'Permissions' select where the sandbox-mode and approval-policy tiers stay orthogonal capabilities (the Codex /approvals shape: presets over two dials). ctx.permission (dsh-permission) owns the config-defined table, validates the default preset's bundle against the composed knob defaults at load (fails loud), and writes a switch THROUGH: one log-only permission/preset event (the audit fact reverse-mapping cannot recover — the planned 'agent' preset shares request's knob values and differs only in composed policy) plus each knob event via its own setter, deduped — a net-zero switch appends nothing. Every knob consumer keeps reading its own fold, untouched. The current preset DERIVES from the effective knob values — the fold breaks bundle ties, a knob state outside the table is the reserved 'custom' value (a state, not an error: shown while it holds, switchable FROM, never a target), and defaultPreset disappears (zero-event state reverse-maps from the composition defaults). The ACP bridge drops the two per-knob selects for the one preset select (advertised only when ctx.permission is composed); pending/anchor/no-op semantics carry over unchanged, with the no-op echo acknowledged before vocabulary validation so a client re-pushing a derived 'custom' current never errors. The sandbox variant example composes the service with a workspace-write default; the permission-switching, escalation-approved and escalation-rejected scenarios are re-recorded under it (escalations now target an outside-workspace /tmp path under danger-full-access, self-cleaning) and config-options is re-authored on the single-select wire.
2026-07-12 21:03:41 +08:00
export interface Config {
/**
* The preset table: name → knob bundle. Defaults to `workspace-write`
* (workspace-write + ask) and `danger-full-access` (danger-full-access +
* never). The name `custom` is reserved for the derived not-a-preset state.
feat(permission): user-facing permission presets — one Permissions select over the two knobs A preset names a bundle of the two mechanism knobs — request = workspace-write + ask, yolo = danger-full-access + never — so the editor shows ONE 'Permissions' select where the sandbox-mode and approval-policy tiers stay orthogonal capabilities (the Codex /approvals shape: presets over two dials). ctx.permission (dsh-permission) owns the config-defined table, validates the default preset's bundle against the composed knob defaults at load (fails loud), and writes a switch THROUGH: one log-only permission/preset event (the audit fact reverse-mapping cannot recover — the planned 'agent' preset shares request's knob values and differs only in composed policy) plus each knob event via its own setter, deduped — a net-zero switch appends nothing. Every knob consumer keeps reading its own fold, untouched. The current preset DERIVES from the effective knob values — the fold breaks bundle ties, a knob state outside the table is the reserved 'custom' value (a state, not an error: shown while it holds, switchable FROM, never a target), and defaultPreset disappears (zero-event state reverse-maps from the composition defaults). The ACP bridge drops the two per-knob selects for the one preset select (advertised only when ctx.permission is composed); pending/anchor/no-op semantics carry over unchanged, with the no-op echo acknowledged before vocabulary validation so a client re-pushing a derived 'custom' current never errors. The sandbox variant example composes the service with a workspace-write default; the permission-switching, escalation-approved and escalation-rejected scenarios are re-recorded under it (escalations now target an outside-workspace /tmp path under danger-full-access, self-cleaning) and config-options is re-authored on the single-select wire.
2026-07-12 21:03:41 +08:00
*/
presets?: Record<string, PresetSpec>
/**
* Default for new sessions. When omitted, the preset matching the composed
* sandbox and approval defaults is used.
*/
defaultPreset?: string
feat(permission): user-facing permission presets — one Permissions select over the two knobs A preset names a bundle of the two mechanism knobs — request = workspace-write + ask, yolo = danger-full-access + never — so the editor shows ONE 'Permissions' select where the sandbox-mode and approval-policy tiers stay orthogonal capabilities (the Codex /approvals shape: presets over two dials). ctx.permission (dsh-permission) owns the config-defined table, validates the default preset's bundle against the composed knob defaults at load (fails loud), and writes a switch THROUGH: one log-only permission/preset event (the audit fact reverse-mapping cannot recover — the planned 'agent' preset shares request's knob values and differs only in composed policy) plus each knob event via its own setter, deduped — a net-zero switch appends nothing. Every knob consumer keeps reading its own fold, untouched. The current preset DERIVES from the effective knob values — the fold breaks bundle ties, a knob state outside the table is the reserved 'custom' value (a state, not an error: shown while it holds, switchable FROM, never a target), and defaultPreset disappears (zero-event state reverse-maps from the composition defaults). The ACP bridge drops the two per-knob selects for the one preset select (advertised only when ctx.permission is composed); pending/anchor/no-op semantics carry over unchanged, with the no-op echo acknowledged before vocabulary validation so a client re-pushing a derived 'custom' current never errors. The sandbox variant example composes the service with a workspace-write default; the permission-switching, escalation-approved and escalation-rejected scenarios are re-recorded under it (escalations now target an outside-workspace /tmp path under danger-full-access, self-cleaning) and config-options is re-authored on the single-select wire.
2026-07-12 21:03:41 +08:00
}
/** One preset's sandbox/approval bundle and optional client presentation. */
feat(permission): user-facing permission presets — one Permissions select over the two knobs A preset names a bundle of the two mechanism knobs — request = workspace-write + ask, yolo = danger-full-access + never — so the editor shows ONE 'Permissions' select where the sandbox-mode and approval-policy tiers stay orthogonal capabilities (the Codex /approvals shape: presets over two dials). ctx.permission (dsh-permission) owns the config-defined table, validates the default preset's bundle against the composed knob defaults at load (fails loud), and writes a switch THROUGH: one log-only permission/preset event (the audit fact reverse-mapping cannot recover — the planned 'agent' preset shares request's knob values and differs only in composed policy) plus each knob event via its own setter, deduped — a net-zero switch appends nothing. Every knob consumer keeps reading its own fold, untouched. The current preset DERIVES from the effective knob values — the fold breaks bundle ties, a knob state outside the table is the reserved 'custom' value (a state, not an error: shown while it holds, switchable FROM, never a target), and defaultPreset disappears (zero-event state reverse-maps from the composition defaults). The ACP bridge drops the two per-knob selects for the one preset select (advertised only when ctx.permission is composed); pending/anchor/no-op semantics carry over unchanged, with the no-op echo acknowledged before vocabulary validation so a client re-pushing a derived 'custom' current never errors. The sandbox variant example composes the service with a workspace-write default; the permission-switching, escalation-approved and escalation-rejected scenarios are re-recorded under it (escalations now target an outside-workspace /tmp path under danger-full-access, self-cleaning) and config-options is re-authored on the single-select wire.
2026-07-12 21:03:41 +08:00
export interface PresetSpec {
feat(sandbox): cross-family file sandbox — one policy home, sandboxed fs provider, fs escalation parity Extend SandboxMode enforcement from bash to the filesystem tools, the sandbox RFC's deferred cross-family phase. - dsh-sandbox-policy (new, ctx.sandboxPolicy): the single home for the deployment default mode + workspaceRoot and the per-session override event, renamed bash/sandbox-mode -> sandbox/mode and moved here with its fold/setter. Decouples the bash seam from dsh-session. - dsh-fs-sandbox (new): SandboxedFileSystem extends LocalFileSystem and fences write/edit by the per-call mode (read-only denies, workspace-write contains to the workspace + temp roots via the shared writableRoots, danger passes through); reads pass through. Structured FS_SANDBOX_DENIED; in-lock parent re-canonicalization. A policy fence in trusted code, not a kernel boundary. - dsh-sandbox: the shared escalation kit (writableRoots, the strictly-wider ladder, denial/hint markers, approveEscalation) both tool families use; approveEscalation takes a structural approver so dsh-sandbox gains no approval/agent dependency, and both tools stay duplication-free. - tool-fs: write/edit advertise sandbox_permissions/justification under a confining ctx.fs, map FS_SANDBOX_DENIED to the shared [sandbox: ...] marker, and resolve the same one-approved-wider retry. - examples/acp-agent: composes sandbox-policy + fs-sandbox, drops the gating that disabled the fs stack under confined modes. RFC docs/rfc/implemented/feature/2026-07-14-cross-family-fs-sandbox.md; the old sandbox RFC's In-process/deferred/FAQ sections updated to shipped fact.
2026-07-14 20:05:57 +08:00
/** The `sandbox/mode` value the preset writes through. */
feat(permission): user-facing permission presets — one Permissions select over the two knobs A preset names a bundle of the two mechanism knobs — request = workspace-write + ask, yolo = danger-full-access + never — so the editor shows ONE 'Permissions' select where the sandbox-mode and approval-policy tiers stay orthogonal capabilities (the Codex /approvals shape: presets over two dials). ctx.permission (dsh-permission) owns the config-defined table, validates the default preset's bundle against the composed knob defaults at load (fails loud), and writes a switch THROUGH: one log-only permission/preset event (the audit fact reverse-mapping cannot recover — the planned 'agent' preset shares request's knob values and differs only in composed policy) plus each knob event via its own setter, deduped — a net-zero switch appends nothing. Every knob consumer keeps reading its own fold, untouched. The current preset DERIVES from the effective knob values — the fold breaks bundle ties, a knob state outside the table is the reserved 'custom' value (a state, not an error: shown while it holds, switchable FROM, never a target), and defaultPreset disappears (zero-event state reverse-maps from the composition defaults). The ACP bridge drops the two per-knob selects for the one preset select (advertised only when ctx.permission is composed); pending/anchor/no-op semantics carry over unchanged, with the no-op echo acknowledged before vocabulary validation so a client re-pushing a derived 'custom' current never errors. The sandbox variant example composes the service with a workspace-write default; the permission-switching, escalation-approved and escalation-rejected scenarios are re-recorded under it (escalations now target an outside-workspace /tmp path under danger-full-access, self-cleaning) and config-options is re-authored on the single-select wire.
2026-07-12 21:03:41 +08:00
sandbox: SandboxMode
/** The `approval/policy` value the preset writes through. */
approval: ApprovalPolicy
/** The display label a client shows for this preset; the raw table key when omitted. */
name?: string
/** One user-facing sentence on what the preset means; omitted when not configured. */
description?: string
}
```
Depends on: [`ApprovalPolicy`](subsystems/approval.md) · [`SandboxMode`](subsystems/sandbox.md)
feat(permission): user-facing permission presets — one Permissions select over the two knobs A preset names a bundle of the two mechanism knobs — request = workspace-write + ask, yolo = danger-full-access + never — so the editor shows ONE 'Permissions' select where the sandbox-mode and approval-policy tiers stay orthogonal capabilities (the Codex /approvals shape: presets over two dials). ctx.permission (dsh-permission) owns the config-defined table, validates the default preset's bundle against the composed knob defaults at load (fails loud), and writes a switch THROUGH: one log-only permission/preset event (the audit fact reverse-mapping cannot recover — the planned 'agent' preset shares request's knob values and differs only in composed policy) plus each knob event via its own setter, deduped — a net-zero switch appends nothing. Every knob consumer keeps reading its own fold, untouched. The current preset DERIVES from the effective knob values — the fold breaks bundle ties, a knob state outside the table is the reserved 'custom' value (a state, not an error: shown while it holds, switchable FROM, never a target), and defaultPreset disappears (zero-event state reverse-maps from the composition defaults). The ACP bridge drops the two per-knob selects for the one preset select (advertised only when ctx.permission is composed); pending/anchor/no-op semantics carry over unchanged, with the no-op echo acknowledged before vocabulary validation so a client re-pushing a derived 'custom' current never errors. The sandbox variant example composes the service with a workspace-write default; the permission-switching, escalation-approved and escalation-rejected scenarios are re-recorded under it (escalations now target an outside-workspace /tmp path under danger-full-access, self-cleaning) and config-options is re-authored on the single-select wire.
2026-07-12 21:03:41 +08:00
Source: [`packages/interaction/permission-presets/src/index.ts:156`](../packages/interaction/permission-presets/src/index.ts)
feat(permission): user-facing permission presets — one Permissions select over the two knobs A preset names a bundle of the two mechanism knobs — request = workspace-write + ask, yolo = danger-full-access + never — so the editor shows ONE 'Permissions' select where the sandbox-mode and approval-policy tiers stay orthogonal capabilities (the Codex /approvals shape: presets over two dials). ctx.permission (dsh-permission) owns the config-defined table, validates the default preset's bundle against the composed knob defaults at load (fails loud), and writes a switch THROUGH: one log-only permission/preset event (the audit fact reverse-mapping cannot recover — the planned 'agent' preset shares request's knob values and differs only in composed policy) plus each knob event via its own setter, deduped — a net-zero switch appends nothing. Every knob consumer keeps reading its own fold, untouched. The current preset DERIVES from the effective knob values — the fold breaks bundle ties, a knob state outside the table is the reserved 'custom' value (a state, not an error: shown while it holds, switchable FROM, never a target), and defaultPreset disappears (zero-event state reverse-maps from the composition defaults). The ACP bridge drops the two per-knob selects for the one preset select (advertised only when ctx.permission is composed); pending/anchor/no-op semantics carry over unchanged, with the no-op echo acknowledged before vocabulary validation so a client re-pushing a derived 'custom' current never errors. The sandbox variant example composes the service with a workspace-write default; the permission-switching, escalation-approved and escalation-rejected scenarios are re-recorded under it (escalations now target an outside-workspace /tmp path under danger-full-access, self-cleaning) and config-options is re-authored on the single-select wire.
2026-07-12 21:03:41 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-persona"></a>
## `@deepseek-ai/dsh-persona`
Requires: `systemPrompt`
```ts config-catalog
/** Plugin config: the persona text this composition contributes. */
export interface Config {
/**
* Persona prose rendered as the `deployment:persona` section. A template:
* complete `{{…}}` groups interpolate strictly against registered prompt
* variables. Empty text drops the section at render, matching the registry.
*/
text: string
/** Make this persona the complete system prompt, suppressing every other section. */
complete?: boolean
/** Suppress dynamic runtime-context snapshots for this persona's agent scope. */
includeRuntimeContext?: boolean
}
```
fix(web): correct the preset-layer contracts review found stale None of these change behavior; each said something that was not true. `SessionCwdConflict`'s doc block had been left stranded above the `AgentPresetConflict` inserted under it, so one class carried a comment about the other and the second carried none. The roster comment named a `.system` directory that does not exist; the shipped root is `config/agent-presets/`, and `system` is the trust its entries carry. The real-composition test attributed the disabled `api-gateway` row to "side effects outside this process" alongside the port and the exporter. It is disabled for a different reason — the api-proxy cannot mount in this layer at all — and hiding that behind the same phrase would leave a later layer unable to tell whether the line can come out. One test claimed to refuse an adoption while asserting only that the header records the preset; it now says what it checks. `PERSONA_SECTION`/`PERSONA_ORDER` existed twice, once in the registry that declares the slot and once restated in the row that replaces it — a drift that would land a preset's persona beside the deployment's instead of shadowing it. The registry exports them now. The preset conflict message read "already runs agent preset undefined" for a session that records none, which is the shape a deployment with no roster produces; it names that case instead, with the regression that reaches it through the gateway. Finally, `PresetTree.write()` drops the `loader/config-update` the inherited method emits — recorded on the override, since a future edit-while-running flow needs its own persistence path.
2026-08-06 13:43:32 +08:00
Source: [`packages/preset/persona/src/index.ts:34`](../packages/preset/persona/src/index.ts)
feat(permission): user-facing permission presets — one Permissions select over the two knobs A preset names a bundle of the two mechanism knobs — request = workspace-write + ask, yolo = danger-full-access + never — so the editor shows ONE 'Permissions' select where the sandbox-mode and approval-policy tiers stay orthogonal capabilities (the Codex /approvals shape: presets over two dials). ctx.permission (dsh-permission) owns the config-defined table, validates the default preset's bundle against the composed knob defaults at load (fails loud), and writes a switch THROUGH: one log-only permission/preset event (the audit fact reverse-mapping cannot recover — the planned 'agent' preset shares request's knob values and differs only in composed policy) plus each knob event via its own setter, deduped — a net-zero switch appends nothing. Every knob consumer keeps reading its own fold, untouched. The current preset DERIVES from the effective knob values — the fold breaks bundle ties, a knob state outside the table is the reserved 'custom' value (a state, not an error: shown while it holds, switchable FROM, never a target), and defaultPreset disappears (zero-event state reverse-maps from the composition defaults). The ACP bridge drops the two per-knob selects for the one preset select (advertised only when ctx.permission is composed); pending/anchor/no-op semantics carry over unchanged, with the no-op echo acknowledged before vocabulary validation so a client re-pushing a derived 'custom' current never errors. The sandbox variant example composes the service with a workspace-write default; the permission-switching, escalation-approved and escalation-rejected scenarios are re-recorded under it (escalations now target an outside-workspace /tmp path under danger-full-access, self-cleaning) and config-options is re-authored on the single-select wire.
2026-07-12 21:03:41 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-plan-mode"></a>
## `@deepseek-ai/dsh-plan-mode`
Requires: `tools` · `systemPrompt`
```ts config-catalog
/** Deployment-owned plan guidance. */
export interface PlanModeConfig {
/** Guidance rendered as the `plan:policy` prompt section while plan mode is active. */
section: string
}
```
Source: [`packages/plan/plan-mode/src/index.ts:70`](../packages/plan/plan-mode/src/index.ts)
<a id="deepseek-aidsh-plugin-package-inventory-deepseek"></a>
## `@deepseek-ai/dsh-plugin-package-inventory-deepseek`
Requires: `agents` · `deepseekLlmApiExtensions` · `loader`
```ts config-catalog
/** Plugin-package request contribution configuration. */
export interface Config {
/** Contribute `dsh_plugin_packages` to official DeepSeek requests. Defaults to `true`. */
enabled?: boolean
}
```
Source: [`packages/llm/plugin-package-inventory-deepseek/src/index.ts:30`](../packages/llm/plugin-package-inventory-deepseek/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-pwsh-local"></a>
## `@deepseek-ai/dsh-pwsh-local`
Requires: `subprocess`
```ts config-catalog
/** Plugin config (all optional — `static Config` supplies the defaults). */
export interface Config {
/** Default working directory for commands (default: process.cwd()). */
cwd?: string
/** Default foreground timeout in milliseconds. */
timeoutMs?: number
/** Upper bound for per-call timeout overrides. */
maxTimeoutMs?: number
/** Per-stream in-memory output cap; overflow spills to a temp file. */
maxOutputBytes?: number
/** Per-stream spill-file cap; larger streams retain only their in-memory tail. */
maxSpillBytes?: number
/** Grace period for kill escalation and inherited pipes; at most `MAX_TIMER_DELAY_MS`. */
graceMs?: number
/**
* Explicit pwsh executable. When omitted, well-known Windows install
* locations and PATH entries are probed in order (PowerShell 7 install,
* PATH entries such as the Microsoft Store install, then Windows
* PowerShell 5.1), falling back to a bare `pwsh` resolved through PATH.
*/
pwshPath?: string
}
```
Source: [`packages/shell/pwsh-local/src/index.ts:58`](../packages/shell/pwsh-local/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-pwsh-sandbox"></a>
## `@deepseek-ai/dsh-pwsh-sandbox`
Requires: `subprocess` · `sandbox` · `sandboxPolicy`
```ts config-catalog
/**
* Plugin config: the local executor's knobs, verbatim. The sandbox policy —
* the default mode and fallback `workspace-write` root — is NOT here: it lives
* on `ctx.sandboxPolicy` (`@deepseek-ai/dsh-sandbox-policy`), which resolves
* each calling session's mode and cwd for every enforcing capability. The
* runner choice is likewise the `ctx.sandbox` provider's config, not this
* executor's.
*/
export type Config = LocalConfig
```
Depends on: [`LocalConfig`](#deepseek-aidsh-pwsh-local)
Source: [`packages/shell/pwsh-sandbox/src/index.ts:40`](../packages/shell/pwsh-sandbox/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-repeat-tool-reminder"></a>
## `@deepseek-ai/dsh-repeat-tool-reminder`
```ts config-catalog
/**
* Plugin config, validated by the same-named schemastery schema plus the
* load-time checks in `apply` (misconfiguration fails loud: an empty
* `thresholds` list, a non-integer, a value below 2, or a duplicate throws at
* plugin load, never a silent fall-back). `include`/`exclude` entries are
* `*`-wildcard predicates over tool names at call time, not references to
* registry entries — a pattern matching no currently registered tool is valid
* (`exclude: [mcp_*]` must stay legal in a deployment that loads no MCP tools).
*/
export interface Config {
/** Consecutive-repeat counts that trigger a reminder (default `[3, 5, 8]`). */
thresholds?: number[]
/** Tool-name patterns to track; empty means every tool is tracked. */
include?: string[]
/** Tool-name patterns transparent to the chain (neither count nor reset). */
exclude?: string[]
/**
* Maximum characters of canonical arguments quoted in the DETAILED reminder
* (default 500). Large payloads (a `write` body, a long command) would
* otherwise ride into the next request unbounded — precisely in a loop
* scenario; the cap bounds the reminder, never the detection (the chain key
* always compares the FULL canonical string).
*/
argumentsPreviewChars?: number
}
```
Source: [`packages/guard/repeat-tool-reminder/src/index.ts:28`](../packages/guard/repeat-tool-reminder/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-sandbox-local"></a>
## `@deepseek-ai/dsh-sandbox-local`
```ts config-catalog
/** Plugin config. All optional — `static Config` supplies the defaults. */
export interface Config {
/**
2026-08-09 15:27:21 +08:00
* Override the runner argv; bwrap-compatible profile arguments are appended. A
* non-empty override asserts full enforcement and skips built-in selection and
* probing. A runner that starts but refuses its profile must be identifiable by
2026-08-09 16:31:15 +08:00
* {@link runnerFailureSignatures}. Consumers classify a spawn rejection only after
* confirming the workdir is usable. `ENOENT` or `EACCES` identifies the runner when
* `error.path` equals argv[0] and `error.syscall` is `spawn` or `spawn <runner>`, or
* when `error.path` is absent and `error.syscall` is exactly `spawn <runner>`.
*/
runnerCommand?: string[]
/**
* Case-insensitive stderr substrings emitted when a configured
* {@link runnerCommand} refuses its profile before executing the wrapped
* command. Required and non-empty with `runnerCommand`; rejected without
* it. Each entry is a non-empty, single-line, case-insensitive substring
* covering the executable runner's own failure dialect.
*/
runnerFailureSignatures?: string[]
/** Positive timeout for each functional probe; zero would mean unbounded to Node. */
probeTimeoutMs?: number
}
```
2026-08-10 15:41:30 +08:00
Source: [`packages/sandbox/sandbox-local/src/index.ts:44`](../packages/sandbox/sandbox-local/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-sandbox-policy"></a>
feat(sandbox): cross-family file sandbox — one policy home, sandboxed fs provider, fs escalation parity Extend SandboxMode enforcement from bash to the filesystem tools, the sandbox RFC's deferred cross-family phase. - dsh-sandbox-policy (new, ctx.sandboxPolicy): the single home for the deployment default mode + workspaceRoot and the per-session override event, renamed bash/sandbox-mode -> sandbox/mode and moved here with its fold/setter. Decouples the bash seam from dsh-session. - dsh-fs-sandbox (new): SandboxedFileSystem extends LocalFileSystem and fences write/edit by the per-call mode (read-only denies, workspace-write contains to the workspace + temp roots via the shared writableRoots, danger passes through); reads pass through. Structured FS_SANDBOX_DENIED; in-lock parent re-canonicalization. A policy fence in trusted code, not a kernel boundary. - dsh-sandbox: the shared escalation kit (writableRoots, the strictly-wider ladder, denial/hint markers, approveEscalation) both tool families use; approveEscalation takes a structural approver so dsh-sandbox gains no approval/agent dependency, and both tools stay duplication-free. - tool-fs: write/edit advertise sandbox_permissions/justification under a confining ctx.fs, map FS_SANDBOX_DENIED to the shared [sandbox: ...] marker, and resolve the same one-approved-wider retry. - examples/acp-agent: composes sandbox-policy + fs-sandbox, drops the gating that disabled the fs stack under confined modes. RFC docs/rfc/implemented/feature/2026-07-14-cross-family-fs-sandbox.md; the old sandbox RFC's In-process/deferred/FAQ sections updated to shipped fact.
2026-07-14 20:05:57 +08:00
## `@deepseek-ai/dsh-sandbox-policy`
```ts config-catalog
/**
* Plugin config: the deployment's sandbox default. All optional — `Config`
* supplies the defaults (`mode: 'read-only'` is the fail-safe default; a
* deployment that wants a workspace-writable agent opts in explicitly). The
* runner choice is NOT here (it is the `ctx.sandbox` provider's config), nor
* is any per-family knob: this is the one shared policy home.
*/
export interface Config {
/** File-sandbox mode a session starts from (default: `read-only`). */
mode?: SandboxMode
/**
* Fallback root for agentless calls and sessions without a cwd (default:
* `process.cwd()`). Normal agent calls use their session cwd instead.
feat(sandbox): cross-family file sandbox — one policy home, sandboxed fs provider, fs escalation parity Extend SandboxMode enforcement from bash to the filesystem tools, the sandbox RFC's deferred cross-family phase. - dsh-sandbox-policy (new, ctx.sandboxPolicy): the single home for the deployment default mode + workspaceRoot and the per-session override event, renamed bash/sandbox-mode -> sandbox/mode and moved here with its fold/setter. Decouples the bash seam from dsh-session. - dsh-fs-sandbox (new): SandboxedFileSystem extends LocalFileSystem and fences write/edit by the per-call mode (read-only denies, workspace-write contains to the workspace + temp roots via the shared writableRoots, danger passes through); reads pass through. Structured FS_SANDBOX_DENIED; in-lock parent re-canonicalization. A policy fence in trusted code, not a kernel boundary. - dsh-sandbox: the shared escalation kit (writableRoots, the strictly-wider ladder, denial/hint markers, approveEscalation) both tool families use; approveEscalation takes a structural approver so dsh-sandbox gains no approval/agent dependency, and both tools stay duplication-free. - tool-fs: write/edit advertise sandbox_permissions/justification under a confining ctx.fs, map FS_SANDBOX_DENIED to the shared [sandbox: ...] marker, and resolve the same one-approved-wider retry. - examples/acp-agent: composes sandbox-policy + fs-sandbox, drops the gating that disabled the fs stack under confined modes. RFC docs/rfc/implemented/feature/2026-07-14-cross-family-fs-sandbox.md; the old sandbox RFC's In-process/deferred/FAQ sections updated to shipped fact.
2026-07-14 20:05:57 +08:00
*/
workspaceRoot?: string
}
```
Depends on: [`SandboxMode`](subsystems/sandbox.md)
feat(sandbox): cross-family file sandbox — one policy home, sandboxed fs provider, fs escalation parity Extend SandboxMode enforcement from bash to the filesystem tools, the sandbox RFC's deferred cross-family phase. - dsh-sandbox-policy (new, ctx.sandboxPolicy): the single home for the deployment default mode + workspaceRoot and the per-session override event, renamed bash/sandbox-mode -> sandbox/mode and moved here with its fold/setter. Decouples the bash seam from dsh-session. - dsh-fs-sandbox (new): SandboxedFileSystem extends LocalFileSystem and fences write/edit by the per-call mode (read-only denies, workspace-write contains to the workspace + temp roots via the shared writableRoots, danger passes through); reads pass through. Structured FS_SANDBOX_DENIED; in-lock parent re-canonicalization. A policy fence in trusted code, not a kernel boundary. - dsh-sandbox: the shared escalation kit (writableRoots, the strictly-wider ladder, denial/hint markers, approveEscalation) both tool families use; approveEscalation takes a structural approver so dsh-sandbox gains no approval/agent dependency, and both tools stay duplication-free. - tool-fs: write/edit advertise sandbox_permissions/justification under a confining ctx.fs, map FS_SANDBOX_DENIED to the shared [sandbox: ...] marker, and resolve the same one-approved-wider retry. - examples/acp-agent: composes sandbox-policy + fs-sandbox, drops the gating that disabled the fs stack under confined modes. RFC docs/rfc/implemented/feature/2026-07-14-cross-family-fs-sandbox.md; the old sandbox RFC's In-process/deferred/FAQ sections updated to shipped fact.
2026-07-14 20:05:57 +08:00
Source: [`packages/sandbox/sandbox-policy/src/index.ts:67`](../packages/sandbox/sandbox-policy/src/index.ts)
feat(sandbox): cross-family file sandbox — one policy home, sandboxed fs provider, fs escalation parity Extend SandboxMode enforcement from bash to the filesystem tools, the sandbox RFC's deferred cross-family phase. - dsh-sandbox-policy (new, ctx.sandboxPolicy): the single home for the deployment default mode + workspaceRoot and the per-session override event, renamed bash/sandbox-mode -> sandbox/mode and moved here with its fold/setter. Decouples the bash seam from dsh-session. - dsh-fs-sandbox (new): SandboxedFileSystem extends LocalFileSystem and fences write/edit by the per-call mode (read-only denies, workspace-write contains to the workspace + temp roots via the shared writableRoots, danger passes through); reads pass through. Structured FS_SANDBOX_DENIED; in-lock parent re-canonicalization. A policy fence in trusted code, not a kernel boundary. - dsh-sandbox: the shared escalation kit (writableRoots, the strictly-wider ladder, denial/hint markers, approveEscalation) both tool families use; approveEscalation takes a structural approver so dsh-sandbox gains no approval/agent dependency, and both tools stay duplication-free. - tool-fs: write/edit advertise sandbox_permissions/justification under a confining ctx.fs, map FS_SANDBOX_DENIED to the shared [sandbox: ...] marker, and resolve the same one-approved-wider retry. - examples/acp-agent: composes sandbox-policy + fs-sandbox, drops the gating that disabled the fs stack under confined modes. RFC docs/rfc/implemented/feature/2026-07-14-cross-family-fs-sandbox.md; the old sandbox RFC's In-process/deferred/FAQ sections updated to shipped fact.
2026-07-14 20:05:57 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-sdk-jsonrpc-server"></a>
## `@deepseek-ai/dsh-sdk-jsonrpc-server`
Requires: `agents`
```ts config-catalog
/** JSON-RPC deployment config plus runtime-only test hooks. */
export interface JsonRpcConfig {
/** Report max-token turn/subagent termination as a successful SDK result. */
maxTokensAsSuccess?: boolean
/** Transport input override; production uses `process.stdin`. */
input?: Readable
/** Transport output override; production uses `process.stdout`. */
output?: Writable
/** Process-exit override; production uses `process.exit`. */
exit?: (code: number) => void
}
```
Depends on: `Readable` (`node:stream`) · `Writable` (`node:stream`)
Source: [`packages/sdk/server/src/index.ts:25`](../packages/sdk/server/src/index.ts)
<a id="deepseek-aidsh-session-log-deepseek"></a>
## `@deepseek-ai/dsh-session-log-deepseek`
Requires: `deepseekLlmApiExtensions` · `sessions`
```ts config-catalog
/** Session-log request contribution configuration. */
export interface Config {
/** Contribute `dsh_session_log` to official DeepSeek requests. Defaults to `false`. */
enabled?: boolean
}
```
Source: [`packages/session/session-log-deepseek/src/index.ts:22`](../packages/session/session-log-deepseek/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-session-persistence-jsonl"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-session-persistence-jsonl`
Requires: `sessions`
```ts config-catalog
feat(session): opt-in packed chunk rows in the JSONL log Providers stream token-sized deltas, so a session log stores hundreds of near-identical assistant/chunk lines whose JSON envelopes dwarf their payloads (~56x measured on a real DeepSeek session, 73% of file bytes). Add a lossless storage codec to dsh-session: packChunkRuns() folds each run of >=3 consecutive same-block delta chunks into one storage row -- text-chunks / reasoning-chunks / tool-call-chunks, bare slash-less tags like the header line's 'session' so rows cannot be confused with session events -- and decodeStorageRecord() expands rows back to the exact original events (seq0/time0 + dt gap array reconstruct every member's seq/time; tool-call rows carry the run-constant id/name). The encoder whitelists exact shapes and stores anything unrecognized verbatim; the decoder validates row-tagged values and fails loud on malformation. The JSONL backend gains a packChunks config (default false). Writing packs only when enabled -- default-off output stays byte-identical to the previous layout, so snapshot goldens are untouched. Reading is layout-blind: scanLog always decodes rows and now checks seq contiguity with a cursor instead of the line index, so packed, unpacked, and mixed files all load identically. Fixture readers (llm-replay parseSessionLog, acp-snapshot normalizeSessionLog) share the codec; the normalizer zeroes a row's time0/dt exactly like an event's time. The two demo bundles plumb packChunks from cordis.yml to the backend. Measured on a real coding session: 105 KB -> 42 KB (-60%), 475 lines -> 74, with reasoning/tool-call heavy sessions saving the most. Covered by example + fast-check round-trip codec tests, backend packed/mixed/torn- tail specs, and an end-to-end demo run loading a packed log through a default-config backend.
2026-07-15 21:26:36 +08:00
/** Plugin config: where the JSONL backend keeps its session logs, and the packed-row write switch. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
export interface Config {
/**
* Root directory for all session files. Required (no default): a default of
* `process.cwd()` would scatter session files as the process's cwd changes
* (bash calls, subprocesses). Sessions group under human-readable project
* directories, then per-session directories. An existing root must be a
* readable directory; an absent root is created on first materialization.
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
*/
root: string
feat(session): opt-in packed chunk rows in the JSONL log Providers stream token-sized deltas, so a session log stores hundreds of near-identical assistant/chunk lines whose JSON envelopes dwarf their payloads (~56x measured on a real DeepSeek session, 73% of file bytes). Add a lossless storage codec to dsh-session: packChunkRuns() folds each run of >=3 consecutive same-block delta chunks into one storage row -- text-chunks / reasoning-chunks / tool-call-chunks, bare slash-less tags like the header line's 'session' so rows cannot be confused with session events -- and decodeStorageRecord() expands rows back to the exact original events (seq0/time0 + dt gap array reconstruct every member's seq/time; tool-call rows carry the run-constant id/name). The encoder whitelists exact shapes and stores anything unrecognized verbatim; the decoder validates row-tagged values and fails loud on malformation. The JSONL backend gains a packChunks config (default false). Writing packs only when enabled -- default-off output stays byte-identical to the previous layout, so snapshot goldens are untouched. Reading is layout-blind: scanLog always decodes rows and now checks seq contiguity with a cursor instead of the line index, so packed, unpacked, and mixed files all load identically. Fixture readers (llm-replay parseSessionLog, acp-snapshot normalizeSessionLog) share the codec; the normalizer zeroes a row's time0/dt exactly like an event's time. The two demo bundles plumb packChunks from cordis.yml to the backend. Measured on a real coding session: 105 KB -> 42 KB (-60%), 475 lines -> 74, with reasoning/tool-call heavy sessions saving the most. Covered by example + fast-check round-trip codec tests, backend packed/mixed/torn- tail specs, and an end-to-end demo run loading a packed log through a default-config backend.
2026-07-15 21:26:36 +08:00
/**
* Write runs of consecutive `assistant/chunk` delta events as packed
* `text-chunks`/`reasoning-chunks`/`tool-call-chunks` rows (lossless,
* ~60% smaller logs measured on a real session). Defaults to true; false
* keeps one `SessionEvent` per line for diagnostics. Reading packed rows is
* unconditional: a log's layout never depends on this switch.
feat(session): opt-in packed chunk rows in the JSONL log Providers stream token-sized deltas, so a session log stores hundreds of near-identical assistant/chunk lines whose JSON envelopes dwarf their payloads (~56x measured on a real DeepSeek session, 73% of file bytes). Add a lossless storage codec to dsh-session: packChunkRuns() folds each run of >=3 consecutive same-block delta chunks into one storage row -- text-chunks / reasoning-chunks / tool-call-chunks, bare slash-less tags like the header line's 'session' so rows cannot be confused with session events -- and decodeStorageRecord() expands rows back to the exact original events (seq0/time0 + dt gap array reconstruct every member's seq/time; tool-call rows carry the run-constant id/name). The encoder whitelists exact shapes and stores anything unrecognized verbatim; the decoder validates row-tagged values and fails loud on malformation. The JSONL backend gains a packChunks config (default false). Writing packs only when enabled -- default-off output stays byte-identical to the previous layout, so snapshot goldens are untouched. Reading is layout-blind: scanLog always decodes rows and now checks seq contiguity with a cursor instead of the line index, so packed, unpacked, and mixed files all load identically. Fixture readers (llm-replay parseSessionLog, acp-snapshot normalizeSessionLog) share the codec; the normalizer zeroes a row's time0/dt exactly like an event's time. The two demo bundles plumb packChunks from cordis.yml to the backend. Measured on a real coding session: 105 KB -> 42 KB (-60%), 475 lines -> 74, with reasoning/tool-call heavy sessions saving the most. Covered by example + fast-check round-trip codec tests, backend packed/mixed/torn- tail specs, and an end-to-end demo run loading a packed log through a default-config backend.
2026-07-15 21:26:36 +08:00
*/
packChunks?: boolean
/** Physical encoding; defaults to checksummed Zstandard frames. */
compression?: JsonlCompression
/** Maximum cold Session preparations retained for history-to-resume reuse. */
preparedSessionCacheSize?: number
/** Fixed live-event coalescing window; not a backend completion deadline. */
writeBatchMaxDelayMs?: number
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
}
/** Physical encoding selected for JSONL session artifacts. */
export type JsonlCompression = 'zstd' | 'none'
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
```
Source: [`packages/session/session-persistence-jsonl/src/index.ts:60`](../packages/session/session-persistence-jsonl/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-session-persistence-sqlite"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-session-persistence-sqlite`
Requires: `sessions`
```ts config-catalog
/** Plugin configuration. */
export interface Config {
/** SQLite database path, or `:memory:` for an in-process database. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
path: string
/** Durable SQLite journal mode; defaults to `wal`. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
journalMode?: JournalMode
/** Maximum wait for another SQLite connection's lock; defaults to 5,000 ms. */
busyTimeoutMs?: number
/** Maximum cold Session preparations retained for history-to-resume reuse. */
preparedSessionCacheSize?: number
/** Fixed live-event coalescing window; not a backend completion deadline. */
writeBatchMaxDelayMs?: number
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
}
/** Durable journal modes accepted by the backend. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
export type JournalMode = 'wal' | 'delete' | 'truncate' | 'persist'
```
Source: [`packages/session/session-persistence-sqlite/src/index.ts:37`](../packages/session/session-persistence-sqlite/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-session-projection-cache"></a>
## `@deepseek-ai/dsh-session-projection-cache`
Requires: `storageDomain` · `sessionProjections` · `sessionPersistence` · `sessions`
```ts config-catalog
/**
* Plugin config. Both throttle triggers are deployment choices with no
* universally correct value, so the composition states them explicitly
* (cordis.yml); the two mandatory write points (`turn/end` and session
* disposal) are policy, not tunables, and always fire.
*/
export interface Config {
/** Committed events per session that force a durable checkpoint write between mandatory points. */
writeEveryEvents: number
/** Longest time (milliseconds) a dirty checkpoint may stay unwritten between mandatory points. */
writeIntervalMs: number
}
```
Source: [`packages/session/session-projection-cache/src/index.ts:42`](../packages/session/session-projection-cache/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-session-query-sqlite"></a>
## `@deepseek-ai/dsh-session-query-sqlite`
Requires: `sessions`
```ts config-catalog
/** Combined session-query configuration backed by SQLite full-text search. */
export interface Config extends SessionQueryConfig {
/**
2026-07-27 12:51:47 +08:00
* Dedicated derived-index path; `:memory:` is supported for ephemeral
* indexes. Missing directories and database files are created owner-only on
* POSIX filesystems; existing modes are preserved.
*/
path: string
/**
* Open the SQLite module and handle at service activation or the first
* search, or `never` to disable full-text search: the inherited exact
* reads, filters, and traces stay available, while `searchSessions` and
* `searchEvents` fail with `SESSION_QUERY_SEARCH_DISABLED` and SQLite is
* never imported or opened. Defaults to `startup`.
*/
openAt?: OpenAt
/** SQLite journal mode. Defaults to `wal`. */
journalMode?: JournalMode
/** Page size when a request omits `limit`. At most `Number.MAX_SAFE_INTEGER - 1`; defaults to 20. */
defaultLimit?: number
/** Largest accepted page size. At most `Number.MAX_SAFE_INTEGER - 1`; defaults to 100. */
maxLimit?: number
/** Maximum snippet length in Unicode code points. Defaults to 240. */
snippetChars?: number
/** Maximum concurrent persisted-log inspections in one inherited batch read. Defaults to 4. */
persistedInspectConcurrency?: number
}
/** SQLite module/handle opening phase; `never` disables full-text search entirely. */
export type OpenAt = 'startup' | 'first-search' | 'never'
/** Supported SQLite journal modes. */
export type JournalMode = 'wal' | 'delete' | 'truncate' | 'persist'
```
Depends on: [`SessionQueryConfig`](../packages/session-query/session-query/src/index.ts)
Source: [`packages/session-query/session-query-sqlite/src/index.ts:89`](../packages/session-query/session-query-sqlite/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-session-reference"></a>
## `@deepseek-ai/dsh-session-reference`
Requires: `sessionQuery`
```ts config-catalog
/** Session-reference service configuration. */
export interface Config {
/** Maximum distinct source sessions referenced by one message, from one to three. */
maxReferences?: number
/** Default host candidate-list limit. */
candidateLimit?: number
/** Maximum rendered UTF-8 bytes for one source snapshot. */
maxReferenceBytes?: number
}
```
Source: [`packages/context/session-reference/src/config.ts:11`](../packages/context/session-reference/src/config.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-session-telemetry-otel"></a>
## `@deepseek-ai/dsh-session-telemetry-otel`
Requires: `sessions`
```ts config-catalog
/**
2026-08-09 15:27:21 +08:00
* Plugin configuration: one sharing policy, two verbatim SDK option objects,
* and one DSH-owned shutdown bound. Uploading modes validate their endpoint
* and shutdown deadline at plugin load; `DISABLED` reads neither.
*/
export interface Config {
/** Sharing policy; defaults to local-only `DISABLED` behavior. */
mode?: SessionTelemetryMode
/**
* Passed verbatim to the SDK's OTLP/HTTP log exporter — the complete
* `OTLPExporterNodeConfigBase` shape (`headers`, `timeoutMillis`,
* `compression`, `keepAlive`, …), owned and documented by the SDK. `url`
* is the one field this package requires and validates itself.
*/
exporter?: OTLPExporterNodeConfigBase & {
/** Full logs endpoint (e.g. `https://collector.example.com/v1/logs`). Required outside `DISABLED`; validated at load. */
url?: string
}
/**
* Passed verbatim to `BatchLogRecordProcessor` (minus the exporter slot,
* which this plugin fills); the SDK owns and documents these knobs.
*/
processor?: Omit<BatchLogRecordProcessorOptions, 'exporter'>
/** Maximum time spent awaiting the SDK provider's complete shutdown path. */
shutdownTimeoutMillis?: number
}
/** Session-sharing policy selected by {@link Config.mode}. */
export enum SessionTelemetryMode {
FULL = 'FULL',
FEEDBACK_ONLY = 'FEEDBACK_ONLY',
DISABLED = 'DISABLED',
}
```
Depends on: `BatchLogRecordProcessorOptions` (`@opentelemetry/sdk-logs`) · `OTLPExporterNodeConfigBase` (`@opentelemetry/otlp-exporter-base`)
Source: [`packages/session/session-telemetry-otel/src/index.ts:91`](../packages/session/session-telemetry-otel/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-session-title"></a>
## `@deepseek-ai/dsh-session-title`
Requires: `sessions`
```ts config-catalog
/** Required deterministic fallback and accepted-title limits. */
export interface Config {
/** Maximum whitespace-delimited words in the built-in fallback. */
readonly fallbackMaxWords: number
/** Maximum UTF-8 bytes in the built-in fallback. */
readonly fallbackMaxBytes: number
/** Maximum UTF-8 bytes in any accepted title. */
readonly maxTitleBytes: number
}
```
Source: [`packages/session/session-title/src/index.ts:79`](../packages/session/session-title/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-session-title-all-prompts-llm"></a>
## `@deepseek-ai/dsh-session-title-all-prompts-llm`
Requires: `sessionTitle` · `llm` · `sessions`
```ts config-catalog
/** Required LLM policy; this plugin adds no defaults. */
export type Config = SessionTitleLlmConfig
```
Depends on: [`SessionTitleLlmConfig`](../packages/session/session-title-llm/src/index.ts)
Source: [`packages/session/session-title-all-prompts-llm/src/index.ts:15`](../packages/session/session-title-all-prompts-llm/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-session-title-first-prompt-llm"></a>
## `@deepseek-ai/dsh-session-title-first-prompt-llm`
Requires: `sessionTitle` · `llm` · `sessions`
```ts config-catalog
/** Required LLM policy; this plugin adds no defaults. */
export type Config = SessionTitleLlmConfig
```
Depends on: [`SessionTitleLlmConfig`](../packages/session/session-title-llm/src/index.ts)
Source: [`packages/session/session-title-first-prompt-llm/src/index.ts:15`](../packages/session/session-title-first-prompt-llm/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-settings-file"></a>
## `@deepseek-ai/dsh-settings-file`
```ts config-catalog
/** Plugin config: file location and hot-reload behavior. */
export interface Config {
/** Settings document path; defaults to `settings.yaml` under the harness home. */
path?: string
/** Harness home used when `path` is omitted; defaults to `$DSH_HOME` or `~/.dsh`. */
dshHome?: string
/** Watch the document and hot-publish external edits; defaults to true. */
watch?: boolean
/** Watcher write-settle window in milliseconds; defaults to 100. */
debounceMs?: number
}
```
Source: [`packages/settings/settings-file/src/index.ts:21`](../packages/settings/settings-file/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-shell-env"></a>
## `@deepseek-ai/dsh-shell-env`
```ts config-catalog
/** Plugin config (all optional — the built-in facts resolve without defaults). */
export interface Config {
/** DeepSeek Harness home directory exposed as `DSH_HOME`; defaults to `$DSH_HOME` or `~/.dsh`. */
dshHome?: string
}
```
Source: [`packages/shell/shell-env/src/index.ts:29`](../packages/shell/shell-env/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-skill"></a>
## `@deepseek-ai/dsh-skill`
```ts config-catalog
/** Skill registry configuration. */
export interface Config {
/** Maximum number of completed cwd/provider catalogs kept in memory. */
readonly collectCacheMaxEntries?: number
}
```
Source: [`packages/skill/skill/src/index.ts:279`](../packages/skill/skill/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-skill-filesystem"></a>
## `@deepseek-ai/dsh-skill-filesystem`
Requires: `skills`
```ts config-catalog
/** Local filesystem skill provider configuration. */
export interface Config {
/** Unique provider name. Defaults to `local`. */
providerName?: string
/** Whether project and user roots are included around custom roots. */
includeDefaultRoots?: boolean
/** DeepSeek Harness config root. Defaults to `$DSH_HOME` or `~/.dsh`. */
dshHome?: string
/** Shared agent config root. Defaults to `$DSH_AGENTS_HOME` or `~/.agents`. */
agentsHome?: string
/** Additional skill roots scanned after project roots and before user roots. */
customSkillDirs?: string[]
/** Whether host-local skill roots are watched for catalog changes. */
watch?: boolean
/** Whether Chokidar uses polling instead of native filesystem events. */
watchUsePolling?: boolean
/** Milliseconds a changed skill entry must remain stable before it is observed. */
watchStabilityThresholdMs?: number
/** Milliseconds between Chokidar stability or polling probes. */
watchPollIntervalMs?: number
/** Maximum distinct project roots whose skill directories remain watched. */
watchMaxProjects?: number
/** Whether watched symbolic links follow their target files. */
watchFollowSymlinks?: boolean
/** Bundled skill root; defaults to `$DSH_BUNDLED_SKILL_DIR` when default roots are included, otherwise mounts none. */
bundledSkillDir?: string
}
```
Source: [`packages/skill/skill-filesystem/src/index.ts:49`](../packages/skill/skill-filesystem/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-spill-local"></a>
## `@deepseek-ai/dsh-spill-local`
```ts config-catalog
/** Plugin config (all optional — `static Config` supplies the defaults). */
export interface Config {
/**
* Root directory for spill files. Omitted uses a lazily-created private
* (0700) per-process directory under the OS temp dir — the safe default for
* a local deployment. Set it to keep spill files under a known location.
*/
root?: string
}
```
Source: [`packages/spill/spill-local/src/index.ts:22`](../packages/spill/spill-local/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-spill-policy"></a>
## `@deepseek-ai/dsh-spill-policy`
Requires: `tools`
```ts config-catalog
/** Plugin config. */
export interface Config {
/**
* The model-facing context cap for a plain-text tool result, in UTF-8 bytes.
* Omitted disables the policy entirely (no-op). When set, a result larger than
* this is spilled and replaced with a preview derived from this same budget.
*/
maxInlineBytes?: number
}
```
Source: [`packages/spill/spill-policy/src/index.ts:60`](../packages/spill/spill-policy/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-storage-domain"></a>
## `@deepseek-ai/dsh-storage-domain`
Requires: `storage`
```ts config-catalog
/**
* Plugin config. Which backend serves which domain is decided here, not
* globally on the hub: `backend` is the default route and `routes` overrides
* it per domain name. A route naming an unregistered backend fails loud at
* `open` with `backend-not-found`.
*/
export interface Config {
/** Default backend name for every domain without an explicit route. Required: there is no universally correct medium. */
backend: string
/** Per-domain overrides: domain name → backend name. */
routes?: Record<string, string>
}
```
Source: [`packages/storage/storage-domain/src/index.ts:52`](../packages/storage/storage-domain/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-storage-json"></a>
## `@deepseek-ai/dsh-storage-json`
Requires: `storage`
```ts config-catalog
/**
* Plugin configuration.
* `root` has NO default on purpose: a `process.cwd()` fallback would scatter
* unit files wherever the process happens to start; assemblies state the
* location explicitly.
*/
export interface Config {
/** Directory holding one `<unit>.json` file per unit. */
root: string
}
```
Source: [`packages/storage/storage-json/src/index.ts:27`](../packages/storage/storage-json/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-storage-sqlite"></a>
## `@deepseek-ai/dsh-storage-sqlite`
Requires: `storage`
```ts config-catalog
/** Plugin configuration. */
export interface Config {
/**
* Filesystem path to the SQLite database file. The special value `:memory:`
* opens an in-process database (tests). On filesystems with POSIX modes,
* missing directories and databases are created owner-only; existing path
* modes are preserved. Filesystem setup errors other than an existing
* database fail the open. The backend does not protect confidentiality or
* integrity when another principal can replace the database entry in its
* parent directory.
*/
path: string
/**
* SQLite `journal_mode` pragma. `wal` (the default) suits local disks; pick
* a rollback-journal mode (`delete`/`truncate`/`persist`) on filesystems
* where WAL's shared-memory files do not work (network mounts). See
* {@link JournalMode}.
*/
journalMode?: JournalMode
}
/**
* Journal modes the backend will run under. `wal` is the default; the
* rollback-journal modes (`delete`/`truncate`/`persist`) exist for
* filesystems where WAL's shared-memory files do not work (network mounts).
* `memory`/`off` are excluded: dropping journal durability silently
* contradicts the durability clause of the KV backend contract.
*/
export type JournalMode = 'wal' | 'delete' | 'truncate' | 'persist'
```
Source: [`packages/storage/storage-sqlite/src/index.ts:24`](../packages/storage/storage-sqlite/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-subagent-acp"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-subagent-acp`
feat(subprocess): migrate lsp-local, subagent-acp, and the env scrubs onto the seam Review direction (tianyicui, PR #660): in a stacked PR, change all other process-running places to use the new service. - lsp-local: LspConnection spawns through ctx.subprocess (piped protocol streams + a no-spill collected stderr tail); its private process-tree helpers (POSIX group signalling, Windows taskkill, liveness polling) are deleted in favor of the seam's handle verbs, and its buildChildEnv now rides scrubbedParentEnv (LSP children also stop inheriting stale DSH_*). The plugin injects 'subprocess'; compositions/tests mount dsh-subprocess-local. - subagent-acp: the ACP child spawns through the seam (piped ndjson streams, inherited stderr); spawn failure surfaces through done-rejection into the same startup race; disposal is handle.dispose with the plugin's configured graces. dsh-subagent-subprocess is DELETED — its dispose ladder and scrub are the seam's, and the isolated-config-dir helper had no consumer. - mcp-client, pty-local, sdk-helper: adopt scrubbedParentEnv as the one scrub definition (their spawns stay put by ownership: the MCP SDK and node-pty own those calls; the SDK wizard runs outside any composition). - Coverage: per-file 100% over every touched src file, with each v8 ignore carrying a platform or contract reason; new suites cover stdio dispositions, the dispose ladder tiers, injected-win32 tree semantics, waitForExit, settled-kill/terminate no-ops, and spawn-failure disposal. - Docs: consumer-migration Agent Note (en; zh follows in this PR), seam note updated in place, subprocess.md rewritten for the reshaped vocabulary (type-equiv re-registered), READMEs and SERVICE_ROLES updated, taskkill added to knip ignoreBinaries.
2026-07-26 15:27:59 +08:00
Requires: `subagents` · `subprocess`
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
```ts config-catalog
/** Config: how to spawn and drive the child ACP agent process. */
export interface Config {
/** Provider name on `ctx.subagents` (default `acp`). */
providerName: string
/** The executable to spawn for each run (the child ACP agent). */
command: string
/** Arguments passed to {@link command}. */
args: string[]
/**
* Working directory override for the child process and its ACP session.
* Must be non-empty; a relative path resolves against the harness launch
* directory at load, and the result must be an existing directory. When
* omitted, each child inherits its delegating parent session's cwd — and
* starting one from a parent session that has no cwd fails.
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
*/
cwd?: string
/**
* How to auto-answer the child's `session/request_permission` prompts:
* `reject` (default — decline every prompt) or `allow` (approve via the first
2026-08-09 15:27:21 +08:00
* `allow_once` or `allow_always` option). No prompt is surfaced to a human.
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
*/
permission: PermissionPolicy
/**
* Extra environment variables for the child process — e.g. the child
* harness's own `DEEPSEEK_API_KEY`. Forwarded on top of a credential-scrubbed
* copy of the parent env, so an explicit key here reaches the child while
* ambient secrets do not leak implicitly.
*/
env: Record<string, string>
/**
* Grace period (ms) for the child's EOF-driven quiesce on dispose — its
* window to flush persistence and tear down its own nested subprocesses
* before the parent escalates to a signal. Must not exceed
* `MAX_TIMER_DELAY_MS`.
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
*/
disposeEofGraceMs?: number
/** Termination-escalation grace (ms); must not exceed `MAX_TIMER_DELAY_MS`. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
disposeGraceMs?: number
}
/** Fixed response to child permission requests: reject by default, or select the first allow option. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
export type PermissionPolicy = 'allow' | 'reject'
```
Source: [`packages/subagent/subagent-acp/src/index.ts:27`](../packages/subagent/subagent-acp/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-subagent-claude-code"></a>
## `@deepseek-ai/dsh-subagent-claude-code`
Requires: `subagents` · `subprocess`
```ts config-catalog
/** Deployment-owned permission, environment, and process-release settings. */
export interface Config {
/** Provider name on `ctx.subagents` (default `claude-code`). */
providerName?: string
/**
* Explicit environment entries layered over the subprocess seam's
* credential-scrubbed parent environment.
*/
env?: Record<string, string>
/**
* Native non-interactive mode fixed for this Provider instance. Defaults to
* `dontAsk`; `acceptEdits` accepts edits, `auto` uses the native classifier,
* `plan` returns a plan without approving execution, and
* `bypassPermissions` explicitly skips permission checks.
*/
permissionMode?: ClaudeCodePermissionMode
/** Grace in milliseconds for Claude Code process-tree termination. */
disposeGraceMs?: number
}
/** Profile-selectable non-interactive Claude Code permission mode. */
export type ClaudeCodePermissionMode = typeof CLAUDE_CODE_PERMISSION_MODES[number]
```
Source: [`packages/subagent/subagent-claude-code/src/index.ts:38`](../packages/subagent/subagent-claude-code/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-subagent-codex"></a>
## `@deepseek-ai/dsh-subagent-codex`
Requires: `subagents` · `subprocess`
```ts config-catalog
/** Deployment-owned permission, environment, and process-release settings. */
export interface Config {
/** Provider name on `ctx.subagents` (default `codex`). */
providerName?: string
/**
* Explicit environment entries layered over the subprocess seam's
* credential-scrubbed parent environment.
*/
env?: Record<string, string>
/** Native non-interactive permission mode fixed for this Provider instance. */
permissionMode?: CodexPermissionMode
/** Grace in milliseconds for app-server process-tree termination. */
disposeGraceMs?: number
}
/** Profile-selectable non-interactive Codex permission mode. */
export type CodexPermissionMode =
| 'never'
| 'approve-for-me'
| 'dangerously-bypass-approvals-and-sandbox'
```
Source: [`packages/subagent/subagent-codex/src/index.ts:36`](../packages/subagent/subagent-codex/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-subagent-dsh-sdk"></a>
## `@deepseek-ai/dsh-subagent-dsh-sdk`
Requires: `subagents`
```ts config-catalog
/** Config: how to spawn and drive the child SDK runtime process. */
export interface Config {
/** Provider name on `ctx.subagents` (default `dsh-sdk`). */
providerName: string
/** Explicit dsh CLI module, resolved and checked at plugin load; omission uses the SDK dependency. */
dshBin?: string
/** Named child profile (default `sdk`). */
profile: string
/** Ordered per-launch profile patch files, resolved and checked at plugin load. */
patches: string[]
/** Absolute isolated Harness home for every nested child process. */
dshHome: string
/**
* Working directory override for the child process and its SDK session
* workspace. Must be non-empty; a relative path resolves against the
* harness launch directory at load, and the result must be an existing
* directory. When omitted, each child inherits its delegating parent
* session's cwd — and starting one from a parent session that has no cwd
* fails.
*/
cwd?: string
/** Provider route the child runtime initializes with (default `deepseek-official`). */
provider: string
/** Model the child runtime initializes with (default `deepseek-v4-flash`). */
model: string
2026-07-28 17:36:44 +08:00
/** Optional per-request output-token cap for the child runtime. */
maxTokens?: number
/**
* Extra environment variables for the child process — e.g. the child
* runtime's own `DEEPSEEK_API_KEY`. Forwarded on top of a credential-scrubbed copy of the parent
* env, so an explicit key here reaches the child while ambient secrets do
* not leak implicitly.
*/
env: Record<string, string>
/** Bound (ms) on the protocol `shutdown` exchange during dispose. */
shutdownTimeoutMs?: number
/**
* Grace period (ms) for the child's EOF-driven quiesce on dispose — its
* window to flush persistence and tear down its own nested subprocesses
* before the parent escalates to a signal.
*/
disposeEofGraceMs?: number
/** Termination confirmation window (ms), including forced exit on every platform. */
disposeGraceMs?: number
}
```
Source: [`packages/subagent/subagent-dsh-sdk/src/index.ts:31`](../packages/subagent/subagent-dsh-sdk/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-subagent-fork-in-process"></a>
## `@deepseek-ai/dsh-subagent-fork-in-process`
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-07-11 22:55:40 +08:00
Requires: `subagents`
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
```ts config-catalog
/** Config: the registry name to register the provider under. */
export interface Config {
/** Provider name on `ctx.subagents` (default `fork`). */
providerName: string
}
```
Source: [`packages/subagent/subagent-fork-in-process/src/index.ts:31`](../packages/subagent/subagent-fork-in-process/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-subagent-spawn-in-process"></a>
## `@deepseek-ai/dsh-subagent-spawn-in-process`
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-07-11 22:55:40 +08:00
Requires: `subagents`
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
```ts config-catalog
/** Config: the registry name to register the provider under. */
export interface Config {
/** Provider name on `ctx.subagents` (default `spawn`). */
providerName: string
}
```
Source: [`packages/subagent/subagent-spawn-in-process/src/index.ts:25`](../packages/subagent/subagent-spawn-in-process/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-subprocess-e2b"></a>
fix(e2b): address review round on cadence config, disposal, and SDK edge cases - subprocess-e2b: the 20 ms remote poll cadence becomes a validated pollMs Config field (each tick is one control-plane request); the README documents the latency-versus-request-count trade. - subprocess-e2b: extract src/remote.ts owning asError, signalOpts, commandOpts, delay, waitTick, and one tolerant signalRemoteGroups shared by the pgid-keyed process ladder and sid-keyed terminal ladder, so the two teardown paths keep identical error tolerance. - subprocess-e2b: service disposal aggregates sibling cleanup failures into one AggregateError instead of discarding all but the first. - subprocess-e2b: waitForProcessGroupId refuses published group ids <= 1, so a same-UID rewrite of the pid file cannot aim termination at kill -- -1; README documents the same-UID control-state limitation. - subprocess-e2b: drain-grace expiry now releases an inherited-output E2B callback blocked on host backpressure before disconnecting, so the SDK settlement cannot stay pinned behind an unread host stream. - subprocess-e2b: spawn/spawnTerminal stop validating typed spec fields (trust-TypeScript rule; pty-local validates its config before specs exist); resolveExecutable rejects separator-containing relative paths per the seam contract; terminal setups tracked as a Set of records. - subprocess-e2b: PTY output push-without-backpressure is a documented contract (flowing consumer folds bytes; paused consumer buffers). - fs-e2b: streamText normalizes the pinned SDK's empty-file '' return into an empty stream instead of throwing on getReader(). - e2b overlays: comment the one-world cwd invariant across e2b.cwd, workspaceRoot, and bash-local's implicit default workdir.
2026-08-02 15:38:00 +08:00
## `@deepseek-ai/dsh-subprocess-e2b`
Requires: `e2b`
```ts config-catalog
/** Configuration for the E2B subprocess adapter. */
export interface Config {
/** Remote status/liveness poll cadence in milliseconds; each tick is one control-plane request. */
pollMs?: number
}
```
Source: [`packages/e2b/subprocess-e2b/src/index.ts:25`](../packages/e2b/subprocess-e2b/src/index.ts)
fix(e2b): address review round on cadence config, disposal, and SDK edge cases - subprocess-e2b: the 20 ms remote poll cadence becomes a validated pollMs Config field (each tick is one control-plane request); the README documents the latency-versus-request-count trade. - subprocess-e2b: extract src/remote.ts owning asError, signalOpts, commandOpts, delay, waitTick, and one tolerant signalRemoteGroups shared by the pgid-keyed process ladder and sid-keyed terminal ladder, so the two teardown paths keep identical error tolerance. - subprocess-e2b: service disposal aggregates sibling cleanup failures into one AggregateError instead of discarding all but the first. - subprocess-e2b: waitForProcessGroupId refuses published group ids <= 1, so a same-UID rewrite of the pid file cannot aim termination at kill -- -1; README documents the same-UID control-state limitation. - subprocess-e2b: drain-grace expiry now releases an inherited-output E2B callback blocked on host backpressure before disconnecting, so the SDK settlement cannot stay pinned behind an unread host stream. - subprocess-e2b: spawn/spawnTerminal stop validating typed spec fields (trust-TypeScript rule; pty-local validates its config before specs exist); resolveExecutable rejects separator-containing relative paths per the seam contract; terminal setups tracked as a Set of records. - subprocess-e2b: PTY output push-without-backpressure is a documented contract (flowing consumer folds bytes; paused consumer buffers). - fs-e2b: streamText normalizes the pinned SDK's empty-file '' return into an empty stream instead of throwing on getReader(). - e2b overlays: comment the one-world cwd invariant across e2b.cwd, workspaceRoot, and bash-local's implicit default workdir.
2026-08-02 15:38:00 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-system-prompt"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-system-prompt`
```ts config-catalog
/** Plugin config: the deployment-authored fragment of the system prompt (see {@link Config.persona} for its contract). */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
export interface Config {
/** Include the fixed DeepSeek Harness identity before the deployment persona (default true). */
includeHarnessIdentity?: boolean
/** Include dynamic runtime-context snapshots in model history (default true). */
includeRuntimeContext?: boolean
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
/**
* Deployment-wide order-0 persona template. A scoped section named
* `deployment:persona` shadows it; `{{variable}}` references are strict.
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
*/
persona?: string
/**
* Model-facing tool names in order, with {@link TOOL_ORDER_REST} exactly once.
2026-08-09 15:27:21 +08:00
* Invalid fields fail at load and unknown names fail at assembly; known names
* hidden in one scope may be absent there. Omitted means lexicographic order.
*/
toolOrder?: string[]
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
}
```
Source: [`packages/core/system-prompt/src/index.ts:186`](../packages/core/system-prompt/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-terminal-bash"></a>
## `@deepseek-ai/dsh-terminal-bash`
Requires: `terminals` · `sandboxPolicy` · `subprocess`
```ts config-catalog
/** Public plugin configuration. */
export interface Config {
/** Backend registry type (default: `shell`). */
backendType?: string
/** Interactive shell dialect (default: `bash`); selects the argv/env/startup defaults. */
shellDialect?: ShellDialect
/** Interactive shell executable (default per dialect: `/bin/bash`, or the resolved pwsh). */
shellPath?: string
/** Shell arguments (default per dialect: bash `--noprofile --norc -i`, pwsh `-NoLogo -NoProfile`). */
shellArgs?: string[]
/** Terminal rows. */
rows?: number
/** Terminal columns. */
cols?: number
/** Maximum retained logical lines. */
scrollbackLines?: number
/** Maximum retained UTF-8 bytes. */
scrollbackMaxBytes?: number
/** Maximum bytes returned by one read or settled viewport. */
maxReadBytes?: number
/** Readiness polling interval. */
pollIntervalMs?: number
/** Delay before Linux exact syscall probes. */
exactProbeAfterMs?: number
/** Silence duration that yields `inferred_idle`. */
idleSilenceMs?: number
/**
* Extra wait beyond `idleSilenceMs`, once a prompt marker was seen, for the shell to
* regain the foreground before `inferred_idle` settles; at least one `pollIntervalMs`.
*/
handoffGraceMs?: number
/** Absolute bound for one send and the complete pwsh startup sequence. */
timeoutMs?: number
/** Grace before teardown escalates to `SIGKILL`. */
disposeGraceMs?: number
}
/** One supported interactive shell dialect. */
export type ShellDialect = 'bash' | 'pwsh'
```
Source: [`packages/terminal/terminal-bash/src/config.ts:10`](../packages/terminal/terminal-bash/src/config.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-time-context"></a>
2026-07-14 16:04:34 +08:00
## `@deepseek-ai/dsh-time-context`
Requires: `agents`
2026-07-14 16:04:34 +08:00
```ts config-catalog
/** Request-preparation clock formatting and append scheduling. Invalid values fail plugin load. */
2026-07-14 16:04:34 +08:00
export interface Config {
/** Fallback display zone when the open turn has no unique browser zone. Omit to use the process zone. */
2026-07-14 16:04:34 +08:00
timeZone?: string
/** Minimum milliseconds between durable injections in one session. Omit or set to 0 to inject at every eligible step. */
2026-07-14 16:04:34 +08:00
refreshIntervalMs?: number
}
```
Source: [`packages/context/time-context/src/index.ts:27`](../packages/context/time-context/src/index.ts)
2026-07-14 16:04:34 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tmux-context"></a>
## `@deepseek-ai/dsh-tmux-context`
Requires: `agents`
```ts config-catalog
/** Per-turn tmux-location scheduling. Invalid values fail plugin load. */
export interface Config {
/** Minimum milliseconds between durable injections in one session. Omit or set to 0 to inject on every eligible change. */
refreshIntervalMs?: number
}
```
Source: [`packages/context/tmux-context/src/index.ts:34`](../packages/context/tmux-context/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-token-meter"></a>
## `@deepseek-ai/dsh-token-meter`
```ts config-catalog
/** Token-meter plugin configuration; the fixed estimator has no settings. */
2026-07-21 14:49:57 +08:00
export type TokenMeterConfig = Record<string, never>
```
Source: [`packages/llm/token-meter/src/types.ts:12`](../packages/llm/token-meter/src/types.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-bash"></a>
## `@deepseek-ai/dsh-tool-bash`
Requires: `tools` · `shell` · `systemPrompt` · `shellEnv`
```ts config-catalog
/** Configuration for the bash tool. */
export interface Config {
/** Expose `run_in_background` (default true); disabled calls are also rejected. */
enableRunInBackground?: boolean
}
```
Source: [`packages/shell/tool-bash/src/index.ts:34`](../packages/shell/tool-bash/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-bash-persistent"></a>
## `@deepseek-ai/dsh-tool-bash-persistent`
Requires: `tools` · `terminals`
```ts config-catalog
/** Configuration for the persistent Bash tool. */
export interface Config {
/** PTY backend used for each owner-isolated persistent shell (default `shell`). */
backendType?: string
/** Wall-clock limit for one command (default 300000). */
timeoutMs?: number
/** Maximum returned command-output characters before clipping (default 16000). */
maxOutputChars?: number
/** Model-facing tool description; deployments may describe their environment. */
description?: string
}
```
Source: [`packages/shell/tool-bash-persistent/src/index.ts:432`](../packages/shell/tool-bash-persistent/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-fs"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-tool-fs`
Requires: `tools` · `fs` · `systemPrompt`
```ts config-catalog
/** Plugin config (all optional — `Config` supplies the defaults). */
export interface Config {
/** Default and maximum number of lines returned by one `read` call. */
readLimit?: number
/** Maximum characters returned for a single line before truncation. */
readMaxLineLength?: number
/** Maximum bytes returned for the selected lines of one `read` call. */
readMaxBytes?: number
/** Files at or above this size stream instead of loading whole into memory. */
readStreamMinSize?: number
}
```
Source: [`packages/fs/tool-fs/src/index.ts:25`](../packages/fs/tool-fs/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-fs-search"></a>
## `@deepseek-ai/dsh-tool-fs-search`
Requires: `tools` · `systemPrompt` · `subprocess`
```ts config-catalog
/** Plugin config; over-cap glob sampling is an explicit deployment choice and the remaining fields have defaults. */
export interface Config {
/** Whether an over-cap `glob` page is sampled across top-level entries instead of taking the modification-time head. */
sampleOverCapGlobResults: boolean
/** Max paths one `glob` call retains inline; later paths go to the formatted spill file. */
globMaxResults?: number
/** Max flat matches one `grep` call retains inline; later matches go to the formatted spill file. */
grepMaxMatches?: number
/** Max bytes retained for one matched-line preview (the cut preserves UTF-8 boundaries). */
grepMaxLineBytes?: number
/** Max bytes of one search's serialized `presentationMeta`; trailing groups/paths drop past it so the persisted card stays bounded. */
searchMetaMaxBytes?: number
/** Max complete raw `rg` stdout bytes a search will parse; larger raw output fails with `SEARCH_RAW_OUTPUT_OVERFLOW`. */
rawOutputMaxBytes?: number
/** Terminate-escalation grace (ms), handed to the subprocess seam and bounded by `MAX_TIMER_DELAY_MS`. */
graceMs?: number
/** Max bytes retained for one search's stderr tail; the excerpt is embedded in `SEARCH_*` error messages, never shown on success. */
stderrMaxBytes?: number
/**
* Cooperative tool-call timeout budget (ms) on both tools, enforced by
* `@deepseek-ai/dsh-tool-call-timeout-policy` through `exec.signal`.
*/
timeoutMs?: number
}
```
Source: [`packages/fs/tool-fs-search/src/index.ts:73`](../packages/fs/tool-fs-search/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-goal"></a>
## `@deepseek-ai/dsh-tool-goal`
Requires: `agents` · `goals` · `tools` · `systemPrompt`
```ts config-catalog
/** Model policy and hard lower bounds for goal-state updates. */
export interface Config {
/** Minimum admitted goal rounds before the model may self-report `blocked`. */
blockedAfterConsecutiveRounds?: number
}
```
Source: [`packages/goal/tool-goal/src/index.ts:26`](../packages/goal/tool-goal/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-jobs"></a>
## `@deepseek-ai/dsh-tool-jobs`
Requires: `tools` · `jobs` · `systemPrompt`
```ts config-catalog
/** Configures bounded `job_output` waits and completion-notice delivery. */
export interface Config {
/** Wait duration applied when `job_output` sets `wait` without `timeout_ms` (default 30s). */
waitTimeoutMs?: number
/** Hard cap on any single wait; a larger model-supplied `timeout_ms` is clamped down to it (default 10min). */
maxWaitTimeoutMs?: number
/** Whether a completion opens a turn on an idle owner (default `wakeup`). */
completionDelivery?: CompletionDelivery
/**
* Turns one owner may have opened by completion wakes before the next
* notice degrades to injection, reset by any user-authored input (default 3).
* Bounds the self-exciting chain where a woken turn starts the job whose
* completion wakes it again.
*/
maxConsecutiveWakes?: number
}
/**
* How an unreported completion reaches an owner that is already idle: `wakeup`
* opens a turn for it, `quiet` leaves it pending until something else wakes the
* owner. A busy owner is injected either way.
*/
export type CompletionDelivery = 'quiet' | 'wakeup'
```
Source: [`packages/jobs/tool-jobs/src/index.ts:32`](../packages/jobs/tool-jobs/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-lsp"></a>
## `@deepseek-ai/dsh-tool-lsp`
Requires: `tools` · `lsp` · `systemPrompt`
```ts config-catalog
/** Plugin configuration: result caps and the timeout budget. */
export interface Config {
/** Largest number of rendered locations before an omission marker (default 100). */
maxLocations?: number
/** Largest complete rendered result in characters, including truncation metadata (default 16000). */
maxResultChars?: number
/** Tool-call timeout budget in ms (default 60000). */
timeoutMs?: number
}
```
Source: [`packages/lsp/tool-lsp/src/index.ts:58`](../packages/lsp/tool-lsp/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-pwsh"></a>
## `@deepseek-ai/dsh-tool-pwsh`
Requires: `tools` · `shell` · `systemPrompt` · `shellEnv`
```ts config-catalog
/** Configuration for the pwsh tool. */
export interface Config {
/** Expose `run_in_background` (default true); disabled calls are also rejected. */
enableRunInBackground?: boolean
}
```
Source: [`packages/shell/tool-pwsh/src/index.ts:52`](../packages/shell/tool-pwsh/src/index.ts)
<a id="deepseek-aidsh-tool-pwsh-persistent"></a>
## `@deepseek-ai/dsh-tool-pwsh-persistent`
Requires: `tools` · `terminals`
```ts config-catalog
/** Configuration for the persistent pwsh tool. */
export interface Config {
/** PTY backend used for each owner-isolated persistent shell (default `shell`). */
backendType?: string
/** Wall-clock limit for one command (default 300000). */
timeoutMs?: number
/** Maximum returned command-output characters before clipping (default 16000). */
maxOutputChars?: number
/** Model-facing tool description; deployments may describe their environment. */
description?: string
}
```
Source: [`packages/shell/tool-pwsh-persistent/src/index.ts:472`](../packages/shell/tool-pwsh-persistent/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-ralph"></a>
## `@deepseek-ai/dsh-tool-ralph`
Requires: `tools` · `workflowEngine` · `subagents` · `systemPrompt`
```ts config-catalog
/** Deployment policy for the fixed Ralph workflow. */
export interface Config {
/** Fresh structured-output provider used for every round (default `spawn`). */
subagentProvider?: string
/** Default and deployment ceiling for one call's round count (default 256). */
maxRounds?: number
/** Maximum serialized characters in one structured handoff (default 16384). */
maxHandoffChars?: number
/** Maximum characters in a successful parent-facing terminal text (default 16384). */
maxResultChars?: number
}
```
2026-07-21 03:08:35 +08:00
Source: [`packages/workflow/tool-ralph/src/index.ts:23`](../packages/workflow/tool-ralph/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-session-query"></a>
## `@deepseek-ai/dsh-tool-session-query`
Requires: `tools` · `systemPrompt` · `sessionQuery`
```ts config-catalog
/** Deployment-owned search count and timeout bounds. */
export interface Config {
/** Maximum authorized hits returned by one search call. Defaults to 100. */
maxSearchResults?: number
/** Cooperative full-text search deadline in milliseconds. Defaults to 30000. */
searchTimeoutMs?: number
}
```
Source: [`packages/session-query/tool-session-query/src/index.ts:29`](../packages/session-query/tool-session-query/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-skill"></a>
## `@deepseek-ai/dsh-tool-skill`
Requires: `agents` · `tools` · `skills`
```ts config-catalog
/** Model-facing skill catalog configuration. */
export interface Config {
/** Maximum normalized description length rendered in the session catalog; minimum 3. */
catalogDescriptionMaxLength?: number
}
```
Source: [`packages/skill/tool-skill/src/index.ts:61`](../packages/skill/tool-skill/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-str-replace-editor"></a>
## `@deepseek-ai/dsh-tool-str-replace-editor`
Requires: `tools` · `fs`
```ts config-catalog
/** Configuration for the string-replacement editor tool. */
export interface Config {
/** Maximum returned view characters before clipping (default 16000). */
maxOutputChars?: number
/** Model-facing tool description. */
description?: string
}
```
Source: [`packages/fs/tool-str-replace-editor/src/index.ts:497`](../packages/fs/tool-str-replace-editor/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-subagent"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-tool-subagent`
Requires: `tools` · `subagents` · `systemPrompt`
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
```ts config-catalog
/** Config: which registered provider this tool delegates to, plus child defaults. */
export interface Config {
/** The `ctx.subagents` provider name to start runs on (e.g. `spawn`, `acp`). */
provider: string
/**
* Model-facing tool name (default `subagent`). Each loaded instance must use
* a distinct name.
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
*/
toolName?: string
/**
* Expose `run_in_background` (default true). Disabled instances omit the
* parameter and reject forced background calls.
*/
enableRunInBackground?: boolean
/**
* Background execution policy (default `one-shot`). `one-shot` defaults calls
* to foreground; `continuable` defaults them to background, requires a provider
* with the `prepareContinuable` capability, and returns the durable child id.
* Follow-up adapters remain independently optional.
*/
backgroundMode?: 'one-shot' | 'continuable'
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
/**
* Agent options applied to every child; omitted fields use child-loop defaults.
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
*/
agentOptions?: AgentOptions
/**
* Per-child persona that shadows `deployment:persona`. Requires the
* provider's `persona` capability; omission preserves the deployment persona.
*/
persona?: string
/**
* Tool filter applied to every child. Filtered tools disappear from its
* prompt and reject execution. Requires the provider's `toolFilter`
* capability; unknown names fail startup.
*/
toolFilter?: {
/** Global tool names the child keeps; everything else is removed. */
allow?: string[]
/** Global tool names removed from the child. */
deny?: string[]
}
/**
* Maximum child depth: a non-negative safe integer (default `3`; `0` forbids
* delegation entirely), or `'provider-managed'` to send no cap. A numeric cap
* requires the provider's `depthLimit` capability (mount fails loud
* otherwise). The provider checks the calling agent's current depth at every
* start; the tool remains model-visible so runtime policy owns rejection.
* `'provider-managed'` is for an out-of-process provider whose recursion
* budget belongs to the child runtime or its own deployment.
*/
maxDepth?: number | 'provider-managed'
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
}
```
Depends on: [`AgentOptions`](subsystems/core.md)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
Source: [`packages/subagent/tool-subagent/src/index.ts:29`](../packages/subagent/tool-subagent/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-subagent-report"></a>
## `@deepseek-ai/dsh-tool-subagent-report`
Requires: `subagents` · `tools` · `systemPrompt`
```ts config-catalog
/** Config: how accepted reports are scheduled on the parent. */
export interface Config {
/**
2026-08-17 15:37:04 +08:00
* Parent scheduling (default `next-step`). `next-step` wakes the parent and
* enters at its nearest step boundary; `quiet` adds the same context without
* waking, so a parked parent waits for another waking input.
*/
reportDelivery?: SubagentReportDelivery
}
```
Depends on: [`SubagentReportDelivery`](subsystems/subagent.md)
Source: [`packages/subagent/tool-subagent-report/src/index.ts:27`](../packages/subagent/tool-subagent-report/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-terminal"></a>
## `@deepseek-ai/dsh-tool-terminal`
Requires: `terminals` · `tools` · `systemPrompt`
```ts config-catalog
/** Model-facing terminal tool configuration. */
export interface Config {
/** Expose `run_in_background` and accept background sends (default true). */
enableRunInBackground?: boolean
/** Maximum UTF-8 bytes in one complete terminal or task-output result. */
maxResultBytes?: number
}
```
Source: [`packages/terminal/tool-terminal/src/index.ts:35`](../packages/terminal/tool-terminal/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-todo"></a>
## `@deepseek-ai/dsh-tool-todo`
Requires: `tools`
```ts config-catalog
/** Model-facing todo tool configuration. */
export interface Config {
/**
* Required deployment choice for whether several todos may be `in_progress` at once. True suits
* agents that run work concurrently — subagents, background commands, workflow fan-out — and the
* description then instructs the model to mark every actively worked task. False restores the
* single-active discipline: the description asks for exactly one, and a call marking more is
* rejected.
*/
allowParallelInProgress: boolean
}
```
Source: [`packages/todo/tool-todo/src/index.ts:29`](../packages/todo/tool-todo/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-web"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-tool-web`
Requires: `tools` · `web` · `systemPrompt`
```ts config-catalog
2026-08-17 15:45:26 +08:00
/** Plugin config: which web tools to register, search bounds, per-tool budgets, and the fetch output cap. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
export interface Config {
/** Register `web_search`. Defaults to true. */
search?: boolean
/** Register `web_fetch`. Defaults to true. */
fetch?: boolean
/** Upper bound on sources returned by one `web_search` call. */
searchMaxResults?: number
2026-08-17 15:45:26 +08:00
/** Upper bound on queries accepted by one `web_search` call. */
searchMaxQueries?: number
/** Cooperative timeout budget (ms) for `web_fetch`. Defaults to 30000. */
fetchTimeoutMs?: number
/** Cooperative timeout budget (ms) for `web_search`. Defaults to 30000. */
searchTimeoutMs?: number
/** Cap on source characters converted and complete `web_fetch` output characters. Defaults to 200000. */
fetchMaxOutputChars?: number
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
}
```
Source: [`packages/web/tool-web/src/index.ts:37`](../packages/web/tool-web/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tool-workflow"></a>
Merge branch 'structured-output-subagent-seam' into worktree-dynamic-workflows # Conflicts: # examples/acp-agent/tests/snapshots/cancel/session.jsonl # examples/acp-agent/tests/snapshots/error-finish/session.jsonl # examples/acp-agent/tests/snapshots/fs-edit/session.jsonl # examples/acp-agent/tests/snapshots/fs-policy-reject/session.jsonl # examples/acp-agent/tests/snapshots/fs-read-window/session.jsonl # examples/acp-agent/tests/snapshots/fs-read/session.jsonl # examples/acp-agent/tests/snapshots/fs-terminal-card/session.jsonl # examples/acp-agent/tests/snapshots/fs-write-overwrite/session.jsonl # examples/acp-agent/tests/snapshots/fs-write/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-ask/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-deny/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-pretool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/multi-turn/session.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.jsonl # examples/acp-agent/tests/snapshots/todo-plan/session.jsonl # examples/acp-agent/tests/snapshots/tool-call-turn/session.jsonl # examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl
2026-07-07 10:00:58 +08:00
## `@deepseek-ai/dsh-tool-workflow`
Requires: `tools` · `workflowEngine` · `systemPrompt`
Merge branch 'structured-output-subagent-seam' into worktree-dynamic-workflows # Conflicts: # examples/acp-agent/tests/snapshots/cancel/session.jsonl # examples/acp-agent/tests/snapshots/error-finish/session.jsonl # examples/acp-agent/tests/snapshots/fs-edit/session.jsonl # examples/acp-agent/tests/snapshots/fs-policy-reject/session.jsonl # examples/acp-agent/tests/snapshots/fs-read-window/session.jsonl # examples/acp-agent/tests/snapshots/fs-read/session.jsonl # examples/acp-agent/tests/snapshots/fs-terminal-card/session.jsonl # examples/acp-agent/tests/snapshots/fs-write-overwrite/session.jsonl # examples/acp-agent/tests/snapshots/fs-write/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-ask/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-deny/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-pretool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/multi-turn/session.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.jsonl # examples/acp-agent/tests/snapshots/todo-plan/session.jsonl # examples/acp-agent/tests/snapshots/tool-call-turn/session.jsonl # examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl
2026-07-07 10:00:58 +08:00
```ts config-catalog
/** Config: the model-facing tool name plus result rendering caps. */
export interface Config {
/** The model-facing tool name to register (default `workflow`). */
toolName?: string
/** Rendered-result ceiling, in characters: a longer JSON value is truncated with a notice (default 50000). */
maxResultChars?: number
}
```
Source: [`packages/workflow/tool-workflow/src/index.ts:33`](../packages/workflow/tool-workflow/src/index.ts)
Merge branch 'structured-output-subagent-seam' into worktree-dynamic-workflows # Conflicts: # examples/acp-agent/tests/snapshots/cancel/session.jsonl # examples/acp-agent/tests/snapshots/error-finish/session.jsonl # examples/acp-agent/tests/snapshots/fs-edit/session.jsonl # examples/acp-agent/tests/snapshots/fs-policy-reject/session.jsonl # examples/acp-agent/tests/snapshots/fs-read-window/session.jsonl # examples/acp-agent/tests/snapshots/fs-read/session.jsonl # examples/acp-agent/tests/snapshots/fs-terminal-card/session.jsonl # examples/acp-agent/tests/snapshots/fs-write-overwrite/session.jsonl # examples/acp-agent/tests/snapshots/fs-write/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-ask/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-deny/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-pretool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/multi-turn/session.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.jsonl # examples/acp-agent/tests/snapshots/todo-plan/session.jsonl # examples/acp-agent/tests/snapshots/tool-call-turn/session.jsonl # examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl
2026-07-07 10:00:58 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-tools"></a>
feat: Code Mode — the registry's mode config, the SDK codegen, and the run_code bridge The dsh-tools half of the Code Mode RFC (its fourth, final change): the registry gains its first config — mode: native | code | both — and OWNS how its tools reach the model. 'code' contributes exactly one wire tool, run_code, plus a lazy tools:sdk prompt section declaring every other tool as a generated TypeScript API (jsonSchemaToTs: total over the defineTool subset, unknown degradation, lexicographic byte-identical rendering); 'both' ships both representations; 'native' is byte-for-byte the old behavior. Non-native modes fail every assembly loudly without a typescript-language ctx.codeRuntime. run_code's dispatch bridge: JSON-normalizes each binding argument before dispatch (what dispatches is what the tool/code-dispatch event logs — the append can never fail on payload shape; BigInt/circulars reject that one call), serializes all program tool calls through a per-run queue (even Promise.all — no concurrency-safety metadata yet), routes every sub-call through tools/pre-execute → tools/post-execute (a deny rejects the program-side promise), drops sub-call additionalContext (no safe outlet mid-run; pinned), owns a run-scoped abort that follows the outer signal in and fires on settlement (in-flight sub-dispatch aborted, queued abandoned, queue drained before returning), and converts a failed run into CodeRunFailedError → a structured isError carrying kind + captured logs. tool/code-dispatch joins SessionEventMap by declaration merging (log-only; deriveMessages ignores it). The composed surface: the tools config forwards through agent-core and both app packages; examples/code-agent + demo:code run the worker runtime under mode code (keyless boot smoke + a with-key e2e proving the collapsed [run_code] header, the dispatch events, and the file the program wrote); two new snapshot scenarios (code-mode-turn, both-mode-turn) record the SDK section, collapsed header, dispatch events, and result card — each its own header-pinning class (the harness gains per-scenario config overlays and per-class pins). Catalogs, graphs, cookbook, hooks-bridge notes, and the RFC (moved to implemented/, restructured to decision-era headings) updated in the same change.
2026-07-08 12:58:23 +08:00
## `@deepseek-ai/dsh-tools`
Requires: `systemPrompt`
```ts config-catalog
/** Plugin config: how the registered tools are presented to the model. */
export interface Config {
/**
* Model presentation. `native` (default) sends every visible schema; `code`
* sends only `run_code` plus a generated SDK prompt and collapses the
* executor to the same surface (a model-direct call may only name
* `run_code`; `run_code` SDK sub-dispatches keep every visible tool); `both`
* sends both forms. Code modes require a `ctx.codeRuntime` whose `language`
* has a registered SDK renderer (TypeScript or Python) and fail prompt
* assembly when it is absent or has no renderer. Under `code`, native names
* in `toolOrder` are invalid.
feat: Code Mode — the registry's mode config, the SDK codegen, and the run_code bridge The dsh-tools half of the Code Mode RFC (its fourth, final change): the registry gains its first config — mode: native | code | both — and OWNS how its tools reach the model. 'code' contributes exactly one wire tool, run_code, plus a lazy tools:sdk prompt section declaring every other tool as a generated TypeScript API (jsonSchemaToTs: total over the defineTool subset, unknown degradation, lexicographic byte-identical rendering); 'both' ships both representations; 'native' is byte-for-byte the old behavior. Non-native modes fail every assembly loudly without a typescript-language ctx.codeRuntime. run_code's dispatch bridge: JSON-normalizes each binding argument before dispatch (what dispatches is what the tool/code-dispatch event logs — the append can never fail on payload shape; BigInt/circulars reject that one call), serializes all program tool calls through a per-run queue (even Promise.all — no concurrency-safety metadata yet), routes every sub-call through tools/pre-execute → tools/post-execute (a deny rejects the program-side promise), drops sub-call additionalContext (no safe outlet mid-run; pinned), owns a run-scoped abort that follows the outer signal in and fires on settlement (in-flight sub-dispatch aborted, queued abandoned, queue drained before returning), and converts a failed run into CodeRunFailedError → a structured isError carrying kind + captured logs. tool/code-dispatch joins SessionEventMap by declaration merging (log-only; deriveMessages ignores it). The composed surface: the tools config forwards through agent-core and both app packages; examples/code-agent + demo:code run the worker runtime under mode code (keyless boot smoke + a with-key e2e proving the collapsed [run_code] header, the dispatch events, and the file the program wrote); two new snapshot scenarios (code-mode-turn, both-mode-turn) record the SDK section, collapsed header, dispatch events, and result card — each its own header-pinning class (the harness gains per-scenario config overlays and per-class pins). Catalogs, graphs, cookbook, hooks-bridge notes, and the RFC (moved to implemented/, restructured to decision-era headings) updated in the same change.
2026-07-08 12:58:23 +08:00
*/
mode?: ToolPresentationMode
/**
* Concurrency cap for a `run_code` program's overlapping sub-calls
* (default 10, the loop scheduler's own default). Sub-calls follow the
* native scheduling contract — only calls whose tools classify
* concurrency-safe overlap; exclusive calls form barriers — so `1`
* restores strictly serial dispatch. Must be a positive integer.
*/
maxParallelSubCalls?: number
feat: Code Mode — the registry's mode config, the SDK codegen, and the run_code bridge The dsh-tools half of the Code Mode RFC (its fourth, final change): the registry gains its first config — mode: native | code | both — and OWNS how its tools reach the model. 'code' contributes exactly one wire tool, run_code, plus a lazy tools:sdk prompt section declaring every other tool as a generated TypeScript API (jsonSchemaToTs: total over the defineTool subset, unknown degradation, lexicographic byte-identical rendering); 'both' ships both representations; 'native' is byte-for-byte the old behavior. Non-native modes fail every assembly loudly without a typescript-language ctx.codeRuntime. run_code's dispatch bridge: JSON-normalizes each binding argument before dispatch (what dispatches is what the tool/code-dispatch event logs — the append can never fail on payload shape; BigInt/circulars reject that one call), serializes all program tool calls through a per-run queue (even Promise.all — no concurrency-safety metadata yet), routes every sub-call through tools/pre-execute → tools/post-execute (a deny rejects the program-side promise), drops sub-call additionalContext (no safe outlet mid-run; pinned), owns a run-scoped abort that follows the outer signal in and fires on settlement (in-flight sub-dispatch aborted, queued abandoned, queue drained before returning), and converts a failed run into CodeRunFailedError → a structured isError carrying kind + captured logs. tool/code-dispatch joins SessionEventMap by declaration merging (log-only; deriveMessages ignores it). The composed surface: the tools config forwards through agent-core and both app packages; examples/code-agent + demo:code run the worker runtime under mode code (keyless boot smoke + a with-key e2e proving the collapsed [run_code] header, the dispatch events, and the file the program wrote); two new snapshot scenarios (code-mode-turn, both-mode-turn) record the SDK section, collapsed header, dispatch events, and result card — each its own header-pinning class (the harness gains per-scenario config overlays and per-class pins). Catalogs, graphs, cookbook, hooks-bridge notes, and the RFC (moved to implemented/, restructured to decision-era headings) updated in the same change.
2026-07-08 12:58:23 +08:00
}
/** How the registry presents its tools to the model (see {@link Config.mode}). */
export type ToolPresentationMode = 'native' | 'code' | 'both'
```
Source: [`packages/core/tools/src/index.ts:654`](../packages/core/tools/src/index.ts)
feat: Code Mode — the registry's mode config, the SDK codegen, and the run_code bridge The dsh-tools half of the Code Mode RFC (its fourth, final change): the registry gains its first config — mode: native | code | both — and OWNS how its tools reach the model. 'code' contributes exactly one wire tool, run_code, plus a lazy tools:sdk prompt section declaring every other tool as a generated TypeScript API (jsonSchemaToTs: total over the defineTool subset, unknown degradation, lexicographic byte-identical rendering); 'both' ships both representations; 'native' is byte-for-byte the old behavior. Non-native modes fail every assembly loudly without a typescript-language ctx.codeRuntime. run_code's dispatch bridge: JSON-normalizes each binding argument before dispatch (what dispatches is what the tool/code-dispatch event logs — the append can never fail on payload shape; BigInt/circulars reject that one call), serializes all program tool calls through a per-run queue (even Promise.all — no concurrency-safety metadata yet), routes every sub-call through tools/pre-execute → tools/post-execute (a deny rejects the program-side promise), drops sub-call additionalContext (no safe outlet mid-run; pinned), owns a run-scoped abort that follows the outer signal in and fires on settlement (in-flight sub-dispatch aborted, queued abandoned, queue drained before returning), and converts a failed run into CodeRunFailedError → a structured isError carrying kind + captured logs. tool/code-dispatch joins SessionEventMap by declaration merging (log-only; deriveMessages ignores it). The composed surface: the tools config forwards through agent-core and both app packages; examples/code-agent + demo:code run the worker runtime under mode code (keyless boot smoke + a with-key e2e proving the collapsed [run_code] header, the dispatch events, and the file the program wrote); two new snapshot scenarios (code-mode-turn, both-mode-turn) record the SDK section, collapsed header, dispatch events, and result card — each its own header-pinning class (the harness gains per-scenario config overlays and per-class pins). Catalogs, graphs, cookbook, hooks-bridge notes, and the RFC (moved to implemented/, restructured to decision-era headings) updated in the same change.
2026-07-08 12:58:23 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-typert-loader"></a>
## `@deepseek-ai/dsh-typert-loader`
Requires: `typert` · `loader`
```ts config-catalog
/** Additional package artifacts whose owning plugins are nested behind another Loader entry. */
export interface Config {
/** Exact npm package names that must resolve and export `./typert`. */
packages?: string[]
}
```
Source: [`packages/typert/loader/src/index.ts:47`](../packages/typert/loader/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-user-approval"></a>
## `@deepseek-ai/dsh-user-approval`
```ts config-catalog
/** Plugin config. All optional — `static Config` supplies the defaults. */
export interface Config {
/**
* The deployment's default {@link ApprovalPolicy} for sessions without an
* `approval/policy` override — `'ask'` delegates to the composed answerers
* (fail-closed with none); `'never'` auto-rejects every ask without
* prompting (the deterministic CI/unattended stance).
*/
readonly policy?: ApprovalPolicy
}
/**
* A session's approval policy — what happens to an {@link ApprovalService}
* ask BEFORE any interactive answerer sees it:
*
* - `'ask'` (the default) — delegate to the composed answerers; with none
* composed the chain falls through to the fail-closed `'unavailable'`.
* - `'never'` — never prompt anyone: every ask resolves `'rejected'`
* deterministically. The strict headless stance (CI, unattended runs) and
* the policy whose outcome is knowable without asking.
*/
export type ApprovalPolicy = 'ask' | 'never'
```
Source: [`packages/interaction/user-approval/src/index.ts:142`](../packages/interaction/user-approval/src/index.ts)
feat: Code Mode — the registry's mode config, the SDK codegen, and the run_code bridge The dsh-tools half of the Code Mode RFC (its fourth, final change): the registry gains its first config — mode: native | code | both — and OWNS how its tools reach the model. 'code' contributes exactly one wire tool, run_code, plus a lazy tools:sdk prompt section declaring every other tool as a generated TypeScript API (jsonSchemaToTs: total over the defineTool subset, unknown degradation, lexicographic byte-identical rendering); 'both' ships both representations; 'native' is byte-for-byte the old behavior. Non-native modes fail every assembly loudly without a typescript-language ctx.codeRuntime. run_code's dispatch bridge: JSON-normalizes each binding argument before dispatch (what dispatches is what the tool/code-dispatch event logs — the append can never fail on payload shape; BigInt/circulars reject that one call), serializes all program tool calls through a per-run queue (even Promise.all — no concurrency-safety metadata yet), routes every sub-call through tools/pre-execute → tools/post-execute (a deny rejects the program-side promise), drops sub-call additionalContext (no safe outlet mid-run; pinned), owns a run-scoped abort that follows the outer signal in and fires on settlement (in-flight sub-dispatch aborted, queued abandoned, queue drained before returning), and converts a failed run into CodeRunFailedError → a structured isError carrying kind + captured logs. tool/code-dispatch joins SessionEventMap by declaration merging (log-only; deriveMessages ignores it). The composed surface: the tools config forwards through agent-core and both app packages; examples/code-agent + demo:code run the worker runtime under mode code (keyless boot smoke + a with-key e2e proving the collapsed [run_code] header, the dispatch events, and the file the program wrote); two new snapshot scenarios (code-mode-turn, both-mode-turn) record the SDK section, collapsed header, dispatch events, and result card — each its own header-pinning class (the harness gains per-scenario config overlays and per-class pins). Catalogs, graphs, cookbook, hooks-bridge notes, and the RFC (moved to implemented/, restructured to decision-era headings) updated in the same change.
2026-07-08 12:58:23 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-web"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-web`
```ts config-catalog
/**
* Config for the web seam. `searchProvider` / `fetchProvider` pin which provider
* wins for each capability; both are optional (a single registered usable
* provider auto-selects). Operational overrides such as environment variables
* must feed these same fields rather than introduce a hidden priority chain.
*/
export interface WebRuntimeConfig {
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
/** Explicit search provider id. Omitted = auto-select when exactly one usable. */
readonly searchProvider?: string
/** Explicit fetch provider id. Omitted = auto-select when exactly one usable. */
readonly fetchProvider?: string
}
```
Source: [`packages/web/web/src/index.ts:55`](../packages/web/web/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-web-app"></a>
## `@deepseek-ai/dsh-web-app`
Requires: `webServer`
```ts config-catalog
/** Plugin config: composed deployment settings plus per-invocation command-line values. */
export interface Config {
/** Permit default-browser handoff after the Loader tree settles; an SSH launch suppresses it. */
openBrowser: boolean
/** Print the URL line on activation; a non-interactive layer can turn it off. */
printUrl: boolean
/**
* Register the model-visible surface context (the `app:web-surface` prompt
* section and the `DSH_WEB_URL` bash variable). A one-shot non-interactive
* layer can turn it off when its user is not in the GUI, so the
* orientation text would be false.
*/
surfaceContext: boolean
/** Explicit `--trusted-host` authorities from this invocation. */
trustedHosts: string[]
}
```
Source: [`packages/bundle/web-app/src/index.ts:43`](../packages/bundle/web-app/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-web-fetch-http"></a>
## `@deepseek-ai/dsh-web-fetch-http`
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
Requires: `web`
```ts config-catalog
/** Plugin config: the provider's transport and size limits plus its `User-Agent` (all defaulted). */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
export interface Config {
/** Maximum accepted request URL length. */
maxUrlLength?: number
/** Maximum response body size in bytes. */
maxResponseBytes?: number
/** Maximum decoded body length in characters. */
maxBodyChars?: number
2026-07-14 05:06:01 +08:00
/** Default fetch timeout in milliseconds, within Node's timer range. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
timeoutMs?: number
/** Maximum number of same-origin redirect hops to follow. */
maxRedirects?: number
/** `User-Agent` header sent on every request. */
userAgent?: string
}
```
Source: [`packages/web/web-fetch-http/src/index.ts:32`](../packages/web/web-fetch-http/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-web-search-deepseek"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-web-search-deepseek`
Requires: `web`
```ts config-catalog
/** Plugin config (all optional — `apply` fills env-var and constant defaults). */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
export interface Config {
/** Literal DeepSeek API key; prefer {@link apiKeyEnv} so no secret enters configuration files. */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
apiKey?: string
/** Credential reference resolved for each search; defaults to `DEEPSEEK_API_KEY`. */
apiKeyEnv?: string
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
/** Anthropic-compatible endpoint base; `/messages` is appended. */
baseURL?: string
/** Anthropic-format model name. Defaults to `deepseek-v4-flash`. */
model?: string
/** `anthropic-version` header value. Defaults to `2023-06-01`. */
apiVersion?: string
/** Upper bound on generated tokens for the Messages request. Defaults to 4096. */
maxTokens?: number
/** Maximum `web_search` server-tool uses per request. Defaults to 5. */
maxUses?: number
}
```
Source: [`packages/web/web-search-deepseek/src/index.ts:46`](../packages/web/web-search-deepseek/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-web-search-exa"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-web-search-exa`
Requires: `web`
```ts config-catalog
/** Plugin config (all optional — `apply` fills env-var and constant defaults). */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
export interface Config {
/** Exa API key. Falls back to `$EXA_API_KEY`. Empty → provider unavailable. */
apiKey?: string
/** Endpoint base; `/search` is appended. Defaults to the public API. */
baseURL?: string
/** Retrieval mode sent as Exa's `type`. Defaults to `auto`. */
searchType?: 'auto' | 'keyword' | 'neural'
/** Default result count when a request carries no `maxResults`. Omitted = none. */
numResults?: number
/** Highlight sentences requested per result. Defaults to 1. */
highlightsPerResult?: number
}
```
Source: [`packages/web/web-search-exa/src/index.ts:35`](../packages/web/web-search-exa/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-web-search-perplexity"></a>
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## `@deepseek-ai/dsh-web-search-perplexity`
Requires: `web`
```ts config-catalog
/** Plugin config (all optional — `apply` fills env-var and constant defaults). */
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
export interface Config {
/** Perplexity API key. Falls back to `$PERPLEXITY_API_KEY`. Empty → unavailable. */
apiKey?: string
/** Endpoint base; `/chat/completions` is appended. Defaults to the public API. */
baseURL?: string
/** Search model name. Defaults to `sonar`. */
model?: string
/** Upper bound on generated answer tokens. Defaults to 1024. */
maxTokens?: number
/** Recency window sent as `search_recency_filter`. Omitted = no filter. */
searchRecency?: 'day' | 'week' | 'month' | 'year'
}
```
Source: [`packages/web/web-search-perplexity/src/index.ts:30`](../packages/web/web-search-perplexity/src/index.ts)
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
<a id="deepseek-aidsh-webhook-github"></a>
## `@deepseek-ai/dsh-webhook-github`
Requires: `webServer` · `webhookRuntime` · `credentials`
```ts config-catalog
/** Required GitHub ingress configuration. */
export interface Config {
/** Adapter instance name carried to rules. */
readonly source: string
/** Exact absolute route path. */
readonly path: string
/** Credential reference containing the shared webhook secret. */
readonly secretEnv: string
/** Positive raw body ceiling in bytes. */
readonly maxBodyBytes: number
}
```
Source: [`packages/webhook/webhook-github/src/index.ts:17`](../packages/webhook/webhook-github/src/index.ts)
2026-08-13 13:43:43 +08:00
<a id="deepseek-aidsh-workflow-worker-thread"></a>
## `@deepseek-ai/dsh-workflow-worker-thread`
Merge branch 'structured-output-subagent-seam' into worktree-dynamic-workflows # Conflicts: # examples/acp-agent/tests/snapshots/cancel/session.jsonl # examples/acp-agent/tests/snapshots/error-finish/session.jsonl # examples/acp-agent/tests/snapshots/fs-edit/session.jsonl # examples/acp-agent/tests/snapshots/fs-policy-reject/session.jsonl # examples/acp-agent/tests/snapshots/fs-read-window/session.jsonl # examples/acp-agent/tests/snapshots/fs-read/session.jsonl # examples/acp-agent/tests/snapshots/fs-terminal-card/session.jsonl # examples/acp-agent/tests/snapshots/fs-write-overwrite/session.jsonl # examples/acp-agent/tests/snapshots/fs-write/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-ask/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-deny/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-pretool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/multi-turn/session.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.jsonl # examples/acp-agent/tests/snapshots/todo-plan/session.jsonl # examples/acp-agent/tests/snapshots/tool-call-turn/session.jsonl # examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl
2026-07-07 10:00:58 +08:00
Requires: `subagents`
```ts config-catalog
/** Plugin config (all optional — `static Config` supplies the defaults). */
export interface Config {
/** The `ctx.subagents` provider children run on (default `spawn`). */
provider?: string
/** Concurrent `agent()` ceiling; `0` (the default) auto-resolves to `min(16, max(1, cores - 2))`. */
maxConcurrentAgents?: number
/** Total `agent()` calls one run may start — the runaway-loop backstop (default 1000). */
maxTotalAgents?: number
/** Items accepted by a single `parallel()`/`pipeline()` call (default 4096). */
maxItemsPerCall?: number
2026-07-09 20:09:10 +08:00
/** vm timeout for the script's initial synchronous slice, inside the worker (default 5000 ms). */
Merge branch 'structured-output-subagent-seam' into worktree-dynamic-workflows # Conflicts: # examples/acp-agent/tests/snapshots/cancel/session.jsonl # examples/acp-agent/tests/snapshots/error-finish/session.jsonl # examples/acp-agent/tests/snapshots/fs-edit/session.jsonl # examples/acp-agent/tests/snapshots/fs-policy-reject/session.jsonl # examples/acp-agent/tests/snapshots/fs-read-window/session.jsonl # examples/acp-agent/tests/snapshots/fs-read/session.jsonl # examples/acp-agent/tests/snapshots/fs-terminal-card/session.jsonl # examples/acp-agent/tests/snapshots/fs-write-overwrite/session.jsonl # examples/acp-agent/tests/snapshots/fs-write/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-ask/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-deny/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-pretool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/multi-turn/session.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.jsonl # examples/acp-agent/tests/snapshots/todo-plan/session.jsonl # examples/acp-agent/tests/snapshots/tool-call-turn/session.jsonl # examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl
2026-07-07 10:00:58 +08:00
syncTimeoutMs?: number
/**
* How long after a cancellation an unsettled script may keep running before
* the run force-settles `cancelled` and its worker is TERMINATED (default
* 5000 ms); also bounds `dispose()`.
Merge branch 'structured-output-subagent-seam' into worktree-dynamic-workflows # Conflicts: # examples/acp-agent/tests/snapshots/cancel/session.jsonl # examples/acp-agent/tests/snapshots/error-finish/session.jsonl # examples/acp-agent/tests/snapshots/fs-edit/session.jsonl # examples/acp-agent/tests/snapshots/fs-policy-reject/session.jsonl # examples/acp-agent/tests/snapshots/fs-read-window/session.jsonl # examples/acp-agent/tests/snapshots/fs-read/session.jsonl # examples/acp-agent/tests/snapshots/fs-terminal-card/session.jsonl # examples/acp-agent/tests/snapshots/fs-write-overwrite/session.jsonl # examples/acp-agent/tests/snapshots/fs-write/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-ask/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-deny/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-pretool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/multi-turn/session.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.jsonl # examples/acp-agent/tests/snapshots/todo-plan/session.jsonl # examples/acp-agent/tests/snapshots/tool-call-turn/session.jsonl # examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl
2026-07-07 10:00:58 +08:00
*/
disposeGraceMs?: number
}
```
Source: [`packages/workflow/workflow-worker-thread/src/index.ts:32`](../packages/workflow/workflow-worker-thread/src/index.ts)
Merge branch 'structured-output-subagent-seam' into worktree-dynamic-workflows # Conflicts: # examples/acp-agent/tests/snapshots/cancel/session.jsonl # examples/acp-agent/tests/snapshots/error-finish/session.jsonl # examples/acp-agent/tests/snapshots/fs-edit/session.jsonl # examples/acp-agent/tests/snapshots/fs-policy-reject/session.jsonl # examples/acp-agent/tests/snapshots/fs-read-window/session.jsonl # examples/acp-agent/tests/snapshots/fs-read/session.jsonl # examples/acp-agent/tests/snapshots/fs-terminal-card/session.jsonl # examples/acp-agent/tests/snapshots/fs-write-overwrite/session.jsonl # examples/acp-agent/tests/snapshots/fs-write/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-ask/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-deny/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-pretool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/multi-turn/session.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.jsonl # examples/acp-agent/tests/snapshots/todo-plan/session.jsonl # examples/acp-agent/tests/snapshots/tool-call-turn/session.jsonl # examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl
2026-07-07 10:00:58 +08:00
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## Loadable plugins with no config
These load from a `cordis.yml` entry with no `config:` block; they declare no configuration API.
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
- `@deepseek-ai/dsh-acp-app` — requires `cmdlineArgs` ([`packages/bundle/acp-app/src/index.ts`](../packages/bundle/acp-app/src/index.ts))
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
- `@deepseek-ai/dsh-agent` ([`packages/core/agent/src/index.ts`](../packages/core/agent/src/index.ts))
- `@deepseek-ai/dsh-api-gateway` — requires `typert` ([`packages/api/gateway/src/index.ts`](../packages/api/gateway/src/index.ts))
- `@deepseek-ai/dsh-api-remotes` — requires `typertGateway` ([`packages/api/remotes/src/index.ts`](../packages/api/remotes/src/index.ts))
- `@deepseek-ai/dsh-api-workspace-controller` — requires `typert` · `workspaceRegistry` ([`packages/api/workspace-controller/src/index.ts`](../packages/api/workspace-controller/src/index.ts))
- `@deepseek-ai/dsh-authorization` — requires `credentials` ([`packages/credentials/authorization/src/index.ts`](../packages/credentials/authorization/src/index.ts))
- `@deepseek-ai/dsh-client-locale` ([`packages/client/locale/src/index.ts`](../packages/client/locale/src/index.ts))
- `@deepseek-ai/dsh-client-modules` — requires `webServer` · `loader` ([`packages/client/modules/src/index.ts`](../packages/client/modules/src/index.ts))
- `@deepseek-ai/dsh-client-ui-agent-preset` ([`packages/client/ui-agent-preset/src/index.ts`](../packages/client/ui-agent-preset/src/index.ts))
- `@deepseek-ai/dsh-client-ui-approval` ([`packages/client/ui-approval/src/index.ts`](../packages/client/ui-approval/src/index.ts))
- `@deepseek-ai/dsh-client-ui-attachment` ([`packages/client/ui-attachment/src/index.ts`](../packages/client/ui-attachment/src/index.ts))
- `@deepseek-ai/dsh-client-ui-brand-official` ([`packages/client/ui-brand-official/src/index.ts`](../packages/client/ui-brand-official/src/index.ts))
- `@deepseek-ai/dsh-client-ui-chat` ([`packages/client/ui-chat/src/index.ts`](../packages/client/ui-chat/src/index.ts))
- `@deepseek-ai/dsh-client-ui-commands` ([`packages/client/ui-commands/src/index.ts`](../packages/client/ui-commands/src/index.ts))
feat(gui): step1 skeleton — dsc web serves built web UI over booted harness host Five new modules: apps/dsc (bin: parseArgs + node:http static server + signal shutdown), packages/host/apiproxy (programmatic harness core composition, agents:[]), packages/client/web-runtime (React-free browser runtime), packages/client/web-ui (React mount), apps/web (vite build entry producing dist consumed by apps/dsc via package exports). Root wiring: apps/* workspace glob, dsh-* paths for host/client groups, demo:web script, apps/web/dist gitignore. No protocol/API routes yet — contract lands in step2 (see missions/tasks/20260719-1902-apiproxy-api-design). Includes the design + implementation archives (spec v2.1, deepseekchat baseline and harness boot research, implementation run log). Acceptance: 12/12 passed incl. real-key llm.stream smoke (51 chunks). feat(gui): apiproxy — four-quadrant RPC contract + fetch carriers, live end to end Contract layer (src/api/, 14 files): four named wire message types (ClientRequest / ServerResponse / ServerRequest / ClientResponse) as a discriminated union over strict bidirectional rpcId (initiator mints, responder echoes; channel and message fully decoupled — HTTP is the client->server pipe, SSE the reverse); narrow RpcRequest<P>/ RpcResponse<T> signature forms; RpcMethodMap with RequestPayload<K>/ ResponseValue<K> derivation; typed RpcError details map; approval/ question responses modeled as ClientResponse via a single /api/respond endpoint (RpcReceipt carrier ack); zod schemas anchored per Wire<T> against exactOptionalPropertyTypes. impl/api-proxy.ts: describe/list/create, both SSE streams (frame queue pump, subscribed baseline, lifecycle frames, signal cleanup); history pages on message boundaries (tail-back scan, partial included in the tail page); prompt dispatches queue->agent.send / steer->agent.steer with rpcId carried through MessageSource; cancel for attached sessions; cold-session resume deduped via a per-id promise map; host-level provider/model defaults injected at create/resume. fetch/: mechanical UNARY_ROUTES table, two-level parse with path==method check, SSE frames completed to ServerRequest full form; client mints -> narrows -> envelopes outbound, verifies rpcId echo inbound, streams SSE frames, four-quadrant onEnvelope tap (debug panel choke point). Real-browser fixes: URL base resolves to location.origin (hardcoded internal base broke real pages), browser-safe export paths. Design archives: contract design.md v2.0 with decision log, core-coverage audit, comparative studies, step2 impl run log. Probed end to end over real HTTP: prompt -> live model stream -> history returns the finished reply. feat(gui): RpcLog debug panel — fixture-driven milestone, playwright-verified 10/10 web-runtime: rpcLog + ui slices (zustand), four-quadrant RpcLogEntry (client-request / server-response / server-request / client-response), onEnvelope tap -> microtask-batched pump with 500-entry ring buffer, ConnectionController (private state, backoff reconnect), fixture API with fake envelopes (?fixture switch), bootWebRuntime; contract types via temporary local copies (api-types.ts, swapped for real imports when W3 client lands). web-ui: components/panels/RpcLog five-piece set (badge with unread count, floating panel, direction glyphs per quadrant, same-rpcId pair highlighting in two families, JSON payload expand, follow/pause, clear), App shell, utils/formatRelative, light-theme CSS variables with dark placeholders. dsc bin: mime lookup fixed to use the actually-served file (naked '/?query' no longer falls through to octet-stream download); shutdown closes SSE keep-alive connections so SIGTERM actually exits. Acceptance: scripts/verify-rpclog-panel.mjs (chromium headless) ALL PASS 10/10 over design.md §D 1-6. pkg: add web scripts for building feat(gui): session milestone — list + conversation over Session OOP, styled RpcLog v2.1 web-runtime: Session/SessionManager object layer (resident instances, mux frame routing, lineage flattening), foldSurface adapter with padding sentinels for paged windows, chunk accumulator for streaming partials, batched change notification (useSyncExternalStore contract), connection sinks + reconnect fix (the 300ms self-abort reconnect storm that made the session list flap is gone), fixture rewritten as a scripted host (60-turn history, typewriter replay, resident pending approval, child session); temporary contract copies deleted in favor of real apiproxy imports. web-ui: sessions screen (list with lineage indent + selection as container-local state), conversation view (turn grouping, reasoning fold, tool cards, steering, pending interaction cards, upward paging with scroll anchoring), input bar with queue/steer/stop; RpcLog panel restyled per docs/web-styling.md (tokenized palette, quadrant badge glyphs now vertical ↑↓⇟⇞, pair highlighting, floating shadow). docs/web-styling.md: living style guide (tokens, visual baseline, coding rules, evolution log). Acceptance: verify-session.mjs 31/31, verify-session-real.mjs 5/5 (real model streaming), verify-rpclog-panel.mjs 10/10. feat(gui): hostruntime split + repo-wide package prefix rename Package split (design: 20260720-0101-hostruntime-split-design): dsh-host-runtime carries bootHost + createApiProxy + startHost() (RunningHost {api, handler, defaults, ctx, dispose} — the seam Electron and any future shell reuses; ctx is the official front-door mount point); dsh-host-webserver carries the node:http static+API bridge (fixed: abort now keys on res 'close' + writableEnded — req 'close' fires on body end since Node 16 and was killing every SSE stream instantly, the reconnect-storm root cause); apps/dsc is now a thin assembly with web/-p subcommands. dsc -p runs the full isomorphic carrier chain in process (second real protocol consumer; probed end-to-end against the live model). Naming rule (user decree): packages under host/ and client/ carry the directory prefix in their npm name — dsh-host-apiproxy, dsh-client-web-runtime, dsh-client-web-ui renamed repo-wide in one frozen batch; explicit tsconfig paths entries added where the wildcard no longer matches. Acceptance: verify-session 31/31, verify-rpclog-panel 10/10, verify-session-real 7/7 (incl. new 12s connection-stability sentinels), tsc green, dsc web + dsc -p smoke both pass. refactor(gui): AbstractApiClient class hierarchy — OO client with inheritable seams AbstractApiClient (apiproxy) carries every protocol invariant: rpcId minting, four-quadrant envelope wrap/unwrap, zod parsing, SSE frame parsing, the payload-direct IApiClient surface (callers no longer mint rpcIds — the carrier does), and the instance-level envelope observation pump (batched via microtask; moved off module-level globals in rpc-log.ts, which is now a pure subscriber mapping envelopes into store entries — the debug panel observes the connection, it is not part of it). Platform subclasses own two abstract seams (doFetch, onEnvelope) plus three protocol-level virtuals for transportless overrides: InProcessApiClient (apiproxy; dsc -p uses new InProcessApiClient( host.handler)), WebApiClient (web-runtime), FixtureApiClient (fixture now subclasses instead of wrapping). Naming per decree: AbstractApiClient / IApiClient; ApiProxy stays the impl-side narrow-form contract. headless.ts call sites drop rpcRequest wrappers (payload-direct); split-design archive updated with the naming-rule ledger. tsc green; verify-session 31/31, verify-rpclog-panel 10/10, verify-session-real 7/7 (12s connection sentinel count=4); dsc -p smoke CALLER-OK. feat(gui): InputBar final form — bug batch, deepseekchat layout, single primary button, running locks input Squashes the whole InputBar iteration batch: IME/caret/auto-grow/focus/dedup bug fixes, layout aligned to the deepseekchat baseline, single primary button with hover flyout, finalized button semantics with the Codex-style icon circle, and running-state locking where stop is the only mid-turn action. The same batch carried the Chinese-to-English code comment sweep (density pruned), folded in here. docs(gui): purge work-log references from code comments 76 design-doc references cleared across the GUI packages: section pointers inlined as self-contained constraint statements, pure pointer comments dropped, milestone codenames and ruling tags out, and the 14 contract file headers switched to the formal RFC (the only sanctioned external reference). web-styling.md now cites the styling RFC instead of the disposable research archive. grep for work-log reference variants is clean across the GUI packages. docs(gui): file-header comments self-contained — drop RFC filename references RFC renames/reorgs must not require a source sweep (the 2026-07-20 two-way merge proved it). 11 headers lose only the '(RFC …)' tail and stay self-contained; api-proxy.ts keeps its minimal-first note. fix(gui): session streaming — freeze interrupted partials, sweep stale running calls, send force-scrolls Aborted turns never emit the finalizing assistant/message, so the accumulated partial and its running tool cards kept rendering below later messages — the "new message lands above the stopped reply" illusion. turn/end side effects now freeze content-bearing partials into interrupted terminal nodes (fractional seq keeps flow order; the live freeze and history replay converge through applyEventSideEffects, so a refresh reconstructs identical frozen nodes) and turn running tool cards into interrupted terminal cards; only content-free partials are swept outright. ConversationView gains the send-force-scroll rule (own words must be visible) alongside the pre-update atBottom follow flag. Regressions pinned as E2-4a–c (real host) and §E1-11h (fixture). feat(gui): webserver hardening verify script feat(gui): dark-mode toggle pinned to the sidebar bottom Interim home before the Settings page exists (the button re-homes with zero logic change — mechanics live in utils/theme.ts): html[data-theme] flip + dsc.theme localStorage, stored choice wins over the OS prefers-color-scheme default, applied in mount() before first paint so a dark reload never flashes light. Moon/sun inline SVG icon button at the sidebar's pinned bottom row. Pure front-end local concern: no RPC, no Session/store involvement. Dark sweep of list/conversation/input card/RPC panel found no unreadable pairs — no token changes needed. docs(gui): GUI RFCs and web styling handbook Layering+RPC protocol and web client architecture RFCs (post-reorg, developer-facing polish folded in) plus the styling engineering handbook. Mission work logs live in the commit above; PRs can be cut from this commit to include formal docs only. fix(gui): client object-layer hardening — audit timing/reference/resilience batches (S3-S5,C1-C3,C5-C8) fix(gui): carrier error channel + webserver backpressure (audit A1-A5,A7-A10,R2,R5) feat(gui): session persistence surface — cold list, project cwd, legacy no-cwd retirement refactor: rename dsc CLI to dsh — apps/cli, bin name, package scope Includes the root tsconfig project-references fix for host/* and client/web-runtime (originally a separate build fix commit). test(gui): three-tier suite — protocol/object/browser lanes, tier-a fill to per-file 100% test(gui): jsdom lane for web-ui + web-runtime coverage gate entry docs(gui): GUI testing system RFC (zh) feat(gui): tool-card views — contract slot, host-computed delivery, three-level card fallback fix(gui): lint clean across GUI packages — wrap long doc comments, drop dead type args, sync-return methods without awaits docs(gui): doc-sync mechanical fixes — JSDoc on apiproxy/host exports, RFC sketch fences ignore-check, md-wrap paragraphs, drop missions links, web-ui plain-ts entry chore(gui): module-graph regen + knip clean — drop dead re-exports, internalize createFixtureApi, scan web-ui tsx and verify mjs scripts build(gui): wire client/host packages into the lib build shape — tsc references + tsdown (web-ui css-external), lib manifests, cordis peer, apiproxy typed subpaths, vite src aliases test(gui): host-side per-file 100% coverage — apiproxy schema/carrier suites, webserver http-bridge suite, host-runtime composition suite; client/* coverage excluded pending the browser-side testing work item docs(gui): package READMEs for the five GUI packages — model-experience audit entries, limitations sections docs(gui): bilingual RFC pairs + client JSDoc completion — translate the three GUI RFCs to English with i18n records and manifest ratchet, Consequences sections both sides, full client/* export JSDoc, regen doc graphs and RFC index fix(scripts): doc-typecheck built-declarations mode maps /src/* subpath wildcards (apiproxy browser-safe channels) docs(gui): apply dsh rename across pr-gates docs — READMEs, layering RFC en, web-ui entry comment, i18n re-record fix(gui): post-rebase lint reconciliation — wrap main-tree long doc comments, read-through narrowing guards, abortError Error normalization, handleUnary generic justification fix(gui): post-rebase doc/test reconciliation — align host specs with evolved carrier contracts (sentinel rpcId, stream/error surfacing, url-path transport messages, defaults.cwd), Agent Note titles and relocated links, KV Cache effect sections, JSDoc on evolved exports fix(gui): second-rebase reconciliation to 509db0cb3 — restore api panel exports the baseline suites consume, knip workspace entries for jsdom lane and apps/web smokes, hoist result narrowing, align testing.md to the narrowed web-ui exclusion fix(test): vitest-scoped tsconfig maps bare imports for tsx specs — with GUI manifests now pointing at lib, an unmapped importer loaded a second copy of the web-runtime singletons fix(gui): typecheck + lint clean over the tool-card batch — brand callIds and object-form turn/end reason in the view spec, narrow fixture arg stringification, wrap long v8-ignore comments docs(gui): export JSDoc for tool-card surfaces + testing-note pairing header docs: rfc for web testing feat: add tools to host-runtime fix(gui): dispatch agent/error via agentEvents in host-runtime spec — mounted invariants plugin rejects raw ctx.emit without the scope carrier fix(gui): restore GUI knip workspaces + scripts/mjs entries and regenerate lockfile after master rebase fix(gui): post-rebase gate repairs — drop context-node envelope (master unwrapped injected content envelopes), regen event matrix, condense testing.md web-ui exclusion within budget fix(session): browser-safe deep-equal in surface — node:util import broke the vite bundle ci(gates): frontend vite build joins pre-push — node: imports in the client closure pass tsc but break the browser bundle test(tui): drop the checkout-dependent process.cwd() harness default — a long worktree path pushes the footer token counters past the 88-column fake terminal test(gui): jsdom behavior E2E — conversation main path over fixture runtime, reconnect banner lifecycle test(gui): jsdom RPC panel behavior — ledger rows, expand, pairing, pause/clear, follow-pause, payload truncation test(gui): jsdom tier-2 — InputBar guards, reasoning fold, JSON blocks, message variants, theme, create-then-select; act-harden banner case test(gui): jsdom tier-3 — ConversationView states/paging/force-bottom, ToolCallCard arms, PendingCard, list rows test(gui): jsdom tails — view-card variants, LogRow directions, registry hygiene, badge overflow, hook ops, mount glue test(gui): jsdom tails round 2 — call-ref blocks, resume follow, view precedence, failed create, empty-diff arm test(gui): jsdom final arms — anchor compensation, follow-off, interval ticks, view halves, node-over-running precedence test(gui): web-ui joins the per-file 100% coverage gate Annotation-only src changes plus the config swap. The web-ui exclusion is replaced by a single index.tsx entry (stale byte-identical duplicate of mount.tsx, nothing imports it; same entry-glue treatment as bin.ts) and the coverage include gains .tsx. v8-ignore sites (each with its reason inline): - ConversationView 3x ref-null guards; InputBar disabled-click guard - ToolCallCard both-null arms + windowless-custom argsRaw arm - LogRow css-module key fallbacks (start/stop block); RpcLogBody 3x ref-null guards - web-runtime drift from the tool-card batch: fixture presenter catch/str typo-guards, dense-array guards (fold-adapter reset, session rebuild, fixture backscan), live view-present arm (fixture replays are text-only; view vocabulary is covered by the history samples) test(gui): close the PR #443 host-side coverage gaps — apiproxy client abort arms, api-proxy cold/view paths, webserver drain - apiproxy fetch/client.ts: 3 new cases (pre-aborted signal short-circuits before transport + string reason mapping, non-Error/string reason falls to the default AbortError message, signal-less doFetch passthrough) - runtime/api-proxy.ts: one v8-ignore (summarizeCold cwd arm — list() filters cwd-less legacy metas) + api-proxy-cold.spec.ts (cold list merge: mtime source, locate-undefined and vanished-log fallbacks, lineage; no-persistence/no-factory resume → internal) + 2 view cases (history views with meta passthrough and orphan/bad-args/presenterless soft-falls, session/disposed open-call cleanup on the mux stream) - webserver/index.ts: /api/big fixture drives both drain-wait legs (full 8MiB readback after drain, mid-chunk disconnect wakes via 'close') feat: app shell fix: rebase conflicts fix: coverage fix(gui): lint clean after rebase — wrap long v8-ignore comments, unconditional v1 detail-block claim chore(gui): remove browser/probe verify scripts from scripts/ The six GUI acceptance/probe scripts (carrier-errors, rpclog-panel, session, session-real, webserver-backpressure, webserver-hardening) leave the repo's scripts/ tree; the three code comments that pointed at them now describe the coverage lane without naming a script path. fix(webserver): guard the request callback — one malformed request must not kill the process The async handle() had no top-level catch, so any throw inside it (a bad %-escape reaching decodeURIComponent, a client dropping mid-body, a response stream erroring) became an unhandled rejection and took the whole process down (audit R1 must-fix). The guard answers 400 when headers are not out yet, destroys the socket when they are, and reports the failure to onError (the package never prints). Spec covers all three legs: %-escape barrage → 400 + server stays alive, non-Error throw wrapped for onError, mid-stream explosion → socket teardown. feat: client AGENTS.md fix: client/AGENTS.md fix: rebase feat(gui): T0 cut 1 — 12 client package skeletons with contract stubs, dshClient declarations, tsdown client preset, theme token sheets feat(gui): T0 cut 2 — pure git mv migration per v3 §11 (connection six, runtime sessions/kernel, ui-conversation chat, ui-primitives markdown family, web shell + e2e) feat(gui): T0 cuts 3+4 — import rewiring to new package names, .legacy demotion of owner-rewrite files, legacy web-runtime/web-ui/apps-web retired to attic feat(gui): connection 对账刀——index.ts 精确导出清单替换 export *,intents.legacy 溶解删除 feat(client/ui-slots): SlotCore real implementation — kind semantics, sync version + microtask-batched notify, onMutate bridge feat(gui): web shell vite alias — retarget to new client packages, shell static surface only feat(gui): host 侧刀属地半——HostWebPluginRegistry(entries 扫描+internal/plugin 去抖重扫+dshClient 校验+exports./client 解析)、GET /plugins/<id>/client.js 分发端点、GET / 与 SPA fallback 注入 __DSH_BOOT__(webPlugins 可选注入,不传行为不变) feat(web-react): add use-sync-external-store dep + local shim typings feat(web-react): bindSnapshotSelector via uSES with-selector shim feat(gui): ui-layout concession-chain solver — pure computeColumns with contract geometry feat(gui): ui-layout LayoutService — four persisted stores, clamped actions, list-driven prune feat(gui): ui-layout AppFrame styles — grid columns, collapse-safe borders, edge drag handles test(gui): 存量 spec 平移——connection 三件+runtime 六件自 attic 捞回改包名路径全绿;api-helpers 按归属拆分(wire 半留 connection、classifier 半随 conversation.ts 入 runtime);boot-intents/preinit/rpc-log 随 intents/rpc-log 退役不迁(记 v3 §3.2 溶解项) feat(client/ui-primitives): StateDot/Button/Pill/Input/Menu atoms, ConnectionBanner de-legacied to pure props, JsonBlock CSS on --dsw tokens feat(web-react): createSnapshotStore engine (rafFlush batch, persist opt-in, dev freeze) + spec feat(gui): ui-layout AppFrame — grid tracks, pointer-capture drag handles with rAF throttle, frame ResizeObserver feat(web-react): useInvoke (external pending store, stable invoke, concurrency count) + spec test(web-react): bind spec — equality bail, custom eq, zero resubscribe, StrictMode, method sources feat(gui): ui-layout index rewiring — real exports, client apply provides ctx.layout and defines three slots feat(web-react): SessionProvider (renderBody deps) + RootBindingProvider + binding contexts + spec feat(gui): web shell AppRoot boot-page styles — self-contained with neutral token fallbacks feat(gui): web shell AppRoot — boot gate over loader status, fail-loud plugin failure list fix(gui): AppRoot gates on explicit settled signal — status-derived readiness races the incrementally filled table feat(client/ui-theme): ThemeService real implementation — registry with built-in light/dark, apply toggles body[data-ds-dark-theme], third-party token overrides as body inline vars feat(web-react): scopedSlots outlet (kind matrix, inject WeakMap caches, per-entry error boundary) + spec feat(gui): web shell module-table seed — pure-library entities for the loader require surface feat(client/i18n): I18nService real implementation — ns×locale registry, stable bind(ns) reference, zh fallback chain, zh/en skeleton dictionaries feat(gui): web shell assembly closure — layout exports via module table, SessionProvider + scopedSlots + RootBindingProvider feat: client/ui-conversation feat: code codedoc build(gui): root bundle green — web shell excluded from the lib workspace (vite app), ui-primitives lib externalizes css side-effect imports (web-ui precedent) gates(gui): verify-cordis-config follows aggregate tsconfig references (root is a shell over host/client programs); module graph regenerated for the twelve client packages chore(gui): retire legacy migration sources — every owner rewrite landed (t0-checklist §7 ledger honored); orphan css of retired components removed gates(gui): knip green groundwork — e2e/tsx entries for the new packages, loader-runtime deps ignored where loading is by specifier string, fake plugin ids un-bare-named, dead test export dropped chore(client): manifest shape batch A — ui-slots/web-react/ui-primitives invariant companions, files whitelist, cordis+invariants peer/dev, tsconfig refs chore(client): manifest shape batch B — connection/runtime/ui-conversation/ui-trajectory files whitelist, cordis peer+dev, explicit invariant lib entries (clientBundle signature) chore(client): manifest shape batch C — i18n/ui-layout/ui-sidebar/ui-theme invariant companions, files whitelist, invariants peer/dev, tsconfig refs chore(client): manifest shape batch D — web shell gains node-half lib entry + invariant companion + uniform files whitelist chore(client): drop verified-unused deps — dsh-tools from runtime/ui-conversation (types ride /presentation), ui-primitives+clsx from ui-layout gates(gui): doc-gate fixes — theme JSDoc prose, three client type-link exemptions, agent-note paths follow the migration, config catalog regenerated gates(gui): type-equiv manifest follows the types.ts extraction, approval JSDoc keeps its link form, persistence catalog regenerated docs(gui): per-constant JSDoc on the contract geometry exports (export-jsdoc gate) test(gates): loader-composition budget covers cold tsx resolution after the program split (was flaking at the default 5s) docs(gui): README substantiation batch 1 — ui-slots/ui-primitives/web-react/connection: Model Experience short form, real deferred-work ledgers, description accuracy pass fix(client): theme/i18n dual-entry split — service classes + cordis merges move to src/client (host catalog scanner no longer misclassifies client services), node halves keep types + empty apply; catalogs regenerated docs(gui): README substantiation batch 2 — runtime/ui-layout/ui-sidebar/ui-conversation: Model Experience short form, package-owned deferred-work ledgers (unload stub, watch approximation, /client value-import rule, global details state, two-state dots, stats duration gap, single-bundle caches) docs(gui): README substantiation batch 3 — ui-trajectory/ui-theme/i18n/web: Model Experience short form, deferred-work ledgers (placeholder charter, no theme toggle owner, empty locale dictionaries, one-shot rendering); both README gates green test(scripts): purity spec adopts clientBundle two-arg signature (explicit libEntry, no default) gates(gui): knip green — declaration-merge dep ignored, fake plugin id assembled at runtime, invariants dep de-duplicated to peer+dev, stale apps/web section dropped feat(gui): 门禁波次 host 三包 invariant 形状——apiproxy explained-empty 伴生(wire 契约层零事件面)、webserver 真关系伴生(manifest 行必解析出 clientPath,防 __DSH_BOOT__ 广告 404 bundle;apps/cli 发布 webPlugins 键供审计)、runtime 补 files 白名单;三包 exports/files/peer+dev/tsconfig refs 齐 fw-react 形状;constraints+invariants 双 gate 零违规 build(client): ui-layout/ui-sidebar tsdown configs adopt the explicit two-arg clientBundle signature (orphaned follow-up of the manifest shape batch) refactor(gui): shell boot becomes a library face — bootWebShell(el) exported for the apps/web entry; main.ts retired refactor(gui): exports 纪律刀1——ui-theme/i18n node index 收敛为只空 apply(Translate/LocaleDict/ThemeTokens 类型下沉 src/client/),ui-conversation 的 I18nService import 改 /client 子路径 build(typecheck): converge to root host aggregate + tsconfig.client.json — delete tsconfig.host.json, verify-cordis-config seeds both aggregates feat(gui): apps/web restored as the vite application — thin main over bootWebShell; dsh-client-web becomes a plain lib (index exports shell surface, vite files and e2e moved out) chore(gates): knip.json rewritten on the master base — same semantics, minimal diff (formatting churn dropped) docs(gui): 时效清扫②——testing.md 删 web-ui 覆盖豁免残句;web-styling.md 加 token 换代头注(--dsw-* 现行、工程约束条款仍有效并注明收编处) docs(gui): 时效清扫③——四对 GUI Agent Note 加路径更新头注(web-runtime/web-ui/dsh-frontend→现行 12 包结构;设计结论存续声明;双语对同步) docs(gui): 时效清扫③b——四对 note 头注的 i18n 配对哈希重录 build(typecheck): minimal-diff tsconfig shape — drop root files entry (purity spec + preset move to client program), compress comments, drop redundant util/home root ref feat(gui): apps/web restoration follow-through — dsh-frontend package name, cli dist resolve, root build:web filter, tsdown exemption dropped, vitest web lane + knip + client aggregate retargeted, e2e paths rebased refactor(gui): exports 纪律刀2——connection wire 六件 git mv 进 src/client/(wire 即该 dshClient 插件的 client 半),node index=只空 apply,/client 半边整面导出(v3 §3.2 清单原样),包内 tests 改 src/client 直取 refactor(gui): exports 纪律刀3——runtime 实现整体下沉 src/client/(sessions/slots/loader;契约类型与 cordis merge 随迁 client/index),node index=只空 apply;./loader exports 指 client/loader;全消费面(web 壳/ui-sidebar/ui-trajectory/tests)bare→/client 机械跟改;vitest.e2e 换 tsconfig.vitest paths(root tsconfig 排除 client 会把 /client import 掉到 exports 的浏览器 dist bundle) refactor(gui): exports 纪律刀3 补遗——ui-layout 三处 bare runtime import 改 /client(刀3 消费面机械跟改漏提交件;跨属地机械一行×3 报备 ui-shell) test(gui): drop the getSessionManager singleton case — the init/get pair is a dead legacy-boot surface with zero live consumers (SessionsService constructs and holds the manager under the plugin architecture); source removal tracked with rt-core refactor(gui): 删 manager.ts 尾部 initSessionManager/getSessionManager 单例对——旧 boot 直连遗物,插件化下 SessionsService 构造持有 manager,全仓零活消费者(convo-b 测试清扫对表,其测试用例已先行退役 7e2c51898);头注释同步去单例措辞 code refactor
2026-07-19 21:17:57 +08:00
- `@deepseek-ai/dsh-client-ui-conversation` ([`packages/client/ui-conversation/src/index.ts`](../packages/client/ui-conversation/src/index.ts))
2026-08-13 02:22:10 +08:00
- `@deepseek-ai/dsh-client-ui-cordis` ([`packages/extensions/ui-cordis/src/index.ts`](../packages/extensions/ui-cordis/src/index.ts))
- `@deepseek-ai/dsh-client-ui-deliverables` — requires `systemPrompt` ([`packages/client/ui-deliverables/src/index.ts`](../packages/client/ui-deliverables/src/index.ts))
- `@deepseek-ai/dsh-client-ui-directory-picker-browse` ([`packages/client/ui-directory-picker-browse/src/index.ts`](../packages/client/ui-directory-picker-browse/src/index.ts))
2026-08-12 01:43:12 +08:00
- `@deepseek-ai/dsh-client-ui-directory-picker-native` ([`packages/client/ui-directory-picker-native/src/index.ts`](../packages/client/ui-directory-picker-native/src/index.ts))
- `@deepseek-ai/dsh-client-ui-goal` ([`packages/client/ui-goal/src/index.ts`](../packages/client/ui-goal/src/index.ts))
- `@deepseek-ai/dsh-client-ui-input-trigger` ([`packages/client/ui-input-trigger/src/index.ts`](../packages/client/ui-input-trigger/src/index.ts))
- `@deepseek-ai/dsh-client-ui-jobs` ([`packages/client/ui-jobs/src/index.ts`](../packages/client/ui-jobs/src/index.ts))
feat(gui): step1 skeleton — dsc web serves built web UI over booted harness host Five new modules: apps/dsc (bin: parseArgs + node:http static server + signal shutdown), packages/host/apiproxy (programmatic harness core composition, agents:[]), packages/client/web-runtime (React-free browser runtime), packages/client/web-ui (React mount), apps/web (vite build entry producing dist consumed by apps/dsc via package exports). Root wiring: apps/* workspace glob, dsh-* paths for host/client groups, demo:web script, apps/web/dist gitignore. No protocol/API routes yet — contract lands in step2 (see missions/tasks/20260719-1902-apiproxy-api-design). Includes the design + implementation archives (spec v2.1, deepseekchat baseline and harness boot research, implementation run log). Acceptance: 12/12 passed incl. real-key llm.stream smoke (51 chunks). feat(gui): apiproxy — four-quadrant RPC contract + fetch carriers, live end to end Contract layer (src/api/, 14 files): four named wire message types (ClientRequest / ServerResponse / ServerRequest / ClientResponse) as a discriminated union over strict bidirectional rpcId (initiator mints, responder echoes; channel and message fully decoupled — HTTP is the client->server pipe, SSE the reverse); narrow RpcRequest<P>/ RpcResponse<T> signature forms; RpcMethodMap with RequestPayload<K>/ ResponseValue<K> derivation; typed RpcError details map; approval/ question responses modeled as ClientResponse via a single /api/respond endpoint (RpcReceipt carrier ack); zod schemas anchored per Wire<T> against exactOptionalPropertyTypes. impl/api-proxy.ts: describe/list/create, both SSE streams (frame queue pump, subscribed baseline, lifecycle frames, signal cleanup); history pages on message boundaries (tail-back scan, partial included in the tail page); prompt dispatches queue->agent.send / steer->agent.steer with rpcId carried through MessageSource; cancel for attached sessions; cold-session resume deduped via a per-id promise map; host-level provider/model defaults injected at create/resume. fetch/: mechanical UNARY_ROUTES table, two-level parse with path==method check, SSE frames completed to ServerRequest full form; client mints -> narrows -> envelopes outbound, verifies rpcId echo inbound, streams SSE frames, four-quadrant onEnvelope tap (debug panel choke point). Real-browser fixes: URL base resolves to location.origin (hardcoded internal base broke real pages), browser-safe export paths. Design archives: contract design.md v2.0 with decision log, core-coverage audit, comparative studies, step2 impl run log. Probed end to end over real HTTP: prompt -> live model stream -> history returns the finished reply. feat(gui): RpcLog debug panel — fixture-driven milestone, playwright-verified 10/10 web-runtime: rpcLog + ui slices (zustand), four-quadrant RpcLogEntry (client-request / server-response / server-request / client-response), onEnvelope tap -> microtask-batched pump with 500-entry ring buffer, ConnectionController (private state, backoff reconnect), fixture API with fake envelopes (?fixture switch), bootWebRuntime; contract types via temporary local copies (api-types.ts, swapped for real imports when W3 client lands). web-ui: components/panels/RpcLog five-piece set (badge with unread count, floating panel, direction glyphs per quadrant, same-rpcId pair highlighting in two families, JSON payload expand, follow/pause, clear), App shell, utils/formatRelative, light-theme CSS variables with dark placeholders. dsc bin: mime lookup fixed to use the actually-served file (naked '/?query' no longer falls through to octet-stream download); shutdown closes SSE keep-alive connections so SIGTERM actually exits. Acceptance: scripts/verify-rpclog-panel.mjs (chromium headless) ALL PASS 10/10 over design.md §D 1-6. pkg: add web scripts for building feat(gui): session milestone — list + conversation over Session OOP, styled RpcLog v2.1 web-runtime: Session/SessionManager object layer (resident instances, mux frame routing, lineage flattening), foldSurface adapter with padding sentinels for paged windows, chunk accumulator for streaming partials, batched change notification (useSyncExternalStore contract), connection sinks + reconnect fix (the 300ms self-abort reconnect storm that made the session list flap is gone), fixture rewritten as a scripted host (60-turn history, typewriter replay, resident pending approval, child session); temporary contract copies deleted in favor of real apiproxy imports. web-ui: sessions screen (list with lineage indent + selection as container-local state), conversation view (turn grouping, reasoning fold, tool cards, steering, pending interaction cards, upward paging with scroll anchoring), input bar with queue/steer/stop; RpcLog panel restyled per docs/web-styling.md (tokenized palette, quadrant badge glyphs now vertical ↑↓⇟⇞, pair highlighting, floating shadow). docs/web-styling.md: living style guide (tokens, visual baseline, coding rules, evolution log). Acceptance: verify-session.mjs 31/31, verify-session-real.mjs 5/5 (real model streaming), verify-rpclog-panel.mjs 10/10. feat(gui): hostruntime split + repo-wide package prefix rename Package split (design: 20260720-0101-hostruntime-split-design): dsh-host-runtime carries bootHost + createApiProxy + startHost() (RunningHost {api, handler, defaults, ctx, dispose} — the seam Electron and any future shell reuses; ctx is the official front-door mount point); dsh-host-webserver carries the node:http static+API bridge (fixed: abort now keys on res 'close' + writableEnded — req 'close' fires on body end since Node 16 and was killing every SSE stream instantly, the reconnect-storm root cause); apps/dsc is now a thin assembly with web/-p subcommands. dsc -p runs the full isomorphic carrier chain in process (second real protocol consumer; probed end-to-end against the live model). Naming rule (user decree): packages under host/ and client/ carry the directory prefix in their npm name — dsh-host-apiproxy, dsh-client-web-runtime, dsh-client-web-ui renamed repo-wide in one frozen batch; explicit tsconfig paths entries added where the wildcard no longer matches. Acceptance: verify-session 31/31, verify-rpclog-panel 10/10, verify-session-real 7/7 (incl. new 12s connection-stability sentinels), tsc green, dsc web + dsc -p smoke both pass. refactor(gui): AbstractApiClient class hierarchy — OO client with inheritable seams AbstractApiClient (apiproxy) carries every protocol invariant: rpcId minting, four-quadrant envelope wrap/unwrap, zod parsing, SSE frame parsing, the payload-direct IApiClient surface (callers no longer mint rpcIds — the carrier does), and the instance-level envelope observation pump (batched via microtask; moved off module-level globals in rpc-log.ts, which is now a pure subscriber mapping envelopes into store entries — the debug panel observes the connection, it is not part of it). Platform subclasses own two abstract seams (doFetch, onEnvelope) plus three protocol-level virtuals for transportless overrides: InProcessApiClient (apiproxy; dsc -p uses new InProcessApiClient( host.handler)), WebApiClient (web-runtime), FixtureApiClient (fixture now subclasses instead of wrapping). Naming per decree: AbstractApiClient / IApiClient; ApiProxy stays the impl-side narrow-form contract. headless.ts call sites drop rpcRequest wrappers (payload-direct); split-design archive updated with the naming-rule ledger. tsc green; verify-session 31/31, verify-rpclog-panel 10/10, verify-session-real 7/7 (12s connection sentinel count=4); dsc -p smoke CALLER-OK. feat(gui): InputBar final form — bug batch, deepseekchat layout, single primary button, running locks input Squashes the whole InputBar iteration batch: IME/caret/auto-grow/focus/dedup bug fixes, layout aligned to the deepseekchat baseline, single primary button with hover flyout, finalized button semantics with the Codex-style icon circle, and running-state locking where stop is the only mid-turn action. The same batch carried the Chinese-to-English code comment sweep (density pruned), folded in here. docs(gui): purge work-log references from code comments 76 design-doc references cleared across the GUI packages: section pointers inlined as self-contained constraint statements, pure pointer comments dropped, milestone codenames and ruling tags out, and the 14 contract file headers switched to the formal RFC (the only sanctioned external reference). web-styling.md now cites the styling RFC instead of the disposable research archive. grep for work-log reference variants is clean across the GUI packages. docs(gui): file-header comments self-contained — drop RFC filename references RFC renames/reorgs must not require a source sweep (the 2026-07-20 two-way merge proved it). 11 headers lose only the '(RFC …)' tail and stay self-contained; api-proxy.ts keeps its minimal-first note. fix(gui): session streaming — freeze interrupted partials, sweep stale running calls, send force-scrolls Aborted turns never emit the finalizing assistant/message, so the accumulated partial and its running tool cards kept rendering below later messages — the "new message lands above the stopped reply" illusion. turn/end side effects now freeze content-bearing partials into interrupted terminal nodes (fractional seq keeps flow order; the live freeze and history replay converge through applyEventSideEffects, so a refresh reconstructs identical frozen nodes) and turn running tool cards into interrupted terminal cards; only content-free partials are swept outright. ConversationView gains the send-force-scroll rule (own words must be visible) alongside the pre-update atBottom follow flag. Regressions pinned as E2-4a–c (real host) and §E1-11h (fixture). feat(gui): webserver hardening verify script feat(gui): dark-mode toggle pinned to the sidebar bottom Interim home before the Settings page exists (the button re-homes with zero logic change — mechanics live in utils/theme.ts): html[data-theme] flip + dsc.theme localStorage, stored choice wins over the OS prefers-color-scheme default, applied in mount() before first paint so a dark reload never flashes light. Moon/sun inline SVG icon button at the sidebar's pinned bottom row. Pure front-end local concern: no RPC, no Session/store involvement. Dark sweep of list/conversation/input card/RPC panel found no unreadable pairs — no token changes needed. docs(gui): GUI RFCs and web styling handbook Layering+RPC protocol and web client architecture RFCs (post-reorg, developer-facing polish folded in) plus the styling engineering handbook. Mission work logs live in the commit above; PRs can be cut from this commit to include formal docs only. fix(gui): client object-layer hardening — audit timing/reference/resilience batches (S3-S5,C1-C3,C5-C8) fix(gui): carrier error channel + webserver backpressure (audit A1-A5,A7-A10,R2,R5) feat(gui): session persistence surface — cold list, project cwd, legacy no-cwd retirement refactor: rename dsc CLI to dsh — apps/cli, bin name, package scope Includes the root tsconfig project-references fix for host/* and client/web-runtime (originally a separate build fix commit). test(gui): three-tier suite — protocol/object/browser lanes, tier-a fill to per-file 100% test(gui): jsdom lane for web-ui + web-runtime coverage gate entry docs(gui): GUI testing system RFC (zh) feat(gui): tool-card views — contract slot, host-computed delivery, three-level card fallback fix(gui): lint clean across GUI packages — wrap long doc comments, drop dead type args, sync-return methods without awaits docs(gui): doc-sync mechanical fixes — JSDoc on apiproxy/host exports, RFC sketch fences ignore-check, md-wrap paragraphs, drop missions links, web-ui plain-ts entry chore(gui): module-graph regen + knip clean — drop dead re-exports, internalize createFixtureApi, scan web-ui tsx and verify mjs scripts build(gui): wire client/host packages into the lib build shape — tsc references + tsdown (web-ui css-external), lib manifests, cordis peer, apiproxy typed subpaths, vite src aliases test(gui): host-side per-file 100% coverage — apiproxy schema/carrier suites, webserver http-bridge suite, host-runtime composition suite; client/* coverage excluded pending the browser-side testing work item docs(gui): package READMEs for the five GUI packages — model-experience audit entries, limitations sections docs(gui): bilingual RFC pairs + client JSDoc completion — translate the three GUI RFCs to English with i18n records and manifest ratchet, Consequences sections both sides, full client/* export JSDoc, regen doc graphs and RFC index fix(scripts): doc-typecheck built-declarations mode maps /src/* subpath wildcards (apiproxy browser-safe channels) docs(gui): apply dsh rename across pr-gates docs — READMEs, layering RFC en, web-ui entry comment, i18n re-record fix(gui): post-rebase lint reconciliation — wrap main-tree long doc comments, read-through narrowing guards, abortError Error normalization, handleUnary generic justification fix(gui): post-rebase doc/test reconciliation — align host specs with evolved carrier contracts (sentinel rpcId, stream/error surfacing, url-path transport messages, defaults.cwd), Agent Note titles and relocated links, KV Cache effect sections, JSDoc on evolved exports fix(gui): second-rebase reconciliation to 509db0cb3 — restore api panel exports the baseline suites consume, knip workspace entries for jsdom lane and apps/web smokes, hoist result narrowing, align testing.md to the narrowed web-ui exclusion fix(test): vitest-scoped tsconfig maps bare imports for tsx specs — with GUI manifests now pointing at lib, an unmapped importer loaded a second copy of the web-runtime singletons fix(gui): typecheck + lint clean over the tool-card batch — brand callIds and object-form turn/end reason in the view spec, narrow fixture arg stringification, wrap long v8-ignore comments docs(gui): export JSDoc for tool-card surfaces + testing-note pairing header docs: rfc for web testing feat: add tools to host-runtime fix(gui): dispatch agent/error via agentEvents in host-runtime spec — mounted invariants plugin rejects raw ctx.emit without the scope carrier fix(gui): restore GUI knip workspaces + scripts/mjs entries and regenerate lockfile after master rebase fix(gui): post-rebase gate repairs — drop context-node envelope (master unwrapped injected content envelopes), regen event matrix, condense testing.md web-ui exclusion within budget fix(session): browser-safe deep-equal in surface — node:util import broke the vite bundle ci(gates): frontend vite build joins pre-push — node: imports in the client closure pass tsc but break the browser bundle test(tui): drop the checkout-dependent process.cwd() harness default — a long worktree path pushes the footer token counters past the 88-column fake terminal test(gui): jsdom behavior E2E — conversation main path over fixture runtime, reconnect banner lifecycle test(gui): jsdom RPC panel behavior — ledger rows, expand, pairing, pause/clear, follow-pause, payload truncation test(gui): jsdom tier-2 — InputBar guards, reasoning fold, JSON blocks, message variants, theme, create-then-select; act-harden banner case test(gui): jsdom tier-3 — ConversationView states/paging/force-bottom, ToolCallCard arms, PendingCard, list rows test(gui): jsdom tails — view-card variants, LogRow directions, registry hygiene, badge overflow, hook ops, mount glue test(gui): jsdom tails round 2 — call-ref blocks, resume follow, view precedence, failed create, empty-diff arm test(gui): jsdom final arms — anchor compensation, follow-off, interval ticks, view halves, node-over-running precedence test(gui): web-ui joins the per-file 100% coverage gate Annotation-only src changes plus the config swap. The web-ui exclusion is replaced by a single index.tsx entry (stale byte-identical duplicate of mount.tsx, nothing imports it; same entry-glue treatment as bin.ts) and the coverage include gains .tsx. v8-ignore sites (each with its reason inline): - ConversationView 3x ref-null guards; InputBar disabled-click guard - ToolCallCard both-null arms + windowless-custom argsRaw arm - LogRow css-module key fallbacks (start/stop block); RpcLogBody 3x ref-null guards - web-runtime drift from the tool-card batch: fixture presenter catch/str typo-guards, dense-array guards (fold-adapter reset, session rebuild, fixture backscan), live view-present arm (fixture replays are text-only; view vocabulary is covered by the history samples) test(gui): close the PR #443 host-side coverage gaps — apiproxy client abort arms, api-proxy cold/view paths, webserver drain - apiproxy fetch/client.ts: 3 new cases (pre-aborted signal short-circuits before transport + string reason mapping, non-Error/string reason falls to the default AbortError message, signal-less doFetch passthrough) - runtime/api-proxy.ts: one v8-ignore (summarizeCold cwd arm — list() filters cwd-less legacy metas) + api-proxy-cold.spec.ts (cold list merge: mtime source, locate-undefined and vanished-log fallbacks, lineage; no-persistence/no-factory resume → internal) + 2 view cases (history views with meta passthrough and orphan/bad-args/presenterless soft-falls, session/disposed open-call cleanup on the mux stream) - webserver/index.ts: /api/big fixture drives both drain-wait legs (full 8MiB readback after drain, mid-chunk disconnect wakes via 'close') feat: app shell fix: rebase conflicts fix: coverage fix(gui): lint clean after rebase — wrap long v8-ignore comments, unconditional v1 detail-block claim chore(gui): remove browser/probe verify scripts from scripts/ The six GUI acceptance/probe scripts (carrier-errors, rpclog-panel, session, session-real, webserver-backpressure, webserver-hardening) leave the repo's scripts/ tree; the three code comments that pointed at them now describe the coverage lane without naming a script path. fix(webserver): guard the request callback — one malformed request must not kill the process The async handle() had no top-level catch, so any throw inside it (a bad %-escape reaching decodeURIComponent, a client dropping mid-body, a response stream erroring) became an unhandled rejection and took the whole process down (audit R1 must-fix). The guard answers 400 when headers are not out yet, destroys the socket when they are, and reports the failure to onError (the package never prints). Spec covers all three legs: %-escape barrage → 400 + server stays alive, non-Error throw wrapped for onError, mid-stream explosion → socket teardown. feat: client AGENTS.md fix: client/AGENTS.md fix: rebase feat(gui): T0 cut 1 — 12 client package skeletons with contract stubs, dshClient declarations, tsdown client preset, theme token sheets feat(gui): T0 cut 2 — pure git mv migration per v3 §11 (connection six, runtime sessions/kernel, ui-conversation chat, ui-primitives markdown family, web shell + e2e) feat(gui): T0 cuts 3+4 — import rewiring to new package names, .legacy demotion of owner-rewrite files, legacy web-runtime/web-ui/apps-web retired to attic feat(gui): connection 对账刀——index.ts 精确导出清单替换 export *,intents.legacy 溶解删除 feat(client/ui-slots): SlotCore real implementation — kind semantics, sync version + microtask-batched notify, onMutate bridge feat(gui): web shell vite alias — retarget to new client packages, shell static surface only feat(gui): host 侧刀属地半——HostWebPluginRegistry(entries 扫描+internal/plugin 去抖重扫+dshClient 校验+exports./client 解析)、GET /plugins/<id>/client.js 分发端点、GET / 与 SPA fallback 注入 __DSH_BOOT__(webPlugins 可选注入,不传行为不变) feat(web-react): add use-sync-external-store dep + local shim typings feat(web-react): bindSnapshotSelector via uSES with-selector shim feat(gui): ui-layout concession-chain solver — pure computeColumns with contract geometry feat(gui): ui-layout LayoutService — four persisted stores, clamped actions, list-driven prune feat(gui): ui-layout AppFrame styles — grid columns, collapse-safe borders, edge drag handles test(gui): 存量 spec 平移——connection 三件+runtime 六件自 attic 捞回改包名路径全绿;api-helpers 按归属拆分(wire 半留 connection、classifier 半随 conversation.ts 入 runtime);boot-intents/preinit/rpc-log 随 intents/rpc-log 退役不迁(记 v3 §3.2 溶解项) feat(client/ui-primitives): StateDot/Button/Pill/Input/Menu atoms, ConnectionBanner de-legacied to pure props, JsonBlock CSS on --dsw tokens feat(web-react): createSnapshotStore engine (rafFlush batch, persist opt-in, dev freeze) + spec feat(gui): ui-layout AppFrame — grid tracks, pointer-capture drag handles with rAF throttle, frame ResizeObserver feat(web-react): useInvoke (external pending store, stable invoke, concurrency count) + spec test(web-react): bind spec — equality bail, custom eq, zero resubscribe, StrictMode, method sources feat(gui): ui-layout index rewiring — real exports, client apply provides ctx.layout and defines three slots feat(web-react): SessionProvider (renderBody deps) + RootBindingProvider + binding contexts + spec feat(gui): web shell AppRoot boot-page styles — self-contained with neutral token fallbacks feat(gui): web shell AppRoot — boot gate over loader status, fail-loud plugin failure list fix(gui): AppRoot gates on explicit settled signal — status-derived readiness races the incrementally filled table feat(client/ui-theme): ThemeService real implementation — registry with built-in light/dark, apply toggles body[data-ds-dark-theme], third-party token overrides as body inline vars feat(web-react): scopedSlots outlet (kind matrix, inject WeakMap caches, per-entry error boundary) + spec feat(gui): web shell module-table seed — pure-library entities for the loader require surface feat(client/i18n): I18nService real implementation — ns×locale registry, stable bind(ns) reference, zh fallback chain, zh/en skeleton dictionaries feat(gui): web shell assembly closure — layout exports via module table, SessionProvider + scopedSlots + RootBindingProvider feat: client/ui-conversation feat: code codedoc build(gui): root bundle green — web shell excluded from the lib workspace (vite app), ui-primitives lib externalizes css side-effect imports (web-ui precedent) gates(gui): verify-cordis-config follows aggregate tsconfig references (root is a shell over host/client programs); module graph regenerated for the twelve client packages chore(gui): retire legacy migration sources — every owner rewrite landed (t0-checklist §7 ledger honored); orphan css of retired components removed gates(gui): knip green groundwork — e2e/tsx entries for the new packages, loader-runtime deps ignored where loading is by specifier string, fake plugin ids un-bare-named, dead test export dropped chore(client): manifest shape batch A — ui-slots/web-react/ui-primitives invariant companions, files whitelist, cordis+invariants peer/dev, tsconfig refs chore(client): manifest shape batch B — connection/runtime/ui-conversation/ui-trajectory files whitelist, cordis peer+dev, explicit invariant lib entries (clientBundle signature) chore(client): manifest shape batch C — i18n/ui-layout/ui-sidebar/ui-theme invariant companions, files whitelist, invariants peer/dev, tsconfig refs chore(client): manifest shape batch D — web shell gains node-half lib entry + invariant companion + uniform files whitelist chore(client): drop verified-unused deps — dsh-tools from runtime/ui-conversation (types ride /presentation), ui-primitives+clsx from ui-layout gates(gui): doc-gate fixes — theme JSDoc prose, three client type-link exemptions, agent-note paths follow the migration, config catalog regenerated gates(gui): type-equiv manifest follows the types.ts extraction, approval JSDoc keeps its link form, persistence catalog regenerated docs(gui): per-constant JSDoc on the contract geometry exports (export-jsdoc gate) test(gates): loader-composition budget covers cold tsx resolution after the program split (was flaking at the default 5s) docs(gui): README substantiation batch 1 — ui-slots/ui-primitives/web-react/connection: Model Experience short form, real deferred-work ledgers, description accuracy pass fix(client): theme/i18n dual-entry split — service classes + cordis merges move to src/client (host catalog scanner no longer misclassifies client services), node halves keep types + empty apply; catalogs regenerated docs(gui): README substantiation batch 2 — runtime/ui-layout/ui-sidebar/ui-conversation: Model Experience short form, package-owned deferred-work ledgers (unload stub, watch approximation, /client value-import rule, global details state, two-state dots, stats duration gap, single-bundle caches) docs(gui): README substantiation batch 3 — ui-trajectory/ui-theme/i18n/web: Model Experience short form, deferred-work ledgers (placeholder charter, no theme toggle owner, empty locale dictionaries, one-shot rendering); both README gates green test(scripts): purity spec adopts clientBundle two-arg signature (explicit libEntry, no default) gates(gui): knip green — declaration-merge dep ignored, fake plugin id assembled at runtime, invariants dep de-duplicated to peer+dev, stale apps/web section dropped feat(gui): 门禁波次 host 三包 invariant 形状——apiproxy explained-empty 伴生(wire 契约层零事件面)、webserver 真关系伴生(manifest 行必解析出 clientPath,防 __DSH_BOOT__ 广告 404 bundle;apps/cli 发布 webPlugins 键供审计)、runtime 补 files 白名单;三包 exports/files/peer+dev/tsconfig refs 齐 fw-react 形状;constraints+invariants 双 gate 零违规 build(client): ui-layout/ui-sidebar tsdown configs adopt the explicit two-arg clientBundle signature (orphaned follow-up of the manifest shape batch) refactor(gui): shell boot becomes a library face — bootWebShell(el) exported for the apps/web entry; main.ts retired refactor(gui): exports 纪律刀1——ui-theme/i18n node index 收敛为只空 apply(Translate/LocaleDict/ThemeTokens 类型下沉 src/client/),ui-conversation 的 I18nService import 改 /client 子路径 build(typecheck): converge to root host aggregate + tsconfig.client.json — delete tsconfig.host.json, verify-cordis-config seeds both aggregates feat(gui): apps/web restored as the vite application — thin main over bootWebShell; dsh-client-web becomes a plain lib (index exports shell surface, vite files and e2e moved out) chore(gates): knip.json rewritten on the master base — same semantics, minimal diff (formatting churn dropped) docs(gui): 时效清扫②——testing.md 删 web-ui 覆盖豁免残句;web-styling.md 加 token 换代头注(--dsw-* 现行、工程约束条款仍有效并注明收编处) docs(gui): 时效清扫③——四对 GUI Agent Note 加路径更新头注(web-runtime/web-ui/dsh-frontend→现行 12 包结构;设计结论存续声明;双语对同步) docs(gui): 时效清扫③b——四对 note 头注的 i18n 配对哈希重录 build(typecheck): minimal-diff tsconfig shape — drop root files entry (purity spec + preset move to client program), compress comments, drop redundant util/home root ref feat(gui): apps/web restoration follow-through — dsh-frontend package name, cli dist resolve, root build:web filter, tsdown exemption dropped, vitest web lane + knip + client aggregate retargeted, e2e paths rebased refactor(gui): exports 纪律刀2——connection wire 六件 git mv 进 src/client/(wire 即该 dshClient 插件的 client 半),node index=只空 apply,/client 半边整面导出(v3 §3.2 清单原样),包内 tests 改 src/client 直取 refactor(gui): exports 纪律刀3——runtime 实现整体下沉 src/client/(sessions/slots/loader;契约类型与 cordis merge 随迁 client/index),node index=只空 apply;./loader exports 指 client/loader;全消费面(web 壳/ui-sidebar/ui-trajectory/tests)bare→/client 机械跟改;vitest.e2e 换 tsconfig.vitest paths(root tsconfig 排除 client 会把 /client import 掉到 exports 的浏览器 dist bundle) refactor(gui): exports 纪律刀3 补遗——ui-layout 三处 bare runtime import 改 /client(刀3 消费面机械跟改漏提交件;跨属地机械一行×3 报备 ui-shell) test(gui): drop the getSessionManager singleton case — the init/get pair is a dead legacy-boot surface with zero live consumers (SessionsService constructs and holds the manager under the plugin architecture); source removal tracked with rt-core refactor(gui): 删 manager.ts 尾部 initSessionManager/getSessionManager 单例对——旧 boot 直连遗物,插件化下 SessionsService 构造持有 manager,全仓零活消费者(convo-b 测试清扫对表,其测试用例已先行退役 7e2c51898);头注释同步去单例措辞 code refactor
2026-07-19 21:17:57 +08:00
- `@deepseek-ai/dsh-client-ui-layout` ([`packages/client/ui-layout/src/index.ts`](../packages/client/ui-layout/src/index.ts))
- `@deepseek-ai/dsh-client-ui-message-feedback` ([`packages/client/ui-message-feedback/src/index.ts`](../packages/client/ui-message-feedback/src/index.ts))
- `@deepseek-ai/dsh-client-ui-model-selection` ([`packages/client/ui-model-selection/src/index.ts`](../packages/client/ui-model-selection/src/index.ts))
- `@deepseek-ai/dsh-client-ui-permission-presets` ([`packages/client/ui-permission-presets/src/index.ts`](../packages/client/ui-permission-presets/src/index.ts))
- `@deepseek-ai/dsh-client-ui-plan` ([`packages/client/ui-plan/src/index.ts`](../packages/client/ui-plan/src/index.ts))
- `@deepseek-ai/dsh-client-ui-reference` ([`packages/client/ui-reference/src/index.ts`](../packages/client/ui-reference/src/index.ts))
- `@deepseek-ai/dsh-client-ui-renderer` ([`packages/client/ui-renderer/src/index.ts`](../packages/client/ui-renderer/src/index.ts))
- `@deepseek-ai/dsh-client-ui-session` ([`packages/client/ui-session/src/index.ts`](../packages/client/ui-session/src/index.ts))
- `@deepseek-ai/dsh-client-ui-settings` ([`packages/client/ui-settings/src/index.ts`](../packages/client/ui-settings/src/index.ts))
- `@deepseek-ai/dsh-client-ui-settings-general` ([`packages/client/ui-settings-general/src/index.ts`](../packages/client/ui-settings-general/src/index.ts))
- `@deepseek-ai/dsh-client-ui-settings-models` ([`packages/client/ui-settings-models/src/index.ts`](../packages/client/ui-settings-models/src/index.ts))
- `@deepseek-ai/dsh-client-ui-settings-plugin-inventory` ([`packages/client/ui-settings-plugin-inventory/src/index.ts`](../packages/client/ui-settings-plugin-inventory/src/index.ts))
- `@deepseek-ai/dsh-client-ui-settings-plugins` ([`packages/client/ui-settings-plugins/src/index.ts`](../packages/client/ui-settings-plugins/src/index.ts))
feat(gui): step1 skeleton — dsc web serves built web UI over booted harness host Five new modules: apps/dsc (bin: parseArgs + node:http static server + signal shutdown), packages/host/apiproxy (programmatic harness core composition, agents:[]), packages/client/web-runtime (React-free browser runtime), packages/client/web-ui (React mount), apps/web (vite build entry producing dist consumed by apps/dsc via package exports). Root wiring: apps/* workspace glob, dsh-* paths for host/client groups, demo:web script, apps/web/dist gitignore. No protocol/API routes yet — contract lands in step2 (see missions/tasks/20260719-1902-apiproxy-api-design). Includes the design + implementation archives (spec v2.1, deepseekchat baseline and harness boot research, implementation run log). Acceptance: 12/12 passed incl. real-key llm.stream smoke (51 chunks). feat(gui): apiproxy — four-quadrant RPC contract + fetch carriers, live end to end Contract layer (src/api/, 14 files): four named wire message types (ClientRequest / ServerResponse / ServerRequest / ClientResponse) as a discriminated union over strict bidirectional rpcId (initiator mints, responder echoes; channel and message fully decoupled — HTTP is the client->server pipe, SSE the reverse); narrow RpcRequest<P>/ RpcResponse<T> signature forms; RpcMethodMap with RequestPayload<K>/ ResponseValue<K> derivation; typed RpcError details map; approval/ question responses modeled as ClientResponse via a single /api/respond endpoint (RpcReceipt carrier ack); zod schemas anchored per Wire<T> against exactOptionalPropertyTypes. impl/api-proxy.ts: describe/list/create, both SSE streams (frame queue pump, subscribed baseline, lifecycle frames, signal cleanup); history pages on message boundaries (tail-back scan, partial included in the tail page); prompt dispatches queue->agent.send / steer->agent.steer with rpcId carried through MessageSource; cancel for attached sessions; cold-session resume deduped via a per-id promise map; host-level provider/model defaults injected at create/resume. fetch/: mechanical UNARY_ROUTES table, two-level parse with path==method check, SSE frames completed to ServerRequest full form; client mints -> narrows -> envelopes outbound, verifies rpcId echo inbound, streams SSE frames, four-quadrant onEnvelope tap (debug panel choke point). Real-browser fixes: URL base resolves to location.origin (hardcoded internal base broke real pages), browser-safe export paths. Design archives: contract design.md v2.0 with decision log, core-coverage audit, comparative studies, step2 impl run log. Probed end to end over real HTTP: prompt -> live model stream -> history returns the finished reply. feat(gui): RpcLog debug panel — fixture-driven milestone, playwright-verified 10/10 web-runtime: rpcLog + ui slices (zustand), four-quadrant RpcLogEntry (client-request / server-response / server-request / client-response), onEnvelope tap -> microtask-batched pump with 500-entry ring buffer, ConnectionController (private state, backoff reconnect), fixture API with fake envelopes (?fixture switch), bootWebRuntime; contract types via temporary local copies (api-types.ts, swapped for real imports when W3 client lands). web-ui: components/panels/RpcLog five-piece set (badge with unread count, floating panel, direction glyphs per quadrant, same-rpcId pair highlighting in two families, JSON payload expand, follow/pause, clear), App shell, utils/formatRelative, light-theme CSS variables with dark placeholders. dsc bin: mime lookup fixed to use the actually-served file (naked '/?query' no longer falls through to octet-stream download); shutdown closes SSE keep-alive connections so SIGTERM actually exits. Acceptance: scripts/verify-rpclog-panel.mjs (chromium headless) ALL PASS 10/10 over design.md §D 1-6. pkg: add web scripts for building feat(gui): session milestone — list + conversation over Session OOP, styled RpcLog v2.1 web-runtime: Session/SessionManager object layer (resident instances, mux frame routing, lineage flattening), foldSurface adapter with padding sentinels for paged windows, chunk accumulator for streaming partials, batched change notification (useSyncExternalStore contract), connection sinks + reconnect fix (the 300ms self-abort reconnect storm that made the session list flap is gone), fixture rewritten as a scripted host (60-turn history, typewriter replay, resident pending approval, child session); temporary contract copies deleted in favor of real apiproxy imports. web-ui: sessions screen (list with lineage indent + selection as container-local state), conversation view (turn grouping, reasoning fold, tool cards, steering, pending interaction cards, upward paging with scroll anchoring), input bar with queue/steer/stop; RpcLog panel restyled per docs/web-styling.md (tokenized palette, quadrant badge glyphs now vertical ↑↓⇟⇞, pair highlighting, floating shadow). docs/web-styling.md: living style guide (tokens, visual baseline, coding rules, evolution log). Acceptance: verify-session.mjs 31/31, verify-session-real.mjs 5/5 (real model streaming), verify-rpclog-panel.mjs 10/10. feat(gui): hostruntime split + repo-wide package prefix rename Package split (design: 20260720-0101-hostruntime-split-design): dsh-host-runtime carries bootHost + createApiProxy + startHost() (RunningHost {api, handler, defaults, ctx, dispose} — the seam Electron and any future shell reuses; ctx is the official front-door mount point); dsh-host-webserver carries the node:http static+API bridge (fixed: abort now keys on res 'close' + writableEnded — req 'close' fires on body end since Node 16 and was killing every SSE stream instantly, the reconnect-storm root cause); apps/dsc is now a thin assembly with web/-p subcommands. dsc -p runs the full isomorphic carrier chain in process (second real protocol consumer; probed end-to-end against the live model). Naming rule (user decree): packages under host/ and client/ carry the directory prefix in their npm name — dsh-host-apiproxy, dsh-client-web-runtime, dsh-client-web-ui renamed repo-wide in one frozen batch; explicit tsconfig paths entries added where the wildcard no longer matches. Acceptance: verify-session 31/31, verify-rpclog-panel 10/10, verify-session-real 7/7 (incl. new 12s connection-stability sentinels), tsc green, dsc web + dsc -p smoke both pass. refactor(gui): AbstractApiClient class hierarchy — OO client with inheritable seams AbstractApiClient (apiproxy) carries every protocol invariant: rpcId minting, four-quadrant envelope wrap/unwrap, zod parsing, SSE frame parsing, the payload-direct IApiClient surface (callers no longer mint rpcIds — the carrier does), and the instance-level envelope observation pump (batched via microtask; moved off module-level globals in rpc-log.ts, which is now a pure subscriber mapping envelopes into store entries — the debug panel observes the connection, it is not part of it). Platform subclasses own two abstract seams (doFetch, onEnvelope) plus three protocol-level virtuals for transportless overrides: InProcessApiClient (apiproxy; dsc -p uses new InProcessApiClient( host.handler)), WebApiClient (web-runtime), FixtureApiClient (fixture now subclasses instead of wrapping). Naming per decree: AbstractApiClient / IApiClient; ApiProxy stays the impl-side narrow-form contract. headless.ts call sites drop rpcRequest wrappers (payload-direct); split-design archive updated with the naming-rule ledger. tsc green; verify-session 31/31, verify-rpclog-panel 10/10, verify-session-real 7/7 (12s connection sentinel count=4); dsc -p smoke CALLER-OK. feat(gui): InputBar final form — bug batch, deepseekchat layout, single primary button, running locks input Squashes the whole InputBar iteration batch: IME/caret/auto-grow/focus/dedup bug fixes, layout aligned to the deepseekchat baseline, single primary button with hover flyout, finalized button semantics with the Codex-style icon circle, and running-state locking where stop is the only mid-turn action. The same batch carried the Chinese-to-English code comment sweep (density pruned), folded in here. docs(gui): purge work-log references from code comments 76 design-doc references cleared across the GUI packages: section pointers inlined as self-contained constraint statements, pure pointer comments dropped, milestone codenames and ruling tags out, and the 14 contract file headers switched to the formal RFC (the only sanctioned external reference). web-styling.md now cites the styling RFC instead of the disposable research archive. grep for work-log reference variants is clean across the GUI packages. docs(gui): file-header comments self-contained — drop RFC filename references RFC renames/reorgs must not require a source sweep (the 2026-07-20 two-way merge proved it). 11 headers lose only the '(RFC …)' tail and stay self-contained; api-proxy.ts keeps its minimal-first note. fix(gui): session streaming — freeze interrupted partials, sweep stale running calls, send force-scrolls Aborted turns never emit the finalizing assistant/message, so the accumulated partial and its running tool cards kept rendering below later messages — the "new message lands above the stopped reply" illusion. turn/end side effects now freeze content-bearing partials into interrupted terminal nodes (fractional seq keeps flow order; the live freeze and history replay converge through applyEventSideEffects, so a refresh reconstructs identical frozen nodes) and turn running tool cards into interrupted terminal cards; only content-free partials are swept outright. ConversationView gains the send-force-scroll rule (own words must be visible) alongside the pre-update atBottom follow flag. Regressions pinned as E2-4a–c (real host) and §E1-11h (fixture). feat(gui): webserver hardening verify script feat(gui): dark-mode toggle pinned to the sidebar bottom Interim home before the Settings page exists (the button re-homes with zero logic change — mechanics live in utils/theme.ts): html[data-theme] flip + dsc.theme localStorage, stored choice wins over the OS prefers-color-scheme default, applied in mount() before first paint so a dark reload never flashes light. Moon/sun inline SVG icon button at the sidebar's pinned bottom row. Pure front-end local concern: no RPC, no Session/store involvement. Dark sweep of list/conversation/input card/RPC panel found no unreadable pairs — no token changes needed. docs(gui): GUI RFCs and web styling handbook Layering+RPC protocol and web client architecture RFCs (post-reorg, developer-facing polish folded in) plus the styling engineering handbook. Mission work logs live in the commit above; PRs can be cut from this commit to include formal docs only. fix(gui): client object-layer hardening — audit timing/reference/resilience batches (S3-S5,C1-C3,C5-C8) fix(gui): carrier error channel + webserver backpressure (audit A1-A5,A7-A10,R2,R5) feat(gui): session persistence surface — cold list, project cwd, legacy no-cwd retirement refactor: rename dsc CLI to dsh — apps/cli, bin name, package scope Includes the root tsconfig project-references fix for host/* and client/web-runtime (originally a separate build fix commit). test(gui): three-tier suite — protocol/object/browser lanes, tier-a fill to per-file 100% test(gui): jsdom lane for web-ui + web-runtime coverage gate entry docs(gui): GUI testing system RFC (zh) feat(gui): tool-card views — contract slot, host-computed delivery, three-level card fallback fix(gui): lint clean across GUI packages — wrap long doc comments, drop dead type args, sync-return methods without awaits docs(gui): doc-sync mechanical fixes — JSDoc on apiproxy/host exports, RFC sketch fences ignore-check, md-wrap paragraphs, drop missions links, web-ui plain-ts entry chore(gui): module-graph regen + knip clean — drop dead re-exports, internalize createFixtureApi, scan web-ui tsx and verify mjs scripts build(gui): wire client/host packages into the lib build shape — tsc references + tsdown (web-ui css-external), lib manifests, cordis peer, apiproxy typed subpaths, vite src aliases test(gui): host-side per-file 100% coverage — apiproxy schema/carrier suites, webserver http-bridge suite, host-runtime composition suite; client/* coverage excluded pending the browser-side testing work item docs(gui): package READMEs for the five GUI packages — model-experience audit entries, limitations sections docs(gui): bilingual RFC pairs + client JSDoc completion — translate the three GUI RFCs to English with i18n records and manifest ratchet, Consequences sections both sides, full client/* export JSDoc, regen doc graphs and RFC index fix(scripts): doc-typecheck built-declarations mode maps /src/* subpath wildcards (apiproxy browser-safe channels) docs(gui): apply dsh rename across pr-gates docs — READMEs, layering RFC en, web-ui entry comment, i18n re-record fix(gui): post-rebase lint reconciliation — wrap main-tree long doc comments, read-through narrowing guards, abortError Error normalization, handleUnary generic justification fix(gui): post-rebase doc/test reconciliation — align host specs with evolved carrier contracts (sentinel rpcId, stream/error surfacing, url-path transport messages, defaults.cwd), Agent Note titles and relocated links, KV Cache effect sections, JSDoc on evolved exports fix(gui): second-rebase reconciliation to 509db0cb3 — restore api panel exports the baseline suites consume, knip workspace entries for jsdom lane and apps/web smokes, hoist result narrowing, align testing.md to the narrowed web-ui exclusion fix(test): vitest-scoped tsconfig maps bare imports for tsx specs — with GUI manifests now pointing at lib, an unmapped importer loaded a second copy of the web-runtime singletons fix(gui): typecheck + lint clean over the tool-card batch — brand callIds and object-form turn/end reason in the view spec, narrow fixture arg stringification, wrap long v8-ignore comments docs(gui): export JSDoc for tool-card surfaces + testing-note pairing header docs: rfc for web testing feat: add tools to host-runtime fix(gui): dispatch agent/error via agentEvents in host-runtime spec — mounted invariants plugin rejects raw ctx.emit without the scope carrier fix(gui): restore GUI knip workspaces + scripts/mjs entries and regenerate lockfile after master rebase fix(gui): post-rebase gate repairs — drop context-node envelope (master unwrapped injected content envelopes), regen event matrix, condense testing.md web-ui exclusion within budget fix(session): browser-safe deep-equal in surface — node:util import broke the vite bundle ci(gates): frontend vite build joins pre-push — node: imports in the client closure pass tsc but break the browser bundle test(tui): drop the checkout-dependent process.cwd() harness default — a long worktree path pushes the footer token counters past the 88-column fake terminal test(gui): jsdom behavior E2E — conversation main path over fixture runtime, reconnect banner lifecycle test(gui): jsdom RPC panel behavior — ledger rows, expand, pairing, pause/clear, follow-pause, payload truncation test(gui): jsdom tier-2 — InputBar guards, reasoning fold, JSON blocks, message variants, theme, create-then-select; act-harden banner case test(gui): jsdom tier-3 — ConversationView states/paging/force-bottom, ToolCallCard arms, PendingCard, list rows test(gui): jsdom tails — view-card variants, LogRow directions, registry hygiene, badge overflow, hook ops, mount glue test(gui): jsdom tails round 2 — call-ref blocks, resume follow, view precedence, failed create, empty-diff arm test(gui): jsdom final arms — anchor compensation, follow-off, interval ticks, view halves, node-over-running precedence test(gui): web-ui joins the per-file 100% coverage gate Annotation-only src changes plus the config swap. The web-ui exclusion is replaced by a single index.tsx entry (stale byte-identical duplicate of mount.tsx, nothing imports it; same entry-glue treatment as bin.ts) and the coverage include gains .tsx. v8-ignore sites (each with its reason inline): - ConversationView 3x ref-null guards; InputBar disabled-click guard - ToolCallCard both-null arms + windowless-custom argsRaw arm - LogRow css-module key fallbacks (start/stop block); RpcLogBody 3x ref-null guards - web-runtime drift from the tool-card batch: fixture presenter catch/str typo-guards, dense-array guards (fold-adapter reset, session rebuild, fixture backscan), live view-present arm (fixture replays are text-only; view vocabulary is covered by the history samples) test(gui): close the PR #443 host-side coverage gaps — apiproxy client abort arms, api-proxy cold/view paths, webserver drain - apiproxy fetch/client.ts: 3 new cases (pre-aborted signal short-circuits before transport + string reason mapping, non-Error/string reason falls to the default AbortError message, signal-less doFetch passthrough) - runtime/api-proxy.ts: one v8-ignore (summarizeCold cwd arm — list() filters cwd-less legacy metas) + api-proxy-cold.spec.ts (cold list merge: mtime source, locate-undefined and vanished-log fallbacks, lineage; no-persistence/no-factory resume → internal) + 2 view cases (history views with meta passthrough and orphan/bad-args/presenterless soft-falls, session/disposed open-call cleanup on the mux stream) - webserver/index.ts: /api/big fixture drives both drain-wait legs (full 8MiB readback after drain, mid-chunk disconnect wakes via 'close') feat: app shell fix: rebase conflicts fix: coverage fix(gui): lint clean after rebase — wrap long v8-ignore comments, unconditional v1 detail-block claim chore(gui): remove browser/probe verify scripts from scripts/ The six GUI acceptance/probe scripts (carrier-errors, rpclog-panel, session, session-real, webserver-backpressure, webserver-hardening) leave the repo's scripts/ tree; the three code comments that pointed at them now describe the coverage lane without naming a script path. fix(webserver): guard the request callback — one malformed request must not kill the process The async handle() had no top-level catch, so any throw inside it (a bad %-escape reaching decodeURIComponent, a client dropping mid-body, a response stream erroring) became an unhandled rejection and took the whole process down (audit R1 must-fix). The guard answers 400 when headers are not out yet, destroys the socket when they are, and reports the failure to onError (the package never prints). Spec covers all three legs: %-escape barrage → 400 + server stays alive, non-Error throw wrapped for onError, mid-stream explosion → socket teardown. feat: client AGENTS.md fix: client/AGENTS.md fix: rebase feat(gui): T0 cut 1 — 12 client package skeletons with contract stubs, dshClient declarations, tsdown client preset, theme token sheets feat(gui): T0 cut 2 — pure git mv migration per v3 §11 (connection six, runtime sessions/kernel, ui-conversation chat, ui-primitives markdown family, web shell + e2e) feat(gui): T0 cuts 3+4 — import rewiring to new package names, .legacy demotion of owner-rewrite files, legacy web-runtime/web-ui/apps-web retired to attic feat(gui): connection 对账刀——index.ts 精确导出清单替换 export *,intents.legacy 溶解删除 feat(client/ui-slots): SlotCore real implementation — kind semantics, sync version + microtask-batched notify, onMutate bridge feat(gui): web shell vite alias — retarget to new client packages, shell static surface only feat(gui): host 侧刀属地半——HostWebPluginRegistry(entries 扫描+internal/plugin 去抖重扫+dshClient 校验+exports./client 解析)、GET /plugins/<id>/client.js 分发端点、GET / 与 SPA fallback 注入 __DSH_BOOT__(webPlugins 可选注入,不传行为不变) feat(web-react): add use-sync-external-store dep + local shim typings feat(web-react): bindSnapshotSelector via uSES with-selector shim feat(gui): ui-layout concession-chain solver — pure computeColumns with contract geometry feat(gui): ui-layout LayoutService — four persisted stores, clamped actions, list-driven prune feat(gui): ui-layout AppFrame styles — grid columns, collapse-safe borders, edge drag handles test(gui): 存量 spec 平移——connection 三件+runtime 六件自 attic 捞回改包名路径全绿;api-helpers 按归属拆分(wire 半留 connection、classifier 半随 conversation.ts 入 runtime);boot-intents/preinit/rpc-log 随 intents/rpc-log 退役不迁(记 v3 §3.2 溶解项) feat(client/ui-primitives): StateDot/Button/Pill/Input/Menu atoms, ConnectionBanner de-legacied to pure props, JsonBlock CSS on --dsw tokens feat(web-react): createSnapshotStore engine (rafFlush batch, persist opt-in, dev freeze) + spec feat(gui): ui-layout AppFrame — grid tracks, pointer-capture drag handles with rAF throttle, frame ResizeObserver feat(web-react): useInvoke (external pending store, stable invoke, concurrency count) + spec test(web-react): bind spec — equality bail, custom eq, zero resubscribe, StrictMode, method sources feat(gui): ui-layout index rewiring — real exports, client apply provides ctx.layout and defines three slots feat(web-react): SessionProvider (renderBody deps) + RootBindingProvider + binding contexts + spec feat(gui): web shell AppRoot boot-page styles — self-contained with neutral token fallbacks feat(gui): web shell AppRoot — boot gate over loader status, fail-loud plugin failure list fix(gui): AppRoot gates on explicit settled signal — status-derived readiness races the incrementally filled table feat(client/ui-theme): ThemeService real implementation — registry with built-in light/dark, apply toggles body[data-ds-dark-theme], third-party token overrides as body inline vars feat(web-react): scopedSlots outlet (kind matrix, inject WeakMap caches, per-entry error boundary) + spec feat(gui): web shell module-table seed — pure-library entities for the loader require surface feat(client/i18n): I18nService real implementation — ns×locale registry, stable bind(ns) reference, zh fallback chain, zh/en skeleton dictionaries feat(gui): web shell assembly closure — layout exports via module table, SessionProvider + scopedSlots + RootBindingProvider feat: client/ui-conversation feat: code codedoc build(gui): root bundle green — web shell excluded from the lib workspace (vite app), ui-primitives lib externalizes css side-effect imports (web-ui precedent) gates(gui): verify-cordis-config follows aggregate tsconfig references (root is a shell over host/client programs); module graph regenerated for the twelve client packages chore(gui): retire legacy migration sources — every owner rewrite landed (t0-checklist §7 ledger honored); orphan css of retired components removed gates(gui): knip green groundwork — e2e/tsx entries for the new packages, loader-runtime deps ignored where loading is by specifier string, fake plugin ids un-bare-named, dead test export dropped chore(client): manifest shape batch A — ui-slots/web-react/ui-primitives invariant companions, files whitelist, cordis+invariants peer/dev, tsconfig refs chore(client): manifest shape batch B — connection/runtime/ui-conversation/ui-trajectory files whitelist, cordis peer+dev, explicit invariant lib entries (clientBundle signature) chore(client): manifest shape batch C — i18n/ui-layout/ui-sidebar/ui-theme invariant companions, files whitelist, invariants peer/dev, tsconfig refs chore(client): manifest shape batch D — web shell gains node-half lib entry + invariant companion + uniform files whitelist chore(client): drop verified-unused deps — dsh-tools from runtime/ui-conversation (types ride /presentation), ui-primitives+clsx from ui-layout gates(gui): doc-gate fixes — theme JSDoc prose, three client type-link exemptions, agent-note paths follow the migration, config catalog regenerated gates(gui): type-equiv manifest follows the types.ts extraction, approval JSDoc keeps its link form, persistence catalog regenerated docs(gui): per-constant JSDoc on the contract geometry exports (export-jsdoc gate) test(gates): loader-composition budget covers cold tsx resolution after the program split (was flaking at the default 5s) docs(gui): README substantiation batch 1 — ui-slots/ui-primitives/web-react/connection: Model Experience short form, real deferred-work ledgers, description accuracy pass fix(client): theme/i18n dual-entry split — service classes + cordis merges move to src/client (host catalog scanner no longer misclassifies client services), node halves keep types + empty apply; catalogs regenerated docs(gui): README substantiation batch 2 — runtime/ui-layout/ui-sidebar/ui-conversation: Model Experience short form, package-owned deferred-work ledgers (unload stub, watch approximation, /client value-import rule, global details state, two-state dots, stats duration gap, single-bundle caches) docs(gui): README substantiation batch 3 — ui-trajectory/ui-theme/i18n/web: Model Experience short form, deferred-work ledgers (placeholder charter, no theme toggle owner, empty locale dictionaries, one-shot rendering); both README gates green test(scripts): purity spec adopts clientBundle two-arg signature (explicit libEntry, no default) gates(gui): knip green — declaration-merge dep ignored, fake plugin id assembled at runtime, invariants dep de-duplicated to peer+dev, stale apps/web section dropped feat(gui): 门禁波次 host 三包 invariant 形状——apiproxy explained-empty 伴生(wire 契约层零事件面)、webserver 真关系伴生(manifest 行必解析出 clientPath,防 __DSH_BOOT__ 广告 404 bundle;apps/cli 发布 webPlugins 键供审计)、runtime 补 files 白名单;三包 exports/files/peer+dev/tsconfig refs 齐 fw-react 形状;constraints+invariants 双 gate 零违规 build(client): ui-layout/ui-sidebar tsdown configs adopt the explicit two-arg clientBundle signature (orphaned follow-up of the manifest shape batch) refactor(gui): shell boot becomes a library face — bootWebShell(el) exported for the apps/web entry; main.ts retired refactor(gui): exports 纪律刀1——ui-theme/i18n node index 收敛为只空 apply(Translate/LocaleDict/ThemeTokens 类型下沉 src/client/),ui-conversation 的 I18nService import 改 /client 子路径 build(typecheck): converge to root host aggregate + tsconfig.client.json — delete tsconfig.host.json, verify-cordis-config seeds both aggregates feat(gui): apps/web restored as the vite application — thin main over bootWebShell; dsh-client-web becomes a plain lib (index exports shell surface, vite files and e2e moved out) chore(gates): knip.json rewritten on the master base — same semantics, minimal diff (formatting churn dropped) docs(gui): 时效清扫②——testing.md 删 web-ui 覆盖豁免残句;web-styling.md 加 token 换代头注(--dsw-* 现行、工程约束条款仍有效并注明收编处) docs(gui): 时效清扫③——四对 GUI Agent Note 加路径更新头注(web-runtime/web-ui/dsh-frontend→现行 12 包结构;设计结论存续声明;双语对同步) docs(gui): 时效清扫③b——四对 note 头注的 i18n 配对哈希重录 build(typecheck): minimal-diff tsconfig shape — drop root files entry (purity spec + preset move to client program), compress comments, drop redundant util/home root ref feat(gui): apps/web restoration follow-through — dsh-frontend package name, cli dist resolve, root build:web filter, tsdown exemption dropped, vitest web lane + knip + client aggregate retargeted, e2e paths rebased refactor(gui): exports 纪律刀2——connection wire 六件 git mv 进 src/client/(wire 即该 dshClient 插件的 client 半),node index=只空 apply,/client 半边整面导出(v3 §3.2 清单原样),包内 tests 改 src/client 直取 refactor(gui): exports 纪律刀3——runtime 实现整体下沉 src/client/(sessions/slots/loader;契约类型与 cordis merge 随迁 client/index),node index=只空 apply;./loader exports 指 client/loader;全消费面(web 壳/ui-sidebar/ui-trajectory/tests)bare→/client 机械跟改;vitest.e2e 换 tsconfig.vitest paths(root tsconfig 排除 client 会把 /client import 掉到 exports 的浏览器 dist bundle) refactor(gui): exports 纪律刀3 补遗——ui-layout 三处 bare runtime import 改 /client(刀3 消费面机械跟改漏提交件;跨属地机械一行×3 报备 ui-shell) test(gui): drop the getSessionManager singleton case — the init/get pair is a dead legacy-boot surface with zero live consumers (SessionsService constructs and holds the manager under the plugin architecture); source removal tracked with rt-core refactor(gui): 删 manager.ts 尾部 initSessionManager/getSessionManager 单例对——旧 boot 直连遗物,插件化下 SessionsService 构造持有 manager,全仓零活消费者(convo-b 测试清扫对表,其测试用例已先行退役 7e2c51898);头注释同步去单例措辞 code refactor
2026-07-19 21:17:57 +08:00
- `@deepseek-ai/dsh-client-ui-sidebar` ([`packages/client/ui-sidebar/src/index.ts`](../packages/client/ui-sidebar/src/index.ts))
- `@deepseek-ai/dsh-client-ui-skill` ([`packages/client/ui-skill/src/index.ts`](../packages/client/ui-skill/src/index.ts))
- `@deepseek-ai/dsh-client-ui-subagent` ([`packages/client/ui-subagent/src/index.ts`](../packages/client/ui-subagent/src/index.ts))
feat(gui): step1 skeleton — dsc web serves built web UI over booted harness host Five new modules: apps/dsc (bin: parseArgs + node:http static server + signal shutdown), packages/host/apiproxy (programmatic harness core composition, agents:[]), packages/client/web-runtime (React-free browser runtime), packages/client/web-ui (React mount), apps/web (vite build entry producing dist consumed by apps/dsc via package exports). Root wiring: apps/* workspace glob, dsh-* paths for host/client groups, demo:web script, apps/web/dist gitignore. No protocol/API routes yet — contract lands in step2 (see missions/tasks/20260719-1902-apiproxy-api-design). Includes the design + implementation archives (spec v2.1, deepseekchat baseline and harness boot research, implementation run log). Acceptance: 12/12 passed incl. real-key llm.stream smoke (51 chunks). feat(gui): apiproxy — four-quadrant RPC contract + fetch carriers, live end to end Contract layer (src/api/, 14 files): four named wire message types (ClientRequest / ServerResponse / ServerRequest / ClientResponse) as a discriminated union over strict bidirectional rpcId (initiator mints, responder echoes; channel and message fully decoupled — HTTP is the client->server pipe, SSE the reverse); narrow RpcRequest<P>/ RpcResponse<T> signature forms; RpcMethodMap with RequestPayload<K>/ ResponseValue<K> derivation; typed RpcError details map; approval/ question responses modeled as ClientResponse via a single /api/respond endpoint (RpcReceipt carrier ack); zod schemas anchored per Wire<T> against exactOptionalPropertyTypes. impl/api-proxy.ts: describe/list/create, both SSE streams (frame queue pump, subscribed baseline, lifecycle frames, signal cleanup); history pages on message boundaries (tail-back scan, partial included in the tail page); prompt dispatches queue->agent.send / steer->agent.steer with rpcId carried through MessageSource; cancel for attached sessions; cold-session resume deduped via a per-id promise map; host-level provider/model defaults injected at create/resume. fetch/: mechanical UNARY_ROUTES table, two-level parse with path==method check, SSE frames completed to ServerRequest full form; client mints -> narrows -> envelopes outbound, verifies rpcId echo inbound, streams SSE frames, four-quadrant onEnvelope tap (debug panel choke point). Real-browser fixes: URL base resolves to location.origin (hardcoded internal base broke real pages), browser-safe export paths. Design archives: contract design.md v2.0 with decision log, core-coverage audit, comparative studies, step2 impl run log. Probed end to end over real HTTP: prompt -> live model stream -> history returns the finished reply. feat(gui): RpcLog debug panel — fixture-driven milestone, playwright-verified 10/10 web-runtime: rpcLog + ui slices (zustand), four-quadrant RpcLogEntry (client-request / server-response / server-request / client-response), onEnvelope tap -> microtask-batched pump with 500-entry ring buffer, ConnectionController (private state, backoff reconnect), fixture API with fake envelopes (?fixture switch), bootWebRuntime; contract types via temporary local copies (api-types.ts, swapped for real imports when W3 client lands). web-ui: components/panels/RpcLog five-piece set (badge with unread count, floating panel, direction glyphs per quadrant, same-rpcId pair highlighting in two families, JSON payload expand, follow/pause, clear), App shell, utils/formatRelative, light-theme CSS variables with dark placeholders. dsc bin: mime lookup fixed to use the actually-served file (naked '/?query' no longer falls through to octet-stream download); shutdown closes SSE keep-alive connections so SIGTERM actually exits. Acceptance: scripts/verify-rpclog-panel.mjs (chromium headless) ALL PASS 10/10 over design.md §D 1-6. pkg: add web scripts for building feat(gui): session milestone — list + conversation over Session OOP, styled RpcLog v2.1 web-runtime: Session/SessionManager object layer (resident instances, mux frame routing, lineage flattening), foldSurface adapter with padding sentinels for paged windows, chunk accumulator for streaming partials, batched change notification (useSyncExternalStore contract), connection sinks + reconnect fix (the 300ms self-abort reconnect storm that made the session list flap is gone), fixture rewritten as a scripted host (60-turn history, typewriter replay, resident pending approval, child session); temporary contract copies deleted in favor of real apiproxy imports. web-ui: sessions screen (list with lineage indent + selection as container-local state), conversation view (turn grouping, reasoning fold, tool cards, steering, pending interaction cards, upward paging with scroll anchoring), input bar with queue/steer/stop; RpcLog panel restyled per docs/web-styling.md (tokenized palette, quadrant badge glyphs now vertical ↑↓⇟⇞, pair highlighting, floating shadow). docs/web-styling.md: living style guide (tokens, visual baseline, coding rules, evolution log). Acceptance: verify-session.mjs 31/31, verify-session-real.mjs 5/5 (real model streaming), verify-rpclog-panel.mjs 10/10. feat(gui): hostruntime split + repo-wide package prefix rename Package split (design: 20260720-0101-hostruntime-split-design): dsh-host-runtime carries bootHost + createApiProxy + startHost() (RunningHost {api, handler, defaults, ctx, dispose} — the seam Electron and any future shell reuses; ctx is the official front-door mount point); dsh-host-webserver carries the node:http static+API bridge (fixed: abort now keys on res 'close' + writableEnded — req 'close' fires on body end since Node 16 and was killing every SSE stream instantly, the reconnect-storm root cause); apps/dsc is now a thin assembly with web/-p subcommands. dsc -p runs the full isomorphic carrier chain in process (second real protocol consumer; probed end-to-end against the live model). Naming rule (user decree): packages under host/ and client/ carry the directory prefix in their npm name — dsh-host-apiproxy, dsh-client-web-runtime, dsh-client-web-ui renamed repo-wide in one frozen batch; explicit tsconfig paths entries added where the wildcard no longer matches. Acceptance: verify-session 31/31, verify-rpclog-panel 10/10, verify-session-real 7/7 (incl. new 12s connection-stability sentinels), tsc green, dsc web + dsc -p smoke both pass. refactor(gui): AbstractApiClient class hierarchy — OO client with inheritable seams AbstractApiClient (apiproxy) carries every protocol invariant: rpcId minting, four-quadrant envelope wrap/unwrap, zod parsing, SSE frame parsing, the payload-direct IApiClient surface (callers no longer mint rpcIds — the carrier does), and the instance-level envelope observation pump (batched via microtask; moved off module-level globals in rpc-log.ts, which is now a pure subscriber mapping envelopes into store entries — the debug panel observes the connection, it is not part of it). Platform subclasses own two abstract seams (doFetch, onEnvelope) plus three protocol-level virtuals for transportless overrides: InProcessApiClient (apiproxy; dsc -p uses new InProcessApiClient( host.handler)), WebApiClient (web-runtime), FixtureApiClient (fixture now subclasses instead of wrapping). Naming per decree: AbstractApiClient / IApiClient; ApiProxy stays the impl-side narrow-form contract. headless.ts call sites drop rpcRequest wrappers (payload-direct); split-design archive updated with the naming-rule ledger. tsc green; verify-session 31/31, verify-rpclog-panel 10/10, verify-session-real 7/7 (12s connection sentinel count=4); dsc -p smoke CALLER-OK. feat(gui): InputBar final form — bug batch, deepseekchat layout, single primary button, running locks input Squashes the whole InputBar iteration batch: IME/caret/auto-grow/focus/dedup bug fixes, layout aligned to the deepseekchat baseline, single primary button with hover flyout, finalized button semantics with the Codex-style icon circle, and running-state locking where stop is the only mid-turn action. The same batch carried the Chinese-to-English code comment sweep (density pruned), folded in here. docs(gui): purge work-log references from code comments 76 design-doc references cleared across the GUI packages: section pointers inlined as self-contained constraint statements, pure pointer comments dropped, milestone codenames and ruling tags out, and the 14 contract file headers switched to the formal RFC (the only sanctioned external reference). web-styling.md now cites the styling RFC instead of the disposable research archive. grep for work-log reference variants is clean across the GUI packages. docs(gui): file-header comments self-contained — drop RFC filename references RFC renames/reorgs must not require a source sweep (the 2026-07-20 two-way merge proved it). 11 headers lose only the '(RFC …)' tail and stay self-contained; api-proxy.ts keeps its minimal-first note. fix(gui): session streaming — freeze interrupted partials, sweep stale running calls, send force-scrolls Aborted turns never emit the finalizing assistant/message, so the accumulated partial and its running tool cards kept rendering below later messages — the "new message lands above the stopped reply" illusion. turn/end side effects now freeze content-bearing partials into interrupted terminal nodes (fractional seq keeps flow order; the live freeze and history replay converge through applyEventSideEffects, so a refresh reconstructs identical frozen nodes) and turn running tool cards into interrupted terminal cards; only content-free partials are swept outright. ConversationView gains the send-force-scroll rule (own words must be visible) alongside the pre-update atBottom follow flag. Regressions pinned as E2-4a–c (real host) and §E1-11h (fixture). feat(gui): webserver hardening verify script feat(gui): dark-mode toggle pinned to the sidebar bottom Interim home before the Settings page exists (the button re-homes with zero logic change — mechanics live in utils/theme.ts): html[data-theme] flip + dsc.theme localStorage, stored choice wins over the OS prefers-color-scheme default, applied in mount() before first paint so a dark reload never flashes light. Moon/sun inline SVG icon button at the sidebar's pinned bottom row. Pure front-end local concern: no RPC, no Session/store involvement. Dark sweep of list/conversation/input card/RPC panel found no unreadable pairs — no token changes needed. docs(gui): GUI RFCs and web styling handbook Layering+RPC protocol and web client architecture RFCs (post-reorg, developer-facing polish folded in) plus the styling engineering handbook. Mission work logs live in the commit above; PRs can be cut from this commit to include formal docs only. fix(gui): client object-layer hardening — audit timing/reference/resilience batches (S3-S5,C1-C3,C5-C8) fix(gui): carrier error channel + webserver backpressure (audit A1-A5,A7-A10,R2,R5) feat(gui): session persistence surface — cold list, project cwd, legacy no-cwd retirement refactor: rename dsc CLI to dsh — apps/cli, bin name, package scope Includes the root tsconfig project-references fix for host/* and client/web-runtime (originally a separate build fix commit). test(gui): three-tier suite — protocol/object/browser lanes, tier-a fill to per-file 100% test(gui): jsdom lane for web-ui + web-runtime coverage gate entry docs(gui): GUI testing system RFC (zh) feat(gui): tool-card views — contract slot, host-computed delivery, three-level card fallback fix(gui): lint clean across GUI packages — wrap long doc comments, drop dead type args, sync-return methods without awaits docs(gui): doc-sync mechanical fixes — JSDoc on apiproxy/host exports, RFC sketch fences ignore-check, md-wrap paragraphs, drop missions links, web-ui plain-ts entry chore(gui): module-graph regen + knip clean — drop dead re-exports, internalize createFixtureApi, scan web-ui tsx and verify mjs scripts build(gui): wire client/host packages into the lib build shape — tsc references + tsdown (web-ui css-external), lib manifests, cordis peer, apiproxy typed subpaths, vite src aliases test(gui): host-side per-file 100% coverage — apiproxy schema/carrier suites, webserver http-bridge suite, host-runtime composition suite; client/* coverage excluded pending the browser-side testing work item docs(gui): package READMEs for the five GUI packages — model-experience audit entries, limitations sections docs(gui): bilingual RFC pairs + client JSDoc completion — translate the three GUI RFCs to English with i18n records and manifest ratchet, Consequences sections both sides, full client/* export JSDoc, regen doc graphs and RFC index fix(scripts): doc-typecheck built-declarations mode maps /src/* subpath wildcards (apiproxy browser-safe channels) docs(gui): apply dsh rename across pr-gates docs — READMEs, layering RFC en, web-ui entry comment, i18n re-record fix(gui): post-rebase lint reconciliation — wrap main-tree long doc comments, read-through narrowing guards, abortError Error normalization, handleUnary generic justification fix(gui): post-rebase doc/test reconciliation — align host specs with evolved carrier contracts (sentinel rpcId, stream/error surfacing, url-path transport messages, defaults.cwd), Agent Note titles and relocated links, KV Cache effect sections, JSDoc on evolved exports fix(gui): second-rebase reconciliation to 509db0cb3 — restore api panel exports the baseline suites consume, knip workspace entries for jsdom lane and apps/web smokes, hoist result narrowing, align testing.md to the narrowed web-ui exclusion fix(test): vitest-scoped tsconfig maps bare imports for tsx specs — with GUI manifests now pointing at lib, an unmapped importer loaded a second copy of the web-runtime singletons fix(gui): typecheck + lint clean over the tool-card batch — brand callIds and object-form turn/end reason in the view spec, narrow fixture arg stringification, wrap long v8-ignore comments docs(gui): export JSDoc for tool-card surfaces + testing-note pairing header docs: rfc for web testing feat: add tools to host-runtime fix(gui): dispatch agent/error via agentEvents in host-runtime spec — mounted invariants plugin rejects raw ctx.emit without the scope carrier fix(gui): restore GUI knip workspaces + scripts/mjs entries and regenerate lockfile after master rebase fix(gui): post-rebase gate repairs — drop context-node envelope (master unwrapped injected content envelopes), regen event matrix, condense testing.md web-ui exclusion within budget fix(session): browser-safe deep-equal in surface — node:util import broke the vite bundle ci(gates): frontend vite build joins pre-push — node: imports in the client closure pass tsc but break the browser bundle test(tui): drop the checkout-dependent process.cwd() harness default — a long worktree path pushes the footer token counters past the 88-column fake terminal test(gui): jsdom behavior E2E — conversation main path over fixture runtime, reconnect banner lifecycle test(gui): jsdom RPC panel behavior — ledger rows, expand, pairing, pause/clear, follow-pause, payload truncation test(gui): jsdom tier-2 — InputBar guards, reasoning fold, JSON blocks, message variants, theme, create-then-select; act-harden banner case test(gui): jsdom tier-3 — ConversationView states/paging/force-bottom, ToolCallCard arms, PendingCard, list rows test(gui): jsdom tails — view-card variants, LogRow directions, registry hygiene, badge overflow, hook ops, mount glue test(gui): jsdom tails round 2 — call-ref blocks, resume follow, view precedence, failed create, empty-diff arm test(gui): jsdom final arms — anchor compensation, follow-off, interval ticks, view halves, node-over-running precedence test(gui): web-ui joins the per-file 100% coverage gate Annotation-only src changes plus the config swap. The web-ui exclusion is replaced by a single index.tsx entry (stale byte-identical duplicate of mount.tsx, nothing imports it; same entry-glue treatment as bin.ts) and the coverage include gains .tsx. v8-ignore sites (each with its reason inline): - ConversationView 3x ref-null guards; InputBar disabled-click guard - ToolCallCard both-null arms + windowless-custom argsRaw arm - LogRow css-module key fallbacks (start/stop block); RpcLogBody 3x ref-null guards - web-runtime drift from the tool-card batch: fixture presenter catch/str typo-guards, dense-array guards (fold-adapter reset, session rebuild, fixture backscan), live view-present arm (fixture replays are text-only; view vocabulary is covered by the history samples) test(gui): close the PR #443 host-side coverage gaps — apiproxy client abort arms, api-proxy cold/view paths, webserver drain - apiproxy fetch/client.ts: 3 new cases (pre-aborted signal short-circuits before transport + string reason mapping, non-Error/string reason falls to the default AbortError message, signal-less doFetch passthrough) - runtime/api-proxy.ts: one v8-ignore (summarizeCold cwd arm — list() filters cwd-less legacy metas) + api-proxy-cold.spec.ts (cold list merge: mtime source, locate-undefined and vanished-log fallbacks, lineage; no-persistence/no-factory resume → internal) + 2 view cases (history views with meta passthrough and orphan/bad-args/presenterless soft-falls, session/disposed open-call cleanup on the mux stream) - webserver/index.ts: /api/big fixture drives both drain-wait legs (full 8MiB readback after drain, mid-chunk disconnect wakes via 'close') feat: app shell fix: rebase conflicts fix: coverage fix(gui): lint clean after rebase — wrap long v8-ignore comments, unconditional v1 detail-block claim chore(gui): remove browser/probe verify scripts from scripts/ The six GUI acceptance/probe scripts (carrier-errors, rpclog-panel, session, session-real, webserver-backpressure, webserver-hardening) leave the repo's scripts/ tree; the three code comments that pointed at them now describe the coverage lane without naming a script path. fix(webserver): guard the request callback — one malformed request must not kill the process The async handle() had no top-level catch, so any throw inside it (a bad %-escape reaching decodeURIComponent, a client dropping mid-body, a response stream erroring) became an unhandled rejection and took the whole process down (audit R1 must-fix). The guard answers 400 when headers are not out yet, destroys the socket when they are, and reports the failure to onError (the package never prints). Spec covers all three legs: %-escape barrage → 400 + server stays alive, non-Error throw wrapped for onError, mid-stream explosion → socket teardown. feat: client AGENTS.md fix: client/AGENTS.md fix: rebase feat(gui): T0 cut 1 — 12 client package skeletons with contract stubs, dshClient declarations, tsdown client preset, theme token sheets feat(gui): T0 cut 2 — pure git mv migration per v3 §11 (connection six, runtime sessions/kernel, ui-conversation chat, ui-primitives markdown family, web shell + e2e) feat(gui): T0 cuts 3+4 — import rewiring to new package names, .legacy demotion of owner-rewrite files, legacy web-runtime/web-ui/apps-web retired to attic feat(gui): connection 对账刀——index.ts 精确导出清单替换 export *,intents.legacy 溶解删除 feat(client/ui-slots): SlotCore real implementation — kind semantics, sync version + microtask-batched notify, onMutate bridge feat(gui): web shell vite alias — retarget to new client packages, shell static surface only feat(gui): host 侧刀属地半——HostWebPluginRegistry(entries 扫描+internal/plugin 去抖重扫+dshClient 校验+exports./client 解析)、GET /plugins/<id>/client.js 分发端点、GET / 与 SPA fallback 注入 __DSH_BOOT__(webPlugins 可选注入,不传行为不变) feat(web-react): add use-sync-external-store dep + local shim typings feat(web-react): bindSnapshotSelector via uSES with-selector shim feat(gui): ui-layout concession-chain solver — pure computeColumns with contract geometry feat(gui): ui-layout LayoutService — four persisted stores, clamped actions, list-driven prune feat(gui): ui-layout AppFrame styles — grid columns, collapse-safe borders, edge drag handles test(gui): 存量 spec 平移——connection 三件+runtime 六件自 attic 捞回改包名路径全绿;api-helpers 按归属拆分(wire 半留 connection、classifier 半随 conversation.ts 入 runtime);boot-intents/preinit/rpc-log 随 intents/rpc-log 退役不迁(记 v3 §3.2 溶解项) feat(client/ui-primitives): StateDot/Button/Pill/Input/Menu atoms, ConnectionBanner de-legacied to pure props, JsonBlock CSS on --dsw tokens feat(web-react): createSnapshotStore engine (rafFlush batch, persist opt-in, dev freeze) + spec feat(gui): ui-layout AppFrame — grid tracks, pointer-capture drag handles with rAF throttle, frame ResizeObserver feat(web-react): useInvoke (external pending store, stable invoke, concurrency count) + spec test(web-react): bind spec — equality bail, custom eq, zero resubscribe, StrictMode, method sources feat(gui): ui-layout index rewiring — real exports, client apply provides ctx.layout and defines three slots feat(web-react): SessionProvider (renderBody deps) + RootBindingProvider + binding contexts + spec feat(gui): web shell AppRoot boot-page styles — self-contained with neutral token fallbacks feat(gui): web shell AppRoot — boot gate over loader status, fail-loud plugin failure list fix(gui): AppRoot gates on explicit settled signal — status-derived readiness races the incrementally filled table feat(client/ui-theme): ThemeService real implementation — registry with built-in light/dark, apply toggles body[data-ds-dark-theme], third-party token overrides as body inline vars feat(web-react): scopedSlots outlet (kind matrix, inject WeakMap caches, per-entry error boundary) + spec feat(gui): web shell module-table seed — pure-library entities for the loader require surface feat(client/i18n): I18nService real implementation — ns×locale registry, stable bind(ns) reference, zh fallback chain, zh/en skeleton dictionaries feat(gui): web shell assembly closure — layout exports via module table, SessionProvider + scopedSlots + RootBindingProvider feat: client/ui-conversation feat: code codedoc build(gui): root bundle green — web shell excluded from the lib workspace (vite app), ui-primitives lib externalizes css side-effect imports (web-ui precedent) gates(gui): verify-cordis-config follows aggregate tsconfig references (root is a shell over host/client programs); module graph regenerated for the twelve client packages chore(gui): retire legacy migration sources — every owner rewrite landed (t0-checklist §7 ledger honored); orphan css of retired components removed gates(gui): knip green groundwork — e2e/tsx entries for the new packages, loader-runtime deps ignored where loading is by specifier string, fake plugin ids un-bare-named, dead test export dropped chore(client): manifest shape batch A — ui-slots/web-react/ui-primitives invariant companions, files whitelist, cordis+invariants peer/dev, tsconfig refs chore(client): manifest shape batch B — connection/runtime/ui-conversation/ui-trajectory files whitelist, cordis peer+dev, explicit invariant lib entries (clientBundle signature) chore(client): manifest shape batch C — i18n/ui-layout/ui-sidebar/ui-theme invariant companions, files whitelist, invariants peer/dev, tsconfig refs chore(client): manifest shape batch D — web shell gains node-half lib entry + invariant companion + uniform files whitelist chore(client): drop verified-unused deps — dsh-tools from runtime/ui-conversation (types ride /presentation), ui-primitives+clsx from ui-layout gates(gui): doc-gate fixes — theme JSDoc prose, three client type-link exemptions, agent-note paths follow the migration, config catalog regenerated gates(gui): type-equiv manifest follows the types.ts extraction, approval JSDoc keeps its link form, persistence catalog regenerated docs(gui): per-constant JSDoc on the contract geometry exports (export-jsdoc gate) test(gates): loader-composition budget covers cold tsx resolution after the program split (was flaking at the default 5s) docs(gui): README substantiation batch 1 — ui-slots/ui-primitives/web-react/connection: Model Experience short form, real deferred-work ledgers, description accuracy pass fix(client): theme/i18n dual-entry split — service classes + cordis merges move to src/client (host catalog scanner no longer misclassifies client services), node halves keep types + empty apply; catalogs regenerated docs(gui): README substantiation batch 2 — runtime/ui-layout/ui-sidebar/ui-conversation: Model Experience short form, package-owned deferred-work ledgers (unload stub, watch approximation, /client value-import rule, global details state, two-state dots, stats duration gap, single-bundle caches) docs(gui): README substantiation batch 3 — ui-trajectory/ui-theme/i18n/web: Model Experience short form, deferred-work ledgers (placeholder charter, no theme toggle owner, empty locale dictionaries, one-shot rendering); both README gates green test(scripts): purity spec adopts clientBundle two-arg signature (explicit libEntry, no default) gates(gui): knip green — declaration-merge dep ignored, fake plugin id assembled at runtime, invariants dep de-duplicated to peer+dev, stale apps/web section dropped feat(gui): 门禁波次 host 三包 invariant 形状——apiproxy explained-empty 伴生(wire 契约层零事件面)、webserver 真关系伴生(manifest 行必解析出 clientPath,防 __DSH_BOOT__ 广告 404 bundle;apps/cli 发布 webPlugins 键供审计)、runtime 补 files 白名单;三包 exports/files/peer+dev/tsconfig refs 齐 fw-react 形状;constraints+invariants 双 gate 零违规 build(client): ui-layout/ui-sidebar tsdown configs adopt the explicit two-arg clientBundle signature (orphaned follow-up of the manifest shape batch) refactor(gui): shell boot becomes a library face — bootWebShell(el) exported for the apps/web entry; main.ts retired refactor(gui): exports 纪律刀1——ui-theme/i18n node index 收敛为只空 apply(Translate/LocaleDict/ThemeTokens 类型下沉 src/client/),ui-conversation 的 I18nService import 改 /client 子路径 build(typecheck): converge to root host aggregate + tsconfig.client.json — delete tsconfig.host.json, verify-cordis-config seeds both aggregates feat(gui): apps/web restored as the vite application — thin main over bootWebShell; dsh-client-web becomes a plain lib (index exports shell surface, vite files and e2e moved out) chore(gates): knip.json rewritten on the master base — same semantics, minimal diff (formatting churn dropped) docs(gui): 时效清扫②——testing.md 删 web-ui 覆盖豁免残句;web-styling.md 加 token 换代头注(--dsw-* 现行、工程约束条款仍有效并注明收编处) docs(gui): 时效清扫③——四对 GUI Agent Note 加路径更新头注(web-runtime/web-ui/dsh-frontend→现行 12 包结构;设计结论存续声明;双语对同步) docs(gui): 时效清扫③b——四对 note 头注的 i18n 配对哈希重录 build(typecheck): minimal-diff tsconfig shape — drop root files entry (purity spec + preset move to client program), compress comments, drop redundant util/home root ref feat(gui): apps/web restoration follow-through — dsh-frontend package name, cli dist resolve, root build:web filter, tsdown exemption dropped, vitest web lane + knip + client aggregate retargeted, e2e paths rebased refactor(gui): exports 纪律刀2——connection wire 六件 git mv 进 src/client/(wire 即该 dshClient 插件的 client 半),node index=只空 apply,/client 半边整面导出(v3 §3.2 清单原样),包内 tests 改 src/client 直取 refactor(gui): exports 纪律刀3——runtime 实现整体下沉 src/client/(sessions/slots/loader;契约类型与 cordis merge 随迁 client/index),node index=只空 apply;./loader exports 指 client/loader;全消费面(web 壳/ui-sidebar/ui-trajectory/tests)bare→/client 机械跟改;vitest.e2e 换 tsconfig.vitest paths(root tsconfig 排除 client 会把 /client import 掉到 exports 的浏览器 dist bundle) refactor(gui): exports 纪律刀3 补遗——ui-layout 三处 bare runtime import 改 /client(刀3 消费面机械跟改漏提交件;跨属地机械一行×3 报备 ui-shell) test(gui): drop the getSessionManager singleton case — the init/get pair is a dead legacy-boot surface with zero live consumers (SessionsService constructs and holds the manager under the plugin architecture); source removal tracked with rt-core refactor(gui): 删 manager.ts 尾部 initSessionManager/getSessionManager 单例对——旧 boot 直连遗物,插件化下 SessionsService 构造持有 manager,全仓零活消费者(convo-b 测试清扫对表,其测试用例已先行退役 7e2c51898);头注释同步去单例措辞 code refactor
2026-07-19 21:17:57 +08:00
- `@deepseek-ai/dsh-client-ui-theme` ([`packages/client/ui-theme/src/index.ts`](../packages/client/ui-theme/src/index.ts))
2026-08-08 15:31:41 +08:00
- `@deepseek-ai/dsh-client-ui-tool` ([`packages/client/ui-tool/src/index.ts`](../packages/client/ui-tool/src/index.ts))
feat(gui): step1 skeleton — dsc web serves built web UI over booted harness host Five new modules: apps/dsc (bin: parseArgs + node:http static server + signal shutdown), packages/host/apiproxy (programmatic harness core composition, agents:[]), packages/client/web-runtime (React-free browser runtime), packages/client/web-ui (React mount), apps/web (vite build entry producing dist consumed by apps/dsc via package exports). Root wiring: apps/* workspace glob, dsh-* paths for host/client groups, demo:web script, apps/web/dist gitignore. No protocol/API routes yet — contract lands in step2 (see missions/tasks/20260719-1902-apiproxy-api-design). Includes the design + implementation archives (spec v2.1, deepseekchat baseline and harness boot research, implementation run log). Acceptance: 12/12 passed incl. real-key llm.stream smoke (51 chunks). feat(gui): apiproxy — four-quadrant RPC contract + fetch carriers, live end to end Contract layer (src/api/, 14 files): four named wire message types (ClientRequest / ServerResponse / ServerRequest / ClientResponse) as a discriminated union over strict bidirectional rpcId (initiator mints, responder echoes; channel and message fully decoupled — HTTP is the client->server pipe, SSE the reverse); narrow RpcRequest<P>/ RpcResponse<T> signature forms; RpcMethodMap with RequestPayload<K>/ ResponseValue<K> derivation; typed RpcError details map; approval/ question responses modeled as ClientResponse via a single /api/respond endpoint (RpcReceipt carrier ack); zod schemas anchored per Wire<T> against exactOptionalPropertyTypes. impl/api-proxy.ts: describe/list/create, both SSE streams (frame queue pump, subscribed baseline, lifecycle frames, signal cleanup); history pages on message boundaries (tail-back scan, partial included in the tail page); prompt dispatches queue->agent.send / steer->agent.steer with rpcId carried through MessageSource; cancel for attached sessions; cold-session resume deduped via a per-id promise map; host-level provider/model defaults injected at create/resume. fetch/: mechanical UNARY_ROUTES table, two-level parse with path==method check, SSE frames completed to ServerRequest full form; client mints -> narrows -> envelopes outbound, verifies rpcId echo inbound, streams SSE frames, four-quadrant onEnvelope tap (debug panel choke point). Real-browser fixes: URL base resolves to location.origin (hardcoded internal base broke real pages), browser-safe export paths. Design archives: contract design.md v2.0 with decision log, core-coverage audit, comparative studies, step2 impl run log. Probed end to end over real HTTP: prompt -> live model stream -> history returns the finished reply. feat(gui): RpcLog debug panel — fixture-driven milestone, playwright-verified 10/10 web-runtime: rpcLog + ui slices (zustand), four-quadrant RpcLogEntry (client-request / server-response / server-request / client-response), onEnvelope tap -> microtask-batched pump with 500-entry ring buffer, ConnectionController (private state, backoff reconnect), fixture API with fake envelopes (?fixture switch), bootWebRuntime; contract types via temporary local copies (api-types.ts, swapped for real imports when W3 client lands). web-ui: components/panels/RpcLog five-piece set (badge with unread count, floating panel, direction glyphs per quadrant, same-rpcId pair highlighting in two families, JSON payload expand, follow/pause, clear), App shell, utils/formatRelative, light-theme CSS variables with dark placeholders. dsc bin: mime lookup fixed to use the actually-served file (naked '/?query' no longer falls through to octet-stream download); shutdown closes SSE keep-alive connections so SIGTERM actually exits. Acceptance: scripts/verify-rpclog-panel.mjs (chromium headless) ALL PASS 10/10 over design.md §D 1-6. pkg: add web scripts for building feat(gui): session milestone — list + conversation over Session OOP, styled RpcLog v2.1 web-runtime: Session/SessionManager object layer (resident instances, mux frame routing, lineage flattening), foldSurface adapter with padding sentinels for paged windows, chunk accumulator for streaming partials, batched change notification (useSyncExternalStore contract), connection sinks + reconnect fix (the 300ms self-abort reconnect storm that made the session list flap is gone), fixture rewritten as a scripted host (60-turn history, typewriter replay, resident pending approval, child session); temporary contract copies deleted in favor of real apiproxy imports. web-ui: sessions screen (list with lineage indent + selection as container-local state), conversation view (turn grouping, reasoning fold, tool cards, steering, pending interaction cards, upward paging with scroll anchoring), input bar with queue/steer/stop; RpcLog panel restyled per docs/web-styling.md (tokenized palette, quadrant badge glyphs now vertical ↑↓⇟⇞, pair highlighting, floating shadow). docs/web-styling.md: living style guide (tokens, visual baseline, coding rules, evolution log). Acceptance: verify-session.mjs 31/31, verify-session-real.mjs 5/5 (real model streaming), verify-rpclog-panel.mjs 10/10. feat(gui): hostruntime split + repo-wide package prefix rename Package split (design: 20260720-0101-hostruntime-split-design): dsh-host-runtime carries bootHost + createApiProxy + startHost() (RunningHost {api, handler, defaults, ctx, dispose} — the seam Electron and any future shell reuses; ctx is the official front-door mount point); dsh-host-webserver carries the node:http static+API bridge (fixed: abort now keys on res 'close' + writableEnded — req 'close' fires on body end since Node 16 and was killing every SSE stream instantly, the reconnect-storm root cause); apps/dsc is now a thin assembly with web/-p subcommands. dsc -p runs the full isomorphic carrier chain in process (second real protocol consumer; probed end-to-end against the live model). Naming rule (user decree): packages under host/ and client/ carry the directory prefix in their npm name — dsh-host-apiproxy, dsh-client-web-runtime, dsh-client-web-ui renamed repo-wide in one frozen batch; explicit tsconfig paths entries added where the wildcard no longer matches. Acceptance: verify-session 31/31, verify-rpclog-panel 10/10, verify-session-real 7/7 (incl. new 12s connection-stability sentinels), tsc green, dsc web + dsc -p smoke both pass. refactor(gui): AbstractApiClient class hierarchy — OO client with inheritable seams AbstractApiClient (apiproxy) carries every protocol invariant: rpcId minting, four-quadrant envelope wrap/unwrap, zod parsing, SSE frame parsing, the payload-direct IApiClient surface (callers no longer mint rpcIds — the carrier does), and the instance-level envelope observation pump (batched via microtask; moved off module-level globals in rpc-log.ts, which is now a pure subscriber mapping envelopes into store entries — the debug panel observes the connection, it is not part of it). Platform subclasses own two abstract seams (doFetch, onEnvelope) plus three protocol-level virtuals for transportless overrides: InProcessApiClient (apiproxy; dsc -p uses new InProcessApiClient( host.handler)), WebApiClient (web-runtime), FixtureApiClient (fixture now subclasses instead of wrapping). Naming per decree: AbstractApiClient / IApiClient; ApiProxy stays the impl-side narrow-form contract. headless.ts call sites drop rpcRequest wrappers (payload-direct); split-design archive updated with the naming-rule ledger. tsc green; verify-session 31/31, verify-rpclog-panel 10/10, verify-session-real 7/7 (12s connection sentinel count=4); dsc -p smoke CALLER-OK. feat(gui): InputBar final form — bug batch, deepseekchat layout, single primary button, running locks input Squashes the whole InputBar iteration batch: IME/caret/auto-grow/focus/dedup bug fixes, layout aligned to the deepseekchat baseline, single primary button with hover flyout, finalized button semantics with the Codex-style icon circle, and running-state locking where stop is the only mid-turn action. The same batch carried the Chinese-to-English code comment sweep (density pruned), folded in here. docs(gui): purge work-log references from code comments 76 design-doc references cleared across the GUI packages: section pointers inlined as self-contained constraint statements, pure pointer comments dropped, milestone codenames and ruling tags out, and the 14 contract file headers switched to the formal RFC (the only sanctioned external reference). web-styling.md now cites the styling RFC instead of the disposable research archive. grep for work-log reference variants is clean across the GUI packages. docs(gui): file-header comments self-contained — drop RFC filename references RFC renames/reorgs must not require a source sweep (the 2026-07-20 two-way merge proved it). 11 headers lose only the '(RFC …)' tail and stay self-contained; api-proxy.ts keeps its minimal-first note. fix(gui): session streaming — freeze interrupted partials, sweep stale running calls, send force-scrolls Aborted turns never emit the finalizing assistant/message, so the accumulated partial and its running tool cards kept rendering below later messages — the "new message lands above the stopped reply" illusion. turn/end side effects now freeze content-bearing partials into interrupted terminal nodes (fractional seq keeps flow order; the live freeze and history replay converge through applyEventSideEffects, so a refresh reconstructs identical frozen nodes) and turn running tool cards into interrupted terminal cards; only content-free partials are swept outright. ConversationView gains the send-force-scroll rule (own words must be visible) alongside the pre-update atBottom follow flag. Regressions pinned as E2-4a–c (real host) and §E1-11h (fixture). feat(gui): webserver hardening verify script feat(gui): dark-mode toggle pinned to the sidebar bottom Interim home before the Settings page exists (the button re-homes with zero logic change — mechanics live in utils/theme.ts): html[data-theme] flip + dsc.theme localStorage, stored choice wins over the OS prefers-color-scheme default, applied in mount() before first paint so a dark reload never flashes light. Moon/sun inline SVG icon button at the sidebar's pinned bottom row. Pure front-end local concern: no RPC, no Session/store involvement. Dark sweep of list/conversation/input card/RPC panel found no unreadable pairs — no token changes needed. docs(gui): GUI RFCs and web styling handbook Layering+RPC protocol and web client architecture RFCs (post-reorg, developer-facing polish folded in) plus the styling engineering handbook. Mission work logs live in the commit above; PRs can be cut from this commit to include formal docs only. fix(gui): client object-layer hardening — audit timing/reference/resilience batches (S3-S5,C1-C3,C5-C8) fix(gui): carrier error channel + webserver backpressure (audit A1-A5,A7-A10,R2,R5) feat(gui): session persistence surface — cold list, project cwd, legacy no-cwd retirement refactor: rename dsc CLI to dsh — apps/cli, bin name, package scope Includes the root tsconfig project-references fix for host/* and client/web-runtime (originally a separate build fix commit). test(gui): three-tier suite — protocol/object/browser lanes, tier-a fill to per-file 100% test(gui): jsdom lane for web-ui + web-runtime coverage gate entry docs(gui): GUI testing system RFC (zh) feat(gui): tool-card views — contract slot, host-computed delivery, three-level card fallback fix(gui): lint clean across GUI packages — wrap long doc comments, drop dead type args, sync-return methods without awaits docs(gui): doc-sync mechanical fixes — JSDoc on apiproxy/host exports, RFC sketch fences ignore-check, md-wrap paragraphs, drop missions links, web-ui plain-ts entry chore(gui): module-graph regen + knip clean — drop dead re-exports, internalize createFixtureApi, scan web-ui tsx and verify mjs scripts build(gui): wire client/host packages into the lib build shape — tsc references + tsdown (web-ui css-external), lib manifests, cordis peer, apiproxy typed subpaths, vite src aliases test(gui): host-side per-file 100% coverage — apiproxy schema/carrier suites, webserver http-bridge suite, host-runtime composition suite; client/* coverage excluded pending the browser-side testing work item docs(gui): package READMEs for the five GUI packages — model-experience audit entries, limitations sections docs(gui): bilingual RFC pairs + client JSDoc completion — translate the three GUI RFCs to English with i18n records and manifest ratchet, Consequences sections both sides, full client/* export JSDoc, regen doc graphs and RFC index fix(scripts): doc-typecheck built-declarations mode maps /src/* subpath wildcards (apiproxy browser-safe channels) docs(gui): apply dsh rename across pr-gates docs — READMEs, layering RFC en, web-ui entry comment, i18n re-record fix(gui): post-rebase lint reconciliation — wrap main-tree long doc comments, read-through narrowing guards, abortError Error normalization, handleUnary generic justification fix(gui): post-rebase doc/test reconciliation — align host specs with evolved carrier contracts (sentinel rpcId, stream/error surfacing, url-path transport messages, defaults.cwd), Agent Note titles and relocated links, KV Cache effect sections, JSDoc on evolved exports fix(gui): second-rebase reconciliation to 509db0cb3 — restore api panel exports the baseline suites consume, knip workspace entries for jsdom lane and apps/web smokes, hoist result narrowing, align testing.md to the narrowed web-ui exclusion fix(test): vitest-scoped tsconfig maps bare imports for tsx specs — with GUI manifests now pointing at lib, an unmapped importer loaded a second copy of the web-runtime singletons fix(gui): typecheck + lint clean over the tool-card batch — brand callIds and object-form turn/end reason in the view spec, narrow fixture arg stringification, wrap long v8-ignore comments docs(gui): export JSDoc for tool-card surfaces + testing-note pairing header docs: rfc for web testing feat: add tools to host-runtime fix(gui): dispatch agent/error via agentEvents in host-runtime spec — mounted invariants plugin rejects raw ctx.emit without the scope carrier fix(gui): restore GUI knip workspaces + scripts/mjs entries and regenerate lockfile after master rebase fix(gui): post-rebase gate repairs — drop context-node envelope (master unwrapped injected content envelopes), regen event matrix, condense testing.md web-ui exclusion within budget fix(session): browser-safe deep-equal in surface — node:util import broke the vite bundle ci(gates): frontend vite build joins pre-push — node: imports in the client closure pass tsc but break the browser bundle test(tui): drop the checkout-dependent process.cwd() harness default — a long worktree path pushes the footer token counters past the 88-column fake terminal test(gui): jsdom behavior E2E — conversation main path over fixture runtime, reconnect banner lifecycle test(gui): jsdom RPC panel behavior — ledger rows, expand, pairing, pause/clear, follow-pause, payload truncation test(gui): jsdom tier-2 — InputBar guards, reasoning fold, JSON blocks, message variants, theme, create-then-select; act-harden banner case test(gui): jsdom tier-3 — ConversationView states/paging/force-bottom, ToolCallCard arms, PendingCard, list rows test(gui): jsdom tails — view-card variants, LogRow directions, registry hygiene, badge overflow, hook ops, mount glue test(gui): jsdom tails round 2 — call-ref blocks, resume follow, view precedence, failed create, empty-diff arm test(gui): jsdom final arms — anchor compensation, follow-off, interval ticks, view halves, node-over-running precedence test(gui): web-ui joins the per-file 100% coverage gate Annotation-only src changes plus the config swap. The web-ui exclusion is replaced by a single index.tsx entry (stale byte-identical duplicate of mount.tsx, nothing imports it; same entry-glue treatment as bin.ts) and the coverage include gains .tsx. v8-ignore sites (each with its reason inline): - ConversationView 3x ref-null guards; InputBar disabled-click guard - ToolCallCard both-null arms + windowless-custom argsRaw arm - LogRow css-module key fallbacks (start/stop block); RpcLogBody 3x ref-null guards - web-runtime drift from the tool-card batch: fixture presenter catch/str typo-guards, dense-array guards (fold-adapter reset, session rebuild, fixture backscan), live view-present arm (fixture replays are text-only; view vocabulary is covered by the history samples) test(gui): close the PR #443 host-side coverage gaps — apiproxy client abort arms, api-proxy cold/view paths, webserver drain - apiproxy fetch/client.ts: 3 new cases (pre-aborted signal short-circuits before transport + string reason mapping, non-Error/string reason falls to the default AbortError message, signal-less doFetch passthrough) - runtime/api-proxy.ts: one v8-ignore (summarizeCold cwd arm — list() filters cwd-less legacy metas) + api-proxy-cold.spec.ts (cold list merge: mtime source, locate-undefined and vanished-log fallbacks, lineage; no-persistence/no-factory resume → internal) + 2 view cases (history views with meta passthrough and orphan/bad-args/presenterless soft-falls, session/disposed open-call cleanup on the mux stream) - webserver/index.ts: /api/big fixture drives both drain-wait legs (full 8MiB readback after drain, mid-chunk disconnect wakes via 'close') feat: app shell fix: rebase conflicts fix: coverage fix(gui): lint clean after rebase — wrap long v8-ignore comments, unconditional v1 detail-block claim chore(gui): remove browser/probe verify scripts from scripts/ The six GUI acceptance/probe scripts (carrier-errors, rpclog-panel, session, session-real, webserver-backpressure, webserver-hardening) leave the repo's scripts/ tree; the three code comments that pointed at them now describe the coverage lane without naming a script path. fix(webserver): guard the request callback — one malformed request must not kill the process The async handle() had no top-level catch, so any throw inside it (a bad %-escape reaching decodeURIComponent, a client dropping mid-body, a response stream erroring) became an unhandled rejection and took the whole process down (audit R1 must-fix). The guard answers 400 when headers are not out yet, destroys the socket when they are, and reports the failure to onError (the package never prints). Spec covers all three legs: %-escape barrage → 400 + server stays alive, non-Error throw wrapped for onError, mid-stream explosion → socket teardown. feat: client AGENTS.md fix: client/AGENTS.md fix: rebase feat(gui): T0 cut 1 — 12 client package skeletons with contract stubs, dshClient declarations, tsdown client preset, theme token sheets feat(gui): T0 cut 2 — pure git mv migration per v3 §11 (connection six, runtime sessions/kernel, ui-conversation chat, ui-primitives markdown family, web shell + e2e) feat(gui): T0 cuts 3+4 — import rewiring to new package names, .legacy demotion of owner-rewrite files, legacy web-runtime/web-ui/apps-web retired to attic feat(gui): connection 对账刀——index.ts 精确导出清单替换 export *,intents.legacy 溶解删除 feat(client/ui-slots): SlotCore real implementation — kind semantics, sync version + microtask-batched notify, onMutate bridge feat(gui): web shell vite alias — retarget to new client packages, shell static surface only feat(gui): host 侧刀属地半——HostWebPluginRegistry(entries 扫描+internal/plugin 去抖重扫+dshClient 校验+exports./client 解析)、GET /plugins/<id>/client.js 分发端点、GET / 与 SPA fallback 注入 __DSH_BOOT__(webPlugins 可选注入,不传行为不变) feat(web-react): add use-sync-external-store dep + local shim typings feat(web-react): bindSnapshotSelector via uSES with-selector shim feat(gui): ui-layout concession-chain solver — pure computeColumns with contract geometry feat(gui): ui-layout LayoutService — four persisted stores, clamped actions, list-driven prune feat(gui): ui-layout AppFrame styles — grid columns, collapse-safe borders, edge drag handles test(gui): 存量 spec 平移——connection 三件+runtime 六件自 attic 捞回改包名路径全绿;api-helpers 按归属拆分(wire 半留 connection、classifier 半随 conversation.ts 入 runtime);boot-intents/preinit/rpc-log 随 intents/rpc-log 退役不迁(记 v3 §3.2 溶解项) feat(client/ui-primitives): StateDot/Button/Pill/Input/Menu atoms, ConnectionBanner de-legacied to pure props, JsonBlock CSS on --dsw tokens feat(web-react): createSnapshotStore engine (rafFlush batch, persist opt-in, dev freeze) + spec feat(gui): ui-layout AppFrame — grid tracks, pointer-capture drag handles with rAF throttle, frame ResizeObserver feat(web-react): useInvoke (external pending store, stable invoke, concurrency count) + spec test(web-react): bind spec — equality bail, custom eq, zero resubscribe, StrictMode, method sources feat(gui): ui-layout index rewiring — real exports, client apply provides ctx.layout and defines three slots feat(web-react): SessionProvider (renderBody deps) + RootBindingProvider + binding contexts + spec feat(gui): web shell AppRoot boot-page styles — self-contained with neutral token fallbacks feat(gui): web shell AppRoot — boot gate over loader status, fail-loud plugin failure list fix(gui): AppRoot gates on explicit settled signal — status-derived readiness races the incrementally filled table feat(client/ui-theme): ThemeService real implementation — registry with built-in light/dark, apply toggles body[data-ds-dark-theme], third-party token overrides as body inline vars feat(web-react): scopedSlots outlet (kind matrix, inject WeakMap caches, per-entry error boundary) + spec feat(gui): web shell module-table seed — pure-library entities for the loader require surface feat(client/i18n): I18nService real implementation — ns×locale registry, stable bind(ns) reference, zh fallback chain, zh/en skeleton dictionaries feat(gui): web shell assembly closure — layout exports via module table, SessionProvider + scopedSlots + RootBindingProvider feat: client/ui-conversation feat: code codedoc build(gui): root bundle green — web shell excluded from the lib workspace (vite app), ui-primitives lib externalizes css side-effect imports (web-ui precedent) gates(gui): verify-cordis-config follows aggregate tsconfig references (root is a shell over host/client programs); module graph regenerated for the twelve client packages chore(gui): retire legacy migration sources — every owner rewrite landed (t0-checklist §7 ledger honored); orphan css of retired components removed gates(gui): knip green groundwork — e2e/tsx entries for the new packages, loader-runtime deps ignored where loading is by specifier string, fake plugin ids un-bare-named, dead test export dropped chore(client): manifest shape batch A — ui-slots/web-react/ui-primitives invariant companions, files whitelist, cordis+invariants peer/dev, tsconfig refs chore(client): manifest shape batch B — connection/runtime/ui-conversation/ui-trajectory files whitelist, cordis peer+dev, explicit invariant lib entries (clientBundle signature) chore(client): manifest shape batch C — i18n/ui-layout/ui-sidebar/ui-theme invariant companions, files whitelist, invariants peer/dev, tsconfig refs chore(client): manifest shape batch D — web shell gains node-half lib entry + invariant companion + uniform files whitelist chore(client): drop verified-unused deps — dsh-tools from runtime/ui-conversation (types ride /presentation), ui-primitives+clsx from ui-layout gates(gui): doc-gate fixes — theme JSDoc prose, three client type-link exemptions, agent-note paths follow the migration, config catalog regenerated gates(gui): type-equiv manifest follows the types.ts extraction, approval JSDoc keeps its link form, persistence catalog regenerated docs(gui): per-constant JSDoc on the contract geometry exports (export-jsdoc gate) test(gates): loader-composition budget covers cold tsx resolution after the program split (was flaking at the default 5s) docs(gui): README substantiation batch 1 — ui-slots/ui-primitives/web-react/connection: Model Experience short form, real deferred-work ledgers, description accuracy pass fix(client): theme/i18n dual-entry split — service classes + cordis merges move to src/client (host catalog scanner no longer misclassifies client services), node halves keep types + empty apply; catalogs regenerated docs(gui): README substantiation batch 2 — runtime/ui-layout/ui-sidebar/ui-conversation: Model Experience short form, package-owned deferred-work ledgers (unload stub, watch approximation, /client value-import rule, global details state, two-state dots, stats duration gap, single-bundle caches) docs(gui): README substantiation batch 3 — ui-trajectory/ui-theme/i18n/web: Model Experience short form, deferred-work ledgers (placeholder charter, no theme toggle owner, empty locale dictionaries, one-shot rendering); both README gates green test(scripts): purity spec adopts clientBundle two-arg signature (explicit libEntry, no default) gates(gui): knip green — declaration-merge dep ignored, fake plugin id assembled at runtime, invariants dep de-duplicated to peer+dev, stale apps/web section dropped feat(gui): 门禁波次 host 三包 invariant 形状——apiproxy explained-empty 伴生(wire 契约层零事件面)、webserver 真关系伴生(manifest 行必解析出 clientPath,防 __DSH_BOOT__ 广告 404 bundle;apps/cli 发布 webPlugins 键供审计)、runtime 补 files 白名单;三包 exports/files/peer+dev/tsconfig refs 齐 fw-react 形状;constraints+invariants 双 gate 零违规 build(client): ui-layout/ui-sidebar tsdown configs adopt the explicit two-arg clientBundle signature (orphaned follow-up of the manifest shape batch) refactor(gui): shell boot becomes a library face — bootWebShell(el) exported for the apps/web entry; main.ts retired refactor(gui): exports 纪律刀1——ui-theme/i18n node index 收敛为只空 apply(Translate/LocaleDict/ThemeTokens 类型下沉 src/client/),ui-conversation 的 I18nService import 改 /client 子路径 build(typecheck): converge to root host aggregate + tsconfig.client.json — delete tsconfig.host.json, verify-cordis-config seeds both aggregates feat(gui): apps/web restored as the vite application — thin main over bootWebShell; dsh-client-web becomes a plain lib (index exports shell surface, vite files and e2e moved out) chore(gates): knip.json rewritten on the master base — same semantics, minimal diff (formatting churn dropped) docs(gui): 时效清扫②——testing.md 删 web-ui 覆盖豁免残句;web-styling.md 加 token 换代头注(--dsw-* 现行、工程约束条款仍有效并注明收编处) docs(gui): 时效清扫③——四对 GUI Agent Note 加路径更新头注(web-runtime/web-ui/dsh-frontend→现行 12 包结构;设计结论存续声明;双语对同步) docs(gui): 时效清扫③b——四对 note 头注的 i18n 配对哈希重录 build(typecheck): minimal-diff tsconfig shape — drop root files entry (purity spec + preset move to client program), compress comments, drop redundant util/home root ref feat(gui): apps/web restoration follow-through — dsh-frontend package name, cli dist resolve, root build:web filter, tsdown exemption dropped, vitest web lane + knip + client aggregate retargeted, e2e paths rebased refactor(gui): exports 纪律刀2——connection wire 六件 git mv 进 src/client/(wire 即该 dshClient 插件的 client 半),node index=只空 apply,/client 半边整面导出(v3 §3.2 清单原样),包内 tests 改 src/client 直取 refactor(gui): exports 纪律刀3——runtime 实现整体下沉 src/client/(sessions/slots/loader;契约类型与 cordis merge 随迁 client/index),node index=只空 apply;./loader exports 指 client/loader;全消费面(web 壳/ui-sidebar/ui-trajectory/tests)bare→/client 机械跟改;vitest.e2e 换 tsconfig.vitest paths(root tsconfig 排除 client 会把 /client import 掉到 exports 的浏览器 dist bundle) refactor(gui): exports 纪律刀3 补遗——ui-layout 三处 bare runtime import 改 /client(刀3 消费面机械跟改漏提交件;跨属地机械一行×3 报备 ui-shell) test(gui): drop the getSessionManager singleton case — the init/get pair is a dead legacy-boot surface with zero live consumers (SessionsService constructs and holds the manager under the plugin architecture); source removal tracked with rt-core refactor(gui): 删 manager.ts 尾部 initSessionManager/getSessionManager 单例对——旧 boot 直连遗物,插件化下 SessionsService 构造持有 manager,全仓零活消费者(convo-b 测试清扫对表,其测试用例已先行退役 7e2c51898);头注释同步去单例措辞 code refactor
2026-07-19 21:17:57 +08:00
- `@deepseek-ai/dsh-client-ui-trajectory` ([`packages/client/ui-trajectory/src/index.ts`](../packages/client/ui-trajectory/src/index.ts))
- `@deepseek-ai/dsh-client-ui-user-questions` ([`packages/client/ui-user-questions/src/index.ts`](../packages/client/ui-user-questions/src/index.ts))
- `@deepseek-ai/dsh-client-ui-workflow-run` ([`packages/client/ui-workflow-run/src/index.ts`](../packages/client/ui-workflow-run/src/index.ts))
- `@deepseek-ai/dsh-client-ui-workspace` ([`packages/client/ui-workspace/src/index.ts`](../packages/client/ui-workspace/src/index.ts))
- `@deepseek-ai/dsh-command-compact` — requires `commands` · `compaction` ([`packages/compaction/command-compact/src/index.ts`](../packages/compaction/command-compact/src/index.ts))
- `@deepseek-ai/dsh-command-feedback` — requires `commands` ([`packages/feedback/command-feedback/src/index.ts`](../packages/feedback/command-feedback/src/index.ts))
2026-07-19 23:55:33 +08:00
- `@deepseek-ai/dsh-command-goal` — requires `commands` · `goals` ([`packages/goal/command-goal/src/index.ts`](../packages/goal/command-goal/src/index.ts))
- `@deepseek-ai/dsh-commands` ([`packages/interaction/commands/src/index.ts`](../packages/interaction/commands/src/index.ts))
2026-08-13 02:22:10 +08:00
- `@deepseek-ai/dsh-cordis-client-runner` ([`packages/extensions/cordis-client-runner/src/index.ts`](../packages/extensions/cordis-client-runner/src/index.ts))
- `@deepseek-ai/dsh-deepseek-llm-api-extensions` ([`packages/llm/deepseek-llm-api-extensions/src/index.ts`](../packages/llm/deepseek-llm-api-extensions/src/index.ts))
- `@deepseek-ai/dsh-fs-e2b` — requires `e2b` ([`packages/e2b/fs-e2b/src/index.ts`](../packages/e2b/fs-e2b/src/index.ts))
- `@deepseek-ai/dsh-fs-observation-policy` ([`packages/fs/fs-observation-policy/src/index.ts`](../packages/fs/fs-observation-policy/src/index.ts))
- `@deepseek-ai/dsh-goal-round-driver` — requires `agents` · `goals` · `sessions` ([`packages/goal/goal-round-driver/src/index.ts`](../packages/goal/goal-round-driver/src/index.ts))
- `@deepseek-ai/dsh-host-directory-picker-auto` — requires `webServer` · `loader` ([`packages/host/directory-picker-auto/src/index.ts`](../packages/host/directory-picker-auto/src/index.ts))
- `@deepseek-ai/dsh-host-directory-picker-native` ([`packages/host/directory-picker-native/src/index.ts`](../packages/host/directory-picker-native/src/index.ts))
- `@deepseek-ai/dsh-host-plugin-inventory` — requires `loader` ([`packages/host/plugin-inventory/src/index.ts`](../packages/host/plugin-inventory/src/index.ts))
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
- `@deepseek-ai/dsh-llm` ([`packages/llm/llm/src/index.ts`](../packages/llm/llm/src/index.ts))
- `@deepseek-ai/dsh-lsp` ([`packages/lsp/lsp/src/index.ts`](../packages/lsp/lsp/src/index.ts))
- `@deepseek-ai/dsh-schedule` — requires `agents` · `sessions` · `tools` · `sessionPersistence` ([`packages/schedule/schedule/src/index.ts`](../packages/schedule/schedule/src/index.ts))
- `@deepseek-ai/dsh-sdk-app` — requires `cmdlineArgs` ([`packages/bundle/sdk-app/src/index.ts`](../packages/bundle/sdk-app/src/index.ts))
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
- `@deepseek-ai/dsh-session` ([`packages/core/session/src/index.ts`](../packages/core/session/src/index.ts))
- `@deepseek-ai/dsh-session-checkpoint-policy` — requires `llm` · `sessionPersistence` · `sessions` · `tools` ([`packages/session/session-checkpoint-policy/src/index.ts`](../packages/session/session-checkpoint-policy/src/index.ts))
- `@deepseek-ai/dsh-session-log-export` — requires `commands` ([`packages/session-query/session-log-export/src/index.ts`](../packages/session-query/session-log-export/src/index.ts))
- `@deepseek-ai/dsh-session-projection` ([`packages/session/session-projection/src/index.ts`](../packages/session/session-projection/src/index.ts))
2026-08-12 20:26:47 +08:00
- `@deepseek-ai/dsh-session-stats` — requires `sessionProjections` ([`packages/session/session-stats/src/index.ts`](../packages/session/session-stats/src/index.ts))
- `@deepseek-ai/dsh-skill-badge` — requires `skills` ([`packages/skill/skill-badge/src/index.ts`](../packages/skill/skill-badge/src/index.ts))
- `@deepseek-ai/dsh-storage` ([`packages/storage/storage/src/index.ts`](../packages/storage/storage/src/index.ts))
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
- `@deepseek-ai/dsh-subagent` ([`packages/subagent/subagent/src/index.ts`](../packages/subagent/subagent/src/index.ts))
- `@deepseek-ai/dsh-subprocess-local` ([`packages/subprocess/subprocess-local/src/index.ts`](../packages/subprocess/subprocess-local/src/index.ts))
- `@deepseek-ai/dsh-terminal` ([`packages/terminal/terminal/src/index.ts`](../packages/terminal/terminal/src/index.ts))
- `@deepseek-ai/dsh-tool-ask-user` — requires `tools` · `userQuestions` ([`packages/interaction/tool-ask-user/src/index.ts`](../packages/interaction/tool-ask-user/src/index.ts))
- `@deepseek-ai/dsh-tool-call-timeout-policy` — requires `tools` ([`packages/guard/timeout-policy/src/index.ts`](../packages/guard/timeout-policy/src/index.ts))
2026-08-13 02:22:10 +08:00
- `@deepseek-ai/dsh-tool-cordis` — requires `tools` · `systemPrompt` · `dynamicCordisRunner` · `cordisInspect` ([`packages/extensions/tool-cordis/src/index.ts`](../packages/extensions/tool-cordis/src/index.ts))
- `@deepseek-ai/dsh-tool-subagent-control` — requires `tools` · `subagents` ([`packages/subagent/tool-subagent-control/src/index.ts`](../packages/subagent/tool-subagent-control/src/index.ts))
- `@deepseek-ai/dsh-user-questions` ([`packages/interaction/user-questions/src/index.ts`](../packages/interaction/user-questions/src/index.ts))
- `@deepseek-ai/dsh-webhook` — requires `agents` · `agentDefaultModel` · `agentPresets` · `permissionPresets` · `sessionTitle` · `workspaceRegistry` ([`packages/webhook/webhook/src/index.ts`](../packages/webhook/webhook/src/index.ts))
- `@deepseek-ai/dsh-workspace` — requires `storageDomain` · `sessionPersistence` ([`packages/workspace/workspace/src/index.ts`](../packages/workspace/workspace/src/index.ts))
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## Seam packages (not directly loadable)
2026-07-19 22:50:49 +08:00
Abstract service classes — a deployment loads a concrete implementation package instead ([capability seams](../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)).
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
2026-07-23 15:20:47 +08:00
- `@deepseek-ai/dsh-attachment` — abstract `AttachmentStore` ([`packages/attachment/attachment/src/index.ts`](../packages/attachment/attachment/src/index.ts))
- `@deepseek-ai/dsh-code-runtime` — abstract `CodeRuntime` ([`packages/code-runtime/code-runtime/src/index.ts`](../packages/code-runtime/code-runtime/src/index.ts))
- `@deepseek-ai/dsh-compaction` — abstract `CompactionEngine` ([`packages/compaction/compaction/src/index.ts`](../packages/compaction/compaction/src/index.ts))
- `@deepseek-ai/dsh-credentials` — abstract `CredentialProvider` ([`packages/credentials/credentials/src/index.ts`](../packages/credentials/credentials/src/index.ts))
- `@deepseek-ai/dsh-file-reference` — abstract `FileReferenceService` ([`packages/context/file-reference/src/index.ts`](../packages/context/file-reference/src/index.ts))
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
- `@deepseek-ai/dsh-fs` — abstract `FileSystem` ([`packages/fs/fs/src/index.ts`](../packages/fs/fs/src/index.ts))
- `@deepseek-ai/dsh-host-directory-picker` — abstract `DirectoryPicker` ([`packages/host/directory-picker/src/index.ts`](../packages/host/directory-picker/src/index.ts))
- `@deepseek-ai/dsh-jobs` — abstract `JobRegistry` ([`packages/jobs/jobs/src/index.ts`](../packages/jobs/jobs/src/index.ts))
- `@deepseek-ai/dsh-sandbox` — abstract `SandboxProvider` ([`packages/sandbox/sandbox/src/index.ts`](../packages/sandbox/sandbox/src/index.ts))
- `@deepseek-ai/dsh-session-persistence` — abstract `SessionPersistence` ([`packages/session/session-persistence/src/index.ts`](../packages/session/session-persistence/src/index.ts))
- `@deepseek-ai/dsh-session-query` — abstract `SessionQueryEngine` ([`packages/session-query/session-query/src/index.ts`](../packages/session-query/session-query/src/index.ts))
- `@deepseek-ai/dsh-settings` — abstract `SettingsProvider` ([`packages/settings/settings/src/index.ts`](../packages/settings/settings/src/index.ts))
- `@deepseek-ai/dsh-shell` — abstract `ShellExecutor` ([`packages/shell/shell/src/index.ts`](../packages/shell/shell/src/index.ts))
- `@deepseek-ai/dsh-spill` — abstract `SpillStore` ([`packages/spill/spill/src/index.ts`](../packages/spill/spill/src/index.ts))
- `@deepseek-ai/dsh-subprocess` — abstract `SubprocessRuntime` ([`packages/subprocess/subprocess/src/index.ts`](../packages/subprocess/subprocess/src/index.ts))
- `@deepseek-ai/dsh-workflow` — abstract `WorkflowEngine` ([`packages/workflow/workflow/src/index.ts`](../packages/workflow/workflow/src/index.ts))
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
## Library packages (no plugin entry)
Imported as libraries by other packages; a `cordis.yml` cannot load them.
- `@deepseek-ai/dsh-acp-snapshot` ([`packages/test-support/acp-snapshot/src/index.ts`](../packages/test-support/acp-snapshot/src/index.ts))
- `@deepseek-ai/dsh-agent-loop-testkit` ([`packages/test-support/agent-loop-testkit/src/index.ts`](../packages/test-support/agent-loop-testkit/src/index.ts))
- `@deepseek-ai/dsh-anonymous-user-id` ([`packages/identity/anonymous-user-id/src/index.ts`](../packages/identity/anonymous-user-id/src/index.ts))
- `@deepseek-ai/dsh-app-boot` ([`packages/boot/app-boot/src/index.ts`](../packages/boot/app-boot/src/index.ts))
- `@deepseek-ai/dsh-atomic-write` ([`packages/util/atomic-write/src/index.ts`](../packages/util/atomic-write/src/index.ts))
- `@deepseek-ai/dsh-base` ([`packages/bundle/base/src/index.ts`](../packages/bundle/base/src/index.ts))
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
- `@deepseek-ai/dsh-brand` ([`packages/util/brand/src/index.ts`](../packages/util/brand/src/index.ts))
- `@deepseek-ai/dsh-client-store` ([`packages/client/store/src/index.ts`](../packages/client/store/src/index.ts))
- `@deepseek-ai/dsh-client-test-runtime` ([`packages/test-support/client-runtime/src/index.ts`](../packages/test-support/client-runtime/src/index.ts))
feat(gui): step1 skeleton — dsc web serves built web UI over booted harness host Five new modules: apps/dsc (bin: parseArgs + node:http static server + signal shutdown), packages/host/apiproxy (programmatic harness core composition, agents:[]), packages/client/web-runtime (React-free browser runtime), packages/client/web-ui (React mount), apps/web (vite build entry producing dist consumed by apps/dsc via package exports). Root wiring: apps/* workspace glob, dsh-* paths for host/client groups, demo:web script, apps/web/dist gitignore. No protocol/API routes yet — contract lands in step2 (see missions/tasks/20260719-1902-apiproxy-api-design). Includes the design + implementation archives (spec v2.1, deepseekchat baseline and harness boot research, implementation run log). Acceptance: 12/12 passed incl. real-key llm.stream smoke (51 chunks). feat(gui): apiproxy — four-quadrant RPC contract + fetch carriers, live end to end Contract layer (src/api/, 14 files): four named wire message types (ClientRequest / ServerResponse / ServerRequest / ClientResponse) as a discriminated union over strict bidirectional rpcId (initiator mints, responder echoes; channel and message fully decoupled — HTTP is the client->server pipe, SSE the reverse); narrow RpcRequest<P>/ RpcResponse<T> signature forms; RpcMethodMap with RequestPayload<K>/ ResponseValue<K> derivation; typed RpcError details map; approval/ question responses modeled as ClientResponse via a single /api/respond endpoint (RpcReceipt carrier ack); zod schemas anchored per Wire<T> against exactOptionalPropertyTypes. impl/api-proxy.ts: describe/list/create, both SSE streams (frame queue pump, subscribed baseline, lifecycle frames, signal cleanup); history pages on message boundaries (tail-back scan, partial included in the tail page); prompt dispatches queue->agent.send / steer->agent.steer with rpcId carried through MessageSource; cancel for attached sessions; cold-session resume deduped via a per-id promise map; host-level provider/model defaults injected at create/resume. fetch/: mechanical UNARY_ROUTES table, two-level parse with path==method check, SSE frames completed to ServerRequest full form; client mints -> narrows -> envelopes outbound, verifies rpcId echo inbound, streams SSE frames, four-quadrant onEnvelope tap (debug panel choke point). Real-browser fixes: URL base resolves to location.origin (hardcoded internal base broke real pages), browser-safe export paths. Design archives: contract design.md v2.0 with decision log, core-coverage audit, comparative studies, step2 impl run log. Probed end to end over real HTTP: prompt -> live model stream -> history returns the finished reply. feat(gui): RpcLog debug panel — fixture-driven milestone, playwright-verified 10/10 web-runtime: rpcLog + ui slices (zustand), four-quadrant RpcLogEntry (client-request / server-response / server-request / client-response), onEnvelope tap -> microtask-batched pump with 500-entry ring buffer, ConnectionController (private state, backoff reconnect), fixture API with fake envelopes (?fixture switch), bootWebRuntime; contract types via temporary local copies (api-types.ts, swapped for real imports when W3 client lands). web-ui: components/panels/RpcLog five-piece set (badge with unread count, floating panel, direction glyphs per quadrant, same-rpcId pair highlighting in two families, JSON payload expand, follow/pause, clear), App shell, utils/formatRelative, light-theme CSS variables with dark placeholders. dsc bin: mime lookup fixed to use the actually-served file (naked '/?query' no longer falls through to octet-stream download); shutdown closes SSE keep-alive connections so SIGTERM actually exits. Acceptance: scripts/verify-rpclog-panel.mjs (chromium headless) ALL PASS 10/10 over design.md §D 1-6. pkg: add web scripts for building feat(gui): session milestone — list + conversation over Session OOP, styled RpcLog v2.1 web-runtime: Session/SessionManager object layer (resident instances, mux frame routing, lineage flattening), foldSurface adapter with padding sentinels for paged windows, chunk accumulator for streaming partials, batched change notification (useSyncExternalStore contract), connection sinks + reconnect fix (the 300ms self-abort reconnect storm that made the session list flap is gone), fixture rewritten as a scripted host (60-turn history, typewriter replay, resident pending approval, child session); temporary contract copies deleted in favor of real apiproxy imports. web-ui: sessions screen (list with lineage indent + selection as container-local state), conversation view (turn grouping, reasoning fold, tool cards, steering, pending interaction cards, upward paging with scroll anchoring), input bar with queue/steer/stop; RpcLog panel restyled per docs/web-styling.md (tokenized palette, quadrant badge glyphs now vertical ↑↓⇟⇞, pair highlighting, floating shadow). docs/web-styling.md: living style guide (tokens, visual baseline, coding rules, evolution log). Acceptance: verify-session.mjs 31/31, verify-session-real.mjs 5/5 (real model streaming), verify-rpclog-panel.mjs 10/10. feat(gui): hostruntime split + repo-wide package prefix rename Package split (design: 20260720-0101-hostruntime-split-design): dsh-host-runtime carries bootHost + createApiProxy + startHost() (RunningHost {api, handler, defaults, ctx, dispose} — the seam Electron and any future shell reuses; ctx is the official front-door mount point); dsh-host-webserver carries the node:http static+API bridge (fixed: abort now keys on res 'close' + writableEnded — req 'close' fires on body end since Node 16 and was killing every SSE stream instantly, the reconnect-storm root cause); apps/dsc is now a thin assembly with web/-p subcommands. dsc -p runs the full isomorphic carrier chain in process (second real protocol consumer; probed end-to-end against the live model). Naming rule (user decree): packages under host/ and client/ carry the directory prefix in their npm name — dsh-host-apiproxy, dsh-client-web-runtime, dsh-client-web-ui renamed repo-wide in one frozen batch; explicit tsconfig paths entries added where the wildcard no longer matches. Acceptance: verify-session 31/31, verify-rpclog-panel 10/10, verify-session-real 7/7 (incl. new 12s connection-stability sentinels), tsc green, dsc web + dsc -p smoke both pass. refactor(gui): AbstractApiClient class hierarchy — OO client with inheritable seams AbstractApiClient (apiproxy) carries every protocol invariant: rpcId minting, four-quadrant envelope wrap/unwrap, zod parsing, SSE frame parsing, the payload-direct IApiClient surface (callers no longer mint rpcIds — the carrier does), and the instance-level envelope observation pump (batched via microtask; moved off module-level globals in rpc-log.ts, which is now a pure subscriber mapping envelopes into store entries — the debug panel observes the connection, it is not part of it). Platform subclasses own two abstract seams (doFetch, onEnvelope) plus three protocol-level virtuals for transportless overrides: InProcessApiClient (apiproxy; dsc -p uses new InProcessApiClient( host.handler)), WebApiClient (web-runtime), FixtureApiClient (fixture now subclasses instead of wrapping). Naming per decree: AbstractApiClient / IApiClient; ApiProxy stays the impl-side narrow-form contract. headless.ts call sites drop rpcRequest wrappers (payload-direct); split-design archive updated with the naming-rule ledger. tsc green; verify-session 31/31, verify-rpclog-panel 10/10, verify-session-real 7/7 (12s connection sentinel count=4); dsc -p smoke CALLER-OK. feat(gui): InputBar final form — bug batch, deepseekchat layout, single primary button, running locks input Squashes the whole InputBar iteration batch: IME/caret/auto-grow/focus/dedup bug fixes, layout aligned to the deepseekchat baseline, single primary button with hover flyout, finalized button semantics with the Codex-style icon circle, and running-state locking where stop is the only mid-turn action. The same batch carried the Chinese-to-English code comment sweep (density pruned), folded in here. docs(gui): purge work-log references from code comments 76 design-doc references cleared across the GUI packages: section pointers inlined as self-contained constraint statements, pure pointer comments dropped, milestone codenames and ruling tags out, and the 14 contract file headers switched to the formal RFC (the only sanctioned external reference). web-styling.md now cites the styling RFC instead of the disposable research archive. grep for work-log reference variants is clean across the GUI packages. docs(gui): file-header comments self-contained — drop RFC filename references RFC renames/reorgs must not require a source sweep (the 2026-07-20 two-way merge proved it). 11 headers lose only the '(RFC …)' tail and stay self-contained; api-proxy.ts keeps its minimal-first note. fix(gui): session streaming — freeze interrupted partials, sweep stale running calls, send force-scrolls Aborted turns never emit the finalizing assistant/message, so the accumulated partial and its running tool cards kept rendering below later messages — the "new message lands above the stopped reply" illusion. turn/end side effects now freeze content-bearing partials into interrupted terminal nodes (fractional seq keeps flow order; the live freeze and history replay converge through applyEventSideEffects, so a refresh reconstructs identical frozen nodes) and turn running tool cards into interrupted terminal cards; only content-free partials are swept outright. ConversationView gains the send-force-scroll rule (own words must be visible) alongside the pre-update atBottom follow flag. Regressions pinned as E2-4a–c (real host) and §E1-11h (fixture). feat(gui): webserver hardening verify script feat(gui): dark-mode toggle pinned to the sidebar bottom Interim home before the Settings page exists (the button re-homes with zero logic change — mechanics live in utils/theme.ts): html[data-theme] flip + dsc.theme localStorage, stored choice wins over the OS prefers-color-scheme default, applied in mount() before first paint so a dark reload never flashes light. Moon/sun inline SVG icon button at the sidebar's pinned bottom row. Pure front-end local concern: no RPC, no Session/store involvement. Dark sweep of list/conversation/input card/RPC panel found no unreadable pairs — no token changes needed. docs(gui): GUI RFCs and web styling handbook Layering+RPC protocol and web client architecture RFCs (post-reorg, developer-facing polish folded in) plus the styling engineering handbook. Mission work logs live in the commit above; PRs can be cut from this commit to include formal docs only. fix(gui): client object-layer hardening — audit timing/reference/resilience batches (S3-S5,C1-C3,C5-C8) fix(gui): carrier error channel + webserver backpressure (audit A1-A5,A7-A10,R2,R5) feat(gui): session persistence surface — cold list, project cwd, legacy no-cwd retirement refactor: rename dsc CLI to dsh — apps/cli, bin name, package scope Includes the root tsconfig project-references fix for host/* and client/web-runtime (originally a separate build fix commit). test(gui): three-tier suite — protocol/object/browser lanes, tier-a fill to per-file 100% test(gui): jsdom lane for web-ui + web-runtime coverage gate entry docs(gui): GUI testing system RFC (zh) feat(gui): tool-card views — contract slot, host-computed delivery, three-level card fallback fix(gui): lint clean across GUI packages — wrap long doc comments, drop dead type args, sync-return methods without awaits docs(gui): doc-sync mechanical fixes — JSDoc on apiproxy/host exports, RFC sketch fences ignore-check, md-wrap paragraphs, drop missions links, web-ui plain-ts entry chore(gui): module-graph regen + knip clean — drop dead re-exports, internalize createFixtureApi, scan web-ui tsx and verify mjs scripts build(gui): wire client/host packages into the lib build shape — tsc references + tsdown (web-ui css-external), lib manifests, cordis peer, apiproxy typed subpaths, vite src aliases test(gui): host-side per-file 100% coverage — apiproxy schema/carrier suites, webserver http-bridge suite, host-runtime composition suite; client/* coverage excluded pending the browser-side testing work item docs(gui): package READMEs for the five GUI packages — model-experience audit entries, limitations sections docs(gui): bilingual RFC pairs + client JSDoc completion — translate the three GUI RFCs to English with i18n records and manifest ratchet, Consequences sections both sides, full client/* export JSDoc, regen doc graphs and RFC index fix(scripts): doc-typecheck built-declarations mode maps /src/* subpath wildcards (apiproxy browser-safe channels) docs(gui): apply dsh rename across pr-gates docs — READMEs, layering RFC en, web-ui entry comment, i18n re-record fix(gui): post-rebase lint reconciliation — wrap main-tree long doc comments, read-through narrowing guards, abortError Error normalization, handleUnary generic justification fix(gui): post-rebase doc/test reconciliation — align host specs with evolved carrier contracts (sentinel rpcId, stream/error surfacing, url-path transport messages, defaults.cwd), Agent Note titles and relocated links, KV Cache effect sections, JSDoc on evolved exports fix(gui): second-rebase reconciliation to 509db0cb3 — restore api panel exports the baseline suites consume, knip workspace entries for jsdom lane and apps/web smokes, hoist result narrowing, align testing.md to the narrowed web-ui exclusion fix(test): vitest-scoped tsconfig maps bare imports for tsx specs — with GUI manifests now pointing at lib, an unmapped importer loaded a second copy of the web-runtime singletons fix(gui): typecheck + lint clean over the tool-card batch — brand callIds and object-form turn/end reason in the view spec, narrow fixture arg stringification, wrap long v8-ignore comments docs(gui): export JSDoc for tool-card surfaces + testing-note pairing header docs: rfc for web testing feat: add tools to host-runtime fix(gui): dispatch agent/error via agentEvents in host-runtime spec — mounted invariants plugin rejects raw ctx.emit without the scope carrier fix(gui): restore GUI knip workspaces + scripts/mjs entries and regenerate lockfile after master rebase fix(gui): post-rebase gate repairs — drop context-node envelope (master unwrapped injected content envelopes), regen event matrix, condense testing.md web-ui exclusion within budget fix(session): browser-safe deep-equal in surface — node:util import broke the vite bundle ci(gates): frontend vite build joins pre-push — node: imports in the client closure pass tsc but break the browser bundle test(tui): drop the checkout-dependent process.cwd() harness default — a long worktree path pushes the footer token counters past the 88-column fake terminal test(gui): jsdom behavior E2E — conversation main path over fixture runtime, reconnect banner lifecycle test(gui): jsdom RPC panel behavior — ledger rows, expand, pairing, pause/clear, follow-pause, payload truncation test(gui): jsdom tier-2 — InputBar guards, reasoning fold, JSON blocks, message variants, theme, create-then-select; act-harden banner case test(gui): jsdom tier-3 — ConversationView states/paging/force-bottom, ToolCallCard arms, PendingCard, list rows test(gui): jsdom tails — view-card variants, LogRow directions, registry hygiene, badge overflow, hook ops, mount glue test(gui): jsdom tails round 2 — call-ref blocks, resume follow, view precedence, failed create, empty-diff arm test(gui): jsdom final arms — anchor compensation, follow-off, interval ticks, view halves, node-over-running precedence test(gui): web-ui joins the per-file 100% coverage gate Annotation-only src changes plus the config swap. The web-ui exclusion is replaced by a single index.tsx entry (stale byte-identical duplicate of mount.tsx, nothing imports it; same entry-glue treatment as bin.ts) and the coverage include gains .tsx. v8-ignore sites (each with its reason inline): - ConversationView 3x ref-null guards; InputBar disabled-click guard - ToolCallCard both-null arms + windowless-custom argsRaw arm - LogRow css-module key fallbacks (start/stop block); RpcLogBody 3x ref-null guards - web-runtime drift from the tool-card batch: fixture presenter catch/str typo-guards, dense-array guards (fold-adapter reset, session rebuild, fixture backscan), live view-present arm (fixture replays are text-only; view vocabulary is covered by the history samples) test(gui): close the PR #443 host-side coverage gaps — apiproxy client abort arms, api-proxy cold/view paths, webserver drain - apiproxy fetch/client.ts: 3 new cases (pre-aborted signal short-circuits before transport + string reason mapping, non-Error/string reason falls to the default AbortError message, signal-less doFetch passthrough) - runtime/api-proxy.ts: one v8-ignore (summarizeCold cwd arm — list() filters cwd-less legacy metas) + api-proxy-cold.spec.ts (cold list merge: mtime source, locate-undefined and vanished-log fallbacks, lineage; no-persistence/no-factory resume → internal) + 2 view cases (history views with meta passthrough and orphan/bad-args/presenterless soft-falls, session/disposed open-call cleanup on the mux stream) - webserver/index.ts: /api/big fixture drives both drain-wait legs (full 8MiB readback after drain, mid-chunk disconnect wakes via 'close') feat: app shell fix: rebase conflicts fix: coverage fix(gui): lint clean after rebase — wrap long v8-ignore comments, unconditional v1 detail-block claim chore(gui): remove browser/probe verify scripts from scripts/ The six GUI acceptance/probe scripts (carrier-errors, rpclog-panel, session, session-real, webserver-backpressure, webserver-hardening) leave the repo's scripts/ tree; the three code comments that pointed at them now describe the coverage lane without naming a script path. fix(webserver): guard the request callback — one malformed request must not kill the process The async handle() had no top-level catch, so any throw inside it (a bad %-escape reaching decodeURIComponent, a client dropping mid-body, a response stream erroring) became an unhandled rejection and took the whole process down (audit R1 must-fix). The guard answers 400 when headers are not out yet, destroys the socket when they are, and reports the failure to onError (the package never prints). Spec covers all three legs: %-escape barrage → 400 + server stays alive, non-Error throw wrapped for onError, mid-stream explosion → socket teardown. feat: client AGENTS.md fix: client/AGENTS.md fix: rebase feat(gui): T0 cut 1 — 12 client package skeletons with contract stubs, dshClient declarations, tsdown client preset, theme token sheets feat(gui): T0 cut 2 — pure git mv migration per v3 §11 (connection six, runtime sessions/kernel, ui-conversation chat, ui-primitives markdown family, web shell + e2e) feat(gui): T0 cuts 3+4 — import rewiring to new package names, .legacy demotion of owner-rewrite files, legacy web-runtime/web-ui/apps-web retired to attic feat(gui): connection 对账刀——index.ts 精确导出清单替换 export *,intents.legacy 溶解删除 feat(client/ui-slots): SlotCore real implementation — kind semantics, sync version + microtask-batched notify, onMutate bridge feat(gui): web shell vite alias — retarget to new client packages, shell static surface only feat(gui): host 侧刀属地半——HostWebPluginRegistry(entries 扫描+internal/plugin 去抖重扫+dshClient 校验+exports./client 解析)、GET /plugins/<id>/client.js 分发端点、GET / 与 SPA fallback 注入 __DSH_BOOT__(webPlugins 可选注入,不传行为不变) feat(web-react): add use-sync-external-store dep + local shim typings feat(web-react): bindSnapshotSelector via uSES with-selector shim feat(gui): ui-layout concession-chain solver — pure computeColumns with contract geometry feat(gui): ui-layout LayoutService — four persisted stores, clamped actions, list-driven prune feat(gui): ui-layout AppFrame styles — grid columns, collapse-safe borders, edge drag handles test(gui): 存量 spec 平移——connection 三件+runtime 六件自 attic 捞回改包名路径全绿;api-helpers 按归属拆分(wire 半留 connection、classifier 半随 conversation.ts 入 runtime);boot-intents/preinit/rpc-log 随 intents/rpc-log 退役不迁(记 v3 §3.2 溶解项) feat(client/ui-primitives): StateDot/Button/Pill/Input/Menu atoms, ConnectionBanner de-legacied to pure props, JsonBlock CSS on --dsw tokens feat(web-react): createSnapshotStore engine (rafFlush batch, persist opt-in, dev freeze) + spec feat(gui): ui-layout AppFrame — grid tracks, pointer-capture drag handles with rAF throttle, frame ResizeObserver feat(web-react): useInvoke (external pending store, stable invoke, concurrency count) + spec test(web-react): bind spec — equality bail, custom eq, zero resubscribe, StrictMode, method sources feat(gui): ui-layout index rewiring — real exports, client apply provides ctx.layout and defines three slots feat(web-react): SessionProvider (renderBody deps) + RootBindingProvider + binding contexts + spec feat(gui): web shell AppRoot boot-page styles — self-contained with neutral token fallbacks feat(gui): web shell AppRoot — boot gate over loader status, fail-loud plugin failure list fix(gui): AppRoot gates on explicit settled signal — status-derived readiness races the incrementally filled table feat(client/ui-theme): ThemeService real implementation — registry with built-in light/dark, apply toggles body[data-ds-dark-theme], third-party token overrides as body inline vars feat(web-react): scopedSlots outlet (kind matrix, inject WeakMap caches, per-entry error boundary) + spec feat(gui): web shell module-table seed — pure-library entities for the loader require surface feat(client/i18n): I18nService real implementation — ns×locale registry, stable bind(ns) reference, zh fallback chain, zh/en skeleton dictionaries feat(gui): web shell assembly closure — layout exports via module table, SessionProvider + scopedSlots + RootBindingProvider feat: client/ui-conversation feat: code codedoc build(gui): root bundle green — web shell excluded from the lib workspace (vite app), ui-primitives lib externalizes css side-effect imports (web-ui precedent) gates(gui): verify-cordis-config follows aggregate tsconfig references (root is a shell over host/client programs); module graph regenerated for the twelve client packages chore(gui): retire legacy migration sources — every owner rewrite landed (t0-checklist §7 ledger honored); orphan css of retired components removed gates(gui): knip green groundwork — e2e/tsx entries for the new packages, loader-runtime deps ignored where loading is by specifier string, fake plugin ids un-bare-named, dead test export dropped chore(client): manifest shape batch A — ui-slots/web-react/ui-primitives invariant companions, files whitelist, cordis+invariants peer/dev, tsconfig refs chore(client): manifest shape batch B — connection/runtime/ui-conversation/ui-trajectory files whitelist, cordis peer+dev, explicit invariant lib entries (clientBundle signature) chore(client): manifest shape batch C — i18n/ui-layout/ui-sidebar/ui-theme invariant companions, files whitelist, invariants peer/dev, tsconfig refs chore(client): manifest shape batch D — web shell gains node-half lib entry + invariant companion + uniform files whitelist chore(client): drop verified-unused deps — dsh-tools from runtime/ui-conversation (types ride /presentation), ui-primitives+clsx from ui-layout gates(gui): doc-gate fixes — theme JSDoc prose, three client type-link exemptions, agent-note paths follow the migration, config catalog regenerated gates(gui): type-equiv manifest follows the types.ts extraction, approval JSDoc keeps its link form, persistence catalog regenerated docs(gui): per-constant JSDoc on the contract geometry exports (export-jsdoc gate) test(gates): loader-composition budget covers cold tsx resolution after the program split (was flaking at the default 5s) docs(gui): README substantiation batch 1 — ui-slots/ui-primitives/web-react/connection: Model Experience short form, real deferred-work ledgers, description accuracy pass fix(client): theme/i18n dual-entry split — service classes + cordis merges move to src/client (host catalog scanner no longer misclassifies client services), node halves keep types + empty apply; catalogs regenerated docs(gui): README substantiation batch 2 — runtime/ui-layout/ui-sidebar/ui-conversation: Model Experience short form, package-owned deferred-work ledgers (unload stub, watch approximation, /client value-import rule, global details state, two-state dots, stats duration gap, single-bundle caches) docs(gui): README substantiation batch 3 — ui-trajectory/ui-theme/i18n/web: Model Experience short form, deferred-work ledgers (placeholder charter, no theme toggle owner, empty locale dictionaries, one-shot rendering); both README gates green test(scripts): purity spec adopts clientBundle two-arg signature (explicit libEntry, no default) gates(gui): knip green — declaration-merge dep ignored, fake plugin id assembled at runtime, invariants dep de-duplicated to peer+dev, stale apps/web section dropped feat(gui): 门禁波次 host 三包 invariant 形状——apiproxy explained-empty 伴生(wire 契约层零事件面)、webserver 真关系伴生(manifest 行必解析出 clientPath,防 __DSH_BOOT__ 广告 404 bundle;apps/cli 发布 webPlugins 键供审计)、runtime 补 files 白名单;三包 exports/files/peer+dev/tsconfig refs 齐 fw-react 形状;constraints+invariants 双 gate 零违规 build(client): ui-layout/ui-sidebar tsdown configs adopt the explicit two-arg clientBundle signature (orphaned follow-up of the manifest shape batch) refactor(gui): shell boot becomes a library face — bootWebShell(el) exported for the apps/web entry; main.ts retired refactor(gui): exports 纪律刀1——ui-theme/i18n node index 收敛为只空 apply(Translate/LocaleDict/ThemeTokens 类型下沉 src/client/),ui-conversation 的 I18nService import 改 /client 子路径 build(typecheck): converge to root host aggregate + tsconfig.client.json — delete tsconfig.host.json, verify-cordis-config seeds both aggregates feat(gui): apps/web restored as the vite application — thin main over bootWebShell; dsh-client-web becomes a plain lib (index exports shell surface, vite files and e2e moved out) chore(gates): knip.json rewritten on the master base — same semantics, minimal diff (formatting churn dropped) docs(gui): 时效清扫②——testing.md 删 web-ui 覆盖豁免残句;web-styling.md 加 token 换代头注(--dsw-* 现行、工程约束条款仍有效并注明收编处) docs(gui): 时效清扫③——四对 GUI Agent Note 加路径更新头注(web-runtime/web-ui/dsh-frontend→现行 12 包结构;设计结论存续声明;双语对同步) docs(gui): 时效清扫③b——四对 note 头注的 i18n 配对哈希重录 build(typecheck): minimal-diff tsconfig shape — drop root files entry (purity spec + preset move to client program), compress comments, drop redundant util/home root ref feat(gui): apps/web restoration follow-through — dsh-frontend package name, cli dist resolve, root build:web filter, tsdown exemption dropped, vitest web lane + knip + client aggregate retargeted, e2e paths rebased refactor(gui): exports 纪律刀2——connection wire 六件 git mv 进 src/client/(wire 即该 dshClient 插件的 client 半),node index=只空 apply,/client 半边整面导出(v3 §3.2 清单原样),包内 tests 改 src/client 直取 refactor(gui): exports 纪律刀3——runtime 实现整体下沉 src/client/(sessions/slots/loader;契约类型与 cordis merge 随迁 client/index),node index=只空 apply;./loader exports 指 client/loader;全消费面(web 壳/ui-sidebar/ui-trajectory/tests)bare→/client 机械跟改;vitest.e2e 换 tsconfig.vitest paths(root tsconfig 排除 client 会把 /client import 掉到 exports 的浏览器 dist bundle) refactor(gui): exports 纪律刀3 补遗——ui-layout 三处 bare runtime import 改 /client(刀3 消费面机械跟改漏提交件;跨属地机械一行×3 报备 ui-shell) test(gui): drop the getSessionManager singleton case — the init/get pair is a dead legacy-boot surface with zero live consumers (SessionsService constructs and holds the manager under the plugin architecture); source removal tracked with rt-core refactor(gui): 删 manager.ts 尾部 initSessionManager/getSessionManager 单例对——旧 boot 直连遗物,插件化下 SessionsService 构造持有 manager,全仓零活消费者(convo-b 测试清扫对表,其测试用例已先行退役 7e2c51898);头注释同步去单例措辞 code refactor
2026-07-19 21:17:57 +08:00
- `@deepseek-ai/dsh-client-ui-primitives` ([`packages/client/ui-primitives/src/index.ts`](../packages/client/ui-primitives/src/index.ts))
- `@deepseek-ai/dsh-client-ui-slots` ([`packages/client/ui-slots/src/index.ts`](../packages/client/ui-slots/src/index.ts))
- `@deepseek-ai/dsh-client-web` ([`packages/client/web/src/index.ts`](../packages/client/web/src/index.ts))
- `@deepseek-ai/dsh-cmdline` ([`packages/boot/cmdline/src/index.ts`](../packages/boot/cmdline/src/index.ts))
- `@deepseek-ai/dsh-code-runtime-python` ([`packages/code-runtime/code-runtime-python/src/index.ts`](../packages/code-runtime/code-runtime-python/src/index.ts))
- `@deepseek-ai/dsh-experimental-webworker-packer` ([`packages/experimental/webworker-packer/src/index.ts`](../packages/experimental/webworker-packer/src/index.ts))
- `@deepseek-ai/dsh-experimental-webworker-runtime` ([`packages/experimental/webworker-runtime/src/index.ts`](../packages/experimental/webworker-runtime/src/index.ts))
- `@deepseek-ai/dsh-home-paths` ([`packages/util/home-paths/src/index.ts`](../packages/util/home-paths/src/index.ts))
feat: generated plugin config catalog (docs/config-catalog.md) scripts/gen-config-catalog.ts walks every packages/<group>/<pkg> entry with the TypeScript compiler API and emits docs/config-catalog.md: per loadable plugin, the verbatim config declaration (JSDoc included) its apply/constructor receives in a ts config-catalog fence, the inject requirements, resolved links for every referenced type (package-local types pasted transitively, other plugins' config types as intra-page anchors, LINK_MAP names to core-data-structures, workspace types to source), and terse classification lists for config-free plugins, abstract seams, and libraries — classification is total, so a new package cannot go undocumented. The walk enforces per-field JSDoc prose on every pasted declaration and statically cross-checks the schemastery schema (z.object keys, z.intersect composition across packages): every schema-validated key must be a declared member of the config type. One violation existed repo-wide — the agents[].id field in dsh-agent-loop — fixed by adding its JSDoc (which shifts the cordis-catalog services page's source pointers; regenerated). verify-config-catalog (--check) joins doc-sync; doc-typecheck learns the ts config-catalog fence; gen-cordis-catalog exports its JSDoc/pointer helpers and LINK_MAP for reuse. Negative-path spec in packages/core/agent-core/tests/gen-config-catalog.spec.ts mirrors the gen-cordis-catalog spec. Decision record: docs/rfc/implemented/process/2026-07-06-generated-config-catalog.md (includes the deliberate acceptance of README ## Config overlap).
2026-07-06 21:57:17 +08:00
- `@deepseek-ai/dsh-hook-protocol` ([`packages/hooks/hook-protocol/src/index.ts`](../packages/hooks/hook-protocol/src/index.ts))
- `@deepseek-ai/dsh-launch-environment` ([`packages/util/launch-environment/src/index.ts`](../packages/util/launch-environment/src/index.ts))
- `@deepseek-ai/dsh-llm-mock-server` ([`packages/test-support/llm-mock-server/src/index.ts`](../packages/test-support/llm-mock-server/src/index.ts))
- `@deepseek-ai/dsh-loader-smoke` ([`packages/test-support/loader-smoke/src/index.ts`](../packages/test-support/loader-smoke/src/index.ts))
- `@deepseek-ai/dsh-native-command` ([`packages/util/native-command/src/index.ts`](../packages/util/native-command/src/index.ts))
- `@deepseek-ai/dsh-output-retention` ([`packages/util/output-retention/src/index.ts`](../packages/util/output-retention/src/index.ts))
- `@deepseek-ai/dsh-sandbox-windows-acl` ([`packages/sandbox/sandbox-windows-acl/src/index.ts`](../packages/sandbox/sandbox-windows-acl/src/index.ts))
- `@deepseek-ai/dsh-scope` ([`packages/core/scope/src/index.ts`](../packages/core/scope/src/index.ts))
- `@deepseek-ai/dsh-sdk-client` ([`packages/sdk/client/src/index.ts`](../packages/sdk/client/src/index.ts))
- `@deepseek-ai/dsh-sdk-protocol` ([`packages/sdk/protocol/src/index.ts`](../packages/sdk/protocol/src/index.ts))
- `@deepseek-ai/dsh-sdk-python-runtime` ([`packages/sdk/python-runtime/src/index.ts`](../packages/sdk/python-runtime/src/index.ts))
- `@deepseek-ai/dsh-session-telemetry` ([`packages/session/session-telemetry/src/index.ts`](../packages/session/session-telemetry/src/index.ts))
- `@deepseek-ai/dsh-session-title-llm` ([`packages/session/session-title-llm/src/index.ts`](../packages/session/session-title-llm/src/index.ts))
- `@deepseek-ai/dsh-subagent-in-process-driver` ([`packages/subagent/subagent-in-process-driver/src/index.ts`](../packages/subagent/subagent-in-process-driver/src/index.ts))
- `@deepseek-ai/dsh-timeout` ([`packages/util/timeout/src/index.ts`](../packages/util/timeout/src/index.ts))
- `@deepseek-ai/dsh-typert-generator` ([`packages/typert/generator/src/index.ts`](../packages/typert/generator/src/index.ts))
- `@deepseek-ai/dsh-typert-protocol` ([`packages/typert/protocol/src/index.ts`](../packages/typert/protocol/src/index.ts))
- `@deepseek-ai/dsh-typert-registry` ([`packages/typert/registry/src/index.ts`](../packages/typert/registry/src/index.ts))
2026-08-21 01:12:49 +08:00
- `@deepseek-ai/dsh-util-crypto` ([`packages/util/crypto/src/index.ts`](../packages/util/crypto/src/index.ts))
- `@deepseek-ai/dsh-win32-process` ([`packages/subprocess/win32-process/src/index.ts`](../packages/subprocess/win32-process/src/index.ts))