mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
Merge origin/master into feat/mcp-auto-reconnect
Integrate master at 8b4ef532 before addressing review feedback so each bot issue remains isolated in its own descendant commit. Resolve the vendor package rescope by moving the PR's new MCP supervisor imports to @deepseek-ai/cordis and @deepseek-ai/schemastery, preserve the reconnect implementation and e2e coverage, and regenerate the merged config and module catalogs with fresh bilingual pairing records.
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: 6837b4c4e069cabce1a6f0a6c68ca3bb449af8a1
|
||||
config-catalog.zh.md: b6569964cb7c267d58d9a963ac893a7aa8f48389
|
||||
config-catalog.md: 1adb51d9271723bdec6e8cbba00b54539a0f8667
|
||||
config-catalog.zh.md: 9bafb49911146011388a24ccdb087c384fd0459c
|
||||
|
||||
@@ -1125,7 +1125,7 @@ export interface ReconnectConfig {
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/mcp/mcp-client/src/index.ts:104`](../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`
|
||||
|
||||
@@ -1177,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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1322,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
|
||||
@@ -2019,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`
|
||||
|
||||
|
||||
@@ -1127,7 +1127,7 @@ export interface ReconnectConfig {
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`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`
|
||||
|
||||
@@ -1179,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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1324,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
|
||||
@@ -2021,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`
|
||||
|
||||
|
||||
@@ -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-primer.md
|
||||
cordis-primer.md: c95909a4a1deab9407efedbb990ef13be6e43a16
|
||||
cordis-primer.zh.md: a18b8b37af19a610b71babbe5e67f96bb09e81b1
|
||||
cordis-primer.md: 93725949a9490f757edebcf3e8391db9e73321b1
|
||||
cordis-primer.zh.md: fd2a327b526b210986bc1574013fca2c0cec5dda
|
||||
|
||||
@@ -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, 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.
|
||||
|
||||
## 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 仅在挂载插件前对条目的 `config` 做插值。条目元数据(`id`、`name`、`group`、`disabled`、`inject`、`intercept` 和 `isolate`)保持字面值;因此 `disabled: !!js ...` 是一个 truthy 对象,会始终禁用该条目。需要根据环境选择挂载哪些插件时,请使用显式的配置覆盖层。
|
||||
|
||||
## 实践规则
|
||||
|
||||
|
||||
@@ -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: 4e68c0e5e6262ec7f31f4ed2d146ee18d3faa02a
|
||||
event-producer-consumer.zh.md: 1879e74f3e8c01143292b82a1745f4438f64e0ac
|
||||
|
||||
@@ -37,12 +37,12 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `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:164`](../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:138`](../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:144`](../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:155`](../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) |
|
||||
|
||||
@@ -39,12 +39,12 @@
|
||||
| `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:164`](../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:138`](../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:144`](../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:155`](../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: f8d152fd5ba8686f912ece192b3eb84594b8f182
|
||||
module-graph.zh.md: 0386fd3bf28134eb2009562c4a07353c8478fe2d
|
||||
module-graph.md: e106302549781e585c467bb61e1b955541b2a20a
|
||||
module-graph.zh.md: 15a4d40bf78bdb20b0fee078263f58886645c1f5
|
||||
|
||||
@@ -253,7 +253,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"]
|
||||
@@ -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
|
||||
@@ -1018,12 +1021,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
|
||||
@@ -1069,10 +1070,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
|
||||
@@ -1391,7 +1388,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) |
|
||||
@@ -1422,7 +1419,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) |
|
||||
@@ -1430,7 +1427,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) |
|
||||
|
||||
@@ -255,7 +255,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"]
|
||||
@@ -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
|
||||
@@ -1020,12 +1023,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
|
||||
@@ -1071,10 +1072,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
|
||||
@@ -1246,7 +1243,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) |
|
||||
@@ -1393,7 +1390,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) |
|
||||
@@ -1424,7 +1421,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) |
|
||||
@@ -1432,7 +1429,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) |
|
||||
|
||||
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/subagent.md
|
||||
subagent.md: 961a16f58cb936205290d23ce6b9d94cb94607d5
|
||||
subagent.zh.md: ac97d27d9824ca62701e11ae99264adbddafbbd8
|
||||
subagent.md: 220ecf493b2d3a84cede34c1cf72dbf0dcd80353
|
||||
subagent.zh.md: b0a0df5a778ed758421225e524c87cf8ef213c0b
|
||||
|
||||
@@ -614,7 +614,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:169`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagent-events"></a>
|
||||
|
||||
@@ -640,7 +640,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:164`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagentprovider-added--emit"></a>
|
||||
|
||||
@@ -657,7 +657,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:138`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagentprovider-removed--emit"></a>
|
||||
|
||||
@@ -674,7 +674,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:144`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagentstart--emit"></a>
|
||||
|
||||
@@ -698,5 +698,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:155`](../../packages/subagent/subagent/src/index.ts)
|
||||
<!-- END GENERATED cordis-surface -->
|
||||
|
||||
@@ -616,7 +616,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:169`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagent-events"></a>
|
||||
|
||||
@@ -642,7 +642,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:164`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagentprovider-added--emit"></a>
|
||||
|
||||
@@ -659,7 +659,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:138`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagentprovider-removed--emit"></a>
|
||||
|
||||
@@ -676,7 +676,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:144`](../../packages/subagent/subagent/src/index.ts)
|
||||
|
||||
<a id="subagentstart--emit"></a>
|
||||
|
||||
@@ -700,5 +700,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:155`](../../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/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/tool-catalog.md
|
||||
tool-catalog.md: dbab9ce2f389dbfe40e7d753ced995a8a384be17
|
||||
tool-catalog.zh.md: e99f8bc78923e616265427c1e0361c832cc0930f
|
||||
tool-catalog.md: f61b6daeb7209d0fa81606bda7718fd42c7f22dc
|
||||
tool-catalog.zh.md: cbecdba084fa64ec78913706221a1558d206cde8
|
||||
|
||||
@@ -284,7 +284,7 @@ Source: [`packages/self-modification/tool-cordis/src/index.ts`](../packages/self
|
||||
|
||||
### `cordis_mount`
|
||||
|
||||
Mount a temporary Cordis Plugin in the current DSH process. This creates an in-memory runtime Plugin, not an installed or configured Plugin. It remains active across later turns until cordis_unmount, toolset unload, or DSH restart. It does not create files, install a package, change cordis.yml or personal/project config, survive restart, or automatically become permanent. To keep it, ask the Agent to implement a normal local, project, or repository Plugin through the regular development workflow. It may affect other sessions in the same process; the sandbox is not a security boundary, and injected services reach the real runtime. `code` runs now as the body of an async JavaScript function in an isolated sandbox and MUST `return` a plugin. Two forms: FUNCTION form `return (ctx) => { … }` — declares no inject, so it can register tools, listen to events, and provide services, but reaching ANY service (e.g. ctx.bash) throws; use it only when you need no services. OBJECT form `return { name?, inject: ['bash', 'llm', …], apply(ctx) { … } }` — declares dependencies, and cordis activates the plugin only after the services exist; PREFER this form. You may reach ONLY the services you list in inject: an undeclared service throws even if it exists, because an undeclared dependency would not be cleaned up if its provider is unmounted. BEFORE calling a service from your code, read cordis_inspect what:"api" — it lists method signatures AND the type shapes of their arguments/returns (do not guess a field's type; e.g. a bash run's stdout is an object, not a string). Inside `apply`, use the standard cordis API: `ctx.on(event, listener)` to observe events (see cordis_inspect what:"events"), or call `harness.registerTool(ctx, harness.defineTool({ name, description, parameters: { text: { type: 'string', required: true } }, output: { schema: { type: 'string' }, render(_args, value) { return [{ type: 'text', text: value }] } }, async execute(args) { return args.text } }))` to give yourself a new tool — it becomes callable on your NEXT step. Tool parameters: each key IS a property — { type: 'string'|'number'|'integer'|'boolean'|'null'|'object'|'array'|'json', required?: true, description?, enum?, const?, items?, properties? }; every direct DSL object declares additionalProperties: true|false, and oneOf: [schema, schema, ...] replaces type for an exact-one union. A raw JSON-Schema { type: 'object', properties, required?: […] } wrapper is also accepted with open-by-default objects. A tool's `execute` MUST return the lossless JSON value declared by `output.schema`; `output.render(args, value)` separately returns Native/model content blocks. Temporary Plugins can COMPOSE: one Plugin may `ctx.provide('name', value)` a service and another may declare `inject: ['name']` to consume it — the consumer stays pending until the provider exists and returns to pending when the provider is unmounted. Everything registered inside `apply` is cleaned up automatically by cordis_unmount. Sandbox globals: `console` (tagged `[cordis:<id>]`, writes through to the harness terminal), `harness.defineTool`, `harness.registerTool`, `btoa`, `atob`, `TextEncoder`, `TextDecoder`. Node APIs are DISABLED — do filesystem/network/timer work through the cordis services, never Node built-ins: `require`, `setTimeout`/`setInterval`, and `fetch` throw redirect errors; `process` and `Buffer` are undefined. Instead use inject: ['fs'] + ctx.fs for files, inject: ['web'] + ctx.web for HTTP, inject: ['bash'] + ctx.bash for processes, and inject: ['timer'] + ctx.setTimeout/ctx.setInterval for timing (fiber effects, auto-cleaned when unmounted) — cordis_inspect what:"api" shows what THIS runtime provides. Write PLAIN JavaScript, not TypeScript (no `as`, no type annotations). Cautions: (1) waterfall events (e.g. tools/pre-execute) hand the listener a trailing `next` callback which MUST be called — returning without `next()` SHORT-CIRCUITS the call; prefer plain notification events unless you intend to intercept. (2) Never await something that only resolves after the current turn (your code runs INSIDE a tool call of that turn — it would deadlock). (3) Your `ctx` is a restricted façade: you can register tools, observe events, provide/consume services, and use timers, but framework internals (ctx.root, ctx.fiber, ctx.extend, ctx.plugin, …) are withheld. It is not a security boundary though — the services you inject (e.g. ctx.bash) reach the real runtime.
|
||||
Mount a temporary Cordis Plugin in the current DSH process. This creates an in-memory runtime Plugin, not an installed or configured Plugin. It remains active across later turns until cordis_unmount, toolset unload, or DSH restart. It does not create files, install a package, change cordis.yml or personal/project config, survive restart, or automatically become permanent. To keep it, ask the Agent to implement an SDK Plugin or installable profile bundle through the regular development workflow. It may affect other sessions in the same process; the sandbox is not a security boundary, and injected services reach the real runtime. `code` runs now as the body of an async JavaScript function in an isolated sandbox and MUST `return` a plugin. Two forms: FUNCTION form `return (ctx) => { … }` — declares no inject, so it can register tools, listen to events, and provide services, but reaching ANY service (e.g. ctx.bash) throws; use it only when you need no services. OBJECT form `return { name?, inject: ['bash', 'llm', …], apply(ctx) { … } }` — declares dependencies, and cordis activates the plugin only after the services exist; PREFER this form. You may reach ONLY the services you list in inject: an undeclared service throws even if it exists, because an undeclared dependency would not be cleaned up if its provider is unmounted. BEFORE calling a service from your code, read cordis_inspect what:"api" — it lists method signatures AND the type shapes of their arguments/returns (do not guess a field's type; e.g. a bash run's stdout is an object, not a string). Inside `apply`, use the standard cordis API: `ctx.on(event, listener)` to observe events (see cordis_inspect what:"events"), or call `harness.registerTool(ctx, harness.defineTool({ name, description, parameters: { text: { type: 'string', required: true } }, output: { schema: { type: 'string' }, render(_args, value) { return [{ type: 'text', text: value }] } }, async execute(args) { return args.text } }))` to give yourself a new tool — it becomes callable on your NEXT step. Tool parameters: each key IS a property — { type: 'string'|'number'|'integer'|'boolean'|'null'|'object'|'array'|'json', required?: true, description?, enum?, const?, items?, properties? }; every direct DSL object declares additionalProperties: true|false, and oneOf: [schema, schema, ...] replaces type for an exact-one union. A raw JSON-Schema { type: 'object', properties, required?: […] } wrapper is also accepted with open-by-default objects. A tool's `execute` MUST return the lossless JSON value declared by `output.schema`; `output.render(args, value)` separately returns Native/model content blocks. Temporary Plugins can COMPOSE: one Plugin may `ctx.provide('name', value)` a service and another may declare `inject: ['name']` to consume it — the consumer stays pending until the provider exists and returns to pending when the provider is unmounted. Everything registered inside `apply` is cleaned up automatically by cordis_unmount. Sandbox globals: `console` (tagged `[cordis:<id>]`, writes through to the harness terminal), `harness.defineTool`, `harness.registerTool`, `btoa`, `atob`, `TextEncoder`, `TextDecoder`. Node APIs are DISABLED — do filesystem/network/timer work through the cordis services, never Node built-ins: `require`, `setTimeout`/`setInterval`, and `fetch` throw redirect errors; `process` and `Buffer` are undefined. Instead use inject: ['fs'] + ctx.fs for files, inject: ['web'] + ctx.web for HTTP, inject: ['bash'] + ctx.bash for processes, and inject: ['timer'] + ctx.setTimeout/ctx.setInterval for timing (fiber effects, auto-cleaned when unmounted) — cordis_inspect what:"api" shows what THIS runtime provides. Write PLAIN JavaScript, not TypeScript (no `as`, no type annotations). Cautions: (1) waterfall events (e.g. tools/pre-execute) hand the listener a trailing `next` callback which MUST be called — returning without `next()` SHORT-CIRCUITS the call; prefer plain notification events unless you intend to intercept. (2) Never await something that only resolves after the current turn (your code runs INSIDE a tool call of that turn — it would deadlock). (3) Your `ctx` is a restricted façade: you can register tools, observe events, provide/consume services, and use timers, but framework internals (ctx.root, ctx.fiber, ctx.extend, ctx.plugin, …) are withheld. It is not a security boundary though — the services you inject (e.g. ctx.bash) reach the real runtime.
|
||||
|
||||
```json
|
||||
{
|
||||
|
||||
@@ -286,7 +286,7 @@ pwsh 工具是 Windows 组合中 bash 执行器 seam 的 PowerShell 方言消费
|
||||
|
||||
### `cordis_mount`
|
||||
|
||||
在当前 DSH 进程中挂载临时 Cordis Plugin。它创建的是内存中的运行时 Plugin,而不是已安装或已配置的 Plugin。该插件会在后续轮次中保持活动,直到执行 cordis_unmount、工具集卸载或 DSH 重启。它不会创建文件、安装包、修改 cordis.yml 或个人/项目配置、在重启后保留,也不会自动转为永久插件。若要保留,请让 Agent 通过常规开发工作流实现普通的本地、项目或仓库 Plugin。它可能影响同一进程中的其他会话;沙箱不是安全边界,注入的服务会访问真实运行时。`code` 会立即作为异步 JavaScript 函数的函数体在隔离沙箱中运行,并且**必须** `return` 一个插件。支持两种形式:函数形式 `return (ctx) => { … }`,它不声明 inject,因此可以注册工具、监听事件和提供服务,但访问**任何**服务(例如 ctx.bash)都会抛出异常;仅在不需要服务时使用。对象形式 `return { name?, inject: ['bash', 'llm', …], apply(ctx) { … } }`,它声明依赖,Cordis 只在服务存在后激活插件;**优先使用**这种形式。你只能访问 inject 中列出的服务:即使未声明的服务存在,访问它也会抛出异常,因为如果提供方被卸载,未声明的依赖将无法清理。代码调用服务**之前**,请读取 cordis_inspect 的 what:"api";它会列出方法签名以及参数/返回值的类型形状,不要猜测字段类型,例如 bash 运行的 stdout 是对象而非字符串。在 `apply` 内,请使用标准 Cordis API:通过 `ctx.on(event, listener)` 观察事件(见 cordis_inspect 的 what:"events"),或调用 `harness.registerTool(ctx, harness.defineTool({ name, description, parameters: { text: { type: 'string', required: true } }, output: { schema: { type: 'string' }, render(_args, value) { return [{ type: 'text', text: value }] } }, async execute(args) { return args.text } }))` 为自己提供新工具;该工具会在你的**下一步骤**可调用。工具参数:每个键**就是**一个属性,即 { type: 'string'|'number'|'integer'|'boolean'|'null'|'object'|'array'|'json', required?: true, description?, enum?, const?, items?, properties? };每个直接 DSL 对象都声明 additionalProperties: true|false,而 oneOf: [schema, schema, ...] 会取代 type,表示恰好匹配一个成员的联合。也接受原始 JSON Schema { type: 'object', properties, required?: […] } 包装层,其中对象默认开放。工具的 `execute` **必须**返回 `output.schema` 声明的无损 JSON 值;`output.render(args, value)` 单独返回 Native/模型内容块。临时 Plugin 可以**组合**:一个 Plugin 可以通过 `ctx.provide('name', value)` 提供服务,另一个则可声明 `inject: ['name']` 来消费它;消费方会在提供方出现前保持等待,提供方卸载后重新回到等待状态。在 `apply` 中注册的一切都会由 cordis_unmount 自动清理。沙箱全局对象:`console`(带 `[cordis:<id>]` 标签,写入 harness 终端)、`harness.defineTool`、`harness.registerTool`、`btoa`、`atob`、`TextEncoder`、`TextDecoder`。Node API 已**禁用**:文件系统/网络/定时工作必须通过 Cordis 服务完成,绝不能使用 Node 内置能力;`require`、`setTimeout`/`setInterval` 和 `fetch` 会抛出重定向错误,`process` 和 `Buffer` 未定义。应改用 inject: ['fs'] + ctx.fs 处理文件、inject: ['web'] + ctx.web 处理 HTTP、inject: ['bash'] + ctx.bash 处理进程、inject: ['timer'] + ctx.setTimeout/ctx.setInterval 处理定时(这些是 fiber effect,卸载时自动清理);cordis_inspect 的 what:"api" 会展示**当前**运行时提供的能力。请编写**纯** JavaScript,不要使用 TypeScript(不得使用 `as` 或类型注解)。注意事项:(1) waterfall(瀑布式事件)事件(例如 tools/pre-execute)会向监听器传入最后一个 `next` 回调,该回调**必须**被调用;不调用 `next()` 就返回会**短路**此次调用。除非你有意拦截,否则请优先使用普通通知事件。(2) 切勿等待只能在当前轮次之后解析的内容;你的代码运行在该轮次的工具调用**内部**,否则会死锁。(3) 你的 `ctx` 是受限门面:可以注册工具、观察事件、提供/消费服务和使用定时器,但不会提供框架内部能力(ctx.root、ctx.fiber、ctx.extend、ctx.plugin 等)。不过,它并非安全边界:你注入的服务(例如 ctx.bash)会访问真实运行时。
|
||||
在当前 DSH 进程中挂载临时 Cordis Plugin。它创建的是内存中的运行时 Plugin,而不是已安装或已配置的 Plugin。该插件会在后续轮次中保持活动,直到执行 cordis_unmount、工具集卸载或 DSH 重启。它不会创建文件、安装包、修改 cordis.yml 或个人/项目配置、在重启后保留,也不会自动转为永久插件。若要保留,请让 Agent 通过常规开发工作流实现 SDK Plugin 或可安装的 profile bundle。它可能影响同一进程中的其他会话;沙箱不是安全边界,注入的服务会访问真实运行时。`code` 会立即作为异步 JavaScript 函数的函数体在隔离沙箱中运行,并且**必须** `return` 一个插件。支持两种形式:函数形式 `return (ctx) => { … }`,它不声明 inject,因此可以注册工具、监听事件和提供服务,但访问**任何**服务(例如 ctx.bash)都会抛出异常;仅在不需要服务时使用。对象形式 `return { name?, inject: ['bash', 'llm', …], apply(ctx) { … } }`,它声明依赖,Cordis 只在服务存在后激活插件;**优先使用**这种形式。你只能访问 inject 中列出的服务:即使未声明的服务存在,访问它也会抛出异常,因为如果提供方被卸载,未声明的依赖将无法清理。代码调用服务**之前**,请读取 cordis_inspect 的 what:"api";它会列出方法签名以及参数/返回值的类型形状,不要猜测字段类型,例如 bash 运行的 stdout 是对象而非字符串。在 `apply` 内,请使用标准 Cordis API:通过 `ctx.on(event, listener)` 观察事件(见 cordis_inspect 的 what:"events"),或调用 `harness.registerTool(ctx, harness.defineTool({ name, description, parameters: { text: { type: 'string', required: true } }, output: { schema: { type: 'string' }, render(_args, value) { return [{ type: 'text', text: value }] } }, async execute(args) { return args.text } }))` 为自己提供新工具;该工具会在你的**下一步骤**可调用。工具参数:每个键**就是**一个属性,即 { type: 'string'|'number'|'integer'|'boolean'|'null'|'object'|'array'|'json', required?: true, description?, enum?, const?, items?, properties? };每个直接 DSL 对象都声明 additionalProperties: true|false,而 oneOf: [schema, schema, ...] 会取代 type,表示恰好匹配一个成员的联合。也接受原始 JSON Schema { type: 'object', properties, required?: […] } 包装层,其中对象默认开放。工具的 `execute` **必须**返回 `output.schema` 声明的无损 JSON 值;`output.render(args, value)` 单独返回 Native/模型内容块。临时 Plugin 可以**组合**:一个 Plugin 可以通过 `ctx.provide('name', value)` 提供服务,另一个则可声明 `inject: ['name']` 来消费它;消费方会在提供方出现前保持等待,提供方卸载后重新回到等待状态。在 `apply` 中注册的一切都会由 cordis_unmount 自动清理。沙箱全局对象:`console`(带 `[cordis:<id>]` 标签,写入 harness 终端)、`harness.defineTool`、`harness.registerTool`、`btoa`、`atob`、`TextEncoder`、`TextDecoder`。Node API 已**禁用**:文件系统/网络/定时工作必须通过 Cordis 服务完成,绝不能使用 Node 内置能力;`require`、`setTimeout`/`setInterval` 和 `fetch` 会抛出重定向错误,`process` 和 `Buffer` 未定义。应改用 inject: ['fs'] + ctx.fs 处理文件、inject: ['web'] + ctx.web 处理 HTTP、inject: ['bash'] + ctx.bash 处理进程、inject: ['timer'] + ctx.setTimeout/ctx.setInterval 处理定时(这些是 fiber effect,卸载时自动清理);cordis_inspect 的 what:"api" 会展示**当前**运行时提供的能力。请编写**纯** JavaScript,不要使用 TypeScript(不得使用 `as` 或类型注解)。注意事项:(1) waterfall(瀑布式事件)事件(例如 tools/pre-execute)会向监听器传入最后一个 `next` 回调,该回调**必须**被调用;不调用 `next()` 就返回会**短路**此次调用。除非你有意拦截,否则请优先使用普通通知事件。(2) 切勿等待只能在当前轮次之后解析的内容;你的代码运行在该轮次的工具调用**内部**,否则会死锁。(3) 你的 `ctx` 是受限门面:可以注册工具、观察事件、提供/消费服务和使用定时器,但不会提供框架内部能力(ctx.root、ctx.fiber、ctx.extend、ctx.plugin 等)。不过,它并非安全边界:你注入的服务(例如 ctx.bash)会访问真实运行时。
|
||||
|
||||
```json
|
||||
{
|
||||
|
||||
@@ -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/user/develop/basic/config.md
|
||||
config.md: 02998c32415b5ba7acf82700034cabc1f7314f33
|
||||
config.zh.md: 161af5d6703b4cc77d63443a5a80846593d1c7fd
|
||||
config.md: 21ba39fd7de1795e9139aff3e2b11743eedd4833
|
||||
config.zh.md: a882c4d59b0ac8e8ec27a5b32da5376b534a7f62
|
||||
|
||||
@@ -9,8 +9,8 @@ Accept configuration supplied through `cordis.yml`.
|
||||
Export a `Config` type and a same-named Schemastery schema. Put defaults directly on the schema fields:
|
||||
|
||||
```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 = 'my-plugin'
|
||||
|
||||
@@ -49,8 +49,8 @@ When loading the plugin, Cordis uses the exported schema to validate configurati
|
||||
Use Schemastery to express stricter validation:
|
||||
|
||||
```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 = 'validated-plugin'
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
在插件中导出一个 `Config` 类型和同名的 Schemastery schema;默认值直接写在 schema 中:
|
||||
|
||||
```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 = 'my-plugin'
|
||||
|
||||
@@ -49,8 +49,8 @@ export function apply(ctx: Context, config: Config) {
|
||||
对于需要严格校验的场景,使用 Schemastery 定义 schema:
|
||||
|
||||
```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 = 'validated-plugin'
|
||||
|
||||
|
||||
@@ -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/user/develop/basic/index.md
|
||||
index.md: 7fe66bb19ddb978a4b5a96768b62151b97bca0ec
|
||||
index.zh.md: 59f4e5b58b6cf1fbc15de8fafb5f4b0db2e220d6
|
||||
index.md: fe525018011809abe4dd18ac5739c54cd330c8f6
|
||||
index.zh.md: 0dbb7275be3c7147395041fb18d49a7f6ea69cdd
|
||||
|
||||
@@ -17,7 +17,7 @@ mkdir -p scratch-plugin/src
|
||||
In Harness, a plugin is a TypeScript module that exports an `apply` function. The framework calls `apply` when loading the plugin and passes a `ctx` context object through which the plugin registers capabilities:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'my-plugin'
|
||||
|
||||
@@ -33,7 +33,7 @@ That is the complete configuration.
|
||||
Create `scratch-plugin/src/my-plugin.ts`:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'hello-plugin'
|
||||
|
||||
@@ -68,7 +68,7 @@ Anything registered through `ctx`—event listeners, tools, or timers—is clean
|
||||
For a resource that needs explicit cleanup, such as a network connection, use `ctx.effect()` to provide its disposer:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export function apply(ctx: Context) {
|
||||
ctx.effect(() => {
|
||||
@@ -87,7 +87,7 @@ export function apply(ctx: Context) {
|
||||
If the plugin consumes another service such as `tools` or `llm`, declare it in `inject`:
|
||||
|
||||
```ts ignore-check
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'my-tool-plugin'
|
||||
export const inject = ['tools']
|
||||
@@ -107,7 +107,7 @@ In addition to a function module, a plugin can use object or class form.
|
||||
### Object form
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export default {
|
||||
name: 'my-plugin',
|
||||
@@ -121,7 +121,7 @@ export default {
|
||||
### Class form
|
||||
|
||||
```ts
|
||||
import { Service, type Context } from 'cordis'
|
||||
import { Service, type Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export default class MyService extends Service {
|
||||
static inject = ['tools']
|
||||
|
||||
@@ -17,7 +17,7 @@ mkdir -p scratch-plugin/src
|
||||
在 Harness 中,插件是一个导出 `apply` 函数的 TypeScript 模块。框架在加载时调用 `apply`,传入一个 `ctx`(上下文对象),你通过 `ctx` 注册能力:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'my-plugin'
|
||||
|
||||
@@ -33,7 +33,7 @@ export function apply(ctx: Context) {
|
||||
创建 `scratch-plugin/src/my-plugin.ts`:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'hello-plugin'
|
||||
|
||||
@@ -68,7 +68,7 @@ pnpm run dsh web --patch ./scratch-plugin/cordis.yml
|
||||
如果你有需要手动清理的资源(比如一个网络连接),用 `ctx.effect()` 告诉框架怎么清理:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export function apply(ctx: Context) {
|
||||
ctx.effect(() => {
|
||||
@@ -87,7 +87,7 @@ export function apply(ctx: Context) {
|
||||
如果你的插件需要使用其他服务(如 `tools`、`llm`),需要声明 `inject`:
|
||||
|
||||
```ts ignore-check
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export const name = 'my-tool-plugin'
|
||||
export const inject = ['tools']
|
||||
@@ -107,7 +107,7 @@ export function apply(ctx: Context) {
|
||||
### 对象形式
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export default {
|
||||
name: 'my-plugin',
|
||||
@@ -121,7 +121,7 @@ export default {
|
||||
### 类形式
|
||||
|
||||
```ts
|
||||
import { Service, type Context } from 'cordis'
|
||||
import { Service, type Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export default class MyService extends Service {
|
||||
static inject = ['tools']
|
||||
|
||||
@@ -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/user/develop/basic/tool.md
|
||||
tool.md: ba2f3b1302ba31735d67be264f498a0395394d06
|
||||
tool.zh.md: 676f8fc996d752a05d94b55d4522e61e3b3e2161
|
||||
tool.md: f110bd2c10caf21ea8c87bc32fd43b01b209a9d1
|
||||
tool.zh.md: a237b6015de0ea6141a94c56aaa6f68c73fa3feb
|
||||
|
||||
@@ -9,7 +9,7 @@ This tutorial adds a `greet` tool to the Web UI. Complete [Your first plugin](./
|
||||
Replace `scratch-plugin/src/my-plugin.ts` with:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { defineTool } from '@deepseek-ai/dsh-tools'
|
||||
|
||||
export const name = 'greet-tool'
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
将 `scratch-plugin/src/my-plugin.ts` 替换为:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { defineTool } from '@deepseek-ai/dsh-tools'
|
||||
|
||||
export const name = 'greet-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/user/develop/framework/events.md
|
||||
events.md: 8a8c076d9c7b40d73182db074c4f494fded8c6dd
|
||||
events.zh.md: 9649d89d575a1b05fa524bd460043da71dc9ae43
|
||||
events.md: 4b5f9ee215186398ee5aee7a438f792f9b5a3639
|
||||
events.zh.md: b48c8020803239d3c9636f81052d3b70afa315f2
|
||||
|
||||
@@ -85,9 +85,9 @@ A waterfall listener **must call `next()`**. Omitting it short-circuits the pipe
|
||||
Harness uses TypeScript declaration merging for type-safe events:
|
||||
|
||||
```ts
|
||||
import 'cordis'
|
||||
import '@deepseek-ai/cordis'
|
||||
|
||||
declare module 'cordis' {
|
||||
declare module '@deepseek-ai/cordis' {
|
||||
interface Events {
|
||||
'my-plugin/ready': (payload: { id: string }) => void
|
||||
'my-plugin/check': (input: string) => boolean | undefined
|
||||
@@ -121,7 +121,7 @@ export function apply(ctx: Context) {
|
||||
This plugin logs tool calls and results:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import '@deepseek-ai/dsh-tools'
|
||||
|
||||
export const name = 'tool-logger'
|
||||
|
||||
@@ -85,9 +85,9 @@ waterfall 监听器**必须调用 `next()`**。不调用 `next` 会短路整个
|
||||
Harness 使用 TypeScript 声明合并来为事件提供类型安全:
|
||||
|
||||
```ts
|
||||
import 'cordis'
|
||||
import '@deepseek-ai/cordis'
|
||||
|
||||
declare module 'cordis' {
|
||||
declare module '@deepseek-ai/cordis' {
|
||||
interface Events {
|
||||
'my-plugin/ready': (payload: { id: string }) => void
|
||||
'my-plugin/check': (input: string) => boolean | undefined
|
||||
@@ -121,7 +121,7 @@ export function apply(ctx: Context) {
|
||||
这个插件记录工具调用和工具结果:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import '@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/user/develop/framework/index.md
|
||||
index.md: 79e925b54509da41535735527e283850384257ec
|
||||
index.zh.md: 962677dc468c9cc233a51d50758247e028d9c3ed
|
||||
index.md: 85701ce281d92da0c805b39291179df73eb65f51
|
||||
index.zh.md: 871aa55ef81a7dcbfe3cbde5986244220ee32f98
|
||||
|
||||
@@ -80,7 +80,7 @@ export function apply(ctx: Context) {
|
||||
To stop a plugin instance early:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
declare const ctx: Context
|
||||
declare function myPlugin(ctx: Context): void
|
||||
@@ -98,7 +98,7 @@ await fiber.dispose()
|
||||
|
||||
## Hot replacement (HMR)
|
||||
|
||||
With `@cordisjs/plugin-hmr` loaded from `cordis.yml`, editing a plugin source file triggers:
|
||||
With `@deepseek-ai/cordis-plugin-hmr` loaded from `cordis.yml`, editing a plugin source file triggers:
|
||||
|
||||
1. Unload the old plugin and clean up its registrations.
|
||||
2. Load the new code.
|
||||
|
||||
@@ -80,7 +80,7 @@ export function apply(ctx: Context) {
|
||||
当你需要提前终止一个插件实例:
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
|
||||
declare const ctx: Context
|
||||
declare function myPlugin(ctx: Context): void
|
||||
@@ -98,7 +98,7 @@ await fiber.dispose()
|
||||
|
||||
## HMR(热模块替换)
|
||||
|
||||
通过 `cordis.yml` 加载 `@cordisjs/plugin-hmr` 后,修改插件源文件会触发:
|
||||
通过 `cordis.yml` 加载 `@deepseek-ai/cordis-plugin-hmr` 后,修改插件源文件会触发:
|
||||
|
||||
1. 卸载旧插件(清理所有注册)
|
||||
2. 重新加载新代码
|
||||
|
||||
@@ -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/user/develop/framework/service.md
|
||||
service.md: 040b1388cc431c30045e05f7d372ab5885bb3f9d
|
||||
service.zh.md: 0786b684c1688440a24cc729288835ad636f8ff7
|
||||
service.md: 3358f82ca5391741a7f531b7504de7335959ad03
|
||||
service.zh.md: 8fb4beeac43051c0f08483fe61e22c588127c360
|
||||
|
||||
@@ -36,7 +36,7 @@ When `apply` runs, every service declared by `inject` is ready. If a service is
|
||||
### Extend Service
|
||||
|
||||
```ts
|
||||
import { Service, type Context } from 'cordis'
|
||||
import { Service, type Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export default class MetricsService extends Service {
|
||||
static inject = ['llm'] // A service may depend on other services.
|
||||
@@ -67,9 +67,9 @@ export function apply(ctx: Context) {
|
||||
Use TypeScript declaration merging to type `ctx.metrics`:
|
||||
|
||||
```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 {
|
||||
metrics: MetricsService
|
||||
}
|
||||
@@ -114,7 +114,7 @@ This prevents a plugin from calling a service that no longer exists.
|
||||
|
||||
```yaml
|
||||
- id: group-a
|
||||
name: '@cordisjs/plugin-group'
|
||||
name: '@deepseek-ai/cordis-plugin-group'
|
||||
group: true
|
||||
isolate:
|
||||
bash: true
|
||||
@@ -125,7 +125,7 @@ This prevents a plugin from calling a service that no longer exists.
|
||||
- name: './src/plugin-a.ts'
|
||||
|
||||
- id: group-b
|
||||
name: '@cordisjs/plugin-group'
|
||||
name: '@deepseek-ai/cordis-plugin-group'
|
||||
group: true
|
||||
isolate:
|
||||
bash: true
|
||||
|
||||
@@ -36,7 +36,7 @@ export function apply(ctx: Context) {
|
||||
### 使用 Service 基类
|
||||
|
||||
```ts
|
||||
import { Service, type Context } from 'cordis'
|
||||
import { Service, type Context } from '@deepseek-ai/cordis'
|
||||
|
||||
export default class MetricsService extends Service {
|
||||
static inject = ['llm'] // A service may depend on other services.
|
||||
@@ -67,9 +67,9 @@ export function apply(ctx: Context) {
|
||||
使用 TypeScript 声明合并让 `ctx.metrics` 有正确类型:
|
||||
|
||||
```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 {
|
||||
metrics: MetricsService
|
||||
}
|
||||
@@ -114,7 +114,7 @@ export function apply(ctx: Context) {
|
||||
|
||||
```yaml
|
||||
- id: group-a
|
||||
name: '@cordisjs/plugin-group'
|
||||
name: '@deepseek-ai/cordis-plugin-group'
|
||||
group: true
|
||||
isolate:
|
||||
bash: true
|
||||
@@ -125,7 +125,7 @@ export function apply(ctx: Context) {
|
||||
- name: './src/plugin-a.ts'
|
||||
|
||||
- id: group-b
|
||||
name: '@cordisjs/plugin-group'
|
||||
name: '@deepseek-ai/cordis-plugin-group'
|
||||
group: true
|
||||
isolate:
|
||||
bash: true
|
||||
|
||||
@@ -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/user/develop/practice/index.md
|
||||
index.md: 1eb33e17ab6c5d0a2b37ff97d5948dfbcba497ca
|
||||
index.zh.md: 31afa80407f81f571615b5ed68a9370775f5188f
|
||||
index.md: 7ca9f0b1abe472dc90c6d4e56543e43b6d2ec727
|
||||
index.zh.md: 216b1cb01b355e411bf1949c59fd3720ae47139e
|
||||
|
||||
@@ -61,9 +61,9 @@ The [capability-seam reference](../../../capability-seams.md) owns the current b
|
||||
|
||||
```ts ignore-check
|
||||
// packages/my-cap/my-cap/src/index.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 {
|
||||
myCap: MyCapService
|
||||
}
|
||||
@@ -91,7 +91,7 @@ export interface MyCapResult {
|
||||
|
||||
```ts ignore-check
|
||||
// packages/my-cap/my-cap-local/src/index.ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { MyCapService, type MyCapRequest, type MyCapResult } from '@deepseek-ai/dsh-my-cap'
|
||||
|
||||
class MyCapLocal extends MyCapService {
|
||||
@@ -112,7 +112,7 @@ export function apply(ctx: Context) {
|
||||
|
||||
```ts ignore-check
|
||||
// packages/my-cap/tool-my-cap/src/index.ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { defineTool } from '@deepseek-ai/dsh-tools'
|
||||
|
||||
export const name = 'tool-my-cap'
|
||||
|
||||
@@ -61,9 +61,9 @@
|
||||
|
||||
```ts ignore-check
|
||||
// packages/my-cap/my-cap/src/index.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 {
|
||||
myCap: MyCapService
|
||||
}
|
||||
@@ -91,7 +91,7 @@ export interface MyCapResult {
|
||||
|
||||
```ts ignore-check
|
||||
// packages/my-cap/my-cap-local/src/index.ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { MyCapService, type MyCapRequest, type MyCapResult } from '@deepseek-ai/dsh-my-cap'
|
||||
|
||||
class MyCapLocal extends MyCapService {
|
||||
@@ -112,7 +112,7 @@ export function apply(ctx: Context) {
|
||||
|
||||
```ts ignore-check
|
||||
// packages/my-cap/tool-my-cap/src/index.ts
|
||||
import type { Context } from 'cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { defineTool } from '@deepseek-ai/dsh-tools'
|
||||
|
||||
export const name = 'tool-my-cap'
|
||||
|
||||
@@ -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/user/develop/practice/llm-adapter.md
|
||||
llm-adapter.md: 7445688530c1ba61e5c065f9f5e49db6498da5b1
|
||||
llm-adapter.zh.md: c726735ff2679584d1c061ef8acddc8981dadd26
|
||||
llm-adapter.md: aba4a6d0c8ee42e78ca5a804d9a0dd9b31c1e240
|
||||
llm-adapter.zh.md: dff9eef464599823d6cd99e83d668485109b2ec0
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user