Merge remote-tracking branch 'origin/master' into feat/read-image-context

# Conflicts:
#	apps/cli/tests/web-agent-presets.e2e.ts
#	packages/fs/tool-fs/package.json
This commit is contained in:
creatixchu
2026-08-11 10:12:14 +08:00
1962 changed files with 25048 additions and 14905 deletions

View File

@@ -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

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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

View File

@@ -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
/**

View File

@@ -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
/**

View File

@@ -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

View File

@@ -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.

View File

@@ -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.

View File

@@ -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

View File

@@ -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 -->

View File

@@ -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 -->

View File

@@ -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

View File

@@ -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 -->

View File

@@ -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 -->

View File

@@ -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

View File

@@ -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>

View File

@@ -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>