Merge remote-tracking branch 'origin/master' into feat/web-session-log-export
# Conflicts: # docs/subsystems/persistence.i18n.yaml # docs/subsystems/persistence.md # docs/subsystems/persistence.zh.md # packages/client/ui-trajectory/README.i18n.yaml # packages/client/ui-trajectory/README.md # packages/client/ui-trajectory/README.zh.md # packages/client/ui-trajectory/package.json # packages/client/ui-trajectory/src/client/TrajectoryView.tsx # packages/client/ui-trajectory/src/client/index.ts # packages/client/ui-trajectory/tests/client-bundle.spec.ts # packages/client/ui-trajectory/tests/views.spec.tsx # packages/host/apiproxy/package.json # pnpm-lock.yaml
This commit is contained in:
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/api-gateway.md
|
||||
api-gateway.md: 4b904f24e5755460b6c629e3d2fd43ffc1aefaaf
|
||||
api-gateway.zh.md: 1e434cbb99450d241d6fde7e570ae1fadf5c0209
|
||||
api-gateway.md: 06f98546c8858af08efcb07c007d8e1b95b90c19
|
||||
api-gateway.zh.md: 82bf8923c45151d0c00e71848be89806427d1ce3
|
||||
|
||||
@@ -17,7 +17,7 @@ Services normally extend `GatewayService` so the constructor explicitly binds th
|
||||
```ts
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { GatewayService, Remote, RemoteScope } from '@deepseek-ai/dsh-type-meta'
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export interface CreateGoalRequest {
|
||||
objective: string
|
||||
@@ -60,7 +60,7 @@ The Client uses concrete functions on ordinary objects, not a JavaScript Proxy.
|
||||
```ts ignore-check
|
||||
import type { SessionId } from '@deepseek-ai/dsh-session/types'
|
||||
import type { AgentContext } from '@deepseek-ai/dsh-client-runtime/client'
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type {} from '@deepseek-ai/dsh-api-remotes/client'
|
||||
|
||||
export const inject = ['remote', 'remote.goals']
|
||||
@@ -151,7 +151,7 @@ pnpm run dsh -- web --dev
|
||||
pnpm run dev:web
|
||||
```
|
||||
|
||||
`dsh` starts the Host source through tsx, so the Host can use the SRC fallback; `dev:web` watches only Client plugins with a `dshClient` declaration and rewrites their `lib/client.js`. It does not analyze Host decorators or generate Remote Client DTS.
|
||||
`dsh` starts the Host source through tsx, so the Host can use the SRC fallback; `dev:web` watches only Client plugins with a `dsh.client` declaration and rewrites their `lib/client.js`. It does not analyze Host decorators or generate Remote Client DTS.
|
||||
|
||||
Changing only a Remote method's implementation body without changing its contract does not require regenerating the TypeRT files. After adding or removing a decorator or changing an export name, namespace, parameter, return value, lookup, Context, or cancellation signature, rerun the ordered lib build so the Host generates the strict contract before the Client compiles and bundles the new contribution:
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ Service 通常继承 `GatewayService`,让 Cordis service key 与默认 Remote
|
||||
```ts
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { GatewayService, Remote, RemoteScope } from '@deepseek-ai/dsh-type-meta'
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export interface CreateGoalRequest {
|
||||
objective: string
|
||||
@@ -60,7 +60,7 @@ Client 使用普通对象上的具体函数,不使用 JavaScript Proxy。直
|
||||
```ts ignore-check
|
||||
import type { SessionId } from '@deepseek-ai/dsh-session/types'
|
||||
import type { AgentContext } from '@deepseek-ai/dsh-client-runtime/client'
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type {} from '@deepseek-ai/dsh-api-remotes/client'
|
||||
|
||||
export const inject = ['remote', 'remote.goals']
|
||||
@@ -151,7 +151,7 @@ pnpm run dsh -- web --dev
|
||||
pnpm run dev:web
|
||||
```
|
||||
|
||||
`dsh` 通过 tsx 启动 Host 源码,所以 Host 可以使用 SRC 回退;`dev:web` 只监听带 `dshClient` 声明的 Client plugin 并重写其 `lib/client.js`,它不会分析 Host decorator,也不会生成 Remote Client DTS。
|
||||
`dsh` 通过 tsx 启动 Host 源码,所以 Host 可以使用 SRC 回退;`dev:web` 只监听带 `dsh.client` 声明的 Client plugin 并重写其 `lib/client.js`,它不会分析 Host decorator,也不会生成 Remote Client DTS。
|
||||
|
||||
只修改 Remote 方法实现体而不改变约定时,无需重新生成 TypeRT 文件。新增或删除 decorator、修改导出名、namespace、参数、返回值、lookup、Context 或取消签名时,重新执行有序 lib 构建,让 Host 先生成严格约定,再让 Client 编译并打包新的贡献:
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/capability-seams.md
|
||||
capability-seams.md: 85aee35af0e3de4d7cdbb715bc60c832c023d5ac
|
||||
capability-seams.zh.md: d3664b649f36b1788c6633497c95d5731ad4a401
|
||||
capability-seams.md: c102167aa76b9ba613b1b434cb0aa58765d26106
|
||||
capability-seams.zh.md: 7c4eab8d5a2d890bdf4513bb9acdc81f55414642
|
||||
|
||||
@@ -437,7 +437,7 @@ flowchart LR
|
||||
| `ctx.spillStore` | `seam` | [`spill`](../packages/spill/spill) | [`spill-local`](../packages/spill/spill-local) | [`spill-policy`](../packages/spill/spill-policy) | - | The backend saves oversized tool text and returns a model-facing locator plus retrieval hint; spill-policy is the tools/post-execute consumer that decides when to spill. |
|
||||
| `ctx.directoryPicker` | `seam` | `directory-picker` | `directory-picker-native`, `directory-picker-browse` | `apiproxy` | - | Discriminated interaction capability: the native backend opens one OS chooser on the host display, the browse backend serves listing/creation primitives for the in-app browser; dual-face backends fill ui-workspace directory-flow slots from their browser halves (no wire advertisement). |
|
||||
| `ctx.httpServer` | `core` | `webserver` | - | `connection`, `modules`, `hmr` | - | Plain node:http carrier: named-route registry, index transform taps, and the static dist fallback; web-transport plugins register their own routes. |
|
||||
| `ctx.clientModuleHost` | `core` | `modules` | - | `hmr` | - | Composes the __DSH_BOOT__ entry graph from an incremental dshClient scan, serves plugin bundles, and notifies rebuilt/graph-changed subscribers. |
|
||||
| `ctx.clientModuleHost` | `core` | `modules` | - | `hmr` | - | Composes the __DSH_BOOT__ entry graph from an incremental dsh.client scan, serves plugin bundles, and notifies rebuilt/graph-changed subscribers. |
|
||||
| `ctx.workflows` | `seam` | [`workflow`](../packages/workflow/workflow) | [`workflow-workerthread`](../packages/workflow/workflow-workerthread) | [`tool-workflow`](../packages/workflow/tool-workflow), [`tool-ralph`](../packages/workflow/tool-ralph) | - | One engine per context, as in bash, with no named-provider registry; the general workflow and fixed Ralph consumers start runs whose agent() calls fan out through ctx.subagents. |
|
||||
|
||||
Maintenance mode: hybrid: services are discovered from Cordis declarations; interface/implementation/consumer roles are classified in `scripts/gen-doc-graphs.ts` with a completeness guard.
|
||||
|
||||
@@ -439,7 +439,7 @@ flowchart LR
|
||||
| `ctx.spillStore` | `seam` | [`spill`](../packages/spill/spill) | [`spill-local`](../packages/spill/spill-local) | [`spill-policy`](../packages/spill/spill-policy) | - | 后端保存过大的工具文本,并返回面向模型的定位信息和取回提示;spill-policy 是 tools/post-execute 消费方,负责决定何时 spill。 |
|
||||
| `ctx.directoryPicker` | `seam` | `directory-picker` | `directory-picker-native`、`directory-picker-browse` | `apiproxy` | - | 带判别标记的交互能力:原生后端在 Host 显示设备上打开一个操作系统选择器,浏览后端为应用内浏览器提供列表与创建原语;双端后端通过其浏览器侧填充 ui-workspace 目录流程的 slot(不通过协议发布)。 |
|
||||
| `ctx.httpServer` | `core` | `webserver` | - | `connection`、`modules`、`hmr` | - | 普通的 node:http 载体:具名路由注册表、索引转换 tap,以及静态 dist 回退;Web 传输插件注册自己的路由。 |
|
||||
| `ctx.clientModuleHost` | `core` | `modules` | - | `hmr` | - | 通过增量 dshClient 扫描组合 __DSH_BOOT__ 入口图,提供插件组合包,并通知重建/图变更订阅方。 |
|
||||
| `ctx.clientModuleHost` | `core` | `modules` | - | `hmr` | - | 通过增量 `dsh.client` 扫描组合 __DSH_BOOT__ 入口图,提供插件组合包,并通知重建/图变更订阅方。 |
|
||||
| `ctx.workflows` | `seam` | [`workflow`](../packages/workflow/workflow) | [`workflow-workerthread`](../packages/workflow/workflow-workerthread) | [`tool-workflow`](../packages/workflow/tool-workflow)、[`tool-ralph`](../packages/workflow/tool-ralph) | - | 每个上下文使用一个引擎,与 bash 相同,且没有具名提供方注册表;通用工作流与固定 Ralph 消费方启动运行,其中的 agent() 调用通过 ctx.subagents 扇出。 |
|
||||
|
||||
维护模式:混合模式。服务从 Cordis 声明中发现;接口、实现和消费方角色在 `scripts/gen-doc-graphs.ts` 中分类,并设有完整性守卫。
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/config-catalog.md
|
||||
config-catalog.md: 0d1d2ddde31a7ea806ec273007d7b5743a553e3b
|
||||
config-catalog.zh.md: dc93f5b4b55b07c52c58405ba4793c2c6eca28df
|
||||
config-catalog.md: e2bab765d147f48f0b50a44c4853136954578f3f
|
||||
config-catalog.zh.md: 4c788f9b5afdf65798e298c3e7c1d97bc14ffb64
|
||||
|
||||
@@ -525,10 +525,15 @@ Source: [`packages/host/frontend-static/src/index.ts:28`](../packages/host/front
|
||||
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
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/fs/fs-local/src/index.ts:39`](../packages/fs/fs-local/src/index.ts)
|
||||
Source: [`packages/fs/fs-local/src/index.ts:40`](../packages/fs/fs-local/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-fs-sandbox`
|
||||
|
||||
@@ -536,10 +541,10 @@ Requires: `sandboxPolicy`
|
||||
|
||||
```ts config-catalog
|
||||
/**
|
||||
* Plugin config: the local backend's knobs, verbatim (only `cwd`, the resolve
|
||||
* base for relative paths). The sandbox default (mode + `workspace-write`
|
||||
* fallback root) is NOT here — `ctx.sandboxPolicy` resolves each calling
|
||||
* session for every enforcing capability.
|
||||
* 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.
|
||||
*/
|
||||
export type Config = LocalConfig
|
||||
```
|
||||
@@ -567,7 +572,7 @@ Source: [`packages/goal/goal/src/index.ts:116`](../packages/goal/goal/src/index.
|
||||
Requires: `agentDefaultModel` · `agents` · `sessions`
|
||||
|
||||
```ts config-catalog
|
||||
/** Plugin config: the task, patched in by the launcher. */
|
||||
/** Plugin config: the task resolved from this app's injected provider service. */
|
||||
export interface Config {
|
||||
/** The prompt text for the single run. */
|
||||
task: string
|
||||
@@ -981,12 +986,24 @@ export interface ReplayModelConfig {
|
||||
description?: string
|
||||
/** Optional positive integer context capacity published by the replay adapter. */
|
||||
contextWindow?: number
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
```
|
||||
|
||||
Depends on: [`RetryPolicyConfig`](../packages/llm/llm/src/index.ts)
|
||||
|
||||
Source: [`packages/support/llm-replay/src/index.ts:744`](../packages/support/llm-replay/src/index.ts)
|
||||
Source: [`packages/support/llm-replay/src/index.ts:769`](../packages/support/llm-replay/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-llm-retry`
|
||||
|
||||
@@ -1069,6 +1086,8 @@ export interface StdioConfig {
|
||||
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). */
|
||||
@@ -1089,10 +1108,24 @@ export interface StreamableHttpConfig {
|
||||
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:100`](../packages/mcp/mcp-client/src/index.ts)
|
||||
Source: [`packages/mcp/mcp-client/src/index.ts:98`](../packages/mcp/mcp-client/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-permission`
|
||||
|
||||
@@ -1144,6 +1177,8 @@ export interface Config {
|
||||
* 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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1289,22 +1324,6 @@ export interface Config {
|
||||
|
||||
Source: [`packages/guard/repeat-tool-guard/src/index.ts:28`](../packages/guard/repeat-tool-guard/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-repository-plugin`
|
||||
|
||||
Requires: `loader`
|
||||
|
||||
```ts config-catalog
|
||||
/** Repository Plugin runtime and source-list configuration. */
|
||||
export interface Config {
|
||||
/** GitHub repository sources with explicit refs and optional `.dsh-plugin` subpaths. */
|
||||
repositories?: string[]
|
||||
/** Persistent generation cache; defaults to `$DSH_HOME/cache/repository-plugins`. */
|
||||
cacheDir?: string
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/self-modification/repository-plugin/src/index.ts:44`](../packages/self-modification/repository-plugin/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-sandbox-local`
|
||||
|
||||
```ts config-catalog
|
||||
@@ -1438,7 +1457,7 @@ export interface Config {
|
||||
export type JournalMode = 'wal' | 'delete' | 'truncate' | 'persist'
|
||||
```
|
||||
|
||||
Source: [`packages/session/session-persistence-sqlite/src/index.ts:67`](../packages/session/session-persistence-sqlite/src/index.ts)
|
||||
Source: [`packages/session/session-persistence-sqlite/src/index.ts:70`](../packages/session/session-persistence-sqlite/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-session-projection-cache`
|
||||
|
||||
@@ -1559,7 +1578,7 @@ export enum TelemetryMode {
|
||||
|
||||
Depends on: `BatchLogRecordProcessorOptions` (`@opentelemetry/sdk-logs`) · `OTLPExporterNodeConfigBase` (`@opentelemetry/otlp-exporter-base`)
|
||||
|
||||
Source: [`packages/session/session-telemetry-otel/src/index.ts:79`](../packages/session/session-telemetry-otel/src/index.ts)
|
||||
Source: [`packages/session/session-telemetry-otel/src/index.ts:91`](../packages/session/session-telemetry-otel/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-session-title`
|
||||
|
||||
@@ -1986,7 +2005,7 @@ export interface Config {
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/core/system-prompt/src/index.ts:177`](../packages/core/system-prompt/src/index.ts)
|
||||
Source: [`packages/core/system-prompt/src/index.ts:186`](../packages/core/system-prompt/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-time-context`
|
||||
|
||||
@@ -2517,33 +2536,28 @@ Source: [`packages/web/web/src/index.ts:55`](../packages/web/web/src/index.ts)
|
||||
Requires: `httpServer`
|
||||
|
||||
```ts config-catalog
|
||||
/** Plugin config: the surface facts the launcher patches over this bundle's defaults. */
|
||||
/** Plugin config: composed deployment settings plus per-invocation command-line values. */
|
||||
export interface Config {
|
||||
/** Whether this process mounted the client-plugin HMR receiver (`dsh web --dev`). */
|
||||
mode: WebMode
|
||||
/** Print the URL line on activation; a headless layer over this bundle turns it off. */
|
||||
/** 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`/`DSH_WEB_MODE` bash variables). A one-shot
|
||||
* layer turns it off: its user is not interacting through the GUI, so the
|
||||
* non-interactive layer can turn it off when its user is not in the GUI, so the
|
||||
* orientation text would be false.
|
||||
*/
|
||||
surfaceContext: boolean
|
||||
/**
|
||||
* LAN IPv4 addresses sampled once by the launcher when the effective bind
|
||||
* is all-interfaces — the exact snapshot the /api trust fence was
|
||||
* configured with, so the printed LAN URL can never name an address the
|
||||
* fence rejects. Empty on a loopback bind.
|
||||
*/
|
||||
lanAddresses: string[]
|
||||
/** Explicit `--trusted-host` authorities from this invocation. */
|
||||
trustedHosts: string[]
|
||||
}
|
||||
|
||||
/** Web runtime mode: production, or development when the client-plugin HMR receiver is active. */
|
||||
export type WebMode = 'production' | 'development'
|
||||
```
|
||||
|
||||
Source: [`packages/bundle/web-app/src/index.ts:32`](../packages/bundle/web-app/src/index.ts)
|
||||
Source: [`packages/bundle/web-app/src/index.ts:43`](../packages/bundle/web-app/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-web-fetch-local`
|
||||
|
||||
@@ -2789,6 +2803,7 @@ Imported as libraries by other packages; a `cordis.yml` cannot load them.
|
||||
- `@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-client-web-react` ([`packages/client/web-react/src/index.ts`](../packages/client/web-react/src/index.ts))
|
||||
- `@deepseek-ai/dsh-cmdline` ([`packages/boot/cmdline/src/index.ts`](../packages/boot/cmdline/src/index.ts))
|
||||
- `@deepseek-ai/dsh-environment` ([`packages/util/environment/src/index.ts`](../packages/util/environment/src/index.ts))
|
||||
- `@deepseek-ai/dsh-helper` ([`packages/scaffold/helper/src/index.ts`](../packages/scaffold/helper/src/index.ts))
|
||||
- `@deepseek-ai/dsh-hook-protocol` ([`packages/hooks/hook-protocol/src/index.ts`](../packages/hooks/hook-protocol/src/index.ts))
|
||||
|
||||
@@ -527,10 +527,15 @@ export interface Config {
|
||||
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
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/fs/fs-local/src/index.ts:39`](../packages/fs/fs-local/src/index.ts)
|
||||
来源:[`packages/fs/fs-local/src/index.ts:40`](../packages/fs/fs-local/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-fs-sandbox`
|
||||
|
||||
@@ -538,10 +543,10 @@ export interface Config {
|
||||
|
||||
```ts config-catalog
|
||||
/**
|
||||
* Plugin config: the local backend's knobs, verbatim (only `cwd`, the resolve
|
||||
* base for relative paths). The sandbox default (mode + `workspace-write`
|
||||
* fallback root) is NOT here — `ctx.sandboxPolicy` resolves each calling
|
||||
* session for every enforcing capability.
|
||||
* 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.
|
||||
*/
|
||||
export type Config = LocalConfig
|
||||
```
|
||||
@@ -569,7 +574,7 @@ export interface Config {
|
||||
需要:`agentDefaultModel` · `agents` · `sessions`
|
||||
|
||||
```ts config-catalog
|
||||
/** Plugin config: the task, patched in by the launcher. */
|
||||
/** Plugin config: the task resolved from this app's injected provider service. */
|
||||
export interface Config {
|
||||
/** The prompt text for the single run. */
|
||||
task: string
|
||||
@@ -983,12 +988,24 @@ export interface ReplayModelConfig {
|
||||
description?: string
|
||||
/** Optional positive integer context capacity published by the replay adapter. */
|
||||
contextWindow?: number
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
```
|
||||
|
||||
依赖:[`RetryPolicyConfig`](../packages/llm/llm/src/index.ts)
|
||||
|
||||
来源:[`packages/support/llm-replay/src/index.ts:744`](../packages/support/llm-replay/src/index.ts)
|
||||
来源:[`packages/support/llm-replay/src/index.ts:769`](../packages/support/llm-replay/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-llm-retry`
|
||||
|
||||
@@ -1071,6 +1088,8 @@ export interface StdioConfig {
|
||||
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). */
|
||||
@@ -1091,10 +1110,24 @@ export interface StreamableHttpConfig {
|
||||
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
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/mcp/mcp-client/src/index.ts:100`](../packages/mcp/mcp-client/src/index.ts)
|
||||
来源:[`packages/mcp/mcp-client/src/index.ts:94`](../packages/mcp/mcp-client/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-permission`
|
||||
|
||||
@@ -1146,6 +1179,8 @@ export interface Config {
|
||||
* 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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1291,22 +1326,6 @@ export interface Config {
|
||||
|
||||
来源:[`packages/guard/repeat-tool-guard/src/index.ts:28`](../packages/guard/repeat-tool-guard/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-repository-plugin`
|
||||
|
||||
需要:`loader`
|
||||
|
||||
```ts config-catalog
|
||||
/** Repository Plugin runtime and source-list configuration. */
|
||||
export interface Config {
|
||||
/** GitHub repository sources with explicit refs and optional `.dsh-plugin` subpaths. */
|
||||
repositories?: string[]
|
||||
/** Persistent generation cache; defaults to `$DSH_HOME/cache/repository-plugins`. */
|
||||
cacheDir?: string
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/self-modification/repository-plugin/src/index.ts:44`](../packages/self-modification/repository-plugin/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-sandbox-local`
|
||||
|
||||
```ts config-catalog
|
||||
@@ -1440,7 +1459,7 @@ export interface Config {
|
||||
export type JournalMode = 'wal' | 'delete' | 'truncate' | 'persist'
|
||||
```
|
||||
|
||||
来源:[`packages/session/session-persistence-sqlite/src/index.ts:67`](../packages/session/session-persistence-sqlite/src/index.ts)
|
||||
来源:[`packages/session/session-persistence-sqlite/src/index.ts:70`](../packages/session/session-persistence-sqlite/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-session-projection-cache`
|
||||
|
||||
@@ -1988,7 +2007,7 @@ export interface Config {
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/core/system-prompt/src/index.ts:177`](../packages/core/system-prompt/src/index.ts)
|
||||
来源:[`packages/core/system-prompt/src/index.ts:186`](../packages/core/system-prompt/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-time-context`
|
||||
|
||||
@@ -2518,33 +2537,28 @@ export interface WebServiceConfig {
|
||||
需要:`httpServer`
|
||||
|
||||
```ts config-catalog
|
||||
/** Plugin config: the surface facts the launcher patches over this bundle's defaults. */
|
||||
/** Plugin config: composed deployment settings plus per-invocation command-line values. */
|
||||
export interface Config {
|
||||
/** Whether this process mounted the client-plugin HMR receiver (`dsh web --dev`). */
|
||||
mode: WebMode
|
||||
/** Print the URL line on activation; a headless layer over this bundle turns it off. */
|
||||
/** 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`/`DSH_WEB_MODE` bash variables). A one-shot
|
||||
* layer turns it off: its user is not interacting through the GUI, so the
|
||||
* non-interactive layer can turn it off when its user is not in the GUI, so the
|
||||
* orientation text would be false.
|
||||
*/
|
||||
surfaceContext: boolean
|
||||
/**
|
||||
* LAN IPv4 addresses sampled once by the launcher when the effective bind
|
||||
* is all-interfaces — the exact snapshot the /api trust fence was
|
||||
* configured with, so the printed LAN URL can never name an address the
|
||||
* fence rejects. Empty on a loopback bind.
|
||||
*/
|
||||
lanAddresses: string[]
|
||||
/** Explicit `--trusted-host` authorities from this invocation. */
|
||||
trustedHosts: string[]
|
||||
}
|
||||
|
||||
/** Web runtime mode: production, or development when the client-plugin HMR receiver is active. */
|
||||
export type WebMode = 'production' | 'development'
|
||||
```
|
||||
|
||||
来源:[`packages/bundle/web-app/src/index.ts:32`](../packages/bundle/web-app/src/index.ts)
|
||||
来源:[`packages/bundle/web-app/src/index.ts:43`](../packages/bundle/web-app/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-web-fetch-local`
|
||||
|
||||
@@ -2789,6 +2803,7 @@ export interface Config {
|
||||
- `@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-client-web-react`([`packages/client/web-react/src/index.ts`](../packages/client/web-react/src/index.ts))
|
||||
- `@deepseek-ai/dsh-cmdline`([`packages/boot/cmdline/src/index.ts`](../packages/boot/cmdline/src/index.ts))
|
||||
- `@deepseek-ai/dsh-environment`([`packages/util/environment/src/index.ts`](../packages/util/environment/src/index.ts))
|
||||
- `@deepseek-ai/dsh-helper`([`packages/scaffold/helper/src/index.ts`](../packages/scaffold/helper/src/index.ts))
|
||||
- `@deepseek-ai/dsh-hook-protocol`([`packages/hooks/hook-protocol/src/index.ts`](../packages/hooks/hook-protocol/src/index.ts))
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cookbook/adding-a-conversation-node.md
|
||||
adding-a-conversation-node.md: ea4ec73eb109af6b0e4c7cf50fc8692942c75dd4
|
||||
adding-a-conversation-node.zh.md: 4b9a8049e2f1d060ec4bc3334036559b989ea562
|
||||
adding-a-conversation-node.md: c1965dc8a3081eebb8c1026ac53d2f7b8964edb7
|
||||
adding-a-conversation-node.zh.md: 92445e1432369a4e42cc372b5d5869c3cdeada4a
|
||||
|
||||
@@ -120,6 +120,7 @@ function viewData(state: ReviewState): ReviewChatData {
|
||||
|
||||
const reviewDefinition: ConversationNodeDefinition<ReviewState> = {
|
||||
kind: 'review-job',
|
||||
target: 'chat',
|
||||
match: (event) => {
|
||||
if (event.type === 'review/start') {
|
||||
return { id: String(event.data.reviewId), role: 'start' }
|
||||
@@ -161,8 +162,8 @@ const reviewDefinition: ConversationNodeDefinition<ReviewState> = {
|
||||
value: viewData(context.state),
|
||||
}
|
||||
},
|
||||
buildViewNode: (context, target) => {
|
||||
if (target !== 'chat' || context.state === undefined) return null
|
||||
buildViewNode: (context) => {
|
||||
if (context.state === undefined) return null
|
||||
return {
|
||||
key: context.key,
|
||||
kind: 'review-job',
|
||||
@@ -196,7 +197,7 @@ export function apply(ctx: ClientContext): void {
|
||||
|
||||
`buildLocationData(context, scope)` optionally publishes Definition-owned data onto an engine-owned Turn or Step. Use declaration merging to give each key a precise value type. Another Node in the same Location can consume that value through its constrained slot hook, such as `useTurnData(key)`, without receiving the Session or scanning `snapshot.chat.nodes`.
|
||||
|
||||
`buildViewNode(context, target)` materializes the final target-specific Node. Preserve `context.key` as the React-facing identity, choose `anchorSeq` from durable ordering evidence, and return only renderer-ready data. Once a target Node has been published, keep returning the same key; use `visibility: 'hidden'` when it must temporarily leave the visible flow rather than withdrawing it with `null`.
|
||||
`target` and `buildViewNode(context)` declare one target-owned rendering contribution and must appear together. Preserve `context.key` as the React-facing identity, choose `anchorSeq` from durable ordering evidence, and return only renderer-ready data. Once a target Node has been published, keep returning the same key; use `visibility: 'hidden'` when it must temporarily leave the visible flow rather than withdrawing it with `null`.
|
||||
|
||||
## 3. Query an earlier business Context only at start
|
||||
|
||||
|
||||
@@ -120,6 +120,7 @@ function viewData(state: ReviewState): ReviewChatData {
|
||||
|
||||
const reviewDefinition: ConversationNodeDefinition<ReviewState> = {
|
||||
kind: 'review-job',
|
||||
target: 'chat',
|
||||
match: (event) => {
|
||||
if (event.type === 'review/start') {
|
||||
return { id: String(event.data.reviewId), role: 'start' }
|
||||
@@ -161,8 +162,8 @@ const reviewDefinition: ConversationNodeDefinition<ReviewState> = {
|
||||
value: viewData(context.state),
|
||||
}
|
||||
},
|
||||
buildViewNode: (context, target) => {
|
||||
if (target !== 'chat' || context.state === undefined) return null
|
||||
buildViewNode: (context) => {
|
||||
if (context.state === undefined) return null
|
||||
return {
|
||||
key: context.key,
|
||||
kind: 'review-job',
|
||||
@@ -196,7 +197,7 @@ export function apply(ctx: ClientContext): void {
|
||||
|
||||
`buildLocationData(context, scope)` 可以把 Definition 拥有的数据发布到引擎拥有的 Turn 或 Step 上。通过 declaration merging 为每个 key 指定精确 value 类型。同一 Location 内的另一个 Node 可以使用受限 slot hook(例如 `useTurnData(key)`)读取该值,无须取得 Session,也无须扫描 `snapshot.chat.nodes`。
|
||||
|
||||
`buildViewNode(context, target)` 物化最终的目标专用 Node。把 `context.key` 保留为 React 侧身份,根据持久排序证据选择 `anchorSeq`,并且只返回 renderer 可以直接使用的数据。某个 target Node 一旦发布,就要继续返回同一个 key;需要暂时离开可见流时使用 `visibility: 'hidden'`,不要改为返回 `null` 撤回它。
|
||||
`target` 与 `buildViewNode(context)` 必须同时声明一项由 target 拥有的渲染贡献。把 `context.key` 保留为 React 侧身份,根据持久排序证据选择 `anchorSeq`,并且只返回 renderer 可以直接使用的数据。某个 target Node 一旦发布,就要继续返回同一个 key;需要暂时离开可见流时使用 `visibility: 'hidden'`,不要改为返回 `null` 撤回它。
|
||||
|
||||
## 3. 只在 start 时查询更早的业务 Context
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cookbook/adding-a-package.md
|
||||
adding-a-package.md: 9e82e6d00177768a6368d1cd9740afa585543171
|
||||
adding-a-package.zh.md: 072df33138a1ead20c497cebd8e4aa960c2d1fc8
|
||||
adding-a-package.md: e108b9e88e0f0e470f96173306af79c69ff695fb
|
||||
adding-a-package.zh.md: 97b4df150fda7010fba048d7acb5e23a87519911
|
||||
|
||||
@@ -22,7 +22,7 @@ packages/<group>/<pkg>/
|
||||
|
||||
Choose an existing group when one matches the package's role (`core`, `llm`, `bash`, `compact`, `subagent`, `todo`, `session-persistence`, `ui`, `util`, or `support`). A new group is allowed, but it is a pure container: no `package.json`, no source files, and packages still sit exactly one level below it.
|
||||
|
||||
package.json invariants (enforced by `pnpm run constraints` / `scripts/check-workspace-constraints.ts`): `private: true`, a `version` matching the root `package.json`, `type: module`, `main: "lib/index.js"`, `types: "lib/types/index.d.ts"`, `exports["."].types: "./lib/types/index.d.ts"`, `exports["."].default: "./lib/index.js"`, `cordis` in BOTH peerDependencies and devDependencies (same range). Mirror every dsh peer dependency in devDependencies. `schemastery` goes in `dependencies` (it is a runtime validator), matching agent-loop. The `files` list contains exactly `lib/index.js`, `lib/invariant.js`, `lib/types/**/*.d.ts`, and package-specific runtime artifacts recognized by the gate; a package whose runtime export points into the emitted tree also includes `lib/types/**/*.js`. Do not publish `src`, declaration maps, JS maps, or stale root declaration files. CLI app packages with a package `bin` include `lib/bin.js` immediately after `lib/index.js` in `files`.
|
||||
package.json invariants (enforced by `pnpm run constraints` / `scripts/check-workspace-constraints.ts`): `private: true`, a `version` matching the root `package.json`, `type: module`, `main: "lib/index.js"`, `types: "lib/types/index.d.ts"`, `exports["."].types: "./lib/types/index.d.ts"`, `exports["."].default: "./lib/index.js"`, `@deepseek-ai/cordis` in BOTH peerDependencies and devDependencies (same range). Mirror every dsh peer dependency in devDependencies. `@deepseek-ai/schemastery` goes in `dependencies` (it is a runtime validator), matching agent-loop. The `files` list contains exactly `lib/index.js`, `lib/invariant.js`, `lib/types/**/*.d.ts`, and package-specific runtime artifacts recognized by the gate; a package whose runtime export points into the emitted tree also includes `lib/types/**/*.js`. Do not publish `src`, declaration maps, JS maps, or stale root declaration files. CLI app packages with a package `bin` include `lib/bin.js` immediately after `lib/index.js` in `files`.
|
||||
|
||||
In-package relative imports use explicit `.ts` specifiers in source (for example, `export * from './types.ts'`). The compiler rewrites those to `.js` in emitted JS and leaves explicit `.ts` specifiers in declarations, which standard NodeNext/Node16 TypeScript consumers resolve to the sibling `.d.ts` files.
|
||||
|
||||
@@ -34,7 +34,7 @@ In-package relative imports use explicit `.ts` specifiers in source (for example
|
||||
| `tsconfig.host.json` (Host package) or `tsconfig.client.json` (Client package) | add `{ "path": "./packages/<group>/<pkg>" }` to `references` — an ordinary package belongs to exactly one aggregate, never both. `api/remotes` uses a repository-specific split because the Host generates a contract that the Client consumes in a later phase; new packages must not copy it ([layout](../development.md#typescript-project-layout)) |
|
||||
| `knip.json` | only if the package has entrypoints that repository discovery does not already cover |
|
||||
|
||||
A `packages/client/*` package additionally extends `tsconfig.base.client.json` instead of `tsconfig.base.json`, and a client plugin package declares `dshClient` in package.json, exports `./client`, and calls the shared tsdown preset (`packages/client/tsdown.client.ts`) — see [packages/client/AGENTS.md](../../packages/client/AGENTS.md) for the client-side contract.
|
||||
A `packages/client/*` package additionally extends `tsconfig.base.client.json` instead of `tsconfig.base.json`, and a client plugin package declares `dsh.client` in package.json, exports `./client`, and calls the shared tsdown preset (`packages/client/tsdown.client.ts`) — see [packages/client/AGENTS.md](../../packages/client/AGENTS.md) for the client-side contract.
|
||||
|
||||
Covered automatically by globs or package-manifest discovery — no edits needed: root `package.json` workspaces, `scripts/publint-all.ts`, `tsdown.config.ts`, `.oxlintrc.json`, `scripts/check-workspace-constraints.ts`.
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ packages/<group>/<pkg>/
|
||||
|
||||
当已有分组与包的角色匹配时,选择该分组(`core`、`llm`、`bash`、`compact`、`subagent`、`todo`、`session-persistence`、`ui`、`util` 或 `support`)。允许新建分组,但分组只是纯容器:没有 `package.json`,没有源文件,包仍然恰好位于其下一层。
|
||||
|
||||
package.json 不变式(由 `pnpm run constraints` / `scripts/check-workspace-constraints.ts` 强制执行):`private: true`,`version` 与根 `package.json` 一致,`type: module`,`main: "lib/index.js"`,`types: "lib/types/index.d.ts"`,`exports["."].types: "./lib/types/index.d.ts"`,`exports["."].default: "./lib/index.js"`,`cordis` 同时出现在 peerDependencies 和 devDependencies 中(相同范围)。每个 dsh 对等依赖(peer dependency)都要在 devDependencies 中镜像。`schemastery` 放在 `dependencies` 中(它是运行时校验器),与 agent-loop 保持一致。`files` 列表精确包含 `lib/index.js`、`lib/invariant.js`、`lib/types/**/*.d.ts` 以及门禁认可的包专用运行时产物;如果包的运行时 export 指向输出树,还要包含 `lib/types/**/*.js`。不要发布 `src`、声明映射、JS map 或陈旧的根声明文件。带有 `bin` 的 CLI 应用包在 `files` 中将 `lib/bin.js` 紧跟在 `lib/index.js` 之后。
|
||||
package.json 不变式(由 `pnpm run constraints` / `scripts/check-workspace-constraints.ts` 强制执行):`private: true`,`version` 与根 `package.json` 一致,`type: module`,`main: "lib/index.js"`,`types: "lib/types/index.d.ts"`,`exports["."].types: "./lib/types/index.d.ts"`,`exports["."].default: "./lib/index.js"`,`@deepseek-ai/cordis` 同时出现在 peerDependencies 和 devDependencies 中(相同范围)。每个 dsh 对等依赖(peer dependency)都要在 devDependencies 中镜像。`@deepseek-ai/schemastery` 放在 `dependencies` 中(它是运行时校验器),与 agent-loop 保持一致。`files` 列表精确包含 `lib/index.js`、`lib/invariant.js`、`lib/types/**/*.d.ts` 以及门禁认可的包专用运行时产物;如果包的运行时 export 指向输出树,还要包含 `lib/types/**/*.js`。不要发布 `src`、声明映射、JS map 或陈旧的根声明文件。带有 `bin` 的 CLI 应用包在 `files` 中将 `lib/bin.js` 紧跟在 `lib/index.js` 之后。
|
||||
|
||||
包内的相对导入在源码中使用显式 `.ts` 后缀(例如 `export * from './types.ts'`)。编译器在输出的 JS 中将其重写为 `.js`,在声明文件中保留显式 `.ts` 后缀;标准的 NodeNext/Node16 TypeScript 消费方会将其解析到同目录的 `.d.ts` 文件。
|
||||
|
||||
@@ -34,7 +34,7 @@ package.json 不变式(由 `pnpm run constraints` / `scripts/check-workspace-c
|
||||
| `tsconfig.host.json`(Host 包)或 `tsconfig.client.json`(Client 包) | 在 `references` 中添加 `{ "path": "./packages/<group>/<pkg>" }`——普通包恰好属于一个 aggregate,绝不两个都加。`api/remotes` 因 Host 生成约定与 Client 消费约定之间存在顺序依赖而使用仓库专属拆分,新增包不得仿照([布局](../development.md#typescript-project-layout)) |
|
||||
| `knip.json` | 仅当包有仓库发现机制尚未覆盖的入口时需要 |
|
||||
|
||||
`packages/client/*` 包改为 extends `tsconfig.base.client.json`(而非 `tsconfig.base.json`);client 插件包还需在 package.json 声明 `dshClient`、导出 `./client`、调用共享 tsdown preset(`packages/client/tsdown.client.ts`)——client 侧见 [packages/client/AGENTS.md](../../packages/client/AGENTS.md)。
|
||||
`packages/client/*` 包改为 extends `tsconfig.base.client.json`(而非 `tsconfig.base.json`);client 插件包还需在 package.json 声明 `dsh.client`、导出 `./client`、调用共享 tsdown preset(`packages/client/tsdown.client.ts`)——client 侧见 [packages/client/AGENTS.md](../../packages/client/AGENTS.md)。
|
||||
|
||||
以下内容由 glob 或包 manifest 发现机制自动覆盖,无需手动编辑:根 `package.json` workspaces、`scripts/publint-all.ts`、`tsdown.config.ts`、`.oxlintrc.json`、`scripts/check-workspace-constraints.ts`。
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cookbook/adding-a-tool.md
|
||||
adding-a-tool.md: b030d3c3a6b7dd66b6594779345a96af3a895bd8
|
||||
adding-a-tool.zh.md: 4272a7a4571782bc213ca29de1a57d51fbd24075
|
||||
adding-a-tool.md: fa39c4b97f3c0eb739ea34d1b43ef46d11285bbf
|
||||
adding-a-tool.zh.md: ab32e90fac5539ee403a36b2dd52e60db3ad603c
|
||||
|
||||
@@ -8,7 +8,7 @@ Reference for the contracts a model-facing tool must satisfy. For an ordered fir
|
||||
|
||||
```ts
|
||||
import { readFile } from 'node:fs/promises'
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { defineTool } from '@deepseek-ai/dsh-tools'
|
||||
|
||||
export const name = 'my-tool'
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
```ts
|
||||
import { readFile } from 'node:fs/promises'
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { defineTool } from '@deepseek-ai/dsh-tools'
|
||||
|
||||
export const name = 'my-tool'
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cookbook/adding-a-vendored-package.md
|
||||
adding-a-vendored-package.md: 724d89c1c7cd728f7123a6975b5500cd40815851
|
||||
adding-a-vendored-package.zh.md: d16ec1056431a4ac1c02d50a5ef0f0a64b67ca6d
|
||||
adding-a-vendored-package.md: 239ac27565204332559038014fabae83fc2d1057
|
||||
adding-a-vendored-package.zh.md: 2bf5c7eeaffec594dbc4d13e0aa33b12a9eccf4f
|
||||
|
||||
@@ -8,7 +8,7 @@ When the harness needs another upstream Cordis package (e.g. `@cordisjs/plugin-h
|
||||
|
||||
```
|
||||
vendor/<dir>/
|
||||
package.json # from upstream; set "private": true, keep name/exports/type
|
||||
package.json # from upstream; set "private": true, rescope the name, keep exports/type
|
||||
tsconfig.json # extends ../../tsconfig.base.json (see configuration below)
|
||||
src/ # the upstream src/ verbatim
|
||||
README.md LICENSE # if upstream ships them
|
||||
@@ -29,7 +29,7 @@ vendor/<dir>/
|
||||
}
|
||||
```
|
||||
|
||||
`package.json` invariants: `"private": true` (vendored packages are never published), keep upstream's `name`/`version`/`exports`/`type`, point declaration metadata at `lib/types`, publish `.d.ts` and `.d.ts.map` declaration outputs, and list its cordis deps in `peerDependencies` (matching the upstream manifest). Transitive upstream deps must themselves be vendored or already present — vendoring one package often means vendoring its dependency tree (e.g. `@cordisjs/plugin-http` pulls `@cordisjs/fetch-file`).
|
||||
`package.json` invariants: `"private": true` (vendored packages are never published), rescope the `name` ([mapping](../rescope.md)) while keeping upstream's `version`/`exports`/`type`, point declaration metadata at `lib/types`, publish `.d.ts` and `.d.ts.map` declaration outputs, and list its cordis deps in `peerDependencies` (matching the upstream manifest). Transitive upstream deps must themselves be vendored or already present — vendoring one package often means vendoring its dependency tree (e.g. `@cordisjs/plugin-http` pulls `@cordisjs/fetch-file`).
|
||||
|
||||
Local relative imports/exports in vendored TypeScript source use explicit `.ts` specifiers after copying. This is a repo-local build difference from upstream: `rewriteRelativeImportExtensions` emits `.js` runtime imports while declarations keep explicit `.ts` specifiers that NodeNext/Node16 TypeScript consumers can resolve.
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
```
|
||||
vendor/<dir>/
|
||||
package.json # from upstream; set "private": true, keep name/exports/type
|
||||
package.json # from upstream; set "private": true, rescope the name, keep exports/type
|
||||
tsconfig.json # extends ../../tsconfig.base.json (see configuration below)
|
||||
src/ # the upstream src/ verbatim
|
||||
README.md LICENSE # if upstream ships them
|
||||
@@ -29,7 +29,7 @@ vendor/<dir>/
|
||||
}
|
||||
```
|
||||
|
||||
`package.json` 的不变式:`"private": true`(vendored 包永不发布);保留上游的 `name`/`version`/`exports`/`type`;声明元数据指向 `lib/types`;发布 `.d.ts` 与 `.d.ts.map` 声明输出;在 `peerDependencies` 中列出其 Cordis 依赖(与上游 manifest(元数据清单)一致)。传递性上游依赖本身也必须被 vendor 或已存在于仓库中——vendor 一个包往往意味着 vendor 其整条依赖树(如 `@cordisjs/plugin-http` 会拉入 `@cordisjs/fetch-file`)。
|
||||
`package.json` 的不变式:`"private": true`(vendored 包永不发布);改写 `name` 的 scope([映射](../rescope.md)),保留上游的 `version`/`exports`/`type`;声明元数据指向 `lib/types`;发布 `.d.ts` 与 `.d.ts.map` 声明输出;在 `peerDependencies` 中列出其 Cordis 依赖(与上游 manifest(元数据清单)一致)。传递性上游依赖本身也必须被 vendor 或已存在于仓库中——vendor 一个包往往意味着 vendor 其整条依赖树(如 `@cordisjs/plugin-http` 会拉入 `@cordisjs/fetch-file`)。
|
||||
|
||||
vendored TypeScript 源码中的本地相对导入/导出在复制后使用显式 `.ts` 后缀。这是仓库本地构建与上游的差异:`rewriteRelativeImportExtensions` 输出 `.js` 运行时导入,而声明文件保留显式 `.ts` 后缀,使 NodeNext/Node16 的 TypeScript 消费方能够解析。
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cookbook/extension-cookbook.md
|
||||
extension-cookbook.md: 95ba269a5d62e14cfde487d5a3aaca5db493657e
|
||||
extension-cookbook.zh.md: e3fbe09f1ec09568e3b259aee361d33ba3e62140
|
||||
extension-cookbook.md: f292075dfdad5016d81521318b38594e3d7ee8b4
|
||||
extension-cookbook.zh.md: 0623c49d9d7075b3823c1fd340b36a5fba21f31e
|
||||
|
||||
@@ -13,7 +13,7 @@ A tool registers on `ctx.tools`. The annotated `defineTool` example (typed `exec
|
||||
This permission gate is one example of a hook plugin. It returns a typed decision from the `tools/pre-execute` gate to allow or deny a call; sandbox, permission, and plan-mode plugins can use this extension point. Hook plugins can intercept other extension points and are not inherently permission gates. A "native hook" is an ordinary Cordis plugin on an interception point; it needs no external protocol.
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type { PreToolDecision, ToolExecution } from '@deepseek-ai/dsh-tools'
|
||||
|
||||
declare function isAllowed(exec: ToolExecution): Promise<boolean>
|
||||
@@ -37,7 +37,7 @@ This waterfall is the reorderable policy layer. Use `ctx.tools.guard()` when an
|
||||
A UI plugin renders from the `session/event` feed (the assistant token stream as `assistant/chunk`, plus turn/step boundaries and tool activity), and drives input back in via `agent.followup()` / `agent.steer()`. A browser plugin contributing a business row to the built-in Web Client instead registers a `ConversationNodeDefinition` and keyed Chat renderer; follow the [Conversation Node guide](adding-a-conversation-node.md).
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
||||
import { SessionId } from '@deepseek-ai/dsh-session'
|
||||
|
||||
@@ -67,7 +67,7 @@ A *protocol driver* adapts a wire peer to `ctx.agents`; it may serve a UI or an
|
||||
[`packages/acp/acp`](../../packages/acp/acp) is the automation-only worked example: it exposes fresh text sessions over Agent Client Protocol JSON-RPC stdio, emits committed assistant text, and registers a one-shot machine permission answerer for agents it owns. Its [README](../../packages/acp/acp/README.md) defines the exact methods, event order, and lifecycle contract.
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'my-protocol-bridge'
|
||||
export const inject = ['agents', 'sessions', 'sessionPersistence']
|
||||
|
||||
@@ -13,7 +13,7 @@ harness 扩展的参考模式。代码片段省略了 import 和辅助实现,
|
||||
这个权限门禁是钩子插件的一个示例。它从 `tools/pre-execute` 门禁返回一个类型化的决策,用于允许或拒绝一次调用;沙箱、权限和 plan-mode 插件都可以使用该扩展点。钩子插件也可以拦截其他扩展点,本身并不等同于权限门禁。「原生钩子」是在拦截点上运行的普通 Cordis 插件,不需要外部协议。
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type { PreToolDecision, ToolExecution } from '@deepseek-ai/dsh-tools'
|
||||
|
||||
declare function isAllowed(exec: ToolExecution): Promise<boolean>
|
||||
@@ -37,7 +37,7 @@ export function apply(ctx: Context) {
|
||||
UI 插件从 `session/event` 事件流渲染(助手 token 流以 `assistant/chunk` 形式到达,加上轮次/步骤边界与工具活动),并通过 `agent.followup()` / `agent.steer()` 将输入驱动回去。如果浏览器插件要向内建 Web Client 贡献业务行,则应注册 `ConversationNodeDefinition` 与 keyed Chat renderer;具体步骤见 [Conversation Node 指南](adding-a-conversation-node.md)。
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
||||
import { SessionId } from '@deepseek-ai/dsh-session'
|
||||
|
||||
@@ -67,7 +67,7 @@ export function apply(ctx: Context) {
|
||||
[`packages/acp/acp`](../../packages/acp/acp) 是仅面向自动化的完整示例:它通过 ACP(Agent Client Protocol)JSON-RPC stdio 提供全新文本会话,发出已提交的助手文本,并为其拥有的 agent 注册一次性机器权限应答器。其 [README](../../packages/acp/acp/README.md) 定义确切的方法、事件顺序和生命周期约定。
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'my-protocol-bridge'
|
||||
export const inject = ['agents', 'sessions', 'sessionPersistence']
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-api/fiber.md
|
||||
fiber.md: 36d2861ac6a53e8186a92d86c65ba228d4b59ee5
|
||||
fiber.zh.md: fafa559ca911677c43893862190009d82c39c56b
|
||||
fiber.md: 182b77390b29b8a90504437d0ccc2dfeba23921a
|
||||
fiber.zh.md: 9ed3e52618586dc3815b9d913439d11a227fb64b
|
||||
|
||||
@@ -34,7 +34,7 @@ Register a cleanup-aware effect on this fiber.
|
||||
|
||||
**Returns** a disposer that tears the effect down and settles once done.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L420)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L415)
|
||||
|
||||
### ctx.fiber
|
||||
|
||||
@@ -97,7 +97,7 @@ public state
|
||||
|
||||
Current lifecycle state; transitions emit `internal/status`.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L192)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L194)
|
||||
|
||||
### fiber.dispose
|
||||
|
||||
@@ -108,7 +108,7 @@ public readonly dispose: () => Promise<void>
|
||||
|
||||
Dispose this fiber: unload the plugin, then settle once cleanup finished.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L194)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L196)
|
||||
|
||||
### fiber.store
|
||||
|
||||
@@ -119,7 +119,7 @@ public store: Dict<Impl> | undefined
|
||||
|
||||
Snapshot of required service implementations while loaded; `undefined` otherwise.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L196)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L198)
|
||||
|
||||
### fiber.inertia
|
||||
|
||||
@@ -130,7 +130,7 @@ public inertia: Promise<void> | undefined
|
||||
|
||||
The in-flight load/unload transition, if one is currently running.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L198)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L200)
|
||||
|
||||
### fiber.name
|
||||
|
||||
@@ -141,7 +141,7 @@ get name()
|
||||
|
||||
The plugin's display name, inherited from the nearest named ancestor, else `'root'`.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L341)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L336)
|
||||
|
||||
### fiber.assertActive()
|
||||
|
||||
@@ -159,7 +159,7 @@ Throw if the fiber has already been disposed.
|
||||
|
||||
**Returns** nothing when the fiber is still active.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L356)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L351)
|
||||
|
||||
### fiber.effect(execute, label?)
|
||||
|
||||
@@ -190,7 +190,7 @@ Register a cleanup-aware effect on this fiber.
|
||||
|
||||
**Returns** a disposer that tears the effect down and settles once done.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L420)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L415)
|
||||
|
||||
### fiber.getEffects()
|
||||
|
||||
@@ -207,7 +207,7 @@ Return metadata for currently registered effects.
|
||||
|
||||
**Returns** one `EffectMeta` tree per labeled live effect.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L573)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L568)
|
||||
|
||||
### fiber.await()
|
||||
|
||||
@@ -225,7 +225,7 @@ Wait for current lifecycle work and rethrow startup errors.
|
||||
|
||||
**Returns** this fiber, once it has settled into a stable state.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L702)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L704)
|
||||
|
||||
### fiber.restart()
|
||||
|
||||
@@ -243,7 +243,7 @@ Dispose and immediately reload this plugin with its current config.
|
||||
|
||||
**Returns** a promise resolving once the reload settled.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L716)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L718)
|
||||
|
||||
### fiber.update(config, noSave?)
|
||||
|
||||
@@ -271,7 +271,7 @@ Runs the `internal/update` waterfall first, so update hooks (and HMR) can veto o
|
||||
|
||||
**Returns** the update waterfall result; the default restart returns a promise.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L734)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L736)
|
||||
|
||||
## Effect
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ effect(execute: () => Effect, label?: string): AsyncDisposable<Promise<void>>
|
||||
|
||||
**返回**一个用于撤销该作用的清理函数,并在清理完成后结算。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L420)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L415)
|
||||
|
||||
### ctx.fiber
|
||||
|
||||
@@ -99,7 +99,7 @@ public state
|
||||
|
||||
当前生命周期状态;状态转换会发出 `internal/status`。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L192)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L194)
|
||||
|
||||
### fiber.dispose
|
||||
|
||||
@@ -110,7 +110,7 @@ public readonly dispose: () => Promise<void>
|
||||
|
||||
dispose 此 fiber:卸载插件,并在清理完成后结算。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L194)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L196)
|
||||
|
||||
### fiber.store
|
||||
|
||||
@@ -121,7 +121,7 @@ public store: Dict<Impl> | undefined
|
||||
|
||||
加载期间所需服务实现的快照;其他情况下为 `undefined`。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L196)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L198)
|
||||
|
||||
### fiber.inertia
|
||||
|
||||
@@ -132,7 +132,7 @@ public inertia: Promise<void> | undefined
|
||||
|
||||
当前正在进行的加载或卸载转换;如果没有此类转换,则为 undefined。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L198)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L200)
|
||||
|
||||
### fiber.name
|
||||
|
||||
@@ -143,7 +143,7 @@ get name()
|
||||
|
||||
插件的显示名称,继承自最近的具名祖先;如果不存在,则为 `'root'`。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L341)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L336)
|
||||
|
||||
### fiber.assertActive()
|
||||
|
||||
@@ -161,7 +161,7 @@ assertActive()
|
||||
|
||||
**返回**:fiber 仍处于活动状态时不返回任何内容。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L356)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L351)
|
||||
|
||||
### fiber.effect(execute, label?)
|
||||
|
||||
@@ -192,7 +192,7 @@ effect(execute: () => Effect, label?: string): AsyncDisposable<Promise<void>>
|
||||
|
||||
**返回**一个用于撤销该作用的清理函数,并在清理完成后结算。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L420)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L415)
|
||||
|
||||
### fiber.getEffects()
|
||||
|
||||
@@ -209,7 +209,7 @@ getEffects()
|
||||
|
||||
**返回**:每个带标签的活动作用对应一棵 `EffectMeta` 树。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L573)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L568)
|
||||
|
||||
### fiber.await()
|
||||
|
||||
@@ -227,7 +227,7 @@ async await()
|
||||
|
||||
**返回**:进入稳定状态后的此 fiber。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L702)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L704)
|
||||
|
||||
### fiber.restart()
|
||||
|
||||
@@ -245,7 +245,7 @@ dispose 此插件,并立即使用其当前配置重新加载。
|
||||
|
||||
**返回**一个在重新加载完成后兑现的 promise。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L716)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L718)
|
||||
|
||||
### fiber.update(config, noSave?)
|
||||
|
||||
@@ -273,7 +273,7 @@ update(config: any, noSave = false)
|
||||
|
||||
**返回**更新 waterfall 的结果;默认的重新启动操作返回一个 promise。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L734)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L736)
|
||||
|
||||
## Effect
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-primer.md
|
||||
cordis-primer.md: c95909a4a1deab9407efedbb990ef13be6e43a16
|
||||
cordis-primer.zh.md: a18b8b37af19a610b71babbe5e67f96bb09e81b1
|
||||
cordis-primer.md: d1e7c5fd8eaaa89fe448d238359389d945cd6346
|
||||
cordis-primer.zh.md: d6ce0f2024f65b006c9505daffaa06a08bb56875
|
||||
|
||||
@@ -35,7 +35,7 @@ For single-decision events, short-circuiting is the design. A policy listener ca
|
||||
|
||||
## Loader Configuration
|
||||
|
||||
`@cordisjs/plugin-include` parses `!!js` into expression nodes, but the Loader interpolates only an entry's `config` before mounting the plugin. Entry metadata (`id`, `name`, `group`, `disabled`, `inject`, `intercept`, and `isolate`) remains literal; `disabled: !!js ...` is therefore a truthy object that always disables the entry. Use explicit config overlays when environment selection changes which plugins are mounted.
|
||||
`@deepseek-ai/cordis-plugin-include` parses `!!js` into expression nodes. Loader interpolates only an entry's `config`, after declared injections activate, against that plugin context (`ctx.serviceName`); Include preserves nested row expressions until target activation. Entry metadata (`id`, `name`, `group`, `disabled`, `inject`, `intercept`, `isolate`) stays literal, so `disabled: !!js ...` always disables the entry. Use overlays when the environment selects plugins.
|
||||
|
||||
## Practical Rules
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ Cordis 是 DeepSeek Harness SDK 底层以 vendor 方式引入的插件框架。
|
||||
|
||||
## Loader 配置
|
||||
|
||||
`@cordisjs/plugin-include` 将 `!!js` 解析为表达式节点,但 Loader 仅在挂载插件前对条目的 `config` 做插值。条目元数据(`id`、`name`、`group`、`disabled`、`inject`、`intercept` 和 `isolate`)保持字面值;因此 `disabled: !!js ...` 是一个 truthy 对象,会始终禁用该条目。需要根据环境选择挂载哪些插件时,请使用显式的配置覆盖层。
|
||||
`@deepseek-ai/cordis-plugin-include` 将 `!!js` 解析为表达式节点。Loader 只在声明的注入激活后,基于该插件上下文(`ctx.serviceName`)插值条目的 `config`;Include 会保留嵌套行表达式,直到目标行激活。条目元数据(`id`、`name`、`group`、`disabled`、`inject`、`intercept`、`isolate`)保持字面值,因此 `disabled: !!js ...` 始终禁用该条目。由环境选择插件时,请使用 overlay。
|
||||
|
||||
## 实践规则
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/01-first-plugin.md
|
||||
01-first-plugin.md: 260026329443f9a5b8860d11a6527dbd687eb44c
|
||||
01-first-plugin.zh.md: 69dedb898c7ea29f99233f07126cd413fa0ddbe2
|
||||
01-first-plugin.md: 448034b54107d5620673052ad388feecc22fe1e1
|
||||
01-first-plugin.zh.md: a1838be61f8099831d59afa266fe40ce6bd165bf
|
||||
|
||||
@@ -9,7 +9,7 @@ In the loader configuration used here, a Cordis plugin module named-exports an `
|
||||
In your `tmp/cordis-tutorial` directory (see [setup](index.md#setup)), create `hello.ts`:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'hello'
|
||||
|
||||
@@ -55,7 +55,7 @@ There is no framework bootstrap code in your file: a plugin describes what it co
|
||||
A function is the most common form, but Cordis accepts three:
|
||||
|
||||
```ts
|
||||
import { Service, type Context } from 'cordis'
|
||||
import { Service, type Context } from '@deepseek-ai/cordis'
|
||||
|
||||
// 1. Function plugin (what you just wrote).
|
||||
export function apply(ctx: Context) {}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
在 `tmp/cordis-tutorial` 目录中(参见[环境设置](index.md#setup))创建 `hello.ts`:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'hello'
|
||||
|
||||
@@ -55,7 +55,7 @@ hello from my first plugin
|
||||
函数是最常见的形式,但 Cordis 接受三种形式:
|
||||
|
||||
```ts
|
||||
import { Service, type Context } from 'cordis'
|
||||
import { Service, type Context } from '@deepseek-ai/cordis'
|
||||
|
||||
// 1. Function plugin (what you just wrote).
|
||||
export function apply(ctx: Context) {}
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/02-lifecycle-and-effects.md
|
||||
02-lifecycle-and-effects.md: 7b195b63a1e8730f27b9dd9af8af6a68a588cee9
|
||||
02-lifecycle-and-effects.zh.md: 4a3f83dedd5c95c7fcb5c1aebbbb8cb2e849b9cf
|
||||
02-lifecycle-and-effects.md: 3e88c6f1e1fb1bc825fb74434520993c855010c3
|
||||
02-lifecycle-and-effects.zh.md: 3cceecfb8334f2ed2ec9942fa876a0e51e1b315f
|
||||
|
||||
@@ -11,7 +11,7 @@ For a resource Cordis does not already manage — a timer, a connection, a watch
|
||||
Create `lifecycle.ts` in `tmp/cordis-tutorial`:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'lifecycle-demo'
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ Cordis 插件可能因修改配置、热重载、显式资源释放或所需服
|
||||
创建 `lifecycle.ts`,将它放在 `tmp/cordis-tutorial` 中:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'lifecycle-demo'
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/03-services.md
|
||||
03-services.md: 82b08b7b8a2ec8a6b340dd1fdc7fa3de98cedff9
|
||||
03-services.zh.md: ba4152454eb79a21b183b867c0ba2ef32cd43923
|
||||
03-services.md: 3f2273ba4061912640e409d7b4deb4cd1b45684f
|
||||
03-services.zh.md: 657271aba6c0b2e824c79fa822e29c8a6dcf4275
|
||||
|
||||
@@ -9,9 +9,9 @@ A **service** is a named capability one plugin provides and other plugins consum
|
||||
Create `greeter.ts` in `tmp/cordis-tutorial`:
|
||||
|
||||
```ts
|
||||
import { Service, type Context } from 'cordis'
|
||||
import { Service, type Context } from '@deepseek-ai/cordis'
|
||||
|
||||
declare module 'cordis' {
|
||||
declare module '@deepseek-ai/cordis' {
|
||||
interface Context {
|
||||
greeter: GreeterService
|
||||
}
|
||||
@@ -37,7 +37,7 @@ export function apply(ctx: Context) {
|
||||
Two pieces work together:
|
||||
|
||||
- **Runtime**: `super(ctx, 'greeter')` registers the instance under the name `greeter`. From then on, any plugin can reach it as `ctx.greeter`. The registration is an effect — unloading the provider removes the service.
|
||||
- **Compile time**: the `declare module 'cordis'` block is TypeScript declaration merging. It adds `greeter` to the `Context` interface so `ctx.greeter` typechecks everywhere. It generates no code; without it the service still works at runtime, but consumers lose type safety.
|
||||
- **Compile time**: the `declare module '@deepseek-ai/cordis'` block is TypeScript declaration merging. It adds `greeter` to the `Context` interface so `ctx.greeter` typechecks everywhere. It generates no code; without it the service still works at runtime, but consumers lose type safety.
|
||||
|
||||
A `Service` subclass is itself a plugin (the class form from chapter 1), so `ctx.plugin(GreeterService)` mounts it like any other.
|
||||
|
||||
@@ -46,7 +46,7 @@ A `Service` subclass is itself a plugin (the class form from chapter 1), so `ctx
|
||||
Create `consumer.ts`:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'consumer'
|
||||
export const inject = ['greeter']
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
创建 `greeter.ts`,将它放在 `tmp/cordis-tutorial` 中:
|
||||
|
||||
```ts
|
||||
import { Service, type Context } from 'cordis'
|
||||
import { Service, type Context } from '@deepseek-ai/cordis'
|
||||
|
||||
declare module 'cordis' {
|
||||
declare module '@deepseek-ai/cordis' {
|
||||
interface Context {
|
||||
greeter: GreeterService
|
||||
}
|
||||
@@ -37,7 +37,7 @@ export function apply(ctx: Context) {
|
||||
两部分协同工作:
|
||||
|
||||
- **运行时**:`super(ctx, 'greeter')` 以名称 `greeter` 注册该实例。此后,任何插件都可以通过 `ctx.greeter` 访问它。注册属于 effect,卸载提供方时会移除该服务。
|
||||
- **编译时**:`declare module 'cordis'` 块使用 TypeScript 声明合并,把 `greeter` 加入 `Context` 接口,使 `ctx.greeter` 在各处都能通过类型检查。它不会生成代码;没有该声明时,服务在运行时仍能工作,但消费方会失去类型安全。
|
||||
- **编译时**:`declare module '@deepseek-ai/cordis'` 块使用 TypeScript 声明合并,把 `greeter` 加入 `Context` 接口,使 `ctx.greeter` 在各处都能通过类型检查。它不会生成代码;没有该声明时,服务在运行时仍能工作,但消费方会失去类型安全。
|
||||
|
||||
`Service` 子类本身就是插件(第 1 章介绍的类形态),因此 `ctx.plugin(GreeterService)` 会像挂载其他插件一样挂载它。
|
||||
|
||||
@@ -46,7 +46,7 @@ export function apply(ctx: Context) {
|
||||
创建 `consumer.ts`:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'consumer'
|
||||
export const inject = ['greeter']
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/04-events.md
|
||||
04-events.md: e77641dffcb82fcb50a24ca2e3e764d152218094
|
||||
04-events.zh.md: 00cce854e9a54fddb594ffa8e306f60a725ac012
|
||||
04-events.md: 0302adf7c81b802b406f5f6737539ccf3eb970f9
|
||||
04-events.zh.md: ae41e757c06a46ef70c250c94a124546769e0112
|
||||
|
||||
@@ -9,9 +9,9 @@ Services support direct calls; **events** let a plugin announce something withou
|
||||
Create `stats.ts` in `tmp/cordis-tutorial` — a service that counts things and announces each change:
|
||||
|
||||
```ts
|
||||
import { Service, type Context } from 'cordis'
|
||||
import { Service, type Context } from '@deepseek-ai/cordis'
|
||||
|
||||
declare module 'cordis' {
|
||||
declare module '@deepseek-ai/cordis' {
|
||||
interface Context {
|
||||
stats: StatsService
|
||||
}
|
||||
@@ -46,7 +46,7 @@ The `interface Events` merge is the event-system twin of the `interface Context`
|
||||
Create `reporter.ts`:
|
||||
|
||||
```ts ignore-check
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type {} from './stats.ts'
|
||||
|
||||
export const name = 'reporter'
|
||||
@@ -96,9 +96,9 @@ Every harness event documents its mode in the generated reference on its owning
|
||||
Waterfall is the mode that powers interception. Each listener receives the arguments plus a `next()` continuation; it can transform what `next()` returns, or return without calling `next()` and short-circuit the rest of the chain — what the Cordis docs call the veto. Create `waterfall-demo.ts`:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
declare module 'cordis' {
|
||||
declare module '@deepseek-ai/cordis' {
|
||||
interface Events {
|
||||
'demo/transform'(input: string, next: () => Promise<string>): Promise<string>
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
创建 `stats.ts`,将它放在 `tmp/cordis-tutorial` 中。它是一项负责计数并在每次变化时发出通知的服务:
|
||||
|
||||
```ts
|
||||
import { Service, type Context } from 'cordis'
|
||||
import { Service, type Context } from '@deepseek-ai/cordis'
|
||||
|
||||
declare module 'cordis' {
|
||||
declare module '@deepseek-ai/cordis' {
|
||||
interface Context {
|
||||
stats: StatsService
|
||||
}
|
||||
@@ -46,7 +46,7 @@ export function apply(ctx: Context) {
|
||||
创建 `reporter.ts`:
|
||||
|
||||
```ts ignore-check
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type {} from './stats.ts'
|
||||
|
||||
export const name = 'reporter'
|
||||
@@ -96,9 +96,9 @@ export function apply(ctx: Context) {
|
||||
waterfall 是实现拦截的模式。每个监听器都会收到参数和一个 `next()` continuation;它可以转换 `next()` 的返回值,也可以不调用 `next()` 就直接返回,从而短路链条的其余部分。Cordis 文档把后一种行为称为否决。创建 `waterfall-demo.ts`:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
declare module 'cordis' {
|
||||
declare module '@deepseek-ai/cordis' {
|
||||
interface Events {
|
||||
'demo/transform'(input: string, next: () => Promise<string>): Promise<string>
|
||||
}
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/05-config.md
|
||||
05-config.md: 834bb140cc1ff976acc8f21c8f54a7fb02636eac
|
||||
05-config.zh.md: f5cc6ac1ca4fa02eba6a1b015b9f6ae3b1a925fc
|
||||
05-config.md: ad73a732242e4015b2976e6fb193ff464e148dfa
|
||||
05-config.zh.md: edb3c4113288dfa80e899fb2e5eb21a67d929ca6
|
||||
|
||||
@@ -9,8 +9,8 @@ Each `cordis.yml` entry can carry a `config` block, and the plugin declares a sc
|
||||
Create `config-demo.ts` in `tmp/cordis-tutorial`:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import Schema from 'schemastery'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import Schema from '@deepseek-ai/schemastery'
|
||||
|
||||
export const name = 'config-demo'
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
创建 `config-demo.ts`,并将其放在 `tmp/cordis-tutorial` 中:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import Schema from 'schemastery'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import Schema from '@deepseek-ai/schemastery'
|
||||
|
||||
export const name = 'config-demo'
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/06-composition-and-hmr.md
|
||||
06-composition-and-hmr.md: a169d7a164be63c939e352e4e5b0bf9bce43da29
|
||||
06-composition-and-hmr.zh.md: 07ae46555c390d625a4397933e2ec5ac059bd270
|
||||
06-composition-and-hmr.md: 490e3de3a98dd823190deefd47e1b6f2f8ba71b5
|
||||
06-composition-and-hmr.zh.md: 4aefb5ecd036929590ab373a2883d90779997b4b
|
||||
|
||||
@@ -22,24 +22,24 @@ Groups nest a sub-list of entries that load and unload as one unit, and `isolate
|
||||
|
||||
## Hot module replacement
|
||||
|
||||
Because unloading releases effects ([chapter 2](02-lifecycle-and-effects.md)) and loading follows dependencies ([chapter 3](03-services.md)), HMR can replace a running plugin by unloading and loading it. The `@cordisjs/plugin-hmr` plugin watches your files and does exactly that on save.
|
||||
Because unloading releases effects ([chapter 2](02-lifecycle-and-effects.md)) and loading follows dependencies ([chapter 3](03-services.md)), HMR can replace a running plugin by unloading and loading it. The `@deepseek-ai/cordis-plugin-hmr` plugin watches your files and does exactly that on save.
|
||||
|
||||
In `tmp/cordis-tutorial`, write `cordis.yml`:
|
||||
|
||||
```yaml
|
||||
- id: logger
|
||||
name: '@cordisjs/plugin-logger-console'
|
||||
name: '@deepseek-ai/cordis-plugin-logger-console'
|
||||
- id: timer
|
||||
name: '@cordisjs/plugin-timer'
|
||||
name: '@deepseek-ai/cordis-plugin-timer'
|
||||
- id: hmr
|
||||
name: '@cordisjs/plugin-hmr'
|
||||
name: '@deepseek-ai/cordis-plugin-hmr'
|
||||
config:
|
||||
root: ['.']
|
||||
- id: hello
|
||||
name: './hello.ts'
|
||||
```
|
||||
|
||||
Two support plugins joined the list: HMR logs through the Cordis logger service, so without a console exporter you would not see its messages, and it `inject`s the `timer` service for debouncing — without `@cordisjs/plugin-timer` it sits in PENDING forever, silently. That silence is the subject of the next section.
|
||||
Two support plugins joined the list: HMR logs through the Cordis logger service, so without a console exporter you would not see its messages, and it `inject`s the `timer` service for debouncing — without `@deepseek-ai/cordis-plugin-timer` it sits in PENDING forever, silently. That silence is the subject of the next section.
|
||||
|
||||
HMR reads Node's loader internals through the Loader's native helper. Run Cordis under tsx:
|
||||
|
||||
@@ -65,7 +65,7 @@ The flip side of dependency-driven loading: a plugin whose `inject` names a serv
|
||||
You can see the states directly. Every context can enumerate the plugin registry; create `diagnose.ts`:
|
||||
|
||||
```ts
|
||||
import { FiberState, type Context } from 'cordis'
|
||||
import { FiberState, type Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'diagnose'
|
||||
|
||||
@@ -85,7 +85,7 @@ export function apply(ctx: Context) {
|
||||
And a plugin with an unsatisfiable dependency, `needs-timer.ts`:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'needs-timer'
|
||||
export const inject = ['timer']
|
||||
@@ -106,7 +106,7 @@ Run it (plain `node --import tsx ../../vendor/cordis/bin.js`; stop with Ctrl-C):
|
||||
needs-timer is PENDING — a required service is missing
|
||||
```
|
||||
|
||||
`inject: ['timer']` has no provider. Add `- name: '@cordisjs/plugin-timer'` to the list and the plugin loads. When a plugin does nothing and reports nothing, inspect its fiber state. Iterating without the PENDING filter also shows the loader's own plugins (Loader, Include) as ACTIVE fibers because plugins mount the config file itself.
|
||||
`inject: ['timer']` has no provider. Add `- name: '@deepseek-ai/cordis-plugin-timer'` to the list and the plugin loads. When a plugin does nothing and reports nothing, inspect its fiber state. Iterating without the PENDING filter also shows the loader's own plugins (Loader, Include) as ACTIVE fibers because plugins mount the config file itself.
|
||||
|
||||
Next: [Into the harness](07-into-the-harness.md) — the same patterns against real harness services.
|
||||
|
||||
|
||||
@@ -22,24 +22,24 @@ Cordis 配置项除了 `name` 和 `config`,还接受其他元数据:
|
||||
|
||||
## 热模块替换
|
||||
|
||||
卸载会释放 effect([第 2 章](02-lifecycle-and-effects.md)),加载则遵循依赖关系([第 3 章](03-services.md)),因此 HMR 可以先卸载、再加载,以替换正在运行的插件。`@cordisjs/plugin-hmr` 插件会监视文件,并在保存时执行这一过程。
|
||||
卸载会释放 effect([第 2 章](02-lifecycle-and-effects.md)),加载则遵循依赖关系([第 3 章](03-services.md)),因此 HMR 可以先卸载、再加载,以替换正在运行的插件。`@deepseek-ai/cordis-plugin-hmr` 插件会监视文件,并在保存时执行这一过程。
|
||||
|
||||
在 `tmp/cordis-tutorial` 中编写 `cordis.yml`:
|
||||
|
||||
```yaml
|
||||
- id: logger
|
||||
name: '@cordisjs/plugin-logger-console'
|
||||
name: '@deepseek-ai/cordis-plugin-logger-console'
|
||||
- id: timer
|
||||
name: '@cordisjs/plugin-timer'
|
||||
name: '@deepseek-ai/cordis-plugin-timer'
|
||||
- id: hmr
|
||||
name: '@cordisjs/plugin-hmr'
|
||||
name: '@deepseek-ai/cordis-plugin-hmr'
|
||||
config:
|
||||
root: ['.']
|
||||
- id: hello
|
||||
name: './hello.ts'
|
||||
```
|
||||
|
||||
列表中增加了两个辅助插件:HMR 通过 Cordis logger 服务记录日志,因此没有控制台导出器时看不到其消息;它还会 `inject` `timer` 服务来实现去抖,如果没有 `@cordisjs/plugin-timer`,它就会永远停在 PENDING,而且不发出任何提示。下一节就讨论这种静默状态。
|
||||
列表中增加了两个辅助插件:HMR 通过 Cordis logger 服务记录日志,因此没有控制台导出器时看不到其消息;它还会 `inject` `timer` 服务来实现去抖,如果没有 `@deepseek-ai/cordis-plugin-timer`,它就会永远停在 PENDING,而且不发出任何提示。下一节就讨论这种静默状态。
|
||||
|
||||
HMR 通过 Loader 的原生辅助工具读取 Node 的 loader 内部结构。请在 tsx 下运行 Cordis:
|
||||
|
||||
@@ -65,7 +65,7 @@ hello from my EDITED plugin
|
||||
你可以直接查看这些状态。每个上下文都能枚举插件注册表;创建 `diagnose.ts`:
|
||||
|
||||
```ts
|
||||
import { FiberState, type Context } from 'cordis'
|
||||
import { FiberState, type Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'diagnose'
|
||||
|
||||
@@ -85,7 +85,7 @@ export function apply(ctx: Context) {
|
||||
再创建一个依赖无法满足的插件 `needs-timer.ts`:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'needs-timer'
|
||||
export const inject = ['timer']
|
||||
@@ -106,7 +106,7 @@ export function apply(ctx: Context) {
|
||||
needs-timer is PENDING — a required service is missing
|
||||
```
|
||||
|
||||
`inject: ['timer']` 没有提供方。向列表添加 `- name: '@cordisjs/plugin-timer'` 后,插件就会加载。如果插件既不执行任何操作,也不报告任何内容,请检查其 fiber 状态。不加 PENDING 过滤条件进行迭代时,还会看到 loader 自身的插件(Loader、Include)处于 ACTIVE,因为配置文件本身也是通过插件挂载的。
|
||||
`inject: ['timer']` 没有提供方。向列表添加 `- name: '@deepseek-ai/cordis-plugin-timer'` 后,插件就会加载。如果插件既不执行任何操作,也不报告任何内容,请检查其 fiber 状态。不加 PENDING 过滤条件进行迭代时,还会看到 loader 自身的插件(Loader、Include)处于 ACTIVE,因为配置文件本身也是通过插件挂载的。
|
||||
|
||||
下一章:[进入 harness](07-into-the-harness.md):把相同模式用于真实的 harness 服务。
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/07-into-the-harness.md
|
||||
07-into-the-harness.md: 69133786f58541b015aed080f4ac8fb2a7e488c0
|
||||
07-into-the-harness.zh.md: bc9c61da984e3eb691eb6bfbe59ae556823e82de
|
||||
07-into-the-harness.md: 41a30f032ac02d8e9e3b17ac8d9cd13e9973e36a
|
||||
07-into-the-harness.zh.md: 159cede00d453796f6a2cacae184229d71e17f87
|
||||
|
||||
@@ -9,7 +9,7 @@ This chapter registers a model-callable tool with the harness's `tools` service,
|
||||
Create `greet-tool.ts` in `tmp/cordis-tutorial`:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { defineTool } from '@deepseek-ai/dsh-tools'
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
|
||||
@@ -53,7 +53,7 @@ Every pattern here is from the earlier chapters: `inject: ['tools']` ([chapter 3
|
||||
Create `tool-logger.ts` — a separate plugin that watches every tool call in the app through the harness's `tools/result` event:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type {} from '@deepseek-ai/dsh-tools'
|
||||
|
||||
export const name = 'tool-logger'
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
创建 `greet-tool.ts`,将它放在 `tmp/cordis-tutorial` 中:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { defineTool } from '@deepseek-ai/dsh-tools'
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
|
||||
@@ -53,7 +53,7 @@ export function apply(ctx: Context) {
|
||||
创建 `tool-logger.ts`。这是一个独立插件,通过 harness 的 `tools/result` 事件观察应用中的每次工具调用:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type {} from '@deepseek-ai/dsh-tools'
|
||||
|
||||
export const name = 'tool-logger'
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/index.md
|
||||
index.md: 307c12854b3075cfd4dd5ea8a19806c58b4e998d
|
||||
index.zh.md: a0107b7d15272e6ef8d526b9c0e03a99275644d6
|
||||
index.md: cf61fec07acd2022591cd858ba4146b6a4ae1a3d
|
||||
index.zh.md: 775bf2fce2138b9edd91f5ee46b93b8c4eb4559e
|
||||
|
||||
@@ -50,8 +50,8 @@ That one-file launcher (see [vendor/cordis/bin.js](../../vendor/cordis/bin.js))
|
||||
The examples use three TypeScript features beyond ordinary modern JavaScript:
|
||||
|
||||
- **Type annotations** describe values without changing runtime behavior: `ctx: Context` says that `ctx` has the Cordis context API, `who: string` accepts text, and `string[]` means an array of strings.
|
||||
- **`import type { Context } from 'cordis'`** imports only type information. It vanishes at runtime, so a plugin file that needs `Context` solely for annotations adds no runtime dependency.
|
||||
- **Declaration merging** (`declare module 'cordis' { ... }`) adds your entries to interfaces that Cordis already declares — for example the type of a new `ctx.greeter` property or event name. It generates no runtime wiring; the plugin separately provides the service or emits the event. Chapter 3 shows the pattern in full.
|
||||
- **`import type { Context } from '@deepseek-ai/cordis'`** imports only type information. It vanishes at runtime, so a plugin file that needs `Context` solely for annotations adds no runtime dependency.
|
||||
- **Declaration merging** (`declare module '@deepseek-ai/cordis' { ... }`) adds your entries to interfaces that Cordis already declares — for example the type of a new `ctx.greeter` property or event name. It generates no runtime wiring; the plugin separately provides the service or emits the event. Chapter 3 shows the pattern in full.
|
||||
|
||||
Chapter 5 also uses an `interface` to describe a configuration object's fields and a generic type such as `Schema<Config>` to say which object fields a schema validates. You can copy those declarations as shown; the surrounding text explains what each one connects.
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@ node --import tsx ../../vendor/cordis/bin.js
|
||||
这些示例使用了普通现代 JavaScript 之外的三项 TypeScript 功能:
|
||||
|
||||
- **类型注解** 描述值,但不会改变运行时行为:`ctx: Context` 表示 `ctx` 具备 Cordis 上下文 API,`who: string` 接受文本,而 `string[]` 表示字符串数组。
|
||||
- **`import type { Context } from 'cordis'`** 只导入类型信息。它在运行时会消失,因此仅为类型注解使用 `Context` 的插件文件不会增加运行时依赖。
|
||||
- **声明合并**(`declare module 'cordis' { ... }`)会为 Cordis 已经声明的接口添加你的条目,例如新 `ctx.greeter` 属性的类型或事件名称。它不会生成任何运行时接线;插件必须另行提供服务或发出事件。第 3 章会完整展示该模式。
|
||||
- **`import type { Context } from '@deepseek-ai/cordis'`** 只导入类型信息。它在运行时会消失,因此仅为类型注解使用 `Context` 的插件文件不会增加运行时依赖。
|
||||
- **声明合并**(`declare module '@deepseek-ai/cordis' { ... }`)会为 Cordis 已经声明的接口添加你的条目,例如新 `ctx.greeter` 属性的类型或事件名称。它不会生成任何运行时接线;插件必须另行提供服务或发出事件。第 3 章会完整展示该模式。
|
||||
|
||||
第 5 章还会使用 `interface` 描述配置对象的字段,并使用 `Schema<Config>` 这类泛型表示 schema 校验哪些对象字段。你可以直接照写这些声明;周围的正文会解释每项声明连接了什么。
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/event-producer-consumer.md
|
||||
event-producer-consumer.md: d2e5cd66c2406cf84320fc1c0537d580214dd93d
|
||||
event-producer-consumer.zh.md: 12ac194d68ed6121cc0b2c5e9bf2c7f77944f57b
|
||||
event-producer-consumer.md: 33e3f8e67291d9f3b50d9a52fc3104e2e218d799
|
||||
event-producer-consumer.zh.md: 2f036ba0cad1d86952424c4d4969795a3862cfd7
|
||||
|
||||
@@ -30,19 +30,19 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `goal/changed` | `emit` | [`packages/goal/goal/src/domain.ts:114`](../packages/goal/goal/src/domain.ts) | [`goal`](../packages/goal/goal) (`emit`) | [`goal-session`](../packages/goal/goal-session) |
|
||||
| `llm/adapters-updated` | `emit` | [`packages/llm/llm/src/index.ts:75`](../packages/llm/llm/src/index.ts) | [`llm`](../packages/llm/llm) (`events.dispatch`) | `apiproxy`, [`llm`](../packages/llm/llm) |
|
||||
| `llm/stream` | `waterfall` | [`packages/llm/llm/src/index.ts:64`](../packages/llm/llm/src/index.ts) | [`llm`](../packages/llm/llm) (`waterfall`) | [`agent-loop`](../packages/core/agent-loop), [`llm`](../packages/llm/llm), [`llm-replay`](../packages/support/llm-replay), [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), [`session-title`](../packages/session/session-title) |
|
||||
| `session/created` | `emit` | [`packages/core/session/src/index.ts:74`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | `apiproxy`, [`compact`](../packages/compact/compact), [`goal`](../packages/goal/goal), [`hook-protocol`](../packages/hooks/hook-protocol), [`llm-retry`](../packages/llm/llm-retry), [`permission`](../packages/interaction/permission), [`plan-mode`](../packages/plan/plan-mode), `server`, [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-telemetry`](../packages/session/session-telemetry), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| `session/disposed` | `emit` | [`packages/core/session/src/index.ts:84`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), `apiproxy`, [`session-persistence`](../packages/session/session-persistence), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-telemetry`](../packages/session/session-telemetry), [`session-title`](../packages/session/session-title) |
|
||||
| `session/event` | `emit` | [`packages/core/session/src/index.ts:96`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`acp`](../packages/acp/acp), [`agent-loop`](../packages/core/agent-loop), `apiproxy`, [`compact`](../packages/compact/compact), [`compact-basic`](../packages/compact/compact-basic), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`loader-smoke`](../packages/support/loader-smoke), `server`, [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-telemetry`](../packages/session/session-telemetry), [`session-telemetry-otel`](../packages/session/session-telemetry-otel), [`session-title`](../packages/session/session-title), [`token-meter`](../packages/llm/token-meter), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `session/flush` | `parallel` | [`packages/core/session/src/index.ts:105`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`session-persistence`](../packages/session/session-persistence), [`session-telemetry`](../packages/session/session-telemetry) |
|
||||
| `session/created` | `emit` | [`packages/core/session/src/index.ts:75`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | `apiproxy`, [`compact`](../packages/compact/compact), [`goal`](../packages/goal/goal), [`hook-protocol`](../packages/hooks/hook-protocol), [`llm-retry`](../packages/llm/llm-retry), [`permission`](../packages/interaction/permission), [`plan-mode`](../packages/plan/plan-mode), `server`, [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-telemetry`](../packages/session/session-telemetry), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| `session/disposed` | `emit` | [`packages/core/session/src/index.ts:85`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), `apiproxy`, [`session-persistence`](../packages/session/session-persistence), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-telemetry`](../packages/session/session-telemetry), [`session-title`](../packages/session/session-title) |
|
||||
| `session/event` | `emit` | [`packages/core/session/src/index.ts:97`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`acp`](../packages/acp/acp), [`agent-loop`](../packages/core/agent-loop), `apiproxy`, [`compact`](../packages/compact/compact), [`compact-basic`](../packages/compact/compact-basic), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`loader-smoke`](../packages/support/loader-smoke), `server`, [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-telemetry`](../packages/session/session-telemetry), [`session-telemetry-otel`](../packages/session/session-telemetry-otel), [`session-title`](../packages/session/session-title), [`token-meter`](../packages/llm/token-meter), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `session/flush` | `parallel` | [`packages/core/session/src/index.ts:106`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`session-persistence`](../packages/session/session-persistence), [`session-telemetry`](../packages/session/session-telemetry) |
|
||||
| `settings/document-updated` | `emit` | [`packages/settings/settings/src/index.ts:170`](../packages/settings/settings/src/index.ts) | [`settings`](../packages/settings/settings) (`events.dispatch`) | `apiproxy` |
|
||||
| `settings/updated` | `emit` | [`packages/settings/settings/src/index.ts:157`](../packages/settings/settings/src/index.ts) | [`settings`](../packages/settings/settings) (`events.dispatch`) | [`settings`](../packages/settings/settings) |
|
||||
| `skills/change` | `emit` | [`packages/skill/skill/src/index.ts:297`](../packages/skill/skill/src/index.ts) | [`skill`](../packages/skill/skill) (`events.dispatch`) | - |
|
||||
| `subagent/end` | `emit` | [`packages/subagent/subagent/src/index.ts:162`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude`](../packages/hooks/hooks-claude), `server`, [`subagent`](../packages/subagent/subagent) |
|
||||
| `subagent/provider-added` | `emit` | [`packages/subagent/subagent/src/index.ts:136`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`emit`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `subagent/provider-removed` | `emit` | [`packages/subagent/subagent/src/index.ts:142`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `subagent/start` | `emit` | [`packages/subagent/subagent/src/index.ts:153`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`subagent`](../packages/subagent/subagent) |
|
||||
| `system-prompt/assemble` | `waterfall` | [`packages/core/system-prompt/src/index.ts:29`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`waterfall`) | [`agent`](../packages/core/agent), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| `system-prompt/change` | `emit` | [`packages/core/system-prompt/src/index.ts:35`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`emit`) | - |
|
||||
| `subagent/end` | `emit` | [`packages/subagent/subagent/src/index.ts:165`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude`](../packages/hooks/hooks-claude), `server`, [`subagent`](../packages/subagent/subagent) |
|
||||
| `subagent/provider-added` | `emit` | [`packages/subagent/subagent/src/index.ts:139`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`emit`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `subagent/provider-removed` | `emit` | [`packages/subagent/subagent/src/index.ts:145`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `subagent/start` | `emit` | [`packages/subagent/subagent/src/index.ts:156`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`subagent`](../packages/subagent/subagent) |
|
||||
| `system-prompt/assemble` | `waterfall` | [`packages/core/system-prompt/src/index.ts:31`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`waterfall`) | [`agent`](../packages/core/agent), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| `system-prompt/change` | `emit` | [`packages/core/system-prompt/src/index.ts:37`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`emit`) | - |
|
||||
| `telemetry/record` | `waterfall` | [`packages/session/session-telemetry/src/index.ts:43`](../packages/session/session-telemetry/src/index.ts) | [`session-telemetry`](../packages/session/session-telemetry) (`waterfall`) | - |
|
||||
| `tools/change` | `emit` | [`packages/core/tools/src/index.ts:193`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`emit`) | - |
|
||||
| `tools/code-dispatch-log` | `waterfall` | [`packages/core/tools/src/index.ts:175`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`spill-policy`](../packages/spill/spill-policy) |
|
||||
|
||||
@@ -32,19 +32,19 @@
|
||||
| `goal/changed` | `emit` | [`packages/goal/goal/src/domain.ts:114`](../packages/goal/goal/src/domain.ts) | [`goal`](../packages/goal/goal) (`emit`) | [`goal-session`](../packages/goal/goal-session) |
|
||||
| `llm/adapters-updated` | `emit` | [`packages/llm/llm/src/index.ts:75`](../packages/llm/llm/src/index.ts) | [`llm`](../packages/llm/llm) (`events.dispatch`) | `apiproxy`, [`llm`](../packages/llm/llm) |
|
||||
| `llm/stream` | `waterfall` | [`packages/llm/llm/src/index.ts:64`](../packages/llm/llm/src/index.ts) | [`llm`](../packages/llm/llm) (`waterfall`) | [`agent-loop`](../packages/core/agent-loop), [`llm`](../packages/llm/llm), [`llm-replay`](../packages/support/llm-replay), [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), [`session-title`](../packages/session/session-title) |
|
||||
| `session/created` | `emit` | [`packages/core/session/src/index.ts:74`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | `apiproxy`, [`compact`](../packages/compact/compact), [`goal`](../packages/goal/goal), [`hook-protocol`](../packages/hooks/hook-protocol), [`llm-retry`](../packages/llm/llm-retry), [`permission`](../packages/interaction/permission), [`plan-mode`](../packages/plan/plan-mode), `server`, [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-telemetry`](../packages/session/session-telemetry), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| `session/disposed` | `emit` | [`packages/core/session/src/index.ts:84`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), `apiproxy`, [`session-persistence`](../packages/session/session-persistence), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-telemetry`](../packages/session/session-telemetry), [`session-title`](../packages/session/session-title) |
|
||||
| `session/event` | `emit` | [`packages/core/session/src/index.ts:96`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`acp`](../packages/acp/acp), [`agent-loop`](../packages/core/agent-loop), `apiproxy`, [`compact`](../packages/compact/compact), [`compact-basic`](../packages/compact/compact-basic), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`loader-smoke`](../packages/support/loader-smoke), `server`, [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-telemetry`](../packages/session/session-telemetry), [`session-telemetry-otel`](../packages/session/session-telemetry-otel), [`session-title`](../packages/session/session-title), [`token-meter`](../packages/llm/token-meter), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `session/flush` | `parallel` | [`packages/core/session/src/index.ts:105`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`session-persistence`](../packages/session/session-persistence), [`session-telemetry`](../packages/session/session-telemetry) |
|
||||
| `session/created` | `emit` | [`packages/core/session/src/index.ts:75`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | `apiproxy`, [`compact`](../packages/compact/compact), [`goal`](../packages/goal/goal), [`hook-protocol`](../packages/hooks/hook-protocol), [`llm-retry`](../packages/llm/llm-retry), [`permission`](../packages/interaction/permission), [`plan-mode`](../packages/plan/plan-mode), `server`, [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-telemetry`](../packages/session/session-telemetry), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| `session/disposed` | `emit` | [`packages/core/session/src/index.ts:85`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), `apiproxy`, [`session-persistence`](../packages/session/session-persistence), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-telemetry`](../packages/session/session-telemetry), [`session-title`](../packages/session/session-title) |
|
||||
| `session/event` | `emit` | [`packages/core/session/src/index.ts:97`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`acp`](../packages/acp/acp), [`agent-loop`](../packages/core/agent-loop), `apiproxy`, [`compact`](../packages/compact/compact), [`compact-basic`](../packages/compact/compact-basic), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`loader-smoke`](../packages/support/loader-smoke), `server`, [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-telemetry`](../packages/session/session-telemetry), [`session-telemetry-otel`](../packages/session/session-telemetry-otel), [`session-title`](../packages/session/session-title), [`token-meter`](../packages/llm/token-meter), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `session/flush` | `parallel` | [`packages/core/session/src/index.ts:106`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`session-persistence`](../packages/session/session-persistence), [`session-telemetry`](../packages/session/session-telemetry) |
|
||||
| `settings/document-updated` | `emit` | [`packages/settings/settings/src/index.ts:170`](../packages/settings/settings/src/index.ts) | [`settings`](../packages/settings/settings) (`events.dispatch`) | `apiproxy` |
|
||||
| `settings/updated` | `emit` | [`packages/settings/settings/src/index.ts:157`](../packages/settings/settings/src/index.ts) | [`settings`](../packages/settings/settings) (`events.dispatch`) | [`settings`](../packages/settings/settings) |
|
||||
| `skills/change` | `emit` | [`packages/skill/skill/src/index.ts:297`](../packages/skill/skill/src/index.ts) | [`skill`](../packages/skill/skill) (`events.dispatch`) | - |
|
||||
| `subagent/end` | `emit` | [`packages/subagent/subagent/src/index.ts:162`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude`](../packages/hooks/hooks-claude), `server`, [`subagent`](../packages/subagent/subagent) |
|
||||
| `subagent/provider-added` | `emit` | [`packages/subagent/subagent/src/index.ts:136`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`emit`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `subagent/provider-removed` | `emit` | [`packages/subagent/subagent/src/index.ts:142`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `subagent/start` | `emit` | [`packages/subagent/subagent/src/index.ts:153`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`subagent`](../packages/subagent/subagent) |
|
||||
| `system-prompt/assemble` | `waterfall` | [`packages/core/system-prompt/src/index.ts:29`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`waterfall`) | [`agent`](../packages/core/agent), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| `system-prompt/change` | `emit` | [`packages/core/system-prompt/src/index.ts:35`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`emit`) | - |
|
||||
| `subagent/end` | `emit` | [`packages/subagent/subagent/src/index.ts:165`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude`](../packages/hooks/hooks-claude), `server`, [`subagent`](../packages/subagent/subagent) |
|
||||
| `subagent/provider-added` | `emit` | [`packages/subagent/subagent/src/index.ts:139`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`emit`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `subagent/provider-removed` | `emit` | [`packages/subagent/subagent/src/index.ts:145`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `subagent/start` | `emit` | [`packages/subagent/subagent/src/index.ts:156`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`subagent`](../packages/subagent/subagent) |
|
||||
| `system-prompt/assemble` | `waterfall` | [`packages/core/system-prompt/src/index.ts:31`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`waterfall`) | [`agent`](../packages/core/agent), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| `system-prompt/change` | `emit` | [`packages/core/system-prompt/src/index.ts:37`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`emit`) | - |
|
||||
| `telemetry/record` | `waterfall` | [`packages/session/session-telemetry/src/index.ts:43`](../packages/session/session-telemetry/src/index.ts) | [`session-telemetry`](../packages/session/session-telemetry) (`waterfall`) | - |
|
||||
| `tools/change` | `emit` | [`packages/core/tools/src/index.ts:193`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`emit`) | - |
|
||||
| `tools/code-dispatch-log` | `waterfall` | [`packages/core/tools/src/index.ts:175`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`spill-policy`](../packages/spill/spill-policy) |
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/module-graph.md
|
||||
module-graph.md: a81c8fa85eb85d5ec31bfff286fceff511880715
|
||||
module-graph.zh.md: b1ec05f45d1dac545e020f6438f2e2b4d197ebdf
|
||||
module-graph.md: 65b291dfc049b30ece7a53f23ad32186759d6fcb
|
||||
module-graph.zh.md: 8bf1993964931209829733bf0a6a07097c1301b9
|
||||
|
||||
@@ -133,6 +133,7 @@ flowchart TD
|
||||
end
|
||||
subgraph group_boot["packages/boot"]
|
||||
pkg_app_boot["app-boot"]
|
||||
pkg_cmdline["cmdline"]
|
||||
end
|
||||
subgraph group_bundle["packages/bundle"]
|
||||
pkg_base["base"]
|
||||
@@ -253,7 +254,6 @@ flowchart TD
|
||||
pkg_telemetry["telemetry"]
|
||||
end
|
||||
subgraph group_self_modification["packages/self-modification"]
|
||||
pkg_repository_plugin["repository-plugin"]
|
||||
pkg_tool_cordis["tool-cordis"]
|
||||
end
|
||||
subgraph group_session["packages/session"]
|
||||
@@ -314,6 +314,7 @@ flowchart TD
|
||||
pkg_timeout --> pkg_invariants
|
||||
pkg_scope --> pkg_invariants
|
||||
pkg_llm_mock_server --> pkg_invariants
|
||||
pkg_cmdline --> pkg_invariants
|
||||
pkg_base --> pkg_invariants
|
||||
pkg_client_modules --> pkg_invariants
|
||||
pkg_client_schema_form --> pkg_invariants
|
||||
@@ -398,9 +399,6 @@ flowchart TD
|
||||
pkg_client_ui_settings --> pkg_client_ui_primitives
|
||||
pkg_client_ui_settings --> pkg_client_ui_slots
|
||||
pkg_client_ui_settings --> pkg_invariants
|
||||
pkg_client_ui_trajectory --> pkg_client_runtime
|
||||
pkg_client_ui_trajectory --> pkg_client_ui_primitives
|
||||
pkg_client_ui_trajectory --> pkg_invariants
|
||||
pkg_credentials_local --> pkg_atomic_write
|
||||
pkg_credentials_local --> pkg_credentials
|
||||
pkg_credentials_local --> pkg_environment
|
||||
@@ -717,6 +715,7 @@ flowchart TD
|
||||
pkg_command_feedback --> pkg_commands
|
||||
pkg_command_feedback --> pkg_invariants
|
||||
pkg_command_feedback --> pkg_session
|
||||
pkg_command_feedback --> pkg_session_telemetry
|
||||
pkg_command_feedback --> pkg_user_id
|
||||
pkg_permission --> pkg_bash
|
||||
pkg_permission --> pkg_commands
|
||||
@@ -825,9 +824,12 @@ flowchart TD
|
||||
pkg_command_compact --> pkg_compact
|
||||
pkg_command_compact --> pkg_invariants
|
||||
pkg_subagent --> pkg_agent
|
||||
pkg_subagent --> pkg_agent_presets
|
||||
pkg_subagent --> pkg_brand
|
||||
pkg_subagent --> pkg_invariants
|
||||
pkg_subagent --> pkg_llm
|
||||
pkg_subagent --> pkg_sandbox
|
||||
pkg_subagent --> pkg_sandbox_policy
|
||||
pkg_subagent --> pkg_scope
|
||||
pkg_subagent --> pkg_session
|
||||
pkg_subagent --> pkg_session_persistence
|
||||
@@ -835,6 +837,7 @@ flowchart TD
|
||||
pkg_subagent --> pkg_session_projection_cache
|
||||
pkg_subagent --> pkg_tasks
|
||||
pkg_subagent --> pkg_tools
|
||||
pkg_subagent --> pkg_user_approval
|
||||
pkg_tool_web --> pkg_invariants
|
||||
pkg_tool_web --> pkg_llm
|
||||
pkg_tool_web --> pkg_system_prompt
|
||||
@@ -888,6 +891,12 @@ flowchart TD
|
||||
pkg_llm_replay --> pkg_invariants
|
||||
pkg_llm_replay --> pkg_llm
|
||||
pkg_llm_replay --> pkg_session
|
||||
pkg_client_ui_trajectory --> pkg_agent
|
||||
pkg_client_ui_trajectory --> pkg_client_runtime
|
||||
pkg_client_ui_trajectory --> pkg_client_ui_primitives
|
||||
pkg_client_ui_trajectory --> pkg_compact
|
||||
pkg_client_ui_trajectory --> pkg_invariants
|
||||
pkg_client_ui_trajectory --> pkg_tools
|
||||
pkg_session_reference --> pkg_agent
|
||||
pkg_session_reference --> pkg_compact
|
||||
pkg_session_reference --> pkg_invariants
|
||||
@@ -922,6 +931,7 @@ flowchart TD
|
||||
pkg_mcp_client --> pkg_invariants
|
||||
pkg_mcp_client --> pkg_llm
|
||||
pkg_mcp_client --> pkg_subprocess
|
||||
pkg_mcp_client --> pkg_timeout
|
||||
pkg_mcp_client --> pkg_tools
|
||||
pkg_tool_bash_persistent --> pkg_agent
|
||||
pkg_tool_bash_persistent --> pkg_invariants
|
||||
@@ -1017,12 +1027,10 @@ flowchart TD
|
||||
pkg_subagent_inprocess --> pkg_agent
|
||||
pkg_subagent_inprocess --> pkg_invariants
|
||||
pkg_subagent_inprocess --> pkg_llm
|
||||
pkg_subagent_inprocess --> pkg_sandbox_policy
|
||||
pkg_subagent_inprocess --> pkg_session
|
||||
pkg_subagent_inprocess --> pkg_subagent
|
||||
pkg_subagent_inprocess --> pkg_system_prompt
|
||||
pkg_subagent_inprocess --> pkg_tools
|
||||
pkg_subagent_inprocess --> pkg_user_approval
|
||||
pkg_tool_subagent --> pkg_agent
|
||||
pkg_tool_subagent --> pkg_invariants
|
||||
pkg_tool_subagent --> pkg_llm
|
||||
@@ -1068,10 +1076,6 @@ flowchart TD
|
||||
pkg_sdk_protocol --> pkg_llm
|
||||
pkg_sdk_protocol --> pkg_session
|
||||
pkg_sdk_protocol --> pkg_subagent
|
||||
pkg_repository_plugin --> pkg_invariants
|
||||
pkg_repository_plugin --> pkg_mcp_client
|
||||
pkg_repository_plugin --> pkg_paths
|
||||
pkg_repository_plugin --> pkg_skill_local
|
||||
pkg_tool_ralph --> pkg_agent
|
||||
pkg_tool_ralph --> pkg_invariants
|
||||
pkg_tool_ralph --> pkg_llm
|
||||
@@ -1255,6 +1259,7 @@ flowchart TD
|
||||
| [`timeout`](../packages/util/timeout) | `util` | [`invariants`](../packages/support/invariants) |
|
||||
| [`scope`](../packages/core/scope) | `core` | [`invariants`](../packages/support/invariants) |
|
||||
| [`llm-mock-server`](../packages/support/llm-mock-server) | `support` | [`invariants`](../packages/support/invariants) |
|
||||
| [`cmdline`](../packages/boot/cmdline) | `boot` | [`invariants`](../packages/support/invariants) |
|
||||
| [`base`](../packages/bundle/base) | `bundle` | [`invariants`](../packages/support/invariants) |
|
||||
| [`client-modules`](../packages/client/modules) | `client` | [`invariants`](../packages/support/invariants) |
|
||||
| [`client-schema-form`](../packages/client/schema-form) | `client` | [`invariants`](../packages/support/invariants) |
|
||||
@@ -1295,7 +1300,6 @@ flowchart TD
|
||||
| [`client-locale`](../packages/client/locale) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-models`](../packages/client/ui-models) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-schema-form`](../packages/client/schema-form), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`client-web-react`](../packages/client/web-react), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-settings`](../packages/client/ui-settings) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`invariants`](../packages/support/invariants) |
|
||||
| [`credentials-local`](../packages/credentials/credentials-local) | `credentials` | [`atomic-write`](../packages/util/atomic-write), [`credentials`](../packages/credentials/credentials), [`environment`](../packages/util/environment), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths) |
|
||||
| [`settings-local`](../packages/settings/settings-local) | `settings` | [`atomic-write`](../packages/util/atomic-write), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths), [`settings`](../packages/settings/settings) |
|
||||
| [`llm-deepseek`](../packages/llm/llm-deepseek) | `llm` | [`credentials`](../packages/credentials/credentials), [`environment`](../packages/util/environment), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`settings`](../packages/settings/settings), [`timeout`](../packages/util/timeout) |
|
||||
@@ -1371,7 +1375,7 @@ flowchart TD
|
||||
| [`client-test-runtime`](../packages/client/test-runtime) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`client-web-react`](../packages/client/web-react), [`host-apiproxy`](../packages/host/apiproxy), [`invariants`](../packages/support/invariants) |
|
||||
| [`tmux-context`](../packages/context/tmux-context) | `context` | [`agent`](../packages/core/agent), [`bash`](../packages/bash/bash), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session) |
|
||||
| [`fs-e2b`](../packages/e2b/fs-e2b) | `e2b` | [`e2b`](../packages/e2b/e2b), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants) |
|
||||
| [`command-feedback`](../packages/feedback/command-feedback) | `feedback` | [`commands`](../packages/interaction/commands), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`user-id`](../packages/session/user-id) |
|
||||
| [`command-feedback`](../packages/feedback/command-feedback) | `feedback` | [`commands`](../packages/interaction/commands), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`session-telemetry`](../packages/session/session-telemetry), [`user-id`](../packages/session/user-id) |
|
||||
| [`permission`](../packages/interaction/permission) | `interaction` | [`bash`](../packages/bash/bash), [`commands`](../packages/interaction/commands), [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`settings`](../packages/settings/settings), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| [`lsp-local`](../packages/lsp/lsp-local) | `lsp` | [`brand`](../packages/util/brand), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`lsp`](../packages/lsp/lsp), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
| [`pty-local`](../packages/pty/pty-local) | `pty` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`pty`](../packages/pty/pty), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`subprocess`](../packages/subprocess/subprocess) |
|
||||
@@ -1390,7 +1394,7 @@ flowchart TD
|
||||
| [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) | `fs` | [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`tools`](../packages/core/tools) |
|
||||
| [`tool-skill`](../packages/skill/tool-skill) | `skill` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`skill`](../packages/skill/skill), [`tools`](../packages/core/tools) |
|
||||
| [`command-compact`](../packages/compact/command-compact) | `compact` | [`commands`](../packages/interaction/commands), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants) |
|
||||
| [`subagent`](../packages/subagent/subagent) | `subagent` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
|
||||
| [`subagent`](../packages/subagent/subagent) | `subagent` | [`agent`](../packages/core/agent), [`agent-presets`](../packages/preset/agent-presets), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| [`tool-web`](../packages/web/tool-web) | `web` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`web`](../packages/web/web) |
|
||||
| [`spill-policy`](../packages/spill/spill-policy) | `spill` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`spill`](../packages/spill/spill), [`tools`](../packages/core/tools) |
|
||||
| [`tool-todo`](../packages/todo/tool-todo) | `todo` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`tools`](../packages/core/tools) |
|
||||
@@ -1400,13 +1404,14 @@ flowchart TD
|
||||
| [`tool-session-query`](../packages/session-query/tool-session-query) | `session-query` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query), [`system-prompt`](../packages/core/system-prompt), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
|
||||
| [`agent-loop-testkit`](../packages/support/agent-loop-testkit) | `support` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
|
||||
| [`llm-replay`](../packages/support/llm-replay) | `support` | [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
|
||||
| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`agent`](../packages/core/agent), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) |
|
||||
| [`session-reference`](../packages/context/session-reference) | `context` | [`agent`](../packages/core/agent), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query) |
|
||||
| [`workspace-context`](../packages/context/workspace-context) | `context` | [`agent`](../packages/core/agent), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`paths`](../packages/util/paths), [`session`](../packages/core/session), [`tools`](../packages/core/tools) |
|
||||
| [`repeat-tool-guard`](../packages/guard/repeat-tool-guard) | `guard` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) |
|
||||
| [`timeout-policy`](../packages/guard/timeout-policy) | `guard` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
|
||||
| [`tool-ask-user`](../packages/interaction/tool-ask-user) | `interaction` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools), [`user-interaction`](../packages/interaction/user-interaction) |
|
||||
| [`tool-lsp`](../packages/lsp/tool-lsp) | `lsp` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`lsp`](../packages/lsp/lsp), [`system-prompt`](../packages/core/system-prompt), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
|
||||
| [`mcp-client`](../packages/mcp/mcp-client) | `mcp` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`subprocess`](../packages/subprocess/subprocess), [`tools`](../packages/core/tools) |
|
||||
| [`mcp-client`](../packages/mcp/mcp-client) | `mcp` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
|
||||
| [`tool-bash-persistent`](../packages/pty/tool-bash-persistent) | `pty` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`pty`](../packages/pty/pty), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
|
||||
| [`tool-pty`](../packages/pty/tool-pty) | `pty` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`pty`](../packages/pty/pty), [`retention`](../packages/util/retention), [`system-prompt`](../packages/core/system-prompt), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
|
||||
| [`tool-cordis`](../packages/self-modification/tool-cordis) | `self-modification` | [`invariants`](../packages/support/invariants), [`scope`](../packages/core/scope), [`tools`](../packages/core/tools) |
|
||||
@@ -1421,7 +1426,7 @@ flowchart TD
|
||||
| [`compact-tool-result-prune`](../packages/compact/compact-tool-result-prune) | `compact` | [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`token-meter`](../packages/llm/token-meter) |
|
||||
| [`subagent-acp`](../packages/subagent/subagent-acp) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
| [`subagent-claude-code`](../packages/subagent/subagent-claude-code) | `subagent` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
| [`subagent-inprocess`](../packages/subagent/subagent-inprocess) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| [`subagent-inprocess`](../packages/subagent/subagent-inprocess) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
|
||||
| [`tool-subagent`](../packages/subagent/tool-subagent) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`subagent`](../packages/subagent/subagent), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
|
||||
| [`tool-subagent-control`](../packages/subagent/tool-subagent-control) | `subagent` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`tools`](../packages/core/tools) |
|
||||
| [`tool-subagent-report`](../packages/subagent/tool-subagent-report) | `subagent` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`subagent`](../packages/subagent/subagent), [`tools`](../packages/core/tools) |
|
||||
@@ -1429,7 +1434,6 @@ flowchart TD
|
||||
| [`web-app`](../packages/bundle/web-app) | `bundle` | [`bash-env`](../packages/bash/bash-env), [`invariants`](../packages/support/invariants), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| [`client-ui-conversation`](../packages/client/ui-conversation) | `client` | [`agent`](../packages/core/agent), [`attachment`](../packages/attachment/attachment), [`brand`](../packages/util/brand), [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`commands`](../packages/interaction/commands), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm-retry`](../packages/llm/llm-retry), [`token-meter`](../packages/llm/token-meter), [`tools`](../packages/core/tools) |
|
||||
| [`sdk-protocol`](../packages/scaffold/protocol) | `scaffold` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent) |
|
||||
| [`repository-plugin`](../packages/self-modification/repository-plugin) | `self-modification` | [`invariants`](../packages/support/invariants), [`mcp-client`](../packages/mcp/mcp-client), [`paths`](../packages/util/paths), [`skill-local`](../packages/skill/skill-local) |
|
||||
| [`tool-ralph`](../packages/workflow/tool-ralph) | `workflow` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`workflow`](../packages/workflow/workflow) |
|
||||
| [`workflow-workerthread`](../packages/workflow/workflow-workerthread) | `workflow` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`tools`](../packages/core/tools), [`workflow`](../packages/workflow/workflow) |
|
||||
| [`compact-basic`](../packages/compact/compact-basic) | `compact` | [`agent`](../packages/core/agent), [`commands`](../packages/interaction/commands), [`compact`](../packages/compact/compact), [`compact-tool-result-prune`](../packages/compact/compact-tool-result-prune), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`token-meter`](../packages/llm/token-meter) |
|
||||
|
||||
@@ -135,6 +135,7 @@ flowchart TD
|
||||
end
|
||||
subgraph group_boot["packages/boot"]
|
||||
pkg_app_boot["app-boot"]
|
||||
pkg_cmdline["cmdline"]
|
||||
end
|
||||
subgraph group_bundle["packages/bundle"]
|
||||
pkg_base["base"]
|
||||
@@ -255,7 +256,6 @@ flowchart TD
|
||||
pkg_telemetry["telemetry"]
|
||||
end
|
||||
subgraph group_self_modification["packages/self-modification"]
|
||||
pkg_repository_plugin["repository-plugin"]
|
||||
pkg_tool_cordis["tool-cordis"]
|
||||
end
|
||||
subgraph group_session["packages/session"]
|
||||
@@ -316,6 +316,7 @@ flowchart TD
|
||||
pkg_timeout --> pkg_invariants
|
||||
pkg_scope --> pkg_invariants
|
||||
pkg_llm_mock_server --> pkg_invariants
|
||||
pkg_cmdline --> pkg_invariants
|
||||
pkg_base --> pkg_invariants
|
||||
pkg_client_modules --> pkg_invariants
|
||||
pkg_client_schema_form --> pkg_invariants
|
||||
@@ -400,9 +401,6 @@ flowchart TD
|
||||
pkg_client_ui_settings --> pkg_client_ui_primitives
|
||||
pkg_client_ui_settings --> pkg_client_ui_slots
|
||||
pkg_client_ui_settings --> pkg_invariants
|
||||
pkg_client_ui_trajectory --> pkg_client_runtime
|
||||
pkg_client_ui_trajectory --> pkg_client_ui_primitives
|
||||
pkg_client_ui_trajectory --> pkg_invariants
|
||||
pkg_credentials_local --> pkg_atomic_write
|
||||
pkg_credentials_local --> pkg_credentials
|
||||
pkg_credentials_local --> pkg_environment
|
||||
@@ -719,6 +717,7 @@ flowchart TD
|
||||
pkg_command_feedback --> pkg_commands
|
||||
pkg_command_feedback --> pkg_invariants
|
||||
pkg_command_feedback --> pkg_session
|
||||
pkg_command_feedback --> pkg_session_telemetry
|
||||
pkg_command_feedback --> pkg_user_id
|
||||
pkg_permission --> pkg_bash
|
||||
pkg_permission --> pkg_commands
|
||||
@@ -827,9 +826,12 @@ flowchart TD
|
||||
pkg_command_compact --> pkg_compact
|
||||
pkg_command_compact --> pkg_invariants
|
||||
pkg_subagent --> pkg_agent
|
||||
pkg_subagent --> pkg_agent_presets
|
||||
pkg_subagent --> pkg_brand
|
||||
pkg_subagent --> pkg_invariants
|
||||
pkg_subagent --> pkg_llm
|
||||
pkg_subagent --> pkg_sandbox
|
||||
pkg_subagent --> pkg_sandbox_policy
|
||||
pkg_subagent --> pkg_scope
|
||||
pkg_subagent --> pkg_session
|
||||
pkg_subagent --> pkg_session_persistence
|
||||
@@ -837,6 +839,7 @@ flowchart TD
|
||||
pkg_subagent --> pkg_session_projection_cache
|
||||
pkg_subagent --> pkg_tasks
|
||||
pkg_subagent --> pkg_tools
|
||||
pkg_subagent --> pkg_user_approval
|
||||
pkg_tool_web --> pkg_invariants
|
||||
pkg_tool_web --> pkg_llm
|
||||
pkg_tool_web --> pkg_system_prompt
|
||||
@@ -890,6 +893,12 @@ flowchart TD
|
||||
pkg_llm_replay --> pkg_invariants
|
||||
pkg_llm_replay --> pkg_llm
|
||||
pkg_llm_replay --> pkg_session
|
||||
pkg_client_ui_trajectory --> pkg_agent
|
||||
pkg_client_ui_trajectory --> pkg_client_runtime
|
||||
pkg_client_ui_trajectory --> pkg_client_ui_primitives
|
||||
pkg_client_ui_trajectory --> pkg_compact
|
||||
pkg_client_ui_trajectory --> pkg_invariants
|
||||
pkg_client_ui_trajectory --> pkg_tools
|
||||
pkg_session_reference --> pkg_agent
|
||||
pkg_session_reference --> pkg_compact
|
||||
pkg_session_reference --> pkg_invariants
|
||||
@@ -924,6 +933,7 @@ flowchart TD
|
||||
pkg_mcp_client --> pkg_invariants
|
||||
pkg_mcp_client --> pkg_llm
|
||||
pkg_mcp_client --> pkg_subprocess
|
||||
pkg_mcp_client --> pkg_timeout
|
||||
pkg_mcp_client --> pkg_tools
|
||||
pkg_tool_bash_persistent --> pkg_agent
|
||||
pkg_tool_bash_persistent --> pkg_invariants
|
||||
@@ -1019,12 +1029,10 @@ flowchart TD
|
||||
pkg_subagent_inprocess --> pkg_agent
|
||||
pkg_subagent_inprocess --> pkg_invariants
|
||||
pkg_subagent_inprocess --> pkg_llm
|
||||
pkg_subagent_inprocess --> pkg_sandbox_policy
|
||||
pkg_subagent_inprocess --> pkg_session
|
||||
pkg_subagent_inprocess --> pkg_subagent
|
||||
pkg_subagent_inprocess --> pkg_system_prompt
|
||||
pkg_subagent_inprocess --> pkg_tools
|
||||
pkg_subagent_inprocess --> pkg_user_approval
|
||||
pkg_tool_subagent --> pkg_agent
|
||||
pkg_tool_subagent --> pkg_invariants
|
||||
pkg_tool_subagent --> pkg_llm
|
||||
@@ -1070,10 +1078,6 @@ flowchart TD
|
||||
pkg_sdk_protocol --> pkg_llm
|
||||
pkg_sdk_protocol --> pkg_session
|
||||
pkg_sdk_protocol --> pkg_subagent
|
||||
pkg_repository_plugin --> pkg_invariants
|
||||
pkg_repository_plugin --> pkg_mcp_client
|
||||
pkg_repository_plugin --> pkg_paths
|
||||
pkg_repository_plugin --> pkg_skill_local
|
||||
pkg_tool_ralph --> pkg_agent
|
||||
pkg_tool_ralph --> pkg_invariants
|
||||
pkg_tool_ralph --> pkg_llm
|
||||
@@ -1245,7 +1249,7 @@ flowchart TD
|
||||
pkg_acp_demo --> pkg_workspace_context
|
||||
```
|
||||
|
||||
| 包 | 分组 | 依赖项 |
|
||||
| Package | Group | Depends on |
|
||||
| --- | --- | --- |
|
||||
| [`invariants`](../packages/support/invariants) | `support` | — |
|
||||
| [`atomic-write`](../packages/util/atomic-write) | `util` | [`invariants`](../packages/support/invariants) |
|
||||
@@ -1257,6 +1261,7 @@ flowchart TD
|
||||
| [`timeout`](../packages/util/timeout) | `util` | [`invariants`](../packages/support/invariants) |
|
||||
| [`scope`](../packages/core/scope) | `core` | [`invariants`](../packages/support/invariants) |
|
||||
| [`llm-mock-server`](../packages/support/llm-mock-server) | `support` | [`invariants`](../packages/support/invariants) |
|
||||
| [`cmdline`](../packages/boot/cmdline) | `boot` | [`invariants`](../packages/support/invariants) |
|
||||
| [`base`](../packages/bundle/base) | `bundle` | [`invariants`](../packages/support/invariants) |
|
||||
| [`client-modules`](../packages/client/modules) | `client` | [`invariants`](../packages/support/invariants) |
|
||||
| [`client-schema-form`](../packages/client/schema-form) | `client` | [`invariants`](../packages/support/invariants) |
|
||||
@@ -1297,7 +1302,6 @@ flowchart TD
|
||||
| [`client-locale`](../packages/client/locale) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-models`](../packages/client/ui-models) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-schema-form`](../packages/client/schema-form), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`client-web-react`](../packages/client/web-react), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-settings`](../packages/client/ui-settings) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`invariants`](../packages/support/invariants) |
|
||||
| [`credentials-local`](../packages/credentials/credentials-local) | `credentials` | [`atomic-write`](../packages/util/atomic-write), [`credentials`](../packages/credentials/credentials), [`environment`](../packages/util/environment), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths) |
|
||||
| [`settings-local`](../packages/settings/settings-local) | `settings` | [`atomic-write`](../packages/util/atomic-write), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths), [`settings`](../packages/settings/settings) |
|
||||
| [`llm-deepseek`](../packages/llm/llm-deepseek) | `llm` | [`credentials`](../packages/credentials/credentials), [`environment`](../packages/util/environment), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`settings`](../packages/settings/settings), [`timeout`](../packages/util/timeout) |
|
||||
@@ -1373,7 +1377,7 @@ flowchart TD
|
||||
| [`client-test-runtime`](../packages/client/test-runtime) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`client-web-react`](../packages/client/web-react), [`host-apiproxy`](../packages/host/apiproxy), [`invariants`](../packages/support/invariants) |
|
||||
| [`tmux-context`](../packages/context/tmux-context) | `context` | [`agent`](../packages/core/agent), [`bash`](../packages/bash/bash), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session) |
|
||||
| [`fs-e2b`](../packages/e2b/fs-e2b) | `e2b` | [`e2b`](../packages/e2b/e2b), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants) |
|
||||
| [`command-feedback`](../packages/feedback/command-feedback) | `feedback` | [`commands`](../packages/interaction/commands), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`user-id`](../packages/session/user-id) |
|
||||
| [`command-feedback`](../packages/feedback/command-feedback) | `feedback` | [`commands`](../packages/interaction/commands), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`session-telemetry`](../packages/session/session-telemetry), [`user-id`](../packages/session/user-id) |
|
||||
| [`permission`](../packages/interaction/permission) | `interaction` | [`bash`](../packages/bash/bash), [`commands`](../packages/interaction/commands), [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`settings`](../packages/settings/settings), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| [`lsp-local`](../packages/lsp/lsp-local) | `lsp` | [`brand`](../packages/util/brand), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`lsp`](../packages/lsp/lsp), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
| [`pty-local`](../packages/pty/pty-local) | `pty` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`pty`](../packages/pty/pty), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`subprocess`](../packages/subprocess/subprocess) |
|
||||
@@ -1392,7 +1396,7 @@ flowchart TD
|
||||
| [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) | `fs` | [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`tools`](../packages/core/tools) |
|
||||
| [`tool-skill`](../packages/skill/tool-skill) | `skill` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`skill`](../packages/skill/skill), [`tools`](../packages/core/tools) |
|
||||
| [`command-compact`](../packages/compact/command-compact) | `compact` | [`commands`](../packages/interaction/commands), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants) |
|
||||
| [`subagent`](../packages/subagent/subagent) | `subagent` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
|
||||
| [`subagent`](../packages/subagent/subagent) | `subagent` | [`agent`](../packages/core/agent), [`agent-presets`](../packages/preset/agent-presets), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| [`tool-web`](../packages/web/tool-web) | `web` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`web`](../packages/web/web) |
|
||||
| [`spill-policy`](../packages/spill/spill-policy) | `spill` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`spill`](../packages/spill/spill), [`tools`](../packages/core/tools) |
|
||||
| [`tool-todo`](../packages/todo/tool-todo) | `todo` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`tools`](../packages/core/tools) |
|
||||
@@ -1402,13 +1406,14 @@ flowchart TD
|
||||
| [`tool-session-query`](../packages/session-query/tool-session-query) | `session-query` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query), [`system-prompt`](../packages/core/system-prompt), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
|
||||
| [`agent-loop-testkit`](../packages/support/agent-loop-testkit) | `support` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
|
||||
| [`llm-replay`](../packages/support/llm-replay) | `support` | [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
|
||||
| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`agent`](../packages/core/agent), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) |
|
||||
| [`session-reference`](../packages/context/session-reference) | `context` | [`agent`](../packages/core/agent), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query) |
|
||||
| [`workspace-context`](../packages/context/workspace-context) | `context` | [`agent`](../packages/core/agent), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`paths`](../packages/util/paths), [`session`](../packages/core/session), [`tools`](../packages/core/tools) |
|
||||
| [`repeat-tool-guard`](../packages/guard/repeat-tool-guard) | `guard` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) |
|
||||
| [`timeout-policy`](../packages/guard/timeout-policy) | `guard` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
|
||||
| [`tool-ask-user`](../packages/interaction/tool-ask-user) | `interaction` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools), [`user-interaction`](../packages/interaction/user-interaction) |
|
||||
| [`tool-lsp`](../packages/lsp/tool-lsp) | `lsp` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`lsp`](../packages/lsp/lsp), [`system-prompt`](../packages/core/system-prompt), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
|
||||
| [`mcp-client`](../packages/mcp/mcp-client) | `mcp` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`subprocess`](../packages/subprocess/subprocess), [`tools`](../packages/core/tools) |
|
||||
| [`mcp-client`](../packages/mcp/mcp-client) | `mcp` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
|
||||
| [`tool-bash-persistent`](../packages/pty/tool-bash-persistent) | `pty` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`pty`](../packages/pty/pty), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
|
||||
| [`tool-pty`](../packages/pty/tool-pty) | `pty` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`pty`](../packages/pty/pty), [`retention`](../packages/util/retention), [`system-prompt`](../packages/core/system-prompt), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
|
||||
| [`tool-cordis`](../packages/self-modification/tool-cordis) | `self-modification` | [`invariants`](../packages/support/invariants), [`scope`](../packages/core/scope), [`tools`](../packages/core/tools) |
|
||||
@@ -1423,7 +1428,7 @@ flowchart TD
|
||||
| [`compact-tool-result-prune`](../packages/compact/compact-tool-result-prune) | `compact` | [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`token-meter`](../packages/llm/token-meter) |
|
||||
| [`subagent-acp`](../packages/subagent/subagent-acp) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
| [`subagent-claude-code`](../packages/subagent/subagent-claude-code) | `subagent` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
| [`subagent-inprocess`](../packages/subagent/subagent-inprocess) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| [`subagent-inprocess`](../packages/subagent/subagent-inprocess) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
|
||||
| [`tool-subagent`](../packages/subagent/tool-subagent) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`subagent`](../packages/subagent/subagent), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
|
||||
| [`tool-subagent-control`](../packages/subagent/tool-subagent-control) | `subagent` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`tools`](../packages/core/tools) |
|
||||
| [`tool-subagent-report`](../packages/subagent/tool-subagent-report) | `subagent` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`subagent`](../packages/subagent/subagent), [`tools`](../packages/core/tools) |
|
||||
@@ -1431,7 +1436,6 @@ flowchart TD
|
||||
| [`web-app`](../packages/bundle/web-app) | `bundle` | [`bash-env`](../packages/bash/bash-env), [`invariants`](../packages/support/invariants), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| [`client-ui-conversation`](../packages/client/ui-conversation) | `client` | [`agent`](../packages/core/agent), [`attachment`](../packages/attachment/attachment), [`brand`](../packages/util/brand), [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`commands`](../packages/interaction/commands), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm-retry`](../packages/llm/llm-retry), [`token-meter`](../packages/llm/token-meter), [`tools`](../packages/core/tools) |
|
||||
| [`sdk-protocol`](../packages/scaffold/protocol) | `scaffold` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent) |
|
||||
| [`repository-plugin`](../packages/self-modification/repository-plugin) | `self-modification` | [`invariants`](../packages/support/invariants), [`mcp-client`](../packages/mcp/mcp-client), [`paths`](../packages/util/paths), [`skill-local`](../packages/skill/skill-local) |
|
||||
| [`tool-ralph`](../packages/workflow/tool-ralph) | `workflow` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`workflow`](../packages/workflow/workflow) |
|
||||
| [`workflow-workerthread`](../packages/workflow/workflow-workerthread) | `workflow` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`tools`](../packages/core/tools), [`workflow`](../packages/workflow/workflow) |
|
||||
| [`compact-basic`](../packages/compact/compact-basic) | `compact` | [`agent`](../packages/core/agent), [`commands`](../packages/interaction/commands), [`compact`](../packages/compact/compact), [`compact-tool-result-prune`](../packages/compact/compact-tool-result-prune), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`token-meter`](../packages/llm/token-meter) |
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/persistence-catalog.md
|
||||
persistence-catalog.md: f44569d3bacec0a832f4b4bca6acf4abb0846a0d
|
||||
persistence-catalog.zh.md: 21ed29a3da2587a604ec90d201030fd644fc5bd4
|
||||
persistence-catalog.md: 88d8f833ce3e6c51692db74519279a5354a1759b
|
||||
persistence-catalog.zh.md: 5ab0fa0c6ccb099ba10b9021625f20486a02d94c
|
||||
|
||||
@@ -7,7 +7,7 @@ Every event type that can appear in a session's durable event log: the complete
|
||||
|
||||
This file is GENERATED from source (`scripts/gen-persistence-catalog.ts`) and verified fresh by `pnpm run verify-persistence-catalog` (part of `doc-sync`) — do not edit it by hand. Declaration blocks retain the source declaration and nested property JSDoc, removing only the indentation imposed by a containing interface/module, and use a `ts persistence-catalog` fence (skipped by doc-typecheck because declarations reference types from their owning modules). Type names in a payload link to the page that documents them. See [the persistence-log-catalog Agent Note](../.agents/notes/archived/process/2026-07-04-persistence-log-catalog.md).
|
||||
|
||||
The envelope declarations below compose each event's `type`, monotonic `seq`, epoch-ms `time`, `data`, and the conditional `surfaceOp`/`sourceEventSeqs` fields. **surface** marks a `SurfaceEventType` member: it produces an LLM message and declares how it joins the surface list. **log-only** marks everything else: a durable, replayable record with no derived-history contribution. Every payload is JSON-serializable (enforced at `Session.append`), and the whole format is pinned at `SESSION_FORMAT_VERSION = 0` — pre-release, no compatibility implied ([the version stance](subsystems/persistence.md)). Scope: the packages in this repo; a downstream plugin can merge further event types, which are outside this catalog by construction.
|
||||
The envelope declarations below compose each event's `type`, monotonic `seq`, epoch-ms `time`, `data`, the optional `ignorable` unknown-type skip marker, and the conditional `surfaceOp`/`sourceEventSeqs` fields. **surface** marks a `SurfaceEventType` member: it produces an LLM message and declares how it joins the surface list. **log-only** marks everything else: a durable, replayable record with no derived-history contribution. Every payload is JSON-serializable (enforced at `Session.append`), and the whole format is pinned at `SESSION_FORMAT_VERSION = 0` — pre-release, no compatibility implied ([the version stance](subsystems/persistence.md)). Scope: the packages in this repo; a downstream plugin can merge further event types, which are outside this catalog by construction.
|
||||
|
||||
## Event envelope
|
||||
|
||||
@@ -63,6 +63,17 @@ export type SessionEvent<T extends SessionEventType = SessionEventType> = {
|
||||
/** Unix epoch milliseconds. */
|
||||
time: number
|
||||
data: SessionEventMap[K]
|
||||
/**
|
||||
* Marks an event a reader may safely skip when it does not recognize
|
||||
* `type`. Absent means required: a reader meeting an unrecognized type
|
||||
* without this marker MUST refuse to reconstruct the session instead of
|
||||
* silently dropping the event, because an unrecognized required event may
|
||||
* change how the rest of the log is interpreted. A writer sets `true` only
|
||||
* on purely informational records whose loss cannot affect reconstruction;
|
||||
* defaulting to required means a forgotten marker over-refuses (an
|
||||
* inconvenience) rather than silently resuming a gutted session.
|
||||
*/
|
||||
ignorable?: true
|
||||
} & (K extends SurfaceEventType ? {
|
||||
/**
|
||||
* Seq numbers of earlier events that this event cites as sources
|
||||
@@ -79,7 +90,7 @@ export type SessionEvent<T extends SessionEventType = SessionEventType> = {
|
||||
}[T]
|
||||
```
|
||||
|
||||
Sources: [`packages/core/session/src/types.ts:316`](../packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:323`](../packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:352`](../packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:384`](../packages/core/session/src/types.ts)
|
||||
Sources: [`packages/core/session/src/types.ts:331`](../packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:338`](../packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:367`](../packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:399`](../packages/core/session/src/types.ts)
|
||||
|
||||
## Events
|
||||
|
||||
@@ -192,7 +203,7 @@ Source: [`packages/interaction/user-approval/src/index.ts:67`](../packages/inter
|
||||
|
||||
Types: [StreamChunk](subsystems/llm-streaming.md)
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:246`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:261`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `assistant/message` — surface
|
||||
|
||||
@@ -208,7 +219,7 @@ Source: [`packages/core/session/src/types.ts:246`](../packages/core/session/src/
|
||||
|
||||
Types: [TokenUsage](subsystems/llm-streaming.md)
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:253`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:268`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `command/*`
|
||||
|
||||
@@ -364,7 +375,7 @@ Source: [`packages/compact/compact/src/types.ts:33`](../packages/compact/compact
|
||||
'feedback/record': { text: string }
|
||||
```
|
||||
|
||||
Source: [`packages/feedback/command-feedback/src/index.ts:25`](../packages/feedback/command-feedback/src/index.ts)
|
||||
Source: [`packages/feedback/command-feedback/src/index.ts:62`](../packages/feedback/command-feedback/src/index.ts)
|
||||
|
||||
### `goal/*`
|
||||
|
||||
@@ -488,7 +499,7 @@ Source: [`packages/plan/plan-mode/src/index.ts:53`](../packages/plan/plan-mode/s
|
||||
'request/context': RequestContext
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:289`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:304`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `request/header` — log-only
|
||||
|
||||
@@ -500,7 +511,7 @@ Source: [`packages/core/session/src/types.ts:289`](../packages/core/session/src/
|
||||
'request/header': { header: EpochHeader; reason: RequestHeaderReason }
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:284`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:299`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `sandbox/*`
|
||||
|
||||
@@ -553,7 +564,7 @@ Source: [`packages/sandbox/sandbox-policy/src/session-mode.ts:33`](../packages/s
|
||||
'session/end-seed': Record<string, never>
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:312`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:327`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `session/title` — log-only
|
||||
|
||||
@@ -589,7 +600,7 @@ Source: [`packages/session/session-title-llm/src/index.ts:43`](../packages/sessi
|
||||
'step/end': { turn: number; step: number }
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:236`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:251`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `step/start` — log-only
|
||||
|
||||
@@ -598,7 +609,7 @@ Source: [`packages/core/session/src/types.ts:236`](../packages/core/session/src/
|
||||
'step/start': { turn: number; step: number }
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:234`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:249`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `subagent/*`
|
||||
|
||||
@@ -628,7 +639,7 @@ Source: [`packages/subagent/subagent/src/descriptor.ts:37`](../packages/subagent
|
||||
|
||||
Types: [TodoItem](subsystems/session.md)
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:279`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:294`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `tool/*`
|
||||
|
||||
@@ -645,7 +656,7 @@ Source: [`packages/core/session/src/types.ts:279`](../packages/core/session/src/
|
||||
|
||||
Types: [CallId](subsystems/core.md)
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:259`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:274`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `tool/code-dispatch` — log-only
|
||||
|
||||
@@ -714,7 +725,7 @@ Source: [`packages/core/tools/src/types.ts:40`](../packages/core/tools/src/types
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:271`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:286`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `turn/*`
|
||||
|
||||
@@ -734,7 +745,7 @@ Source: [`packages/core/session/src/types.ts:271`](../packages/core/session/src/
|
||||
|
||||
Types: [TurnEndReason](subsystems/session.md)
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:232`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:247`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `turn/start` — log-only
|
||||
|
||||
@@ -748,7 +759,7 @@ Source: [`packages/core/session/src/types.ts:232`](../packages/core/session/src/
|
||||
'turn/start': { turn: number }
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:223`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:238`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `user/*`
|
||||
|
||||
@@ -765,7 +776,7 @@ Source: [`packages/core/session/src/types.ts:223`](../packages/core/session/src/
|
||||
'user/message': UserMessage
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:244`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:259`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `web/*`
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
英文源文件根据源码生成(`scripts/gen-persistence-catalog.ts`),并由 `pnpm run verify-persistence-catalog`(`doc-sync`(文档同步门禁)的一部分)验证新鲜度;本中文文件作为经评审对侧通过双语配对维护。声明块保留源码声明和嵌套属性的 JSDoc,只移除其所在接口/模块带来的缩进,并使用 `ts persistence-catalog` 围栏(doc-typecheck 会跳过这些围栏,因为声明引用了其所属模块中的类型)。payload 中的类型名称会链接到记录该类型的页面。参见 [persistence-log-catalog Agent Note](../.agents/notes/archived/process/2026-07-04-persistence-log-catalog.md)。
|
||||
|
||||
以下信封声明组合了每个事件的 `type`、单调递增的 `seq`、以 epoch 毫秒表示的 `time`、`data`,以及条件字段 `surfaceOp`/`sourceEventSeqs`。**surface** 表示 `SurfaceEventType` 成员:它会生成一条 LLM(大语言模型)消息,并声明该事件如何加入 surface 列表。**log-only** 表示其他所有事件:这类记录可持久化、可回放,但不参与派生历史。每个 payload 均可进行 JSON 序列化(在 `Session.append` 处强制执行),整个格式固定为 `SESSION_FORMAT_VERSION = 0`:这是预发布格式,不暗示任何兼容性(参见[版本立场](subsystems/persistence.md))。范围仅限本仓库中的包;下游插件可以继续合并其他事件类型,而这些类型按设计不属于本目录。
|
||||
以下信封声明组合了每个事件的 `type`、单调递增的 `seq`、以 epoch 毫秒表示的 `time`、`data`、可选的未知类型跳过标记 `ignorable`,以及条件字段 `surfaceOp`/`sourceEventSeqs`。**surface** 表示 `SurfaceEventType` 成员:它会生成一条 LLM(大语言模型)消息,并声明该事件如何加入 surface 列表。**log-only** 表示其他所有事件:这类记录可持久化、可回放,但不参与派生历史。每个 payload 均可进行 JSON 序列化(在 `Session.append` 处强制执行),整个格式固定为 `SESSION_FORMAT_VERSION = 0`:这是预发布格式,不暗示任何兼容性(参见[版本立场](subsystems/persistence.md))。范围仅限本仓库中的包;下游插件可以继续合并其他事件类型,而这些类型按设计不属于本目录。
|
||||
|
||||
## 事件信封
|
||||
|
||||
@@ -65,6 +65,17 @@ export type SessionEvent<T extends SessionEventType = SessionEventType> = {
|
||||
/** Unix epoch milliseconds. */
|
||||
time: number
|
||||
data: SessionEventMap[K]
|
||||
/**
|
||||
* Marks an event a reader may safely skip when it does not recognize
|
||||
* `type`. Absent means required: a reader meeting an unrecognized type
|
||||
* without this marker MUST refuse to reconstruct the session instead of
|
||||
* silently dropping the event, because an unrecognized required event may
|
||||
* change how the rest of the log is interpreted. A writer sets `true` only
|
||||
* on purely informational records whose loss cannot affect reconstruction;
|
||||
* defaulting to required means a forgotten marker over-refuses (an
|
||||
* inconvenience) rather than silently resuming a gutted session.
|
||||
*/
|
||||
ignorable?: true
|
||||
} & (K extends SurfaceEventType ? {
|
||||
/**
|
||||
* Seq numbers of earlier events that this event cites as sources
|
||||
|
||||
6
docs/rescope.i18n.yaml
Normal file
6
docs/rescope.i18n.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/rescope.md
|
||||
rescope.md: 3dde39875021e7a4161e1ae66550e9dedf5eb4fa
|
||||
rescope.zh.md: a7f355cf651fb063bf2d4c3cefe18babd4a57401
|
||||
53
docs/rescope.md
Normal file
53
docs/rescope.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Vendored package rescope
|
||||
|
||||
English | [中文](rescope.zh.md)
|
||||
|
||||
The Cordis framework and its foundation libraries are vendored under [`vendor/`](../vendor/README.md) and published under the `@deepseek-ai` scope, because every harness package declares the framework as a peer dependency: publishing the harness publishes this layer with it, and under the upstream names that publication would squat them on the registry. This page is the name mapping; the decision and its consequences live in the [rescope Agent Note](../.agents/notes/implemented/process/2026-08-10-vendor-package-rescope.md), and the upstream commits in [`vendor/README.md`](../vendor/README.md).
|
||||
|
||||
## Name mapping
|
||||
|
||||
| Directory | Upstream name | Published name | Version | Role |
|
||||
|---|---|---|---|---|
|
||||
| `vendor/cordis/` | `cordis` | `@deepseek-ai/cordis` | 4.0.0-rc.7 | Framework core: `Context`, `Service`, `Fiber`, events |
|
||||
| `vendor/cosmokit/` | `cosmokit` | `@deepseek-ai/cosmokit` | 1.8.1 | Shared utilities the framework and Schemastery build on |
|
||||
| `vendor/schemastery/` | `schemastery` | `@deepseek-ai/schemastery` | 3.18.0 | Config schemas (`Schema`) behind every plugin's `Config` |
|
||||
| `vendor/loader/` | `@cordisjs/plugin-loader` | `@deepseek-ai/cordis-plugin-loader` | 1.0.0-rc.5 | `cordis.yml` loading, plugin resolution, repository cache |
|
||||
| `vendor/include/` | `@cordisjs/plugin-include` | `@deepseek-ai/cordis-plugin-include` | 1.0.4 | Config includes and patch overlays |
|
||||
| `vendor/group/` | `@cordisjs/plugin-group` | `@deepseek-ai/cordis-plugin-group` | 1.0.0 | Nested plugin groups |
|
||||
| `vendor/timer/` | `@cordisjs/plugin-timer` | `@deepseek-ai/cordis-plugin-timer` | 1.1.2 | Disposal-aware timers on `ctx` |
|
||||
| `vendor/hmr/` | `@cordisjs/plugin-hmr` | `@deepseek-ai/cordis-plugin-hmr` | 1.0.15 | Hot module replacement for plugins and config |
|
||||
| `vendor/logger-console/` | `@cordisjs/plugin-logger-console` | `@deepseek-ai/cordis-plugin-logger-console` | 1.0.0 | Console logger exporter |
|
||||
|
||||
Subpath exports keep their path: `@cordisjs/plugin-loader/repository` becomes `@deepseek-ai/cordis-plugin-loader/repository`.
|
||||
|
||||
## What the rename does not touch
|
||||
|
||||
- **Directory names and versions.** `vendor/hmr/` stays `vendor/hmr/`, and every package keeps the upstream version its manifest table row records, so the vendored tree still reads as an upstream snapshot.
|
||||
- **Dependency ranges.** A dependency entry changes its key, never its range: `"cordis": "^4.0.0-rc.7"` becomes `"@deepseek-ai/cordis": "^4.0.0-rc.7"`. `linkWorkspacePackages` resolves those preserved ranges to the pinned workspaces.
|
||||
- **The Loader's `cordis:` builtin prefix.** `cordis:include` and `cordis:group` are a protocol prefix, not a package name.
|
||||
- **The `cordis.yml` configuration family**, including `*.cordis.yml`, `*.cordis.snapshot.yml`, and `cordis.patch.yml`.
|
||||
- **Harness packages whose own names contain the word**, such as `@deepseek-ai/dsh-tool-cordis`.
|
||||
- **Upstream runtime identifiers**, such as Schemastery's `Symbol.for('schemastery')` and its `vendor:` metadata field.
|
||||
- **Prose outside `docs/`.** `vendor/*/README.md`, package READMEs, and Agent Notes keep the names they were written with; a bare `cordis` there can also be the Python SDK's option name or an agent-preset id. Inside `docs/`, prose and every Markdown fence follow the rename.
|
||||
|
||||
## What your code has to change
|
||||
|
||||
| Site | Before | After |
|
||||
|---|---|---|
|
||||
| Module import | `import { Context } from 'cordis'` | `import { Context } from '@deepseek-ai/cordis'` |
|
||||
| Typed-event merge | `declare module 'cordis'` | `declare module '@deepseek-ai/cordis'` |
|
||||
| `package.json` dependency key | `"@cordisjs/plugin-hmr": "^1.0.15"` | `"@deepseek-ai/cordis-plugin-hmr": "^1.0.15"` |
|
||||
| `cordis.yml` plugin entry | `name: '@cordisjs/plugin-include'` | `name: '@deepseek-ai/cordis-plugin-include'` |
|
||||
|
||||
## Applying, verifying, and reverting
|
||||
|
||||
[`scripts/rescope-vendor.ts`](../scripts/rescope-vendor.ts) owns the mapping above and performs the rename, so no reference is renamed by hand:
|
||||
|
||||
```sh
|
||||
pnpm run rescope-vendor # report what would change
|
||||
pnpm run rescope-vendor --apply # rewrite every reference
|
||||
pnpm run rescope-vendor:check # assert the post-state; runs in the hygiene gate
|
||||
pnpm run rescope-vendor --apply --reverse # return to the upstream names
|
||||
```
|
||||
|
||||
Re-apply it after an upstream sync ([procedure](../vendor/README.md)), and follow it with the regeneration it prints: `pnpm install` for the lockfile, `pnpm run gen-third-party-notices`, and `pnpm run verify-translation-pairing --write` for the bilingual pairs it touched.
|
||||
53
docs/rescope.zh.md
Normal file
53
docs/rescope.zh.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Vendored 包改名
|
||||
|
||||
[English](rescope.md) | 中文
|
||||
|
||||
Cordis 框架及其基础库以源码形式 vendored 在 [`vendor/`](../vendor/README.md) 下,并以 `@deepseek-ai` scope 发布:每个 harness 包都把框架声明为 peer dependency,发布 harness 就会连带发布这一层,用上游名发布等于在 registry 上占用别人的名字。本页是名字映射表;决策与影响见 [改名 Agent Note](../.agents/notes/implemented/process/2026-08-10-vendor-package-rescope.md),上游 commit 见 [`vendor/README.md`](../vendor/README.md)。
|
||||
|
||||
## 名字映射
|
||||
|
||||
| 目录 | 上游名 | 发布名 | 版本 | 角色 |
|
||||
|---|---|---|---|---|
|
||||
| `vendor/cordis/` | `cordis` | `@deepseek-ai/cordis` | 4.0.0-rc.7 | 框架核心:`Context`、`Service`、`Fiber`、事件 |
|
||||
| `vendor/cosmokit/` | `cosmokit` | `@deepseek-ai/cosmokit` | 1.8.1 | 框架与 Schemastery 共用的基础工具 |
|
||||
| `vendor/schemastery/` | `schemastery` | `@deepseek-ai/schemastery` | 3.18.0 | 配置 schema(`Schema`),每个插件的 `Config` 都基于它 |
|
||||
| `vendor/loader/` | `@cordisjs/plugin-loader` | `@deepseek-ai/cordis-plugin-loader` | 1.0.0-rc.5 | `cordis.yml` 装载、插件解析、repository 缓存 |
|
||||
| `vendor/include/` | `@cordisjs/plugin-include` | `@deepseek-ai/cordis-plugin-include` | 1.0.4 | 配置包含与 patch 叠加 |
|
||||
| `vendor/group/` | `@cordisjs/plugin-group` | `@deepseek-ai/cordis-plugin-group` | 1.0.0 | 嵌套插件分组 |
|
||||
| `vendor/timer/` | `@cordisjs/plugin-timer` | `@deepseek-ai/cordis-plugin-timer` | 1.1.2 | `ctx` 上随 disposal 回收的定时器 |
|
||||
| `vendor/hmr/` | `@cordisjs/plugin-hmr` | `@deepseek-ai/cordis-plugin-hmr` | 1.0.15 | 插件与配置的热替换 |
|
||||
| `vendor/logger-console/` | `@cordisjs/plugin-logger-console` | `@deepseek-ai/cordis-plugin-logger-console` | 1.0.0 | 控制台日志导出 |
|
||||
|
||||
子路径导出保持原路径:`@cordisjs/plugin-loader/repository` 变成 `@deepseek-ai/cordis-plugin-loader/repository`。
|
||||
|
||||
## 改名不碰什么
|
||||
|
||||
- **目录名与版本号。** `vendor/hmr/` 仍是 `vendor/hmr/`,每个包保留清单表那行记录的上游版本,所以 vendored 树依旧读作一份上游快照。
|
||||
- **依赖 range。** 依赖条目只换键、不换范围:`"cordis": "^4.0.0-rc.7"` 变成 `"@deepseek-ai/cordis": "^4.0.0-rc.7"`;`linkWorkspacePackages` 靠这些保留下来的范围把它们解析到固定的 workspace。
|
||||
- **Loader 的 `cordis:` 内建前缀。** `cordis:include`、`cordis:group` 是协议前缀,不是包名。
|
||||
- **`cordis.yml` 配置文件家族**,包括 `*.cordis.yml`、`*.cordis.snapshot.yml`、`cordis.patch.yml`。
|
||||
- **名字里带这个词的 harness 包**,例如 `@deepseek-ai/dsh-tool-cordis`。
|
||||
- **上游运行时标识符**,例如 Schemastery 的 `Symbol.for('schemastery')` 及其 `vendor:` 元数据字段。
|
||||
- **`docs/` 之外的散文。** `vendor/*/README.md`、各包 README 与 Agent Note 保留写作当时的名字;那里的裸 `cordis` 也可能是 Python SDK 的选项名或某个 agent-preset 的 id。`docs/` 之内,散文与所有 Markdown 围栏都跟着改。
|
||||
|
||||
## 你的代码要改什么
|
||||
|
||||
| 位置 | 改前 | 改后 |
|
||||
|---|---|---|
|
||||
| 模块 import | `import { Context } from 'cordis'` | `import { Context } from '@deepseek-ai/cordis'` |
|
||||
| 类型事件声明合并 | `declare module 'cordis'` | `declare module '@deepseek-ai/cordis'` |
|
||||
| `package.json` 依赖键 | `"@cordisjs/plugin-hmr": "^1.0.15"` | `"@deepseek-ai/cordis-plugin-hmr": "^1.0.15"` |
|
||||
| `cordis.yml` 插件条目 | `name: '@cordisjs/plugin-include'` | `name: '@deepseek-ai/cordis-plugin-include'` |
|
||||
|
||||
## 施加、核验与回退
|
||||
|
||||
上面这份映射由 [`scripts/rescope-vendor.ts`](../scripts/rescope-vendor.ts) 承载并执行改名,任何引用都不靠手改:
|
||||
|
||||
```sh
|
||||
pnpm run rescope-vendor # report what would change
|
||||
pnpm run rescope-vendor --apply # rewrite every reference
|
||||
pnpm run rescope-vendor:check # assert the post-state; runs in the hygiene gate
|
||||
pnpm run rescope-vendor --apply --reverse # return to the upstream names
|
||||
```
|
||||
|
||||
上游 sync 之后重跑它([流程](../vendor/README.md)),并接上它打印的重生成:`pnpm install` 重生成 lockfile、`pnpm run gen-third-party-notices`、以及对它触及的双语对跑 `pnpm run verify-translation-pairing --write`。
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/README.md
|
||||
README.md: 7d66cfcf66ffb0bed9430892308934c1f10982f4
|
||||
README.zh.md: 90e2b28b15870387539500568bb85b525db63ef6
|
||||
README.md: fddbf460c8e9e7c6f9ed1d3375bdabe65947661f
|
||||
README.zh.md: febc5a97426fef5ec4b2b80d9677957369994a3b
|
||||
|
||||
@@ -45,7 +45,7 @@ One page per subsystem of the DeepSeek Harness: what it is, the data structures
|
||||
| [http-server.md](http-server.md) | the HTTP carrier: `WebRouteKind`/`WebRoute`, match order, the claimable fallback seat, index taps |
|
||||
| [storage.md](storage.md) | the storage subsystem: the backend contract (`StorageBackend`), `StorageForms`, `DomainSpec`/`Domain`, `domain/changed` |
|
||||
| [workspace.md](workspace.md) | the workspace registry: `Workspace`/`WorkspaceId`, registration and resolution, the session `cwd` relationship |
|
||||
| [client-modules.md](client-modules.md) | the web plugin table: `dshClient` declarations, `WebBootGraph` wire composition, the bundle route and index tap |
|
||||
| [client-modules.md](client-modules.md) | the web plugin table: `dsh.client` declarations, `WebBootGraph` wire composition, the bundle route and index tap |
|
||||
| [session-projection.md](session-projection.md) | the projection seam: `SessionProjectionMap`, the pure `ProjectionDefinition` unit, `ProjectionSnapshot`'s consistent cut, the change feed |
|
||||
| [telemetry.md](telemetry.md) | the outbound session-reporting capability seam: `TelemetryRecord`/`TelemetrySeverity`, the `TelemetryBackend` contract, and the `telemetry/record` redact waterfall |
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
| [http-server.md](http-server.md) | HTTP 载体:`WebRouteKind`/`WebRoute`、匹配顺序、可认领的回退席位、index 转换 |
|
||||
| [storage.md](storage.md) | 存储子系统:后端约定(`StorageBackend`)、`StorageForms`、`DomainSpec`/`Domain`、`domain/changed` |
|
||||
| [workspace.md](workspace.md) | 工作区注册表:`Workspace`/`WorkspaceId`、注册与解析、与会话 `cwd` 的关系 |
|
||||
| [client-modules.md](client-modules.md) | Web 插件表:`dshClient` 声明、`WebBootGraph` 线上组合、bundle 路由与 index 转换 |
|
||||
| [client-modules.md](client-modules.md) | Web 插件表:`dsh.client` 声明、`WebBootGraph` 线上组合、bundle 路由与 index 转换 |
|
||||
| [session-projection.md](session-projection.md) | 投影 seam:`SessionProjectionMap`、纯函数 `ProjectionDefinition` 单元、`ProjectionSnapshot` 的一致切面、变更馈送 |
|
||||
| [telemetry.md](telemetry.md) | 对外会话上报能力 seam:`TelemetryRecord`/`TelemetrySeverity`、`TelemetryBackend` 约定和 `telemetry/record` 脱敏 waterfall |
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/client-modules.md
|
||||
client-modules.md: 808fa62b2e5a4351b1dc98bbe4f3d2af63c9dd2b
|
||||
client-modules.zh.md: dcab60bea7c54770cc5e6032afb39d6dd189d037
|
||||
client-modules.md: 14fa5b2ca94c109a8c6bbe2ce09bde73a4448769
|
||||
client-modules.zh.md: 7c4df1689dc8df27f7e394763e3bde4320d5c632
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
English | [中文](client-modules.zh.md)
|
||||
|
||||
The web plugin table: the Node half of the client module system in [dsh-client-modules](../../packages/client/modules), provided as `ctx.clientModuleHost` (`ClientModuleHostService`). It scans the host Loader's entries for `dshClient` packages, composes the `window.__DSH_BOOT__` entry graph, serves each bundle at `/plugins/<id>/client.js`, and taps the index render to inject the boot manifest — the four faces of one service. It is an optional capability of the web GUI stack, not part of the agent-loop spine, and it is a consumer of [dsh-host-webserver](../../packages/host/webserver): the carrier described in [http-server.md](http-server.md) supplies the prefix route and index tap this service registers. The same package's browser half (`ctx.modules`, the lazy-CJS module table that fetches and materializes these bundles) is kernel machinery documented in the [package README](../../packages/client/modules/README.md), not here.
|
||||
The web plugin table: the Node half of the client module system in [dsh-client-modules](../../packages/client/modules), provided as `ctx.clientModuleHost` (`ClientModuleHostService`). It scans the host Loader's entries for packages declaring `dsh.client`, composes the `window.__DSH_BOOT__` entry graph, serves each bundle at `/plugins/<id>/client.js`, and taps the index render to inject the boot manifest — the four faces of one service. It is an optional capability of the web GUI stack, not part of the agent-loop spine, and it is a consumer of [dsh-host-webserver](../../packages/host/webserver): the carrier described in [http-server.md](http-server.md) supplies the prefix route and index tap this service registers. The same package's browser half (`ctx.modules`, the lazy-CJS module table that fetches and materializes these bundles) is kernel machinery documented in the [package README](../../packages/client/modules/README.md), not here.
|
||||
|
||||
Source: [`packages/client/modules/src/client/manifest.ts`](../../packages/client/modules/src/client/manifest.ts)
|
||||
|
||||
@@ -15,7 +15,7 @@ The graph is the wire single source between the Node and browser halves: the hos
|
||||
* One composed client entry pushed by the host (a graph row). Wire
|
||||
* single source: the host node half (package root) produces this same shape.
|
||||
* `immediately` marks stage-one prefetch; `inject` is informational graph
|
||||
* metadata (the authoritative edges live in each package's dshClient
|
||||
* metadata (the authoritative edges live in each package's `dsh.client`
|
||||
* declaration and reach fibers through entry creation).
|
||||
*/
|
||||
interface WebBootEntry {
|
||||
@@ -46,7 +46,7 @@ Each row's `rev` is the bundle's content hash and rides the URL as a cache-busti
|
||||
|
||||
## The scan
|
||||
|
||||
A package joins the table by declaring `dshClient` (`platform: 'web'`, optional `inject` edges, optional `immediately`) in its package.json and exporting its built bundle at `exports["./client"]`. Package resolution anchors at the config tree's `ctx.baseUrl` — the cordis.yml directory, whose package declares every composed plugin as a dependency — and construction throws when that anchor is unset.
|
||||
A package joins the table by declaring `dsh.client` (`platform: 'web'`, optional `inject` edges, optional `immediately`) in its package.json and exporting its built bundle at `exports["./client"]`. Package resolution anchors at the config tree's `ctx.baseUrl` — the cordis.yml directory, whose package declares every composed plugin as a dependency — and construction throws when that anchor is unset.
|
||||
|
||||
Scanning is incremental per package; there is no full-rescan code path. Every cordis `internal/plugin` emission (fiber construction or disposal) marks the fiber's entry name dirty, and a microtask flush reconciles each dirty name against the live loader entries. The activation pass seeds the same dirty set with all current entries and flushes synchronously, so first scan and steady state share one implementation — with opposite failure postures. At activation, a malformed declaration or missing bundle among the already-loaded entries aggregates into one loud `AggregateError` listing every broken package: the fiber FAILS and the boot's fail-loud sweep reports it. In steady state, a broken package logs a warning and must not poison the others.
|
||||
|
||||
@@ -74,7 +74,7 @@ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnp
|
||||
|
||||
### `ctx.clientModuleHost` — `ClientModuleHostService`
|
||||
|
||||
The web plugin table service: incremental dshClient scan + wire composition + bundle route + index tap. Construction runs the activation scan synchronously — a malformed declaration or missing bundle among the already-loaded entries aggregates into one loud throw (FAILED fiber; the boot activation audit reports it).
|
||||
The web plugin table service: incremental `dsh.client` scan + wire composition + bundle route + index tap. Construction runs the activation scan synchronously — a malformed declaration or missing bundle among the already-loaded entries aggregates into one loud throw (FAILED fiber; the boot activation audit reports it).
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](client-modules.md) | 中文
|
||||
|
||||
Web 插件表:[dsh-client-modules](../../packages/client/modules) 中 client 模块系统的 Node 半,以 `ctx.clientModuleHost`(`ClientModuleHostService`)形式提供。它扫描宿主 Loader 的 entry 找出 `dshClient` 包(package),组合出 `window.__DSH_BOOT__` entry 图,在 `/plugins/<id>/client.js` 提供各个 bundle,并经 index 转换(index tap)注入启动 manifest(元数据清单)——这是同一个服务的四个面。它是 Web GUI 栈的一项可选能力,不属于 agent loop(智能体循环)主干,并且是 [dsh-host-webserver](../../packages/host/webserver) 的消费方:[http-server.md](http-server.md) 所述的载体提供本服务注册的前缀路由与 index 转换。同一个包的浏览器半(`ctx.modules`,即拉取并物化这些 bundle 的 lazy CJS 模块表)属于内核机件,记录在[包 README](../../packages/client/modules/README.md)中,不在本页。
|
||||
Web 插件表:[dsh-client-modules](../../packages/client/modules) 中 client 模块系统的 Node 半,以 `ctx.clientModuleHost`(`ClientModuleHostService`)形式提供。它扫描宿主 Loader 的 entry,找出声明了 `dsh.client` 的包(package),组合出 `window.__DSH_BOOT__` entry 图,在 `/plugins/<id>/client.js` 提供各个 bundle,并经 index 转换(index tap)注入启动 manifest(元数据清单)——这是同一个服务的四个面。它是 Web GUI 栈的一项可选能力,不属于 agent loop(智能体循环)主干,并且是 [dsh-host-webserver](../../packages/host/webserver) 的消费方:[http-server.md](http-server.md) 所述的载体提供本服务注册的前缀路由与 index 转换。同一个包的浏览器半(`ctx.modules`,即拉取并物化这些 bundle 的 lazy CJS 模块表)属于内核机件,记录在[包 README](../../packages/client/modules/README.md)中,不在本页。
|
||||
|
||||
源码:[`packages/client/modules/src/client/manifest.ts`](../../packages/client/modules/src/client/manifest.ts)
|
||||
|
||||
@@ -15,7 +15,7 @@ Web 插件表:[dsh-client-modules](../../packages/client/modules) 中 client
|
||||
* One composed client entry pushed by the host (a graph row). Wire
|
||||
* single source: the host node half (package root) produces this same shape.
|
||||
* `immediately` marks stage-one prefetch; `inject` is informational graph
|
||||
* metadata (the authoritative edges live in each package's dshClient
|
||||
* metadata (the authoritative edges live in each package's `dsh.client`
|
||||
* declaration and reach fibers through entry creation).
|
||||
*/
|
||||
interface WebBootEntry {
|
||||
@@ -46,7 +46,7 @@ interface WebBootGraph {
|
||||
|
||||
## 扫描
|
||||
|
||||
包加入这张表的方式,是在自己的 package.json 中声明 `dshClient`(`platform: 'web'`、可选的 `inject` 边、可选的 `immediately`),并在 `exports["./client"]` 导出构建好的 bundle。包解析锚定在配置树的 `ctx.baseUrl`——即 cordis.yml 所在目录,该目录的包把每个被组合的插件声明为依赖——这一锚点未设置时,构造即抛错。
|
||||
包加入这张表的方式,是在自己的 package.json 中声明 `dsh.client`(`platform: 'web'`、可选的 `inject` 边、可选的 `immediately`),并在 `exports["./client"]` 导出构建好的 bundle。包解析锚定在配置树的 `ctx.baseUrl`——即 cordis.yml 所在目录,该目录的包把每个被组合的插件声明为依赖——这一锚点未设置时,构造即抛错。
|
||||
|
||||
扫描是单包增量的;不存在全量重扫代码路径。fiber 构造或 dispose(资源释放)时的每次 cordis `internal/plugin` 发射都把该 fiber 的 entry 名标脏,一次微任务 flush 把每个脏名与实时 loader entry 对账。激活趟以全部当前 entry 灌入同一个脏集合并同步 flush,因此初扫与稳态共享一条实现——但失败姿态相反。激活时,已加载 entry 中的畸形声明或缺失 bundle 会聚合为一个大声的 `AggregateError`,列出每个损坏的包:该 fiber 进入 FAILED,由启动的大声失败 sweep 上报。稳态下,损坏的包只记录一条警告,且不得殃及其他包。
|
||||
|
||||
@@ -74,7 +74,7 @@ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnp
|
||||
|
||||
### `ctx.clientModuleHost` — `ClientModuleHostService`
|
||||
|
||||
The web plugin table service: incremental dshClient scan + wire composition + bundle route + index tap. Construction runs the activation scan synchronously — a malformed declaration or missing bundle among the already-loaded entries aggregates into one loud throw (FAILED fiber; the boot activation audit reports it).
|
||||
The web plugin table service: incremental `dsh.client` scan + wire composition + bundle route + index tap. Construction runs the activation scan synchronously — a malformed declaration or missing bundle among the already-loaded entries aggregates into one loud throw (FAILED fiber; the boot activation audit reports it).
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/core.md
|
||||
core.md: 75f55fe5b1837576ba79564b9aee7e289f5f16f4
|
||||
core.zh.md: 7cd55b41c8f1358a89c6f35a4d3f733ccd8550ee
|
||||
core.md: ad00c4da7d77b0e1ab4728173b202ebc17fb56a0
|
||||
core.zh.md: 9c606023c85369643e7148f829526b1f75ea3631
|
||||
|
||||
@@ -419,6 +419,45 @@ async resolve(id?: string): Promise<AgentPreset>
|
||||
*/
|
||||
async mount(agentCtx: Context, id?: string): Promise<AgentPreset>
|
||||
|
||||
/**
|
||||
* Join one agent to the SAME standing composition another already runs on.
|
||||
*
|
||||
* This is how a child agent inherits its parent's capabilities. It is a bind,
|
||||
* not a mount: the parent's generation is already composed, so the child gets
|
||||
* that exact instance — the same plugin objects, the same tool registrations,
|
||||
* the same prompt sections. Re-resolving the parent's preset by id instead
|
||||
* would re-read the roster, and a composition file edited since the parent
|
||||
* started would hand the child a DIFFERENT generation than the one its
|
||||
* parent's history was produced under (and a preset deleted since would fail
|
||||
* the child outright while its parent keeps running).
|
||||
*
|
||||
* Synchronous, and with no composition failure mode of its own — it reads no
|
||||
* roster, mounts nothing, and touches no file — which is what lets a child
|
||||
* creation window use it: the two in-process subagent drivers compose their
|
||||
* children inside a synchronous `setup`. It still rejects a caller error, as
|
||||
* the `@throws` below record.
|
||||
*
|
||||
* A parent that joined no preset — a rosterless deployment — yields no join
|
||||
* and no error: there, the model-facing rows sit in the host composition and
|
||||
* the child already sees them through the global layer.
|
||||
* @param agentCtx - the joining agent's scope context.
|
||||
* @param parentCtx - the scope context of the agent whose composition to join.
|
||||
* @returns the preset id joined, or undefined when the parent joined none.
|
||||
* @throws when `agentCtx` carries no scope, or has already joined a preset.
|
||||
*/
|
||||
composeFrom(agentCtx: Context, parentCtx: Context): string | undefined
|
||||
|
||||
/**
|
||||
* The preset one live agent runs on.
|
||||
*
|
||||
* Read from the live scope chain rather than from the session, so it answers
|
||||
* for an agent whose session has not recorded a preset yet — a child agent
|
||||
* whose durable header is being built from its parent's composition.
|
||||
* @param agentCtx - the agent's scope context.
|
||||
* @returns the preset id, or undefined when the agent joined none.
|
||||
*/
|
||||
composedPreset(agentCtx: Context): string | undefined
|
||||
|
||||
/**
|
||||
* Read one preset's composition text.
|
||||
* @param id - the preset id.
|
||||
|
||||
@@ -427,6 +427,45 @@ async resolve(id?: string): Promise<AgentPreset>
|
||||
*/
|
||||
async mount(agentCtx: Context, id?: string): Promise<AgentPreset>
|
||||
|
||||
/**
|
||||
* Join one agent to the SAME standing composition another already runs on.
|
||||
*
|
||||
* This is how a child agent inherits its parent's capabilities. It is a bind,
|
||||
* not a mount: the parent's generation is already composed, so the child gets
|
||||
* that exact instance — the same plugin objects, the same tool registrations,
|
||||
* the same prompt sections. Re-resolving the parent's preset by id instead
|
||||
* would re-read the roster, and a composition file edited since the parent
|
||||
* started would hand the child a DIFFERENT generation than the one its
|
||||
* parent's history was produced under (and a preset deleted since would fail
|
||||
* the child outright while its parent keeps running).
|
||||
*
|
||||
* Synchronous, and with no composition failure mode of its own — it reads no
|
||||
* roster, mounts nothing, and touches no file — which is what lets a child
|
||||
* creation window use it: the two in-process subagent drivers compose their
|
||||
* children inside a synchronous `setup`. It still rejects a caller error, as
|
||||
* the `@throws` below record.
|
||||
*
|
||||
* A parent that joined no preset — a rosterless deployment — yields no join
|
||||
* and no error: there, the model-facing rows sit in the host composition and
|
||||
* the child already sees them through the global layer.
|
||||
* @param agentCtx - the joining agent's scope context.
|
||||
* @param parentCtx - the scope context of the agent whose composition to join.
|
||||
* @returns the preset id joined, or undefined when the parent joined none.
|
||||
* @throws when `agentCtx` carries no scope, or has already joined a preset.
|
||||
*/
|
||||
composeFrom(agentCtx: Context, parentCtx: Context): string | undefined
|
||||
|
||||
/**
|
||||
* The preset one live agent runs on.
|
||||
*
|
||||
* Read from the live scope chain rather than from the session, so it answers
|
||||
* for an agent whose session has not recorded a preset yet — a child agent
|
||||
* whose durable header is being built from its parent's composition.
|
||||
* @param agentCtx - the agent's scope context.
|
||||
* @returns the preset id, or undefined when the agent joined none.
|
||||
*/
|
||||
composedPreset(agentCtx: Context): string | undefined
|
||||
|
||||
/**
|
||||
* Read one preset's composition text.
|
||||
* @param id - the preset id.
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/filesystem.md
|
||||
filesystem.md: 3c154af0fa4ee6d28f2379c5392dcc9b194a2c99
|
||||
filesystem.zh.md: 5b8a136af156c63de72e260d5859d8bac7b827c5
|
||||
filesystem.md: 00e28130db9f60e6ad5f8c582ca5531482cdeb32
|
||||
filesystem.zh.md: 5cf6be12f41b36c8149a941a4d251c4497ed4738
|
||||
|
||||
@@ -136,10 +136,11 @@ interface FsWriteOutcome {
|
||||
version: FsVersion
|
||||
/**
|
||||
* The file's content BEFORE the write, or `null` when the file did not exist
|
||||
* (a create) or was undiffable (binary/non-UTF-8). LF-normalized storage text
|
||||
* (the diff basis), never a diff — a consumer computes the result-time
|
||||
* contextual diff from `before`/`after` when `before` is present, else falls
|
||||
* back to a whole-file diff.
|
||||
* (a create) or the backend declined a contextual basis (for example, a
|
||||
* binary/non-UTF-8 prior file or either overwrite side reaching its exclusive limit).
|
||||
* LF-normalized storage text (the diff basis), never a diff — a consumer
|
||||
* computes the result-time contextual diff from `before`/`after` when
|
||||
* `before` is present, else falls back to a whole-file diff.
|
||||
*/
|
||||
before: string | null
|
||||
/** The file's content AFTER the write, LF-normalized to share `before`'s diff basis. */
|
||||
|
||||
@@ -136,10 +136,11 @@ interface FsWriteOutcome {
|
||||
version: FsVersion
|
||||
/**
|
||||
* The file's content BEFORE the write, or `null` when the file did not exist
|
||||
* (a create) or was undiffable (binary/non-UTF-8). LF-normalized storage text
|
||||
* (the diff basis), never a diff — a consumer computes the result-time
|
||||
* contextual diff from `before`/`after` when `before` is present, else falls
|
||||
* back to a whole-file diff.
|
||||
* (a create) or the backend declined a contextual basis (for example, a
|
||||
* binary/non-UTF-8 prior file or either overwrite side reaching its exclusive limit).
|
||||
* LF-normalized storage text (the diff basis), never a diff — a consumer
|
||||
* computes the result-time contextual diff from `before`/`after` when
|
||||
* `before` is present, else falls back to a whole-file diff.
|
||||
*/
|
||||
before: string | null
|
||||
/** The file's content AFTER the write, LF-normalized to share `before`'s diff basis. */
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/persistence.md
|
||||
persistence.md: 363d28034b58d007d1440afcb8fb9137b0048091
|
||||
persistence.zh.md: e208720eae1902ad429fa358c112fe9188f8d8dd
|
||||
persistence.md: 62729a66154f1b1656ac7575f0fcbb3099544c3d
|
||||
persistence.zh.md: 1e0a9869291e212c8a4942514ab541cabb57783c
|
||||
|
||||
@@ -87,6 +87,10 @@ interface SessionHeader {
|
||||
}
|
||||
```
|
||||
|
||||
## Format refusal — logs a build cannot faithfully read
|
||||
|
||||
A backend refuses a log it cannot faithfully interpret with `SessionFormatUnsupportedError`, distinct from `SessionPersistenceCorruptionError` because nothing is damaged. A header `version` ahead of `SESSION_FORMAT_VERSION` names the direction ("written by a newer harness — upgrade the harness to open it"); one behind it states that this build ships no upgrade path. After legacy-shape normalization, an event type outside this build's generated vocabulary (`KNOWN_SESSION_EVENT_TYPES`, emitted by `gen-persistence-catalog`) refuses the same way unless the event's envelope carries `ignorable: true` — silently skipping an unrecognized required event could change how the rest of the log must be read. The message appends the raw log path when the backend keeps one artifact per session, so the refused text stays reachable. The JSONL backend refuses a foreign version straight from the raw header line, before validating today's header shape or decoding any event row — a structurally different future format still reports the upgrade direction, never "corrupt"; SQLite gates whole-file structure through its own `SCHEMA_VERSION` pragma first. Design rationale and the deferred upgrader chain live in the [session-log-version-mechanism note](../../.agents/notes/implemented/architecture/2026-08-10-session-log-version-mechanism.md).
|
||||
|
||||
## `CreateSessionOptions` — seeding and metadata
|
||||
|
||||
Creating a `Session` through the store takes a `seed` (initial replay or fork history) and `meta` (the storage-level fields the store folds into a `SessionHeader`). The store fills in `version`/`id` and defaults `createdAt`; the caller may supply the validated absolute `cwd`, the `parentSession` lineage, the `seedLength` seed boundary, the optional coarse `origin`, the `delegationDepth`, the `agentPreset` the agent was composed from, and an existing `createdAt`. `origin: 'subagent'` lets product navigation hide duplicate child rows; it does not prove that a descriptor is valid or that the child can resume.
|
||||
@@ -373,5 +377,5 @@ abstract listSnapshots(signal?: AbortSignal): Promise<SessionPersistenceSnapshot
|
||||
|
||||
Types: [SessionEvent](session.md) · [SessionId](core.md)
|
||||
|
||||
Source: [`packages/session/session-persistence/src/index.ts:82`](../../packages/session/session-persistence/src/index.ts)
|
||||
Source: [`packages/session/session-persistence/src/index.ts:84`](../../packages/session/session-persistence/src/index.ts)
|
||||
<!-- END GENERATED cordis-surface -->
|
||||
|
||||
@@ -87,6 +87,10 @@ interface SessionHeader {
|
||||
}
|
||||
```
|
||||
|
||||
## 格式拒绝:本构建无法可靠读取的日志
|
||||
|
||||
后端用 `SessionFormatUnsupportedError` 拒绝无法可靠解读的日志,它与 `SessionPersistenceCorruptionError` 区分,因为数据没有损坏。header 的 `version` 比 `SESSION_FORMAT_VERSION` 新时,消息说明方向("由更新的 harness 写入,请升级 harness 后打开");比它旧时说明本构建没有升级路径。经过 legacy 形状归一化后,本构建生成词汇表(`KNOWN_SESSION_EVENT_TYPES`,由 `gen-persistence-catalog` 生成)之外的事件类型同样被拒绝,除非该事件的信封带 `ignorable: true`:静默跳过一个不认识的必需事件可能改变日志其余部分的解读方式。后端为每个会话保留独立文件时,消息附上原始日志路径,被拒绝的文本仍然可读。JSONL 后端直接从原始 header 行拒绝外来版本,先于当前 header 形状校验和任何事件行解码,因此结构完全不同的未来格式仍会报告升级方向,绝不会报"损坏";SQLite 则先由自己的 `SCHEMA_VERSION` pragma 把关整个文件的结构。设计理由与推迟建设的升级器链见 [session-log 版本机制 Agent Note](../../.agents/notes/implemented/architecture/2026-08-10-session-log-version-mechanism.md)。
|
||||
|
||||
## `CreateSessionOptions`:seed 与元数据
|
||||
|
||||
通过 store 创建 `Session` 时会接收 `seed`(初始回放或 fork 历史)与 `meta`(store 折叠进 `SessionHeader` 的存储层字段)。store 填充 `version`/`id` 并为 `createdAt` 提供默认值;调用方可以提供已校验的绝对 `cwd`、`parentSession` 谱系、`seedLength` 种子边界、可选的粗粒度 `origin`、`delegationDepth`、该 agent 所依据组装的 `agentPreset` 以及已有的 `createdAt`。`origin: 'subagent'` 让产品导航能够隐藏重复的 child 行;它不证明描述符有效,也不证明 child 可以恢复。
|
||||
@@ -373,5 +377,5 @@ abstract listSnapshots(signal?: AbortSignal): Promise<SessionPersistenceSnapshot
|
||||
|
||||
Types: [SessionEvent](session.md) · [SessionId](core.md)
|
||||
|
||||
Source: [`packages/session/session-persistence/src/index.ts:82`](../../packages/session/session-persistence/src/index.ts)
|
||||
Source: [`packages/session/session-persistence/src/index.ts:84`](../../packages/session/session-persistence/src/index.ts)
|
||||
<!-- END GENERATED cordis-surface -->
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/session.md
|
||||
session.md: 0b78e51ebf6e2ad5c312268ad4bfb4392b0486df
|
||||
session.zh.md: d1e91f684a835e08406f524efe876baa1a6a72cb
|
||||
session.md: 990b249cde9f02343f2c668aee5d7c000837df56
|
||||
session.zh.md: 39e8ff1e8831fd75c8929c93e263622bb5aa6ea4
|
||||
|
||||
@@ -215,6 +215,17 @@ type SessionEvent<T extends SessionEventType = SessionEventType> = {
|
||||
/** Unix epoch milliseconds. */
|
||||
time: number
|
||||
data: SessionEventMap[K]
|
||||
/**
|
||||
* Marks an event a reader may safely skip when it does not recognize
|
||||
* `type`. Absent means required: a reader meeting an unrecognized type
|
||||
* without this marker MUST refuse to reconstruct the session instead of
|
||||
* silently dropping the event, because an unrecognized required event may
|
||||
* change how the rest of the log is interpreted. A writer sets `true` only
|
||||
* on purely informational records whose loss cannot affect reconstruction;
|
||||
* defaulting to required means a forgotten marker over-refuses (an
|
||||
* inconvenience) rather than silently resuming a gutted session.
|
||||
*/
|
||||
ignorable?: true
|
||||
} & (K extends SurfaceEventType ? {
|
||||
/**
|
||||
* Seq numbers of earlier events that this event cites as sources
|
||||
@@ -733,7 +744,7 @@ fork(source: SessionForkSource, boundary?: number, childSessionId?: SessionId):
|
||||
|
||||
Types: [CreateSessionOptions](persistence.md) · [PrepareSessionOptions](persistence.md) · [SessionId](core.md)
|
||||
|
||||
Source: [`packages/core/session/src/index.ts:810`](../../packages/core/session/src/index.ts)
|
||||
Source: [`packages/core/session/src/index.ts:813`](../../packages/core/session/src/index.ts)
|
||||
|
||||
<a id="session-events"></a>
|
||||
|
||||
@@ -762,7 +773,7 @@ Creation announcement during session publication. A synchronous throw vetoes and
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/session/src/index.ts:74`](../../packages/core/session/src/index.ts)
|
||||
Source: [`packages/core/session/src/index.ts:75`](../../packages/core/session/src/index.ts)
|
||||
|
||||
<a id="sessiondisposed--emit"></a>
|
||||
|
||||
@@ -785,7 +796,7 @@ Emitted once when an announced session leaves the store, including publication r
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/session/src/index.ts:84`](../../packages/core/session/src/index.ts)
|
||||
Source: [`packages/core/session/src/index.ts:85`](../../packages/core/session/src/index.ts)
|
||||
|
||||
<a id="sessionevent--emit"></a>
|
||||
|
||||
@@ -810,7 +821,7 @@ Post-commit, fire-and-forget append feed. The listener snapshot resolves before
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/session/src/index.ts:96`](../../packages/core/session/src/index.ts)
|
||||
Source: [`packages/core/session/src/index.ts:97`](../../packages/core/session/src/index.ts)
|
||||
|
||||
<a id="sessionflush--parallel"></a>
|
||||
|
||||
@@ -832,5 +843,5 @@ Awaited parallel durability checkpoint: every listener runs and the caller await
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/session/src/index.ts:105`](../../packages/core/session/src/index.ts)
|
||||
Source: [`packages/core/session/src/index.ts:106`](../../packages/core/session/src/index.ts)
|
||||
<!-- END GENERATED cordis-surface -->
|
||||
|
||||
@@ -217,6 +217,17 @@ type SessionEvent<T extends SessionEventType = SessionEventType> = {
|
||||
/** Unix epoch milliseconds. */
|
||||
time: number
|
||||
data: SessionEventMap[K]
|
||||
/**
|
||||
* Marks an event a reader may safely skip when it does not recognize
|
||||
* `type`. Absent means required: a reader meeting an unrecognized type
|
||||
* without this marker MUST refuse to reconstruct the session instead of
|
||||
* silently dropping the event, because an unrecognized required event may
|
||||
* change how the rest of the log is interpreted. A writer sets `true` only
|
||||
* on purely informational records whose loss cannot affect reconstruction;
|
||||
* defaulting to required means a forgotten marker over-refuses (an
|
||||
* inconvenience) rather than silently resuming a gutted session.
|
||||
*/
|
||||
ignorable?: true
|
||||
} & (K extends SurfaceEventType ? {
|
||||
/**
|
||||
* Seq numbers of earlier events that this event cites as sources
|
||||
@@ -737,7 +748,7 @@ fork(source: SessionForkSource, boundary?: number, childSessionId?: SessionId):
|
||||
|
||||
Types: [CreateSessionOptions](persistence.md) · [PrepareSessionOptions](persistence.md) · [SessionId](core.md)
|
||||
|
||||
Source: [`packages/core/session/src/index.ts:810`](../../packages/core/session/src/index.ts)
|
||||
Source: [`packages/core/session/src/index.ts:813`](../../packages/core/session/src/index.ts)
|
||||
|
||||
<a id="session-events"></a>
|
||||
|
||||
@@ -766,7 +777,7 @@ Creation announcement during session publication. A synchronous throw vetoes and
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/session/src/index.ts:74`](../../packages/core/session/src/index.ts)
|
||||
Source: [`packages/core/session/src/index.ts:75`](../../packages/core/session/src/index.ts)
|
||||
|
||||
<a id="sessiondisposed--emit"></a>
|
||||
|
||||
@@ -789,7 +800,7 @@ Emitted once when an announced session leaves the store, including publication r
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/session/src/index.ts:84`](../../packages/core/session/src/index.ts)
|
||||
Source: [`packages/core/session/src/index.ts:85`](../../packages/core/session/src/index.ts)
|
||||
|
||||
<a id="sessionevent--emit"></a>
|
||||
|
||||
@@ -814,7 +825,7 @@ Post-commit, fire-and-forget append feed. The listener snapshot resolves before
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/session/src/index.ts:96`](../../packages/core/session/src/index.ts)
|
||||
Source: [`packages/core/session/src/index.ts:97`](../../packages/core/session/src/index.ts)
|
||||
|
||||
<a id="sessionflush--parallel"></a>
|
||||
|
||||
@@ -836,5 +847,5 @@ Awaited parallel durability checkpoint: every listener runs and the caller await
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/session/src/index.ts:105`](../../packages/core/session/src/index.ts)
|
||||
Source: [`packages/core/session/src/index.ts:106`](../../packages/core/session/src/index.ts)
|
||||
<!-- END GENERATED cordis-surface -->
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/subagent.md
|
||||
subagent.md: 961a16f58cb936205290d23ce6b9d94cb94607d5
|
||||
subagent.zh.md: ac97d27d9824ca62701e11ae99264adbddafbbd8
|
||||
subagent.md: 42359215b2e21028e13734c2a4cd2488f86a07af
|
||||
subagent.zh.md: 0d1d4c42fa774867679ff248bfc99b0024b04257
|
||||
|
||||
@@ -293,7 +293,12 @@ The outcome of a one-shot run, resolved by `SubagentRun.result`. `structured` is
|
||||
* The terminal outcome of a subagent run, resolved by {@link SubagentRun.result}.
|
||||
*/
|
||||
interface SubagentResult {
|
||||
/** The child's final assistant output (the last assistant message's content). */
|
||||
/**
|
||||
* The child's final assistant output is the content of its last non-empty
|
||||
* assistant message. Empty-content messages, including usage-only messages,
|
||||
* are skipped. Without a non-empty message, the output is its accumulated
|
||||
* assistant text stream, or `[]` when the child produced neither.
|
||||
*/
|
||||
readonly output: ContentBlock[]
|
||||
/**
|
||||
* The structured result after a requested `outputSchema` was successfully
|
||||
@@ -614,7 +619,7 @@ async start(name: string, request: SubagentStartRequest): Promise<SubagentRun>
|
||||
|
||||
Types: [Agent](core.md) · [ContentBlock](llm-streaming.md) · [MessageId](llm-streaming.md) · [SessionId](core.md)
|
||||
|
||||
Source: [`packages/subagent/subagent/src/index.ts:167`](../../packages/subagent/subagent/src/index.ts)
|
||||
Source: [`packages/subagent/subagent/src/index.ts:170`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagent-events"></a>
|
||||
|
||||
@@ -640,7 +645,7 @@ A published child settled. Scope-filtered dispatch uses the same delegating pare
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/subagent/subagent/src/index.ts:162`](../../packages/subagent/subagent/src/index.ts)
|
||||
Source: [`packages/subagent/subagent/src/index.ts:165`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagentprovider-added--emit"></a>
|
||||
|
||||
@@ -657,7 +662,7 @@ A provider became resolvable in the registry.
|
||||
'subagent/provider-added'(provider: SubagentProvider): void
|
||||
```
|
||||
|
||||
Source: [`packages/subagent/subagent/src/index.ts:136`](../../packages/subagent/subagent/src/index.ts)
|
||||
Source: [`packages/subagent/subagent/src/index.ts:139`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagentprovider-removed--emit"></a>
|
||||
|
||||
@@ -674,7 +679,7 @@ A provider left the registry. Accepted runs remain holder-owned.
|
||||
'subagent/provider-removed'(name: string): void
|
||||
```
|
||||
|
||||
Source: [`packages/subagent/subagent/src/index.ts:142`](../../packages/subagent/subagent/src/index.ts)
|
||||
Source: [`packages/subagent/subagent/src/index.ts:145`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagentstart--emit"></a>
|
||||
|
||||
@@ -698,5 +703,5 @@ A provider established a published child. For in-process providers, `ctx.agents.
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/subagent/subagent/src/index.ts:153`](../../packages/subagent/subagent/src/index.ts)
|
||||
Source: [`packages/subagent/subagent/src/index.ts:156`](../../packages/subagent/subagent/src/index.ts)
|
||||
<!-- END GENERATED cordis-surface -->
|
||||
|
||||
@@ -293,7 +293,12 @@ type SubagentDescendantListEntry = SubagentListEntry & {
|
||||
* The terminal outcome of a subagent run, resolved by {@link SubagentRun.result}.
|
||||
*/
|
||||
interface SubagentResult {
|
||||
/** The child's final assistant output (the last assistant message's content). */
|
||||
/**
|
||||
* The child's final assistant output is the content of its last non-empty
|
||||
* assistant message. Empty-content messages, including usage-only messages,
|
||||
* are skipped. Without a non-empty message, the output is its accumulated
|
||||
* assistant text stream, or `[]` when the child produced neither.
|
||||
*/
|
||||
readonly output: ContentBlock[]
|
||||
/**
|
||||
* The structured result after a requested `outputSchema` was successfully
|
||||
@@ -616,7 +621,7 @@ async start(name: string, request: SubagentStartRequest): Promise<SubagentRun>
|
||||
|
||||
Types: [Agent](core.md) · [ContentBlock](llm-streaming.md) · [MessageId](llm-streaming.md) · [SessionId](core.md)
|
||||
|
||||
Source: [`packages/subagent/subagent/src/index.ts:167`](../../packages/subagent/subagent/src/index.ts)
|
||||
Source: [`packages/subagent/subagent/src/index.ts:170`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagent-events"></a>
|
||||
|
||||
@@ -642,7 +647,7 @@ A published child settled. Scope-filtered dispatch uses the same delegating pare
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/subagent/subagent/src/index.ts:162`](../../packages/subagent/subagent/src/index.ts)
|
||||
Source: [`packages/subagent/subagent/src/index.ts:165`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagentprovider-added--emit"></a>
|
||||
|
||||
@@ -659,7 +664,7 @@ A provider became resolvable in the registry.
|
||||
'subagent/provider-added'(provider: SubagentProvider): void
|
||||
```
|
||||
|
||||
Source: [`packages/subagent/subagent/src/index.ts:136`](../../packages/subagent/subagent/src/index.ts)
|
||||
Source: [`packages/subagent/subagent/src/index.ts:139`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagentprovider-removed--emit"></a>
|
||||
|
||||
@@ -676,7 +681,7 @@ A provider left the registry. Accepted runs remain holder-owned.
|
||||
'subagent/provider-removed'(name: string): void
|
||||
```
|
||||
|
||||
Source: [`packages/subagent/subagent/src/index.ts:142`](../../packages/subagent/subagent/src/index.ts)
|
||||
Source: [`packages/subagent/subagent/src/index.ts:145`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagentstart--emit"></a>
|
||||
|
||||
@@ -700,5 +705,5 @@ A provider established a published child. For in-process providers, `ctx.agents.
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/subagent/subagent/src/index.ts:153`](../../packages/subagent/subagent/src/index.ts)
|
||||
Source: [`packages/subagent/subagent/src/index.ts:156`](../../packages/subagent/subagent/src/index.ts)
|
||||
<!-- END GENERATED cordis-surface -->
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/system-prompt.md
|
||||
system-prompt.md: bdc0e994fb8e784a19814574c405d8cc3dce2d11
|
||||
system-prompt.zh.md: db6932b18f4721020fed567d49727f863eb06608
|
||||
system-prompt.md: 56617ef9d3d8da89673a4624abcef73e58d72cab
|
||||
system-prompt.zh.md: cafea4f9689879b3fd8d0e1fff7249fcb02a7c12
|
||||
|
||||
@@ -39,7 +39,7 @@ interface ToolProviderResult {
|
||||
|
||||
## Prompt sections
|
||||
|
||||
`PromptSection` is a readonly same-process registration contract. Its text may be static or resolved from the current assembly context.
|
||||
`PromptSection` is a readonly same-process registration contract. Its text may be static or resolved from the current assembly context. One effective `complete` section becomes the sole prompt section after cooperative assembly.
|
||||
|
||||
```ts type-equiv
|
||||
/** One contributed section of the system prompt (registry input). */
|
||||
@@ -58,6 +58,13 @@ interface PromptSection {
|
||||
* interpolated later, by {@link renderPrompt}.
|
||||
*/
|
||||
readonly text: string | ((context: AssembleContext) => string)
|
||||
/**
|
||||
* Treat this contribution as the complete system prompt. Assembly still
|
||||
* runs the cooperative waterfall so tools, contexts, and variables can be
|
||||
* resolved, then restores this exact section as the sole prompt section.
|
||||
* More than one effective complete section makes assembly fail.
|
||||
*/
|
||||
readonly complete?: boolean
|
||||
}
|
||||
```
|
||||
|
||||
@@ -132,14 +139,16 @@ variable(name: string, provider: (context: AssembleContext) => string | undefine
|
||||
/**
|
||||
* Assemble global and scoped providers, detach tool parameters, apply
|
||||
* canonical ordering, then run the assembly waterfall. Scoped sections and
|
||||
* variables shadow globals; the returned waterfall value is authoritative.
|
||||
* variables shadow globals. The returned waterfall value is authoritative
|
||||
* except that an effective complete section is restored afterwards as the
|
||||
* sole prompt section.
|
||||
* @param context - the optional scope and plugin-defined assembly fields.
|
||||
* @returns the authoritative post-waterfall assembly.
|
||||
* @returns the post-waterfall assembly with any complete prompt enforced.
|
||||
*/
|
||||
async assemble(context: AssembleContext = {}): Promise<PromptAssembly>
|
||||
```
|
||||
|
||||
Source: [`packages/core/system-prompt/src/index.ts:325`](../../packages/core/system-prompt/src/index.ts)
|
||||
Source: [`packages/core/system-prompt/src/index.ts:334`](../../packages/core/system-prompt/src/index.ts)
|
||||
|
||||
<a id="system-prompt-events"></a>
|
||||
|
||||
@@ -149,7 +158,7 @@ Source: [`packages/core/system-prompt/src/index.ts:325`](../../packages/core/sys
|
||||
|
||||
#### `system-prompt/assemble` — waterfall
|
||||
|
||||
Expert waterfall over the assembled sections, contexts, tools, and variables. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): scoped listeners receive only that scope's assemblies. The returned value is authoritative. A supplied signal controls only this explicit assembly request and must not be retained to control later turns.
|
||||
Expert waterfall over the assembled sections, contexts, tools, and variables. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): scoped listeners receive only that scope's assemblies. The returned value is authoritative. A supplied signal controls only this explicit assembly request and must not be retained to control later turns. A registered complete section is restored after this waterfall, so listeners cannot add to or replace that scope's system prompt.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
@@ -157,7 +166,9 @@ Expert waterfall over the assembled sections, contexts, tools, and variables. Sc
|
||||
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): scoped listeners
|
||||
* receive only that scope's assemblies. The returned value is authoritative.
|
||||
* A supplied signal controls only this explicit assembly request and must not
|
||||
* be retained to control later turns.
|
||||
* be retained to control later turns. A registered complete section is
|
||||
* restored after this waterfall, so listeners cannot add to or replace
|
||||
* that scope's system prompt.
|
||||
* @param assembly - the mutable assembly built from registered providers.
|
||||
* @param context - the caller's per-assembly context.
|
||||
* @mode waterfall
|
||||
@@ -167,7 +178,7 @@ Expert waterfall over the assembled sections, contexts, tools, and variables. Sc
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/system-prompt/src/index.ts:29`](../../packages/core/system-prompt/src/index.ts)
|
||||
Source: [`packages/core/system-prompt/src/index.ts:31`](../../packages/core/system-prompt/src/index.ts)
|
||||
|
||||
<a id="system-promptchange--emit"></a>
|
||||
|
||||
@@ -184,5 +195,5 @@ Emitted when any prompt provider changes. This registry notification is unfilter
|
||||
'system-prompt/change'(): void
|
||||
```
|
||||
|
||||
Source: [`packages/core/system-prompt/src/index.ts:35`](../../packages/core/system-prompt/src/index.ts)
|
||||
Source: [`packages/core/system-prompt/src/index.ts:37`](../../packages/core/system-prompt/src/index.ts)
|
||||
<!-- END GENERATED cordis-surface -->
|
||||
|
||||
@@ -39,7 +39,7 @@ interface ToolProviderResult {
|
||||
|
||||
## 提示词段落
|
||||
|
||||
`PromptSection` 是一份只读的同进程注册约定。其文本可以是静态的,也可以从当前组装上下文动态解析。
|
||||
`PromptSection` 是一份只读的同进程注册约定。其文本可以是静态的,也可以从当前组装上下文动态解析。协作式组装完成后,一个有效的 `complete` 段会成为唯一的提示词段落。
|
||||
|
||||
```ts type-equiv
|
||||
/** One contributed section of the system prompt (registry input). */
|
||||
@@ -58,6 +58,13 @@ interface PromptSection {
|
||||
* interpolated later, by {@link renderPrompt}.
|
||||
*/
|
||||
readonly text: string | ((context: AssembleContext) => string)
|
||||
/**
|
||||
* Treat this contribution as the complete system prompt. Assembly still
|
||||
* runs the cooperative waterfall so tools, contexts, and variables can be
|
||||
* resolved, then restores this exact section as the sole prompt section.
|
||||
* More than one effective complete section makes assembly fail.
|
||||
*/
|
||||
readonly complete?: boolean
|
||||
}
|
||||
```
|
||||
|
||||
@@ -132,14 +139,16 @@ variable(name: string, provider: (context: AssembleContext) => string | undefine
|
||||
/**
|
||||
* Assemble global and scoped providers, detach tool parameters, apply
|
||||
* canonical ordering, then run the assembly waterfall. Scoped sections and
|
||||
* variables shadow globals; the returned waterfall value is authoritative.
|
||||
* variables shadow globals. The returned waterfall value is authoritative
|
||||
* except that an effective complete section is restored afterwards as the
|
||||
* sole prompt section.
|
||||
* @param context - the optional scope and plugin-defined assembly fields.
|
||||
* @returns the authoritative post-waterfall assembly.
|
||||
* @returns the post-waterfall assembly with any complete prompt enforced.
|
||||
*/
|
||||
async assemble(context: AssembleContext = {}): Promise<PromptAssembly>
|
||||
```
|
||||
|
||||
Source: [`packages/core/system-prompt/src/index.ts:325`](../../packages/core/system-prompt/src/index.ts)
|
||||
Source: [`packages/core/system-prompt/src/index.ts:334`](../../packages/core/system-prompt/src/index.ts)
|
||||
|
||||
<a id="system-prompt-events"></a>
|
||||
|
||||
@@ -149,7 +158,7 @@ Source: [`packages/core/system-prompt/src/index.ts:325`](../../packages/core/sys
|
||||
|
||||
#### `system-prompt/assemble` — waterfall
|
||||
|
||||
Expert waterfall over the assembled sections, contexts, tools, and variables. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): scoped listeners receive only that scope's assemblies. The returned value is authoritative. A supplied signal controls only this explicit assembly request and must not be retained to control later turns.
|
||||
Expert waterfall over the assembled sections, contexts, tools, and variables. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): scoped listeners receive only that scope's assemblies. The returned value is authoritative. A supplied signal controls only this explicit assembly request and must not be retained to control later turns. A registered complete section is restored after this waterfall, so listeners cannot add to or replace that scope's system prompt.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
@@ -157,7 +166,9 @@ Expert waterfall over the assembled sections, contexts, tools, and variables. Sc
|
||||
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): scoped listeners
|
||||
* receive only that scope's assemblies. The returned value is authoritative.
|
||||
* A supplied signal controls only this explicit assembly request and must not
|
||||
* be retained to control later turns.
|
||||
* be retained to control later turns. A registered complete section is
|
||||
* restored after this waterfall, so listeners cannot add to or replace
|
||||
* that scope's system prompt.
|
||||
* @param assembly - the mutable assembly built from registered providers.
|
||||
* @param context - the caller's per-assembly context.
|
||||
* @mode waterfall
|
||||
@@ -167,7 +178,7 @@ Expert waterfall over the assembled sections, contexts, tools, and variables. Sc
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/system-prompt/src/index.ts:29`](../../packages/core/system-prompt/src/index.ts)
|
||||
Source: [`packages/core/system-prompt/src/index.ts:31`](../../packages/core/system-prompt/src/index.ts)
|
||||
|
||||
<a id="system-promptchange--emit"></a>
|
||||
|
||||
@@ -184,5 +195,5 @@ Emitted when any prompt provider changes. This registry notification is unfilter
|
||||
'system-prompt/change'(): void
|
||||
```
|
||||
|
||||
Source: [`packages/core/system-prompt/src/index.ts:35`](../../packages/core/system-prompt/src/index.ts)
|
||||
Source: [`packages/core/system-prompt/src/index.ts:37`](../../packages/core/system-prompt/src/index.ts)
|
||||
<!-- END GENERATED cordis-surface -->
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/telemetry.md
|
||||
telemetry.md: 5ea5c67210ce1387cbd886935e914baf7f904fbb
|
||||
telemetry.zh.md: bd8fc8acc4c8522d8b1e4bc543431c0abf224411
|
||||
telemetry.md: 97694a9a5a209224087d0d8454d83e29ce568ea4
|
||||
telemetry.zh.md: 9e8b17f4bddb3debdf4dff9d3c3fed1296ebf3d7
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
English | [中文](telemetry.zh.md)
|
||||
|
||||
Outbound session reporting is one [capability seam](../capability-seams.md): its Service Definition ([dsh-session-telemetry](../../packages/session/session-telemetry), `ctx.telemetry`) declares the minimal backend contract, and its capture coordinator owns the capture points, fixed chunk projection, `telemetry/record` redaction waterfall, and handoff cursor; the Service provider a deployment loads ([dsh-session-telemetry-otel](../../packages/session/session-telemetry-otel)) uses the OpenTelemetry JS SDK's log pipeline with its configuration unchanged. This optional capability is not part of the agent loop, and nothing here reaches a model request. The harness stops after it calls `emit()`; the reporting SDK owns batching, retry, queueing, and loss policy. The [revival Agent Note](../../.agents/notes/implemented/feature/2026-07-23-session-telemetry-otel-revival.md) records that rule and the rejected alternatives. The [Service Definition README](../../packages/session/session-telemetry/README.md) defines the capture-point, cursor, and projection contracts.
|
||||
Outbound session reporting is split as a [capability seam](../capability-seams.md): the Service Definition and capture coordinator ([dsh-session-telemetry](../../packages/session/session-telemetry), `ctx.telemetry`) own the capture points, fixed chunk projection, `telemetry/record` redaction waterfall, handoff cursor, and minimal backend contract; the Service provider a deployment loads ([dsh-session-telemetry-otel](../../packages/session/session-telemetry-otel)) is the OpenTelemetry JS SDK's log pipeline configured verbatim. It is one optional capability, not part of the agent-loop spine, and nothing here reaches a model request. The boundary axiom — the harness's aspect ends at `emit()`; batching, retry, queueing, and loss policy belong to the reporting SDK — and the rejected alternatives are pinned in the [revival Agent Note](../../.agents/notes/implemented/feature/2026-07-23-session-telemetry-otel-revival.md); the capture points, cursor, and projection contracts live in the [Service Definition README](../../packages/session/session-telemetry/README.md).
|
||||
|
||||
Source: [`packages/session/session-telemetry/src/index.ts`](../../packages/session/session-telemetry/src/index.ts)
|
||||
|
||||
@@ -56,6 +56,21 @@ interface TelemetryRecord {
|
||||
|
||||
Only the first `assistant/chunk` of each `(turn, step)` ships — the stream-started signal; the rest drop at capture, so `seq` gaps are routine on the wire and never a loss signal. Every other [session event](session.md) type, including plugin-merged ones the seam never heard of, passes through whole. Delivery is best-effort: the cursor marks handed-off, not delivered, records can be lost (crash, reload window) and duplicated (cursor-less re-adoption, SDK retries), so receivers dedupe ledger records on `(session.id, event.seq)`; ops records deliberately omit that identity — they are signals to alert on, not entries to sum, and tolerate duplicates instead.
|
||||
|
||||
## The sharing disclosure
|
||||
|
||||
The seam's acknowledgement contract (owned by the [Service Definition README's sharing-disclosure section](../../packages/session/session-telemetry/README.md#the-sharing-disclosure)): every backend discloses its deployment-selected sharing policy through the required abstract `sharing` member on `ctx.telemetry`, and consumers render "not configured" only when no telemetry service is mounted. The disclosure states the current policy, never delivery or retention — handoff is the non-blocking enqueue, and batching, retry, and loss policy stay the reporting SDK's.
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
* Deployment-selected session-sharing policy disclosed by a mounted
|
||||
* {@link Telemetry} backend to human-facing acknowledgement surfaces (the
|
||||
* `/feedback` command's confirmation text). The seam owns the vocabulary so
|
||||
* any backend can disclose a policy without depending on the OTel package;
|
||||
* the values mirror the OTel backend's serialized `TelemetryMode` choices.
|
||||
*/
|
||||
type TelemetrySharingStatus = 'full' | 'feedback-only' | 'disabled'
|
||||
```
|
||||
|
||||
## The backend contract
|
||||
|
||||
```ts type-equiv
|
||||
@@ -104,7 +119,7 @@ interface TelemetryBackend {
|
||||
}
|
||||
```
|
||||
|
||||
`Telemetry` (`ctx.telemetry`, [signatures](#ctxtelemetry--telemetry-abstract-seam)) is the loadable form of this contract: each context accepts one implementation and throws on a duplicate. A backend constructs `TelemetryCoordinator` in its constructor to install capture.
|
||||
`Telemetry` (`ctx.telemetry`, [signatures](#ctxtelemetry--telemetry-abstract-seam)) is the contract's loadable form — one implementation per context, duplicate load throws — and a backend composes the seam's `TelemetryCoordinator` in its constructor to install the capture side.
|
||||
|
||||
## The redact waterfall: `telemetry/record`
|
||||
|
||||
@@ -141,7 +156,7 @@ flush?(): void
|
||||
abstract shutdown(): Promise<void>
|
||||
```
|
||||
|
||||
Source: [`packages/session/session-telemetry/src/index.ts:139`](../../packages/session/session-telemetry/src/index.ts)
|
||||
Source: [`packages/session/session-telemetry/src/index.ts:148`](../../packages/session/session-telemetry/src/index.ts)
|
||||
|
||||
<a id="telemetry-events"></a>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](telemetry.md) | 中文
|
||||
|
||||
对外会话上报是一项[能力 seam](../capability-seams.md):其 Service Definition([dsh-session-telemetry](../../packages/session/session-telemetry),`ctx.telemetry`)声明最小后端约定,其捕获协调器负责捕获点、固定分片投影、`telemetry/record` 脱敏 waterfall(瀑布式事件)和 handoff 游标;部署方加载的 Service provider([dsh-session-telemetry-otel](../../packages/session/session-telemetry-otel))按原配置使用 OpenTelemetry JS SDK 日志流水线。这项能力可选,不属于 agent loop(智能体循环),这里也没有任何内容会进入模型请求。Harness 调用 `emit()` 后停止处理;上报 SDK 负责批处理、重试、排队和丢失策略。[复活 Agent Note](../../.agents/notes/implemented/feature/2026-07-23-session-telemetry-otel-revival.md)记录了这条规则和被否决的替代方案。[Service Definition README](../../packages/session/session-telemetry/README.md) 定义捕获点、游标和投影约定。
|
||||
对外的会话上报拆分为一项[能力 seam](../capability-seams.md):Service Definition 与捕获协调器([dsh-session-telemetry](../../packages/session/session-telemetry),`ctx.telemetry`)拥有捕获点、固定分片投影、`telemetry/record` 脱敏 waterfall(瀑布式事件)、handoff 游标与最小后端约定;部署方加载的 Service provider([dsh-session-telemetry-otel](../../packages/session/session-telemetry-otel))则是原样配置的 OpenTelemetry JS SDK 日志流水线。它是一项可选能力,不属于 agent loop(智能体循环)主干,这里也没有任何内容会进入模型请求。边界公理(harness 的职责止于 `emit()`;批处理、重试、排队与丢失策略都属于上报 SDK)连同被否决的替代方案,均已在[复活 Agent Note(agent 决策记录)](../../.agents/notes/implemented/feature/2026-07-23-session-telemetry-otel-revival.md)中定案;捕获点、游标与投影的约定见 [Service Definition README](../../packages/session/session-telemetry/README.md)。
|
||||
|
||||
源码:[`packages/session/session-telemetry/src/index.ts`](../../packages/session/session-telemetry/src/index.ts)
|
||||
|
||||
@@ -56,6 +56,21 @@ interface TelemetryRecord {
|
||||
|
||||
每个 `(turn, step)` 只发出第一条 `assistant/chunk`,即「流已开始」的信号;其余分片在捕获时丢弃,因此导出流中的 `seq` 缺口是常态,绝不是丢失信号。其他所有[会话事件](session.md)类型都会完整透传,包括该 seam 从未听说过、由插件合并进来的事件类型。投递是尽力而为的:游标标记的是「已交接」而非「已送达」,记录可能丢失(崩溃、重载窗口)也可能重复(无游标的重新接管、SDK 重试),因此接收端对 ledger 记录基于 `(session.id, event.seq)` 去重;ops 记录刻意省略这类标识——它们是用于告警的信号,而非用于累加的条目,重复被容忍而非被去重。
|
||||
|
||||
## 共享披露
|
||||
|
||||
该 seam 的确认契约(归属 [Service Definition README 的共享披露段](../../packages/session/session-telemetry/README.md#the-sharing-disclosure)):每个后端都通过 `ctx.telemetry` 上必需的抽象 `sharing` 成员披露其部署级共享策略,消费方只有在未挂载任何遥测服务时才渲染「未配置」。披露只陈述当前策略,绝不承诺投递或留存——交接是非阻塞入队,批处理、重试与丢失策略仍归上报 SDK。
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
* Deployment-selected session-sharing policy disclosed by a mounted
|
||||
* {@link Telemetry} backend to human-facing acknowledgement surfaces (the
|
||||
* `/feedback` command's confirmation text). The seam owns the vocabulary so
|
||||
* any backend can disclose a policy without depending on the OTel package;
|
||||
* the values mirror the OTel backend's serialized `TelemetryMode` choices.
|
||||
*/
|
||||
type TelemetrySharingStatus = 'full' | 'feedback-only' | 'disabled'
|
||||
```
|
||||
|
||||
## 后端约定
|
||||
|
||||
```ts type-equiv
|
||||
@@ -104,7 +119,7 @@ interface TelemetryBackend {
|
||||
}
|
||||
```
|
||||
|
||||
`Telemetry`(`ctx.telemetry`,[签名](#ctxtelemetry--telemetry-abstract-seam))是该约定的可加载类型:每个上下文只允许一个实现,重复加载会抛出异常。后端在构造函数中创建 `TelemetryCoordinator`,以安装捕获处理。
|
||||
`Telemetry`(`ctx.telemetry`,[签名](#ctxtelemetry--telemetry-abstract-seam))是该约定的可加载形态:每个上下文只允许一个实现,重复加载会抛出异常;后端在其构造函数中组合 seam 的 `TelemetryCoordinator`,以此装配捕获侧。
|
||||
|
||||
## 脱敏 waterfall:`telemetry/record`
|
||||
|
||||
@@ -141,7 +156,7 @@ flush?(): void
|
||||
abstract shutdown(): Promise<void>
|
||||
```
|
||||
|
||||
Source: [`packages/session/session-telemetry/src/index.ts:139`](../../packages/session/session-telemetry/src/index.ts)
|
||||
Source: [`packages/session/session-telemetry/src/index.ts:148`](../../packages/session/session-telemetry/src/index.ts)
|
||||
|
||||
<a id="telemetry-events"></a>
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/tools.md
|
||||
tools.md: f8d86704a2237219530c8c23b46a68383458e1cf
|
||||
tools.zh.md: 87269e5532b0cdfb0a38501d7b98c9986665df1d
|
||||
tools.md: 6ff2d967c5631d096dd78236ffd0383ddb2b0493
|
||||
tools.zh.md: 82ade5d8d4117387138296cf54fbc8e88ad335e7
|
||||
|
||||
@@ -150,19 +150,20 @@ type InferArgs<S> = InferProperties<S, []>
|
||||
|
||||
Registration is a trusted same-process contract. The registry borrows the typed definition as readonly input, requires `output`, validates its raw schema, and checks semantic requirements such as a positive finite `timeoutMs`; `schemas()` constructs the model-facing projection when building a request, so execution and presentation share one resolved definition without leaking callbacks onto the wire.
|
||||
|
||||
## `ToolRestriction` — one scope's live global filter
|
||||
## `ToolRestriction` — one scope's live filter over what it inherits
|
||||
|
||||
`ToolRestriction` applies only to the live deployment-global tool layer. The registry compiles readonly names into private sets, intersects multiple restrictions, then overlays scope-local tools. A deny-only filter admits later unlisted globals, while an allow-list excludes them.
|
||||
`ToolRestriction` applies to the tools a scope inherits: the deployment-global layer plus every ancestor scope on its chain. The registry compiles readonly names into private sets, intersects multiple restrictions, then overlays the scope's OWN registrations, which stay exempt so a delegated child keeps the tools it answers through. A deny-only filter admits later unlisted inherited tools, while an allow-list excludes them.
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
* Per-scope filter over global tools. Restrictions intersect and do not affect
|
||||
* scoped registrations or the reserved Code Mode transport.
|
||||
* Per-scope filter over the tools a scope INHERITS — the global layer and
|
||||
* every ancestor layer on its chain. Restrictions intersect, and do not affect
|
||||
* the scope's own registrations or the reserved Code Mode transport.
|
||||
*/
|
||||
interface ToolRestriction {
|
||||
/** Global tool names that stay visible; everything else is removed. */
|
||||
/** Inherited tool names that stay visible; every other inherited one is removed. */
|
||||
readonly allow?: readonly string[]
|
||||
/** Global tool names removed from visibility. */
|
||||
/** Inherited tool names removed from visibility. */
|
||||
readonly deny?: readonly string[]
|
||||
}
|
||||
```
|
||||
@@ -565,7 +566,7 @@ async execute(exec: ToolExecutionInput): Promise<ToolExecutionResult>
|
||||
|
||||
Types: [ScopeKey](scope.md)
|
||||
|
||||
Source: [`packages/core/tools/src/index.ts:760`](../../packages/core/tools/src/index.ts)
|
||||
Source: [`packages/core/tools/src/index.ts:761`](../../packages/core/tools/src/index.ts)
|
||||
|
||||
<a id="tools-events"></a>
|
||||
|
||||
|
||||
@@ -150,19 +150,20 @@ type InferArgs<S> = InferProperties<S, []>
|
||||
|
||||
注册是一项受信任的同进程约定。注册表以 readonly 输入借用已类型化定义,要求它声明 `output`,校验其原始 schema,并检查 `timeoutMs` 必须为正有限值等语义要求;`schemas()` 在构建请求时生成面向模型的投影,使执行和展示共享同一份已解析定义,而不会将回调泄漏到协议上。
|
||||
|
||||
## `ToolRestriction` — 单个作用域的实时全局过滤器
|
||||
## `ToolRestriction` — 单个作用域对其继承内容的实时过滤器
|
||||
|
||||
`ToolRestriction` 仅作用于实时的部署全局工具层。注册表将 readonly 名称编译为私有集合,对多个限制取交集,再叠加作用域本地工具。仅 deny 的过滤器允许后续未列出的全局工具通过,而 allow 列表则排除它们。
|
||||
`ToolRestriction` 作用于该作用域继承来的工具:部署全局层,加上其链上的每个祖先作用域。注册表将 readonly 名称编译为私有集合,对多个限制取交集,再叠加该作用域**自身**的注册——后者不受约束,因此被委派的子 agent 会保留其回报所依赖的工具。仅 deny 的过滤器允许后续未列出的继承工具通过,而 allow 列表则排除它们。
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
* Per-scope filter over global tools. Restrictions intersect and do not affect
|
||||
* scoped registrations or the reserved Code Mode transport.
|
||||
* Per-scope filter over the tools a scope INHERITS — the global layer and
|
||||
* every ancestor layer on its chain. Restrictions intersect, and do not affect
|
||||
* the scope's own registrations or the reserved Code Mode transport.
|
||||
*/
|
||||
interface ToolRestriction {
|
||||
/** Global tool names that stay visible; everything else is removed. */
|
||||
/** Inherited tool names that stay visible; every other inherited one is removed. */
|
||||
readonly allow?: readonly string[]
|
||||
/** Global tool names removed from visibility. */
|
||||
/** Inherited tool names removed from visibility. */
|
||||
readonly deny?: readonly string[]
|
||||
}
|
||||
```
|
||||
@@ -565,7 +566,7 @@ async execute(exec: ToolExecutionInput): Promise<ToolExecutionResult>
|
||||
|
||||
Types: [ScopeKey](scope.md)
|
||||
|
||||
Source: [`packages/core/tools/src/index.ts:760`](../../packages/core/tools/src/index.ts)
|
||||
Source: [`packages/core/tools/src/index.ts:761`](../../packages/core/tools/src/index.ts)
|
||||
|
||||
<a id="tools-events"></a>
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/testing.md
|
||||
testing.md: f5e8a478ec86c29c52f4127c51682c1c44fd23a7
|
||||
testing.zh.md: bd1fa7d23263d7c6e3bed65ef4ed09576ca47cc1
|
||||
testing.md: f330bb1e02f3613c63f3989a8f9128f737bf5c52
|
||||
testing.zh.md: db6facb4fa4bf07eda0a6ee7e558c8c60d4c331e
|
||||
|
||||
@@ -9,7 +9,7 @@ How this repo tests, tier by tier, and the rules that keep a green suite meaning
|
||||
- **Unit** (`pnpm run test`): vitest over package and example specs under their `tests/**` directories plus repository script specs under `scripts/**/*.spec.ts`; tests stay with the code area they exercise. Every registry gets an HMR-safety test (dispose the contributing fiber, assert cleanup). Prefer edge cases, error paths, event ordering, concurrency races, and permanent tests for contract regressions (see `packages/core/agent-loop/tests/contract-regressions.spec.ts`).
|
||||
- **Coverage gate** (`pnpm run test:coverage`): the gating run, per-file 100% on `packages/*/*/src`. An uncovered line is often dead code the gate is correctly flagging for deletion, not a missing test to bolt on. Line coverage is necessary, never sufficient — it proves lines ran, not that the feature works as shipped. Per-file 100% on `packages/bash/pwsh-local/src` needs a real `pwsh`: without one its executor suites self-skip and `vitest.config.ts` exempts the file so pwsh-less hosts stay green, while CI runners ship pwsh and enforce the full bar.
|
||||
- **Real-API e2e** (`pnpm run test:e2e`): with-key tests against live provider APIs — the DeepSeek model plus provider-specific smokes that gate on their own keys (`EXA_API_KEY`, `PERPLEXITY_API_KEY`, …); each suite self-skips without its key so keyless CI stays green ([real-API e2e Agent Note](../.agents/notes/implemented/testing/2026-06-19-real-api-e2e-ci.md)).
|
||||
- **Snapshot** (`pnpm run test:snapshot`): keyless expected outputs cover external behavior — transport contracts and presentation, while persisted logs pin assembled backend behavior. ACP boots the real automation-server example, replays a recorded session, and diffs normalized JSON-RPC plus the re-persisted log ([ACP snapshot Agent Note](../.agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.md)); headless backend scenarios boot their explicit example composition through an unexported JSONL test driver, while `apps/cli` separately owns product `dsh run` acceptance. Use `pnpm run test:snapshot:record` when a model transcript changes and `pnpm run test:snapshot:refresh` when replay input remains valid; review every JSONL and expected-output diff. One ACP scenario (`text-turn`) pins full system-prompt/tool-schema content; other fixtures tokenize it so an edit churns one line ([pinned-header Agent Note](../.agents/notes/archived/testing/2026-07-06-pin-request-header-content-in-one-scenario.md)).
|
||||
- **Snapshot** (`pnpm run test:snapshot`): keyless expected outputs cover external behavior — transport contracts and presentation, while persisted logs pin assembled backend behavior. ACP boots the real automation-server example, replays a recorded session, and diffs normalized JSON-RPC plus the re-persisted log ([ACP snapshot Agent Note](../.agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.md)); headless backend scenarios boot their explicit example composition through an unexported JSONL test driver, while `apps/cli` separately owns product `dsh --profile headless` acceptance. Use `pnpm run test:snapshot:record` when a model transcript changes and `pnpm run test:snapshot:refresh` when replay input remains valid; review every JSONL and expected-output diff. One ACP scenario (`text-turn`) pins full system-prompt/tool-schema content; other fixtures tokenize it so an edit churns one line ([pinned-header Agent Note](../.agents/notes/archived/testing/2026-07-06-pin-request-header-content-in-one-scenario.md)).
|
||||
- **Web browser snapshot** (`pnpm run test:web`; required Linux PR gate): Chromium compares replayed browser output with `apps/web/tests/snapshots/`. CI forces read-only `DSH_SNAPSHOT=replay`, never writing expected outputs; record/refresh stay local and every diff is reviewed ([web e2e lane](../.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.md), [CI gate decision](../.agents/notes/implemented/testing/2026-07-30-web-browser-snapshot-ci-gate.md)). `test:web` [builds first](../.agents/notes/implemented/bug-fix/2026-07-28-themed-scrollbars-and-reserved-gutter.md) for plugin CSS.
|
||||
|
||||
Committed session-format JSONL uses the canonical packed-row layout, and the keyless snapshot gate discovers every such fixture by its `session` header; the [temporary migrator](../scripts/migrate-packed-session-fixtures.ts) rewrites older fixture layouts.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
- **单元测试**(`pnpm run test`):vitest 运行包(package)和示例各自的 `tests/**` 目录下的测试,以及匹配 `scripts/**/*.spec.ts` 的仓库脚本测试;测试文件与其所覆盖的代码区域放在一起。每个注册表都有一个 HMR(热模块替换)安全测试(dispose(资源释放)贡献的 fiber,断言清理完成)。优先覆盖边界情况、错误路径、事件顺序、并发竞态,以及针对约定回归的永久测试(见 `packages/core/agent-loop/tests/contract-regressions.spec.ts`)。
|
||||
- **覆盖率门禁**(`pnpm run test:coverage`):门禁级运行,对 `packages/*/*/src` 按文件 100% 覆盖。未覆盖的行往往是门禁正确标记出的死代码(应删除),而非需要补写的测试。行覆盖率是必要条件,但永远不是充分条件:它证明行被执行过,不证明功能按交付预期工作。`packages/bash/pwsh-local/src` 的按文件 100% 覆盖需要真实的 `pwsh`:缺少它时其 executor 套件会自动跳过,`vitest.config.ts` 会豁免该文件以使无 pwsh 的主机保持绿色,而 CI runner 自带 pwsh,仍按完整标准执行门禁。
|
||||
- **真实 API e2e**(`pnpm run test:e2e`):带密钥测试调用真实提供方 API,包括 DeepSeek 模型以及各提供方特有的冒烟测试;这些测试各自由自己的密钥控制(`EXA_API_KEY`、`PERPLEXITY_API_KEY` 等),缺少密钥时套件会自动跳过,使 keyless CI 保持绿色([真实 API e2e Agent Note](../.agents/notes/implemented/testing/2026-06-19-real-api-e2e-ci.md))。
|
||||
- **快照**(`pnpm run test:snapshot`):无密钥预期输出覆盖对外行为(传输约定与呈现),持久化日志则固定组装后的后端行为。ACP 启动真实的自动化服务器示例、回放录制会话,并对归一化 JSON-RPC 与重新持久化的日志执行 diff([ACP 快照 Agent Note](../.agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.md));headless 后端场景通过未导出的 JSONL 测试 driver 启动各自显式的示例组装,而 `apps/cli` 则单独负责产品 CLI(命令行界面)`dsh run` 的验收。当模型 transcript(文本记录)发生变化时使用 `pnpm run test:snapshot:record`,回放输入仍然有效时使用 `pnpm run test:snapshot:refresh`;请审查每一处 JSONL 与预期输出差异。一个 ACP 场景(`text-turn`)固定完整的系统提示词与工具 schema 内容;其他 fixture(测试前置数据)将其 token 化,因此修改只会扰动一行([pinned-header Agent Note](../.agents/notes/archived/testing/2026-07-06-pin-request-header-content-in-one-scenario.md))。
|
||||
- **快照**(`pnpm run test:snapshot`):无密钥预期输出覆盖对外行为(传输约定与呈现),持久化日志则固定组装后的后端行为。ACP 启动真实的自动化服务器示例、回放录制会话,并对归一化 JSON-RPC 与重新持久化的日志执行 diff([ACP 快照 Agent Note](../.agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.md));headless 后端场景通过未导出的 JSONL 测试 driver 启动各自显式的示例组装,而 `apps/cli` 则单独负责产品 CLI(命令行界面)`dsh --profile headless` 的验收。当模型 transcript(文本记录)发生变化时使用 `pnpm run test:snapshot:record`,回放输入仍然有效时使用 `pnpm run test:snapshot:refresh`;请审查每一处 JSONL 与预期输出差异。一个 ACP 场景(`text-turn`)固定完整的系统提示词与工具 schema 内容;其他 fixture(测试前置数据)将其 token 化,因此修改只会扰动一行([pinned-header Agent Note](../.agents/notes/archived/testing/2026-07-06-pin-request-header-content-in-one-scenario.md))。
|
||||
- **Web 浏览器快照**(`pnpm run test:web`;必需的 Linux PR(Pull Request)门禁):Chromium 将回放后的浏览器输出与 `apps/web/tests/snapshots/` 比较。CI 强制只读的 `DSH_SNAPSHOT=replay`,绝不写入预期输出;record/refresh 留在本地,每处 diff 都须评审([web e2e 车道](../.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.md)、[CI 门禁决策](../.agents/notes/implemented/testing/2026-07-30-web-browser-snapshot-ci-gate.md))。`test:web` 会[先构建](../.agents/notes/implemented/bug-fix/2026-07-28-themed-scrollbars-and-reserved-gutter.md)以交付插件 CSS。
|
||||
|
||||
签入仓库的会话格式 JSONL 使用规范打包行布局,无密钥快照门禁会通过 `session` header 发现每一份此类 fixture;[临时迁移器](../scripts/migrate-packed-session-fixtures.ts)会改写旧版 fixture 布局。
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/tool-catalog.md
|
||||
tool-catalog.md: dbab9ce2f389dbfe40e7d753ced995a8a384be17
|
||||
tool-catalog.zh.md: e99f8bc78923e616265427c1e0361c832cc0930f
|
||||
tool-catalog.md: f61b6daeb7209d0fa81606bda7718fd42c7f22dc
|
||||
tool-catalog.zh.md: cbecdba084fa64ec78913706221a1558d206cde8
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user