Merge branch 'worktree/jobs-api-review-3052' into worktree/jobs-api-review-3127
# Conflicts: # packages/client/ui-jobs/src/client/JobListAction.tsx # packages/shell/bash-local/tests/executor.spec.ts
This commit is contained in:
commit
c4bc8b847a
1836 files changed
+37648
-15031
No files matched your search
+1
-1
@@ -37,7 +37,7 @@ Placement: bugs → postmortems; rationale → Agent Notes; procedures → cookb
|
||||
## Writing rules
|
||||
|
||||
- **Document current state.** Keep history in commits, PRs, Agent Notes, postmortems, or scoped persistence records. Other prose names live mechanisms, not changes or stack positions. General Session-format prose links [version/status authority](session-format-status.md); retain numbers for version-specific contracts, examples, or evidence.
|
||||
- **Every non-trivial change includes at least one Agent Note in the same PR.** Update the owning note or add one; only mechanical/local edits are exempt ([scope](../.agents/notes/README.md#when-to-write-one)).
|
||||
- **Apply the Agent Note creation criteria.** Mechanical/local edits are exempt, including local UI changes; keep existing owning notes accurate ([scope](../.agents/notes/README.md#when-to-write-one)).
|
||||
- **One physical line per paragraph** (`verify-md-wrap`): use editor soft-wrap. Code blocks, tables, and list structure keep their formatting; code comments stay under the linter's column limit.
|
||||
- **Fenced `ts` blocks must compile** (`doc-typecheck`); a pasted type declaration and its original JSDoc use ` ```ts type-equiv `, while a body-stripped public class declaration uses ` ```ts public-api `; register either in the manifest so neither can drift ([mechanics](development.md#documenting-types-verbatim-ts-type-equiv)).
|
||||
- **The owning [subsystems page](subsystems/README.md) updates in the same change** that reshapes a documented type. `verify-type-equiv` catches drifted pastes, not never-documented new types; a type is documented on its declaring package group's page ([page scoping](../.agents/notes/implemented/process/2026-08-03-package-anchored-subsystem-pages.md)).
|
||||
|
||||
@@ -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/architecture.md
|
||||
architecture.md: c7839a67dd16c264a6b73b4c47b412d5d1551a47
|
||||
architecture.zh.md: 6ae6f06c49460b209b3e6ac375d8549d8d2cfa24
|
||||
architecture.md: 4a4305ee43f2281ce40725778809b47c0fb5c07a
|
||||
architecture.zh.md: f34e2101d4e3f52d3d3d17a034b4fb7d86cdd3a3
|
||||
@@ -50,7 +50,7 @@ The Python SDK follows the same application architecture. Its runtime wheel pack
|
||||
|
||||
## Desktop application
|
||||
|
||||
The [Electron desktop application](../apps/desktop/README.md) carries its exact dsh production runtime in signed resources and owns the reserved `$DSH_HOME/profiles/desktop`. Shared profile helpers initialize its files, reconcile installed bundles, and project missing dependencies without replacing pnpm-owned packages. CLI and Desktop share product data, while executable packages, activation choices, and lockfiles remain separate. The public CLI cannot manage Desktop’s profile.
|
||||
The [Electron desktop application](../apps/desktop/README.md) carries its exact dsh production runtime in signed resources and owns the reserved `$DSH_HOME/profiles/desktop`. Shared profile helpers initialize its files, reconcile installed bundles, and resolve installation and bundle dependencies without replacing pnpm-owned packages. CLI and Desktop share product data, while executable packages, activation choices, and lockfiles remain separate. The public CLI cannot manage Desktop’s profile.
|
||||
|
||||
Electron starts the private Desktop Host in Electron Node mode. The Host invokes the shared CLI profile runner and complete Web application. The window immediately loads packaged Web assets and waits for boot injections before activating client plugins in the same document. Web owns RPC and streams; the desktop carrier connects the local page to the authenticated Host. Node IPC carries boot injections, readiness, fatal errors, and shutdown. Desktop defaults to port `19387`; profile configuration can override it. Shell-owned UI runs plugin transactions through bundled pnpm with normal user and profile configuration.
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ Python SDK 遵循相同的应用架构。其运行时 wheel 把普通 `dsh` CLI
|
||||
|
||||
## 桌面应用
|
||||
|
||||
[Electron 桌面应用](../apps/desktop/README.zh.md)在签名资源中携带精确匹配的 dsh 生产运行时,并拥有保留的 `$DSH_HOME/profiles/desktop`。共享 profile helper 初始化其文件、协调已安装 bundle,并补全缺失依赖而不替换 pnpm 拥有的包。CLI 与 Desktop 共享产品数据,可执行包、启用选择与锁文件保持独立。公开 CLI 不能管理 Desktop profile。
|
||||
[Electron 桌面应用](../apps/desktop/README.zh.md)在签名资源中携带精确匹配的 dsh 生产运行时,并拥有保留的 `$DSH_HOME/profiles/desktop`。共享 profile helper 初始化其文件、协调已安装 bundle,并解析安装与 bundle 的依赖而不替换 pnpm 拥有的包。CLI 与 Desktop 共享产品数据,可执行包、启用选择与锁文件保持独立。公开 CLI 不能管理 Desktop profile。
|
||||
|
||||
Electron 使用 Electron Node 模式启动私有 Desktop Host。Host 调用共享 CLI profile runner 与完整 Web 应用。窗口立即加载打包 Web 资源,等待启动注入后在同一文档中激活客户端插件。Web 负责 RPC 与流;桌面载体将本地页面连接到已认证的 Host。Node IPC 承载启动注入、就绪、致命错误与关闭。Desktop 默认端口为 `19387`,profile 配置可覆盖。壳拥有的 UI 通过内置 pnpm 执行插件事务,并遵循正常用户与 profile 配置。
|
||||
|
||||
|
||||
@@ -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: e90fc21918b8c46d38c2d3cca1b2bd098d1c42e5
|
||||
config-catalog.zh.md: 27f8a63dc0304a73e296c2bb1578aabd6981c194
|
||||
config-catalog.md: c2377682b6e2a6948299ab525263c21e5ecaba41
|
||||
config-catalog.zh.md: fccd084d26b85ef4112c98078bb0194ba87bc67e
|
||||
+13
-6
@@ -221,7 +221,7 @@ Source: [`packages/api/job-controller/src/index.ts:36`](../packages/api/job-cont
|
||||
|
||||
## `@deepseek-ai/dsh-api-session-controller`
|
||||
|
||||
Requires: `agentDefaultModel` · `agents` · `attachments` · `fileUploads` · `llm` · `sessions` · `sessionProjections` · `sessionQuery` · `typert` · `workspaceRegistry`
|
||||
Requires: `agentDefaultModel` · `agents` · `attachments` · `fileUploads` · `fs` · `llm` · `sessions` · `sessionProjections` · `sessionQuery` · `typert` · `workspaceRegistry`
|
||||
|
||||
```ts config-catalog
|
||||
/** Session Controller deployment policy. */
|
||||
@@ -231,7 +231,7 @@ export interface Config {
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/api/session-controller/src/index.ts:71`](../packages/api/session-controller/src/index.ts)
|
||||
Source: [`packages/api/session-controller/src/index.ts:73`](../packages/api/session-controller/src/index.ts)
|
||||
|
||||
<a id="deepseek-aidsh-api-settings-controller"></a>
|
||||
|
||||
@@ -898,7 +898,7 @@ export interface Config {
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/fs/fs-local/src/index.ts:43`](../packages/fs/fs-local/src/index.ts)
|
||||
Source: [`packages/fs/fs-local/src/index.ts:45`](../packages/fs/fs-local/src/index.ts)
|
||||
|
||||
<a id="deepseek-aidsh-fs-sandbox"></a>
|
||||
|
||||
@@ -1911,7 +1911,7 @@ Source: [`packages/plan/plan-mode/src/index.ts:64`](../packages/plan/plan-mode/s
|
||||
Requires: `loader` · `profileContext`
|
||||
|
||||
```ts config-catalog
|
||||
/** The pnpm executable and the limits for package diagnostics and registry lookups. */
|
||||
/** The pnpm executable, the registries asked, and the limits for package diagnostics and registry lookups. */
|
||||
export interface Config {
|
||||
/** The pnpm executable name or path; resolved through `PATH` like the `dsh plugin` command. */
|
||||
pnpmCommand?: string
|
||||
@@ -1921,10 +1921,18 @@ export interface Config {
|
||||
lockWaitMs?: number
|
||||
/** Bound on one registry lookup an inspection runs, in milliseconds. */
|
||||
inspectTimeoutMs?: number
|
||||
/** The registry lookups and installations ask first, as an http(s) URL; absent, the one pnpm's own configuration names. */
|
||||
registry?: string
|
||||
/**
|
||||
* Registries asked in turn, as http(s) URLs, while the one before is unreachable or holds no copy of the package.
|
||||
* A registry outside this set and `registry` is asked alone, and so is the one pnpm's own configuration names
|
||||
* unless that is npm's own registry or one of these.
|
||||
*/
|
||||
fallbackRegistries?: string[]
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/boot/plugin-manager/src/index.ts:33`](../packages/boot/plugin-manager/src/index.ts)
|
||||
Source: [`packages/boot/plugin-manager/src/index.ts:35`](../packages/boot/plugin-manager/src/index.ts)
|
||||
|
||||
<a id="deepseek-aidsh-plugin-package-inventory-deepseek"></a>
|
||||
|
||||
@@ -3955,7 +3963,6 @@ Imported as libraries by other packages; a `cordis.yml` cannot load them.
|
||||
- `@deepseek-ai/dsh-cmdline` ([`packages/boot/cmdline/src/index.ts`](../packages/boot/cmdline/src/index.ts))
|
||||
- `@deepseek-ai/dsh-deque` ([`packages/util/deque/src/index.ts`](../packages/util/deque/src/index.ts))
|
||||
- `@deepseek-ai/dsh-experimental-agent-team-profile` ([`packages/experimental/agent-team-profile/src/index.ts`](../packages/experimental/agent-team-profile/src/index.ts))
|
||||
- `@deepseek-ai/dsh-experimental-agent-team-web-profile` ([`packages/experimental/agent-team-web-profile/src/index.ts`](../packages/experimental/agent-team-web-profile/src/index.ts))
|
||||
- `@deepseek-ai/dsh-experimental-browser-use-runtime` ([`packages/experimental/browser-use-runtime/src/index.ts`](../packages/experimental/browser-use-runtime/src/index.ts))
|
||||
- `@deepseek-ai/dsh-experimental-webworker-packer` ([`packages/experimental/webworker-packer/src/index.ts`](../packages/experimental/webworker-packer/src/index.ts))
|
||||
- `@deepseek-ai/dsh-experimental-webworker-runtime` ([`packages/experimental/webworker-runtime/src/index.ts`](../packages/experimental/webworker-runtime/src/index.ts))
|
||||
|
||||
@@ -225,7 +225,7 @@ export interface Config {
|
||||
|
||||
## `@deepseek-ai/dsh-api-session-controller`
|
||||
|
||||
需要:`agentDefaultModel` · `agents` · `attachments` · `fileUploads` · `llm` · `sessions` · `sessionProjections` · `sessionQuery` · `typert` · `workspaceRegistry`
|
||||
需要:`agentDefaultModel` · `agents` · `attachments` · `fileUploads` · `fs` · `llm` · `sessions` · `sessionProjections` · `sessionQuery` · `typert` · `workspaceRegistry`
|
||||
|
||||
```ts config-catalog
|
||||
/** Session Controller deployment policy. */
|
||||
@@ -235,7 +235,7 @@ export interface Config {
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/api/session-controller/src/index.ts:71`](../packages/api/session-controller/src/index.ts)
|
||||
来源:[`packages/api/session-controller/src/index.ts:73`](../packages/api/session-controller/src/index.ts)
|
||||
|
||||
<a id="deepseek-aidsh-api-settings-controller"></a>
|
||||
|
||||
@@ -902,7 +902,7 @@ export interface Config {
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/fs/fs-local/src/index.ts:43`](../packages/fs/fs-local/src/index.ts)
|
||||
来源:[`packages/fs/fs-local/src/index.ts:45`](../packages/fs/fs-local/src/index.ts)
|
||||
|
||||
<a id="deepseek-aidsh-fs-sandbox"></a>
|
||||
|
||||
@@ -1915,7 +1915,7 @@ export interface PlanModeConfig {
|
||||
依赖: `loader` · `profileContext`
|
||||
|
||||
```ts config-catalog
|
||||
/** The pnpm executable and the limits for package diagnostics and registry lookups. */
|
||||
/** The pnpm executable, the registries asked, and the limits for package diagnostics and registry lookups. */
|
||||
export interface Config {
|
||||
/** The pnpm executable name or path; resolved through `PATH` like the `dsh plugin` command. */
|
||||
pnpmCommand?: string
|
||||
@@ -1925,10 +1925,18 @@ export interface Config {
|
||||
lockWaitMs?: number
|
||||
/** Bound on one registry lookup an inspection runs, in milliseconds. */
|
||||
inspectTimeoutMs?: number
|
||||
/** The registry lookups and installations ask first, as an http(s) URL; absent, the one pnpm's own configuration names. */
|
||||
registry?: string
|
||||
/**
|
||||
* Registries asked in turn, as http(s) URLs, while the one before is unreachable or holds no copy of the package.
|
||||
* A registry outside this set and `registry` is asked alone, and so is the one pnpm's own configuration names
|
||||
* unless that is npm's own registry or one of these.
|
||||
*/
|
||||
fallbackRegistries?: string[]
|
||||
}
|
||||
```
|
||||
|
||||
来源: [`packages/boot/plugin-manager/src/index.ts:33`](../packages/boot/plugin-manager/src/index.ts)
|
||||
来源: [`packages/boot/plugin-manager/src/index.ts:35`](../packages/boot/plugin-manager/src/index.ts)
|
||||
|
||||
<a id="deepseek-aidsh-plugin-package-inventory-deepseek"></a>
|
||||
|
||||
@@ -3958,7 +3966,6 @@ export interface Config {
|
||||
- `@deepseek-ai/dsh-cmdline`([`packages/boot/cmdline/src/index.ts`](../packages/boot/cmdline/src/index.ts))
|
||||
- `@deepseek-ai/dsh-deque`([`packages/util/deque/src/index.ts`](../packages/util/deque/src/index.ts))
|
||||
- `@deepseek-ai/dsh-experimental-agent-team-profile`([`packages/experimental/agent-team-profile/src/index.ts`](../packages/experimental/agent-team-profile/src/index.ts))
|
||||
- `@deepseek-ai/dsh-experimental-agent-team-web-profile`([`packages/experimental/agent-team-web-profile/src/index.ts`](../packages/experimental/agent-team-web-profile/src/index.ts))
|
||||
- `@deepseek-ai/dsh-experimental-browser-use-runtime` ([`packages/experimental/browser-use-runtime/src/index.ts`](../packages/experimental/browser-use-runtime/src/index.ts))
|
||||
- `@deepseek-ai/dsh-experimental-webworker-packer`([`packages/experimental/webworker-packer/src/index.ts`](../packages/experimental/webworker-packer/src/index.ts))
|
||||
- `@deepseek-ai/dsh-experimental-webworker-runtime`([`packages/experimental/webworker-runtime/src/index.ts`](../packages/experimental/webworker-runtime/src/index.ts))
|
||||
|
||||
@@ -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: 1f82bbefe620f10fc8e7d4e4224afa2f9516a410
|
||||
event-producer-consumer.zh.md: 406a983a419d8be655e9e7d14f898269b2b58214
|
||||
event-producer-consumer.md: e7161f6572f2b6ac6e7ecb8022c47815d120f868
|
||||
event-producer-consumer.zh.md: 41a071f3baf0bcb4ce249a81083a87620833ad9d
|
||||
@@ -51,9 +51,9 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `llm/adapters-updated` | `emit` | [`packages/llm/llm/src/types.ts:23`](../packages/llm/llm/src/types.ts) | [`llm`](../packages/llm/llm) (`events.dispatch`) | [`acp`](../packages/acp/acp), [`llm`](../packages/llm/llm), `remotes` |
|
||||
| `llm/stream` | `waterfall` | [`packages/llm/llm/src/index.ts:72`](../packages/llm/llm/src/index.ts) | [`llm`](../packages/llm/llm) (`waterfall`) | [`agent-loop`](../packages/core/agent-loop), [`llm`](../packages/llm/llm), [`llm-replay`](../packages/test-support/llm-replay), [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), [`session-title`](../packages/session/session-title) |
|
||||
| `permission-presets/catalog-changed` | `emit` | [`packages/interaction/permission-presets/src/types.ts:44`](../packages/interaction/permission-presets/src/types.ts) | [`permission-presets`](../packages/interaction/permission-presets) (`events.dispatch`) | `remotes` |
|
||||
| `plugin-manager/changed` | `emit` | [`packages/boot/plugin-manager/src/types.ts:188`](../packages/boot/plugin-manager/src/types.ts) | [`plugin-manager`](../packages/boot/plugin-manager) (`emit`) | `remotes` |
|
||||
| `plugin-manager/install-log` | `emit` | [`packages/boot/plugin-manager/src/types.ts:194`](../packages/boot/plugin-manager/src/types.ts) | [`plugin-manager`](../packages/boot/plugin-manager) (`emit`) | `remotes` |
|
||||
| `plugin-manager/install-state` | `emit` | [`packages/boot/plugin-manager/src/types.ts:200`](../packages/boot/plugin-manager/src/types.ts) | [`plugin-manager`](../packages/boot/plugin-manager) (`emit`) | `remotes` |
|
||||
| `plugin-manager/changed` | `emit` | [`packages/boot/plugin-manager/src/types.ts:223`](../packages/boot/plugin-manager/src/types.ts) | [`plugin-manager`](../packages/boot/plugin-manager) (`emit`) | `remotes` |
|
||||
| `plugin-manager/install-log` | `emit` | [`packages/boot/plugin-manager/src/types.ts:229`](../packages/boot/plugin-manager/src/types.ts) | [`plugin-manager`](../packages/boot/plugin-manager) (`emit`) | `remotes` |
|
||||
| `plugin-manager/install-state` | `emit` | [`packages/boot/plugin-manager/src/types.ts:236`](../packages/boot/plugin-manager/src/types.ts) | [`plugin-manager`](../packages/boot/plugin-manager) (`emit`) | `remotes` |
|
||||
| `session-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`) | - |
|
||||
| `session/created` | `emit` | [`packages/core/session/src/index.ts:50`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`compaction`](../packages/compaction/compaction), [`goal`](../packages/goal/goal), [`hook-protocol`](../packages/hooks/hook-protocol), [`llm-retry`](../packages/llm/llm-retry), [`permission-presets`](../packages/interaction/permission-presets), [`plan-mode`](../packages/plan/plan-mode), [`schedule`](../packages/schedule/schedule), `server`, [`session`](../packages/core/session), `session-controller`, [`session-log-deepseek`](../packages/session/session-log-deepseek), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-telemetry`](../packages/session/session-telemetry), [`session-title`](../packages/session/session-title), [`time-context`](../packages/context/time-context), [`tool-todo`](../packages/todo/tool-todo), [`tool-workflow`](../packages/workflow/tool-workflow), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| `session/disposed` | `emit` | [`packages/core/session/src/index.ts:60`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), `agent-team`, `file-upload`, `session-controller`, [`session-persistence-jsonl`](../packages/session/session-persistence-jsonl), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-telemetry`](../packages/session/session-telemetry), [`session-title`](../packages/session/session-title), [`workspace-changes`](../packages/deliverables/workspace-changes) |
|
||||
@@ -74,7 +74,7 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `tools/pre-execute` | `waterfall` | [`packages/core/tools/src/index.ts:146`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | `auto-review`, [`hooks-claude-code`](../packages/hooks/hooks-claude-code), [`hooks-codex`](../packages/hooks/hooks-codex), [`tool-jobs`](../packages/jobs/tool-jobs), [`workspace-changes`](../packages/deliverables/workspace-changes) |
|
||||
| `tools/ptc-dispatch-log` | `waterfall` | [`packages/core/tools/src/index.ts:183`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`spill-policy`](../packages/spill/spill-policy) |
|
||||
| `tools/result` | `emit` | [`packages/core/tools/src/index.ts:191`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`events.dispatch`) | [`agent-instructions`](../packages/context/agent-instructions), [`subagent-in-process-driver`](../packages/subagent/subagent-in-process-driver), [`tool-present`](../packages/deliverables/tool-present) |
|
||||
| `user-questions/request` | `waterfall` | [`packages/interaction/user-questions/src/types.ts:85`](../packages/interaction/user-questions/src/types.ts) | [`user-questions`](../packages/interaction/user-questions) (`waterfall`) | `remotes` |
|
||||
| `user-questions/request` | `waterfall` | [`packages/interaction/user-questions/src/types.ts:88`](../packages/interaction/user-questions/src/types.ts) | [`user-questions`](../packages/interaction/user-questions) (`waterfall`) | `remotes` |
|
||||
| `webserver/index-inject` | `emit` | [`packages/host/webserver/src/index.ts:34`](../packages/host/webserver/src/index.ts) | `webserver` (`emit`) | `connection`, `inspector`, `modules`, `ui-sidebar-documentpreview` |
|
||||
| `workflow/agent-end` | `emit` | [`packages/workflow/workflow/src/index.ts:79`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | [`tool-workflow`](../packages/workflow/tool-workflow), [`workflow`](../packages/workflow/workflow) |
|
||||
| `workflow/agent-start` | `emit` | [`packages/workflow/workflow/src/index.ts:68`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | [`tool-workflow`](../packages/workflow/tool-workflow), [`workflow`](../packages/workflow/workflow) |
|
||||
|
||||
@@ -53,9 +53,9 @@
|
||||
| `llm/adapters-updated` | `emit` | [`packages/llm/llm/src/types.ts:23`](../packages/llm/llm/src/types.ts) | [`llm`](../packages/llm/llm) (`events.dispatch`) | [`acp`](../packages/acp/acp), [`llm`](../packages/llm/llm), `remotes` |
|
||||
| `llm/stream` | `waterfall` | [`packages/llm/llm/src/index.ts:72`](../packages/llm/llm/src/index.ts) | [`llm`](../packages/llm/llm) (`waterfall`) | [`agent-loop`](../packages/core/agent-loop), [`llm`](../packages/llm/llm), [`llm-replay`](../packages/test-support/llm-replay), [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), [`session-title`](../packages/session/session-title) |
|
||||
| `permission-presets/catalog-changed` | `emit` | [`packages/interaction/permission-presets/src/types.ts:44`](../packages/interaction/permission-presets/src/types.ts) | [`permission-presets`](../packages/interaction/permission-presets) (`events.dispatch`) | `remotes` |
|
||||
| `plugin-manager/changed` | `emit` | [`packages/boot/plugin-manager/src/types.ts:188`](../packages/boot/plugin-manager/src/types.ts) | [`plugin-manager`](../packages/boot/plugin-manager) (`emit`) | `remotes` |
|
||||
| `plugin-manager/install-log` | `emit` | [`packages/boot/plugin-manager/src/types.ts:194`](../packages/boot/plugin-manager/src/types.ts) | [`plugin-manager`](../packages/boot/plugin-manager) (`emit`) | `remotes` |
|
||||
| `plugin-manager/install-state` | `emit` | [`packages/boot/plugin-manager/src/types.ts:200`](../packages/boot/plugin-manager/src/types.ts) | [`plugin-manager`](../packages/boot/plugin-manager) (`emit`) | `remotes` |
|
||||
| `plugin-manager/changed` | `emit` | [`packages/boot/plugin-manager/src/types.ts:223`](../packages/boot/plugin-manager/src/types.ts) | [`plugin-manager`](../packages/boot/plugin-manager) (`emit`) | `remotes` |
|
||||
| `plugin-manager/install-log` | `emit` | [`packages/boot/plugin-manager/src/types.ts:229`](../packages/boot/plugin-manager/src/types.ts) | [`plugin-manager`](../packages/boot/plugin-manager) (`emit`) | `remotes` |
|
||||
| `plugin-manager/install-state` | `emit` | [`packages/boot/plugin-manager/src/types.ts:236`](../packages/boot/plugin-manager/src/types.ts) | [`plugin-manager`](../packages/boot/plugin-manager) (`emit`) | `remotes` |
|
||||
| `session-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`) | - |
|
||||
| `session/created` | `emit` | [`packages/core/session/src/index.ts:50`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`compaction`](../packages/compaction/compaction), [`goal`](../packages/goal/goal), [`hook-protocol`](../packages/hooks/hook-protocol), [`llm-retry`](../packages/llm/llm-retry), [`permission-presets`](../packages/interaction/permission-presets), [`plan-mode`](../packages/plan/plan-mode), [`schedule`](../packages/schedule/schedule), `server`, [`session`](../packages/core/session), `session-controller`, [`session-log-deepseek`](../packages/session/session-log-deepseek), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-telemetry`](../packages/session/session-telemetry), [`session-title`](../packages/session/session-title), [`time-context`](../packages/context/time-context), [`tool-todo`](../packages/todo/tool-todo), [`tool-workflow`](../packages/workflow/tool-workflow), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| `session/disposed` | `emit` | [`packages/core/session/src/index.ts:60`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), `agent-team`, `file-upload`, `session-controller`, [`session-persistence-jsonl`](../packages/session/session-persistence-jsonl), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-telemetry`](../packages/session/session-telemetry), [`session-title`](../packages/session/session-title), [`workspace-changes`](../packages/deliverables/workspace-changes) |
|
||||
@@ -76,7 +76,7 @@
|
||||
| `tools/pre-execute` | `waterfall` | [`packages/core/tools/src/index.ts:146`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | `auto-review`, [`hooks-claude-code`](../packages/hooks/hooks-claude-code), [`hooks-codex`](../packages/hooks/hooks-codex), [`tool-jobs`](../packages/jobs/tool-jobs), [`workspace-changes`](../packages/deliverables/workspace-changes) |
|
||||
| `tools/ptc-dispatch-log` | `waterfall` | [`packages/core/tools/src/index.ts:183`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`spill-policy`](../packages/spill/spill-policy) |
|
||||
| `tools/result` | `emit` | [`packages/core/tools/src/index.ts:191`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`events.dispatch`) | [`agent-instructions`](../packages/context/agent-instructions), [`subagent-in-process-driver`](../packages/subagent/subagent-in-process-driver), [`tool-present`](../packages/deliverables/tool-present) |
|
||||
| `user-questions/request` | `waterfall` | [`packages/interaction/user-questions/src/types.ts:85`](../packages/interaction/user-questions/src/types.ts) | [`user-questions`](../packages/interaction/user-questions) (`waterfall`) | `remotes` |
|
||||
| `user-questions/request` | `waterfall` | [`packages/interaction/user-questions/src/types.ts:88`](../packages/interaction/user-questions/src/types.ts) | [`user-questions`](../packages/interaction/user-questions) (`waterfall`) | `remotes` |
|
||||
| `webserver/index-inject` | `emit` | [`packages/host/webserver/src/index.ts:34`](../packages/host/webserver/src/index.ts) | `webserver` (`emit`) | `connection`, `inspector`, `modules`, `ui-sidebar-documentpreview` |
|
||||
| `workflow/agent-end` | `emit` | [`packages/workflow/workflow/src/index.ts:79`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | [`tool-workflow`](../packages/workflow/tool-workflow), [`workflow`](../packages/workflow/workflow) |
|
||||
| `workflow/agent-start` | `emit` | [`packages/workflow/workflow/src/index.ts:68`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | [`tool-workflow`](../packages/workflow/tool-workflow), [`workflow`](../packages/workflow/workflow) |
|
||||
|
||||
@@ -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: 262e08802c9f1698f897bf1c4797d79c2b972260
|
||||
module-graph.zh.md: 178ad6b2d9f0a1567bf62fb6be66261167e7b929
|
||||
module-graph.md: 3d1f13cbadcb7933be82e6974ea4b46f91697244
|
||||
module-graph.zh.md: d607e1eb450004876a37113d372118d9fae8a18f
|
||||
+14
-15
@@ -232,7 +232,6 @@ flowchart TD
|
||||
subgraph group_experimental["packages/experimental"]
|
||||
pkg_experimental_agent_team["experimental-agent-team"]
|
||||
pkg_experimental_agent_team_profile["experimental-agent-team-profile"]
|
||||
pkg_experimental_agent_team_web_profile["experimental-agent-team-web-profile"]
|
||||
pkg_experimental_auto_review["experimental-auto-review"]
|
||||
pkg_experimental_browser_use_chrome_devtools_mcp["experimental-browser-use-chrome-devtools-mcp"]
|
||||
pkg_experimental_browser_use_playwright_mcp["experimental-browser-use-playwright-mcp"]
|
||||
@@ -1118,18 +1117,6 @@ flowchart TD
|
||||
pkg_compaction_tool_result_pruner --> pkg_llm
|
||||
pkg_compaction_tool_result_pruner --> pkg_session
|
||||
pkg_compaction_tool_result_pruner --> pkg_token_meter
|
||||
pkg_session_reference --> pkg_agent
|
||||
pkg_session_reference --> pkg_compaction
|
||||
pkg_session_reference --> pkg_llm
|
||||
pkg_session_reference --> pkg_output_retention
|
||||
pkg_session_reference --> pkg_session
|
||||
pkg_session_reference --> pkg_session_projection
|
||||
pkg_session_reference --> pkg_session_projection_cache
|
||||
pkg_session_reference --> pkg_session_query
|
||||
pkg_session_reference --> pkg_session_title
|
||||
pkg_session_reference --> pkg_spill
|
||||
pkg_session_reference --> pkg_system_prompt
|
||||
pkg_session_reference --> pkg_typert_protocol
|
||||
pkg_webhook_github --> pkg_credentials
|
||||
pkg_webhook_github --> pkg_host_webserver
|
||||
pkg_webhook_github --> pkg_session
|
||||
@@ -1212,6 +1199,19 @@ flowchart TD
|
||||
pkg_compaction_basic --> pkg_llm
|
||||
pkg_compaction_basic --> pkg_session
|
||||
pkg_compaction_basic --> pkg_token_meter
|
||||
pkg_session_reference --> pkg_agent
|
||||
pkg_session_reference --> pkg_compaction
|
||||
pkg_session_reference --> pkg_llm
|
||||
pkg_session_reference --> pkg_output_retention
|
||||
pkg_session_reference --> pkg_session
|
||||
pkg_session_reference --> pkg_session_projection
|
||||
pkg_session_reference --> pkg_session_projection_cache
|
||||
pkg_session_reference --> pkg_session_query
|
||||
pkg_session_reference --> pkg_session_title
|
||||
pkg_session_reference --> pkg_spill
|
||||
pkg_session_reference --> pkg_subagent
|
||||
pkg_session_reference --> pkg_system_prompt
|
||||
pkg_session_reference --> pkg_typert_protocol
|
||||
pkg_experimental_agent_team --> pkg_agent
|
||||
pkg_experimental_agent_team --> pkg_invariants
|
||||
pkg_experimental_agent_team --> pkg_llm
|
||||
@@ -1383,7 +1383,6 @@ flowchart TD
|
||||
| [`client-web`](../packages/client/web) | `client` | — |
|
||||
| [`office-to-pdf`](../packages/document/office-to-pdf) | `document` | — |
|
||||
| [`experimental-agent-team-profile`](../packages/experimental/agent-team-profile) | `experimental` | — |
|
||||
| [`experimental-agent-team-web-profile`](../packages/experimental/agent-team-web-profile) | `experimental` | — |
|
||||
| [`experimental-webworker-packer`](../packages/experimental/webworker-packer) | `experimental` | — |
|
||||
| [`client-ui-cordis`](../packages/extensions/ui-cordis) | `extensions` | — |
|
||||
| [`cordis-client-runner`](../packages/extensions/cordis-client-runner) | `extensions` | — |
|
||||
@@ -1570,7 +1569,6 @@ flowchart TD
|
||||
| [`plugin-manager`](../packages/boot/plugin-manager) | `boot` | [`brand`](../packages/util/brand), [`hmr`](../packages/boot/hmr), [`host-plugin-inventory`](../packages/host/plugin-inventory), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`subprocess`](../packages/subprocess/subprocess), [`tools`](../packages/core/tools), [`typert-protocol`](../packages/typert/protocol), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| [`headless`](../packages/bundle/headless) | `bundle` | [`agent`](../packages/core/agent), [`agent-default-model`](../packages/core/agent-default-model), [`fs`](../packages/fs/fs), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query) |
|
||||
| [`compaction-tool-result-pruner`](../packages/compaction/compaction-tool-result-pruner) | `compaction` | [`compaction`](../packages/compaction/compaction), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`token-meter`](../packages/llm/token-meter) |
|
||||
| [`session-reference`](../packages/context/session-reference) | `context` | [`agent`](../packages/core/agent), [`compaction`](../packages/compaction/compaction), [`llm`](../packages/llm/llm), [`output-retention`](../packages/util/output-retention), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-query`](../packages/session-query/session-query), [`session-title`](../packages/session/session-title), [`spill`](../packages/spill/spill), [`system-prompt`](../packages/core/system-prompt), [`typert-protocol`](../packages/typert/protocol) |
|
||||
| [`webhook-github`](../packages/webhook/webhook-github) | `webhook` | [`credentials`](../packages/credentials/credentials), [`host-webserver`](../packages/host/webserver), [`session`](../packages/core/session), [`webhook`](../packages/webhook/webhook) |
|
||||
| [`subagent-acp`](../packages/subagent/subagent-acp) | `subagent` | [`agent`](../packages/core/agent), [`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` | [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
@@ -1581,6 +1579,7 @@ flowchart TD
|
||||
| [`hooks-claude-code`](../packages/hooks/hooks-claude-code) | `hooks` | [`agent`](../packages/core/agent), [`hook-protocol`](../packages/hooks/hook-protocol), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`subagent`](../packages/subagent/subagent), [`tools`](../packages/core/tools) |
|
||||
| [`api-session-controller`](../packages/api/session-controller) | `api` | [`agent`](../packages/core/agent), [`agent-default-model`](../packages/core/agent-default-model), [`agent-presets`](../packages/preset/agent-presets), [`api-gateway`](../packages/api/gateway), [`attachment`](../packages/attachment/attachment), [`client-connection`](../packages/client/connection), [`client-file-upload`](../packages/client/file-upload), [`commands`](../packages/interaction/commands), [`file-reference`](../packages/context/file-reference), [`fs`](../packages/fs/fs), [`llm`](../packages/llm/llm), [`native-command`](../packages/util/native-command), [`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), [`session-query`](../packages/session-query/session-query), [`session-title`](../packages/session/session-title), [`skill`](../packages/skill/skill), [`subagent`](../packages/subagent/subagent), [`typert-protocol`](../packages/typert/protocol), [`typert-registry`](../packages/typert/registry), [`util-time`](../packages/util/time), [`util-values`](../packages/util/values), [`util-workspace-path`](../packages/util/workspace-path), [`workspace`](../packages/workspace/workspace) |
|
||||
| [`compaction-basic`](../packages/compaction/compaction-basic) | `compaction` | [`agent`](../packages/core/agent), [`commands`](../packages/interaction/commands), [`compaction`](../packages/compaction/compaction), [`compaction-tool-result-pruner`](../packages/compaction/compaction-tool-result-pruner), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`token-meter`](../packages/llm/token-meter) |
|
||||
| [`session-reference`](../packages/context/session-reference) | `context` | [`agent`](../packages/core/agent), [`compaction`](../packages/compaction/compaction), [`llm`](../packages/llm/llm), [`output-retention`](../packages/util/output-retention), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-query`](../packages/session-query/session-query), [`session-title`](../packages/session/session-title), [`spill`](../packages/spill/spill), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`typert-protocol`](../packages/typert/protocol) |
|
||||
| [`experimental-agent-team`](../packages/experimental/agent-team) | `experimental` | [`agent`](../packages/core/agent), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`subagent`](../packages/subagent/subagent), [`typert-protocol`](../packages/typert/protocol) |
|
||||
| [`sdk-protocol`](../packages/sdk/protocol) | `sdk` | [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent) |
|
||||
| [`tool-ralph`](../packages/workflow/tool-ralph) | `workflow` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`workflow`](../packages/workflow/workflow) |
|
||||
|
||||
+14
-15
@@ -234,7 +234,6 @@ flowchart TD
|
||||
subgraph group_experimental["packages/experimental"]
|
||||
pkg_experimental_agent_team["experimental-agent-team"]
|
||||
pkg_experimental_agent_team_profile["experimental-agent-team-profile"]
|
||||
pkg_experimental_agent_team_web_profile["experimental-agent-team-web-profile"]
|
||||
pkg_experimental_auto_review["experimental-auto-review"]
|
||||
pkg_experimental_browser_use_chrome_devtools_mcp["experimental-browser-use-chrome-devtools-mcp"]
|
||||
pkg_experimental_browser_use_playwright_mcp["experimental-browser-use-playwright-mcp"]
|
||||
@@ -1120,18 +1119,6 @@ flowchart TD
|
||||
pkg_compaction_tool_result_pruner --> pkg_llm
|
||||
pkg_compaction_tool_result_pruner --> pkg_session
|
||||
pkg_compaction_tool_result_pruner --> pkg_token_meter
|
||||
pkg_session_reference --> pkg_agent
|
||||
pkg_session_reference --> pkg_compaction
|
||||
pkg_session_reference --> pkg_llm
|
||||
pkg_session_reference --> pkg_output_retention
|
||||
pkg_session_reference --> pkg_session
|
||||
pkg_session_reference --> pkg_session_projection
|
||||
pkg_session_reference --> pkg_session_projection_cache
|
||||
pkg_session_reference --> pkg_session_query
|
||||
pkg_session_reference --> pkg_session_title
|
||||
pkg_session_reference --> pkg_spill
|
||||
pkg_session_reference --> pkg_system_prompt
|
||||
pkg_session_reference --> pkg_typert_protocol
|
||||
pkg_webhook_github --> pkg_credentials
|
||||
pkg_webhook_github --> pkg_host_webserver
|
||||
pkg_webhook_github --> pkg_session
|
||||
@@ -1214,6 +1201,19 @@ flowchart TD
|
||||
pkg_compaction_basic --> pkg_llm
|
||||
pkg_compaction_basic --> pkg_session
|
||||
pkg_compaction_basic --> pkg_token_meter
|
||||
pkg_session_reference --> pkg_agent
|
||||
pkg_session_reference --> pkg_compaction
|
||||
pkg_session_reference --> pkg_llm
|
||||
pkg_session_reference --> pkg_output_retention
|
||||
pkg_session_reference --> pkg_session
|
||||
pkg_session_reference --> pkg_session_projection
|
||||
pkg_session_reference --> pkg_session_projection_cache
|
||||
pkg_session_reference --> pkg_session_query
|
||||
pkg_session_reference --> pkg_session_title
|
||||
pkg_session_reference --> pkg_spill
|
||||
pkg_session_reference --> pkg_subagent
|
||||
pkg_session_reference --> pkg_system_prompt
|
||||
pkg_session_reference --> pkg_typert_protocol
|
||||
pkg_experimental_agent_team --> pkg_agent
|
||||
pkg_experimental_agent_team --> pkg_invariants
|
||||
pkg_experimental_agent_team --> pkg_llm
|
||||
@@ -1385,7 +1385,6 @@ flowchart TD
|
||||
| [`client-web`](../packages/client/web) | `client` | — |
|
||||
| [`office-to-pdf`](../packages/document/office-to-pdf) | `document` | — |
|
||||
| [`experimental-agent-team-profile`](../packages/experimental/agent-team-profile) | `experimental` | — |
|
||||
| [`experimental-agent-team-web-profile`](../packages/experimental/agent-team-web-profile) | `experimental` | — |
|
||||
| [`experimental-webworker-packer`](../packages/experimental/webworker-packer) | `experimental` | — |
|
||||
| [`client-ui-cordis`](../packages/extensions/ui-cordis) | `extensions` | — |
|
||||
| [`cordis-client-runner`](../packages/extensions/cordis-client-runner) | `extensions` | — |
|
||||
@@ -1572,7 +1571,6 @@ flowchart TD
|
||||
| [`plugin-manager`](../packages/boot/plugin-manager) | `boot` | [`brand`](../packages/util/brand), [`hmr`](../packages/boot/hmr), [`host-plugin-inventory`](../packages/host/plugin-inventory), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`subprocess`](../packages/subprocess/subprocess), [`tools`](../packages/core/tools), [`typert-protocol`](../packages/typert/protocol), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| [`headless`](../packages/bundle/headless) | `bundle` | [`agent`](../packages/core/agent), [`agent-default-model`](../packages/core/agent-default-model), [`fs`](../packages/fs/fs), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query) |
|
||||
| [`compaction-tool-result-pruner`](../packages/compaction/compaction-tool-result-pruner) | `compaction` | [`compaction`](../packages/compaction/compaction), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`token-meter`](../packages/llm/token-meter) |
|
||||
| [`session-reference`](../packages/context/session-reference) | `context` | [`agent`](../packages/core/agent), [`compaction`](../packages/compaction/compaction), [`llm`](../packages/llm/llm), [`output-retention`](../packages/util/output-retention), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-query`](../packages/session-query/session-query), [`session-title`](../packages/session/session-title), [`spill`](../packages/spill/spill), [`system-prompt`](../packages/core/system-prompt), [`typert-protocol`](../packages/typert/protocol) |
|
||||
| [`webhook-github`](../packages/webhook/webhook-github) | `webhook` | [`credentials`](../packages/credentials/credentials), [`host-webserver`](../packages/host/webserver), [`session`](../packages/core/session), [`webhook`](../packages/webhook/webhook) |
|
||||
| [`subagent-acp`](../packages/subagent/subagent-acp) | `subagent` | [`agent`](../packages/core/agent), [`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` | [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
@@ -1583,6 +1581,7 @@ flowchart TD
|
||||
| [`hooks-claude-code`](../packages/hooks/hooks-claude-code) | `hooks` | [`agent`](../packages/core/agent), [`hook-protocol`](../packages/hooks/hook-protocol), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`subagent`](../packages/subagent/subagent), [`tools`](../packages/core/tools) |
|
||||
| [`api-session-controller`](../packages/api/session-controller) | `api` | [`agent`](../packages/core/agent), [`agent-default-model`](../packages/core/agent-default-model), [`agent-presets`](../packages/preset/agent-presets), [`api-gateway`](../packages/api/gateway), [`attachment`](../packages/attachment/attachment), [`client-connection`](../packages/client/connection), [`client-file-upload`](../packages/client/file-upload), [`commands`](../packages/interaction/commands), [`file-reference`](../packages/context/file-reference), [`fs`](../packages/fs/fs), [`llm`](../packages/llm/llm), [`native-command`](../packages/util/native-command), [`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), [`session-query`](../packages/session-query/session-query), [`session-title`](../packages/session/session-title), [`skill`](../packages/skill/skill), [`subagent`](../packages/subagent/subagent), [`typert-protocol`](../packages/typert/protocol), [`typert-registry`](../packages/typert/registry), [`util-time`](../packages/util/time), [`util-values`](../packages/util/values), [`util-workspace-path`](../packages/util/workspace-path), [`workspace`](../packages/workspace/workspace) |
|
||||
| [`compaction-basic`](../packages/compaction/compaction-basic) | `compaction` | [`agent`](../packages/core/agent), [`commands`](../packages/interaction/commands), [`compaction`](../packages/compaction/compaction), [`compaction-tool-result-pruner`](../packages/compaction/compaction-tool-result-pruner), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`token-meter`](../packages/llm/token-meter) |
|
||||
| [`session-reference`](../packages/context/session-reference) | `context` | [`agent`](../packages/core/agent), [`compaction`](../packages/compaction/compaction), [`llm`](../packages/llm/llm), [`output-retention`](../packages/util/output-retention), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-query`](../packages/session-query/session-query), [`session-title`](../packages/session/session-title), [`spill`](../packages/spill/spill), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`typert-protocol`](../packages/typert/protocol) |
|
||||
| [`experimental-agent-team`](../packages/experimental/agent-team) | `experimental` | [`agent`](../packages/core/agent), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`subagent`](../packages/subagent/subagent), [`typert-protocol`](../packages/typert/protocol) |
|
||||
| [`sdk-protocol`](../packages/sdk/protocol) | `sdk` | [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent) |
|
||||
| [`tool-ralph`](../packages/workflow/tool-ralph) | `workflow` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`workflow`](../packages/workflow/workflow) |
|
||||
|
||||
@@ -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/agent-team.md
|
||||
agent-team.md: 6f20ee11cbaf66028a5a3123d1682a0e9a87b014
|
||||
agent-team.zh.md: 5f2cfae582f275f25380cbe996f5bad711c0f917
|
||||
agent-team.md: 653bbbcad50d723690c013161a0c25eea301ff0b
|
||||
agent-team.zh.md: e9ef2d5dc824a81d1c666d0ea7a270c0cfe2c92e
|
||||
@@ -21,7 +21,7 @@ interface TeamMemberSnapshot {
|
||||
}
|
||||
```
|
||||
|
||||
Every member starts in `provisioning` and reaches exactly one terminal roster phase, `active` or `failed`. Runtime `running`/`idle`/`inactive` status is derived separately and never rewrites this record.
|
||||
Every member starts in `provisioning` and reaches exactly one terminal roster phase, `active` or `failed`. Roster `running`/`inactive` status is derived separately and never rewrites this record.
|
||||
|
||||
## Durable mailbox
|
||||
|
||||
@@ -38,7 +38,7 @@ interface TeamMessageSnapshot {
|
||||
}
|
||||
```
|
||||
|
||||
Every message attempts Steer delivery. A running target receives it at the nearest step boundary, an idle target starts a turn, and an inactive teammate cold-resumes. Scheduling is not stored in the durable record because callers cannot select another mode.
|
||||
Every message attempts Steer delivery. A running target receives it at the nearest step boundary; an inactive target starts a turn if loaded or cold-resumes otherwise. Scheduling is not stored in the durable record because callers cannot select another mode.
|
||||
|
||||
The target Session keeps message identity and sender attribution on both the pending inbox item and the eventual user message. Folding that source across inbox and history is the target-side de-duplication key; the model-visible framing repeats the id and sender.
|
||||
|
||||
@@ -168,7 +168,7 @@ async waitForChange(caller: Agent, timeoutMs: number, signal: AbortSignal): Prom
|
||||
* @param targetName - durable teammate name.
|
||||
* @returns the target status sampled before cancellation.
|
||||
*/
|
||||
interrupt(caller: Agent, targetName: string): { previousStatus: 'running' | 'idle' | 'inactive' }
|
||||
interrupt(caller: Agent, targetName: string): { previousStatus: 'running' | 'inactive' }
|
||||
|
||||
/**
|
||||
* Resolve a caller without throwing, used by scoped-tool installation and observers.
|
||||
|
||||
@@ -21,7 +21,7 @@ interface TeamMemberSnapshot {
|
||||
}
|
||||
```
|
||||
|
||||
每个 member 都从 `provisioning` 开始,并且只到达一个终态 roster phase:`active` 或 `failed`。运行时 `running`/`idle`/`inactive` 状态单独派生,绝不会重写该记录。
|
||||
每个 member 都从 `provisioning` 开始,并且只到达一个终态 roster phase:`active` 或 `failed`。roster 的 `running`/`inactive` 状态单独派生,绝不会重写该记录。
|
||||
|
||||
## 持久 mailbox
|
||||
|
||||
@@ -38,7 +38,7 @@ interface TeamMessageSnapshot {
|
||||
}
|
||||
```
|
||||
|
||||
每条消息都会尝试 Steer 投递。running target 在最近的步骤边界收到消息,idle target 启动一个轮次,inactive teammate 则冷恢复。调用方不能选择其他模式,因此持久记录不存储调度方式。
|
||||
每条消息都会尝试 Steer 投递。running target 在最近的步骤边界收到消息,inactive target 在已加载时启动一个轮次,否则冷恢复。调用方不能选择其他模式,因此持久记录不存储调度方式。
|
||||
|
||||
target Session 会在 pending inbox 条目和最终用户消息上保留消息身份与发送者归因。跨 inbox 与历史折叠该 source 构成 target 侧去重键;模型可见的 framing 会重复 id 和发送者。
|
||||
|
||||
@@ -168,7 +168,7 @@ async waitForChange(caller: Agent, timeoutMs: number, signal: AbortSignal): Prom
|
||||
* @param targetName - durable teammate name.
|
||||
* @returns the target status sampled before cancellation.
|
||||
*/
|
||||
interrupt(caller: Agent, targetName: string): { previousStatus: 'running' | 'idle' | 'inactive' }
|
||||
interrupt(caller: Agent, targetName: string): { previousStatus: 'running' | 'inactive' }
|
||||
|
||||
/**
|
||||
* Resolve a caller without throwing, used by scoped-tool installation and observers.
|
||||
|
||||
@@ -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/boot.md
|
||||
boot.md: 6bceb5deb087d49dff6958d51549c7942d0e224a
|
||||
boot.zh.md: c3addc59008e9f7e5812f5f2eefbc751cd731fba
|
||||
boot.md: 90ad5c760823e2451e7d138288778c0b2bfa625f
|
||||
boot.zh.md: 7a08fb8a8640ba0a6ad8c174ac7eb2fe433f6ab6
|
||||
+25
-9
@@ -12,9 +12,11 @@ The [boot package group](../../packages/boot/README.md) owns launcher-provided p
|
||||
|
||||
`BundleInfo` carries the package name, optional installed version, selected enablement, removal availability and optional resolution error.
|
||||
|
||||
`InstallBundleOptions.enabled` defaults to true. False installs without selecting the bundle layer. `approvedBuilds` grants persistent script permission to the supplied pending package names before installation.
|
||||
`InstallBundleOptions.enabled` defaults to true. False installs without selecting the bundle layer. `approvedBuilds` grants persistent script permission to the supplied pending package names before installation. `registry` names the registry asked first; absent, the configured one.
|
||||
|
||||
`ChangeResult.changed` reports a disk edit independently of `application`: `applied`, `restart-required`, `overridden` or `failed`. Optional `error` carries a localizable code and external diagnostic. `packageResult` records the pnpm exit code, bounded output, truncation flag and complete diagnostic log path. `pendingBuilds` lists undecided packages across the profile; `approvedBuilds` records the names granted permission by this operation.
|
||||
`PluginRegistries` carries the configured first registry, `null` for the one pnpm's own configuration names, the fallbacks asked after it, and `resolved`, the URL pnpm's own configuration names or `null` while unread. `InspectOptions.registry` names the registry a lookup asks first.
|
||||
|
||||
`ChangeResult.changed` reports a disk edit independently of `application`: `applied`, `restart-required`, `overridden` or `failed`. Optional `error` carries a localizable code and external diagnostic. `packageResult` records the pnpm exit code, bounded output, truncation flag and complete diagnostic log path. `pendingBuilds` lists undecided packages across the profile; `approvedBuilds` records the names granted permission by this operation; `registries` lists the registries an installation asked, in order; `failedAt` says whether the last failed run could not reach the registry it asked or the host a git or tarball spec is fetched from.
|
||||
|
||||
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
||||
|
||||
@@ -72,12 +74,18 @@ Manage profile files and apply their declared reload lifecycle.
|
||||
*/
|
||||
@Remote listBundles(): Promise<BundleInfo[]>
|
||||
|
||||
/** Read the registries this manager asks: the configured first one, its fallbacks in order, and what pnpm's own configuration names.
|
||||
* @returns The registries in pnpm's comparison form; null is the one pnpm's own configuration names, `resolved` as pnpm reads it now.
|
||||
*/
|
||||
@Remote async registries(): Promise<PluginRegistries>
|
||||
|
||||
/** Read what a spec names before installing it.
|
||||
* @param spec One package spec: a registry name, an absolute path, a git address, or a tarball.
|
||||
* @param options The registry asked first.
|
||||
* @param signal Ends a registry lookup early.
|
||||
* @returns The package the spec names, or why it is refused.
|
||||
*/
|
||||
@Remote async inspect(spec: string, signal?: AbortSignal): Promise<PluginSpecInspection>
|
||||
@Remote async inspect(spec: string, options?: InspectOptions, signal?: AbortSignal): Promise<PluginSpecInspection>
|
||||
|
||||
/** Persist a plugin entry's desired enablement and apply it on live profiles.
|
||||
* @param id Loader entry identity returned by listPlugins.
|
||||
@@ -98,12 +106,19 @@ Manage profile files and apply their declared reload lifecycle.
|
||||
* that fails, is cancelled, or adds a package without a bundle patch restores
|
||||
* `package.json` and `pnpm-lock.yaml` as they were; downloaded files can stay.
|
||||
* @param spec One package spec, including local paths relative to the invocation directory.
|
||||
* @param options Whether to activate the installed bundle (defaults to true), the request id a cancellation names, and
|
||||
* the pending build scripts to allow for this profile before pnpm runs.
|
||||
* @returns Package-manager diagnostics and observed activation outcome.
|
||||
* @param options Whether to activate the installed bundle (defaults to true), the request id a cancellation names,
|
||||
* the pending build scripts to allow for this profile before pnpm runs, and the registry asked first.
|
||||
* @returns Package-manager diagnostics, the registries asked, and the observed activation outcome.
|
||||
*/
|
||||
@Remote installBundle(spec: string, options?: InstallBundleOptions): Promise<ChangeResult>
|
||||
|
||||
/** Recover the result of an active installation without cancelling it.
|
||||
* @param requestId The id supplied when installation started.
|
||||
* @returns The installation's outcome after it settles, or null if no active request has that id.
|
||||
* Completed results are not retained; null establishes neither success nor cancellation.
|
||||
*/
|
||||
@Remote async waitForInstall(requestId: PluginInstallRequestId): Promise<ChangeResult | null>
|
||||
|
||||
/** Stop an installation this manager owns and wait until its files are back.
|
||||
* @param requestId The id the installation was started with.
|
||||
* @returns `cancelled` once pnpm exited and the files are restored, `too-late` once the bundle is being
|
||||
@@ -208,13 +223,14 @@ Source: [`packages/boot/plugin-manager/src/types.ts`](../../packages/boot/plugin
|
||||
|
||||
#### `plugin-manager/install-state` — emit
|
||||
|
||||
An installation moved between its Host phases.
|
||||
An installation moved between its Host phases. `installing` is announced once per registry the installation asks, with the attempt's registry and position; `cancelling` and `applying` once.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* An installation moved between its Host phases.
|
||||
* An installation moved between its Host phases. `installing` is announced once per registry the
|
||||
* installation asks, with the attempt's registry and position; `cancelling` and `applying` once.
|
||||
* @mode emit
|
||||
* @param progress - the installation's request id and phase.
|
||||
* @param progress - the installation's request id and phase, with the attempt while installing.
|
||||
*/
|
||||
'plugin-manager/install-state'(progress: PluginInstallProgress): void
|
||||
```
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
|
||||
`BundleInfo` 包含包名、可选的安装版本、组合层选择状态、删除可用性及可选的解析错误。
|
||||
|
||||
`InstallBundleOptions.enabled` 默认为 true,false 表示安装但不选择组合包层。`approvedBuilds` 在安装前向指定的待审批包名授予持久脚本权限。
|
||||
`InstallBundleOptions.enabled` 默认为 true,false 表示安装但不选择组合包层。`approvedBuilds` 在安装前向指定的待审批包名授予持久脚本权限。`registry` 指定首先询问的注册表;缺省为配置的那个。
|
||||
|
||||
`ChangeResult.changed` 报告磁盘修改,独立于 `application`:`applied`、`restart-required`、`overridden` 或 `failed`。可选的 `error` 包含可本地化的错误码和外部诊断。`packageResult` 记录 pnpm 退出码、有界输出、截断标志及完整诊断日志路径。`pendingBuilds` 列出整个 profile 尚未决定的包;`approvedBuilds` 记录本次操作授予权限的包名。
|
||||
`PluginRegistries` 携带配置的第一个注册表(`null` 即 pnpm 自身配置指定的那个)、随后依次询问的备选注册表,以及 `resolved`——pnpm 自身配置指向的 URL,未读到时为 `null`。`InspectOptions.registry` 指定一次查询首先询问的注册表。
|
||||
|
||||
`ChangeResult.changed` 报告磁盘修改,独立于 `application`:`applied`、`restart-required`、`overridden` 或 `failed`。可选的 `error` 包含可本地化的错误码和外部诊断。`packageResult` 记录 pnpm 退出码、有界输出、截断标志及完整诊断日志路径。`pendingBuilds` 列出整个 profile 尚未决定的包;`approvedBuilds` 记录本次操作授予权限的包名;`registries` 按顺序列出一次安装问过的注册表;`failedAt` 说明最后一次失败的运行连不上的是所问的注册表,还是 git 或 tarball spec 自身拉取的主机。
|
||||
|
||||
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
||||
|
||||
@@ -72,12 +74,18 @@ Manage profile files and apply their declared reload lifecycle.
|
||||
*/
|
||||
@Remote listBundles(): Promise<BundleInfo[]>
|
||||
|
||||
/** Read the registries this manager asks: the configured first one, its fallbacks in order, and what pnpm's own configuration names.
|
||||
* @returns The registries in pnpm's comparison form; null is the one pnpm's own configuration names, `resolved` as pnpm reads it now.
|
||||
*/
|
||||
@Remote async registries(): Promise<PluginRegistries>
|
||||
|
||||
/** Read what a spec names before installing it.
|
||||
* @param spec One package spec: a registry name, an absolute path, a git address, or a tarball.
|
||||
* @param options The registry asked first.
|
||||
* @param signal Ends a registry lookup early.
|
||||
* @returns The package the spec names, or why it is refused.
|
||||
*/
|
||||
@Remote async inspect(spec: string, signal?: AbortSignal): Promise<PluginSpecInspection>
|
||||
@Remote async inspect(spec: string, options?: InspectOptions, signal?: AbortSignal): Promise<PluginSpecInspection>
|
||||
|
||||
/** Persist a plugin entry's desired enablement and apply it on live profiles.
|
||||
* @param id Loader entry identity returned by listPlugins.
|
||||
@@ -98,12 +106,19 @@ Manage profile files and apply their declared reload lifecycle.
|
||||
* that fails, is cancelled, or adds a package without a bundle patch restores
|
||||
* `package.json` and `pnpm-lock.yaml` as they were; downloaded files can stay.
|
||||
* @param spec One package spec, including local paths relative to the invocation directory.
|
||||
* @param options Whether to activate the installed bundle (defaults to true), the request id a cancellation names, and
|
||||
* the pending build scripts to allow for this profile before pnpm runs.
|
||||
* @returns Package-manager diagnostics and observed activation outcome.
|
||||
* @param options Whether to activate the installed bundle (defaults to true), the request id a cancellation names,
|
||||
* the pending build scripts to allow for this profile before pnpm runs, and the registry asked first.
|
||||
* @returns Package-manager diagnostics, the registries asked, and the observed activation outcome.
|
||||
*/
|
||||
@Remote installBundle(spec: string, options?: InstallBundleOptions): Promise<ChangeResult>
|
||||
|
||||
/** Recover the result of an active installation without cancelling it.
|
||||
* @param requestId The id supplied when installation started.
|
||||
* @returns The installation's outcome after it settles, or null if no active request has that id.
|
||||
* Completed results are not retained; null establishes neither success nor cancellation.
|
||||
*/
|
||||
@Remote async waitForInstall(requestId: PluginInstallRequestId): Promise<ChangeResult | null>
|
||||
|
||||
/** Stop an installation this manager owns and wait until its files are back.
|
||||
* @param requestId The id the installation was started with.
|
||||
* @returns `cancelled` once pnpm exited and the files are restored, `too-late` once the bundle is being
|
||||
@@ -208,13 +223,14 @@ Source: [`packages/boot/plugin-manager/src/types.ts`](../../packages/boot/plugin
|
||||
|
||||
#### `plugin-manager/install-state` — emit
|
||||
|
||||
An installation moved between its Host phases.
|
||||
An installation moved between its Host phases. `installing` is announced once per registry the installation asks, with the attempt's registry and position; `cancelling` and `applying` once.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* An installation moved between its Host phases.
|
||||
* An installation moved between its Host phases. `installing` is announced once per registry the
|
||||
* installation asks, with the attempt's registry and position; `cancelling` and `applying` once.
|
||||
* @mode emit
|
||||
* @param progress - the installation's request id and phase.
|
||||
* @param progress - the installation's request id and phase, with the attempt while installing.
|
||||
*/
|
||||
'plugin-manager/install-state'(progress: PluginInstallProgress): void
|
||||
```
|
||||
|
||||
@@ -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: 89f3e675628bca71f001170b5efabb241134dfb0
|
||||
client-modules.zh.md: 1a41b4bd061ebf83f80c6f7c1633932da13b5942
|
||||
client-modules.md: 5a62340ff3baa3cd2ed63d453fe2a055b2753ac0
|
||||
client-modules.zh.md: b5a145460f30f3de6be6434315b94c01e04f6378
|
||||
@@ -22,7 +22,10 @@ The graph is the wire single source between the Node and browser halves. The hos
|
||||
interface WebBootEntry {
|
||||
/** Entry name == package name. */
|
||||
id: string
|
||||
/** Revisioned single-resource combo endpoint used by HMR. */
|
||||
/**
|
||||
* Revisioned single-resource combo reference used by HMR. It is relative to
|
||||
* the document, so the browser resolves it under whatever mount served the page.
|
||||
*/
|
||||
url: string
|
||||
/** Opaque plugin-artifact revision used for HMR cache busting. */
|
||||
rev: string
|
||||
@@ -45,7 +48,7 @@ type WebBootBatchPhase = 'bootstrap' | 'application'
|
||||
interface WebBootBatch {
|
||||
/** Parser-blocking bootstrap or preloaded application scheduling. */
|
||||
phase: WebBootBatchPhase
|
||||
/** Revisioned combo script endpoint. */
|
||||
/** Content-addressed combo script reference, document-relative like {@link WebBootEntry.url}. */
|
||||
url: string
|
||||
/** Revision derived from the ordered entry revisions. */
|
||||
rev: string
|
||||
@@ -82,7 +85,7 @@ Package metadata — including the negative "not a client package" verdict — i
|
||||
|
||||
## The bundle route and index injection
|
||||
|
||||
`GET`/`HEAD /plugins/??<package-a>/client.js,<package-b>/client.js&rev=<rev>` addresses one generated combo script; a one-resource request uses the same form and is the HMR path. The script is concatenated once on its first `GET` and ends with an absolute `sourceMappingURL` whose resource suffixes are `.js.map`. The map files are not read by startup, index rendering, script `GET`, or `HEAD`; the first map `GET` reads and validates them, composes one Indexed Source Map v3, and caches that body. An authored component map supplies its section; a component without one receives an identity section whose `sourcesContent` is the captured bundle and whose source name is its packaged `sourceURL` or plugin route. Every startup request URL is at most 3 KiB measured as UTF-8 bytes; partitioning uses the longer map form. All application URLs are preloaded, and all bootstrap URLs execute before the graph global and Vite entry. Materialized responses use long-lived immutable caching. Unknown or altered resource lists, missing revisions, and stale revisions answer 404 rather than serving different bytes or letting the SPA fallback return HTML as JavaScript; other methods are 405. The injection rows carry the current graph on every index render, so a reload always boots against the live composition.
|
||||
`GET`/`HEAD /plugins/??<package-a>/client.js,<package-b>/client.js&rev=<rev>` addresses one generated combo script; a one-resource request uses the same form and is the HMR path. The script is concatenated once on its first `GET` and ends with a `sourceMappingURL` that carries the combo query alone — `??<package-a>/client.js.map,<package-b>/client.js.map&rev=<rev>`, resolved against the script's own directory rather than the document. The map files are not read by startup, index rendering, script `GET`, or `HEAD`; the first map `GET` reads and validates them, composes one Indexed Source Map v3, and caches that body. An authored component map supplies its section; a component without one receives an identity section whose `sourcesContent` is the captured bundle and whose source name is its packaged `sourceURL` or plugin route. Every startup request URL is at most 3 KiB measured as UTF-8 bytes; partitioning uses the longer map form. All application URLs are preloaded, and all bootstrap URLs execute before the graph global and Vite entry. Materialized responses use long-lived immutable caching. Unknown or altered resource lists, missing revisions, and stale revisions answer 404 rather than serving different bytes or letting the SPA fallback return HTML as JavaScript; other methods are 405. The injection rows carry the current graph on every index render, so a reload always boots against the live composition.
|
||||
|
||||
## The service
|
||||
|
||||
|
||||
@@ -22,7 +22,10 @@ Web 插件表:[dsh-client-modules](../../packages/client/modules) 中 client
|
||||
interface WebBootEntry {
|
||||
/** Entry name == package name. */
|
||||
id: string
|
||||
/** Revisioned single-resource combo endpoint used by HMR. */
|
||||
/**
|
||||
* Revisioned single-resource combo reference used by HMR. It is relative to
|
||||
* the document, so the browser resolves it under whatever mount served the page.
|
||||
*/
|
||||
url: string
|
||||
/** Opaque plugin-artifact revision used for HMR cache busting. */
|
||||
rev: string
|
||||
@@ -45,7 +48,7 @@ type WebBootBatchPhase = 'bootstrap' | 'application'
|
||||
interface WebBootBatch {
|
||||
/** Parser-blocking bootstrap or preloaded application scheduling. */
|
||||
phase: WebBootBatchPhase
|
||||
/** Revisioned combo script endpoint. */
|
||||
/** Content-addressed combo script reference, document-relative like {@link WebBootEntry.url}. */
|
||||
url: string
|
||||
/** Revision derived from the ordered entry revisions. */
|
||||
rev: string
|
||||
@@ -82,7 +85,7 @@ interface WebBootGraph {
|
||||
|
||||
## bundle 路由与 index 注入
|
||||
|
||||
`GET`/`HEAD /plugins/??<package-a>/client.js,<package-b>/client.js&rev=<rev>` 寻址一份生成的 combo 脚本;单资源请求采用同一形式,也是 HMR 路径。脚本在首次 `GET` 时只拼接一次,并以绝对 `sourceMappingURL` 结尾,其中每个资源后缀改为 `.js.map`。启动、index 渲染、脚本 `GET` 和 `HEAD` 都不会读取 map 文件;首次 map `GET` 才会读取并校验这些文件、组合一份 Indexed Source Map v3,并缓存该 body。组件有自带 map 时直接用于对应 section;没有时则获得 identity section,其 `sourcesContent` 是捕获的 bundle,source 名取打包后的 `sourceURL` 或插件路由。每条启动请求 URL 按 UTF-8 字节计算都不超过 3 KiB;切分按更长的 map 形式计算。所有 application URL 都会预加载,所有 bootstrap URL 都会在图全局量与 Vite entry 之前执行。已物化响应使用长期 immutable 缓存。未知或被修改的资源列表、缺少 revision 及陈旧 revision 都返回 404,绝不提供其他字节,也不会让 SPA fallback 把 HTML 当作 JavaScript 返回;其他方法返回 405。注入行在每次 index 渲染时携带当前图,因此重新加载总是基于实时组合启动。
|
||||
`GET`/`HEAD /plugins/??<package-a>/client.js,<package-b>/client.js&rev=<rev>` 寻址一份生成的 combo 脚本;单资源请求采用同一形式,也是 HMR 路径。脚本在首次 `GET` 时只拼接一次,并以 `sourceMappingURL` 结尾,该引用只携带 combo 查询串——`??<package-a>/client.js.map,<package-b>/client.js.map&rev=<rev>`,按脚本自身目录而非文档解析。启动、index 渲染、脚本 `GET` 和 `HEAD` 都不会读取 map 文件;首次 map `GET` 才会读取并校验这些文件、组合一份 Indexed Source Map v3,并缓存该 body。组件有自带 map 时直接用于对应 section;没有时则获得 identity section,其 `sourcesContent` 是捕获的 bundle,source 名取打包后的 `sourceURL` 或插件路由。每条启动请求 URL 按 UTF-8 字节计算都不超过 3 KiB;切分按更长的 map 形式计算。所有 application URL 都会预加载,所有 bootstrap URL 都会在图全局量与 Vite entry 之前执行。已物化响应使用长期 immutable 缓存。未知或被修改的资源列表、缺少 revision 及陈旧 revision 都返回 404,绝不提供其他字节,也不会让 SPA fallback 把 HTML 当作 JavaScript 返回;其他方法返回 405。注入行在每次 index 渲染时携带当前图,因此重新加载总是基于实时组合启动。
|
||||
|
||||
## 服务
|
||||
|
||||
|
||||
@@ -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-resources.md
|
||||
client-resources.md: d89ba6af433cd41066835be85d348b8fdf2afef0
|
||||
client-resources.zh.md: 6bfbb3e4470f89c1a90853427ca6f3a684120b3e
|
||||
client-resources.md: 09acaf72eb5ee6f6003d9b275afa8a73f0822771
|
||||
client-resources.zh.md: 4a0e30d2d885d143b1bc59ca58f59fd8d1f3e9b7
|
||||
@@ -15,6 +15,7 @@ A resource address is a `dsh-resource://<type>/…` URL. The host names the prot
|
||||
| `dsh-resource://file/session/s1/notes/a.md` | `file` | the metadata of `notes/a.md` under session `s1`'s workspace root, when the `file` provider is registered |
|
||||
| `dsh-resource://file/absolute/home/me/notes.md` | `file` | parseable but fails with `workspace-file/unknown-workspace`: no authorizing Session, and neither current nor Tab Session is borrowed |
|
||||
| `DSH-RESOURCE://File/session/s1/a` | `file` | a distinct record: addresses compare as strings, and `openResource` accepts only the canonical lower-case spelling that `fileAddressFor` emits |
|
||||
| `dsh-resource://subagentchat/session/c1?parent=p1&mode=continuable` | `subagentchat` | an addressed subagent Conversation whose value owns a `SessionReference` until the resource closes |
|
||||
| `sidebar://guide` | — | `none`: a navigation address |
|
||||
| `/home/me/notes.md` | — | `none`: not a URL |
|
||||
|
||||
@@ -84,7 +85,7 @@ A consumer presents `failed` itself: the model keeps the last value beside the f
|
||||
|
||||
A resource is alive while it has a holder: a subscribed `useResource`, or a pin. `ctx.resources.pin(address, signal)` keeps a resource open without subscribing until `signal` aborts, and an already-aborted signal pins nothing; the right Sidebar pins every open tab record's address for the record's life, so switching tabs unmounts a body without closing its stream. The first holder opens the provider's stream; the last release aborts it, discards the value, and returns the snapshot to `loading` (provider present) or `none` (absent). A frame the provider yields after that release is dropped, and the iterator is returned. `ctx.resources.source(address)` is the bare observable behind the hook, reference-stable per address, for callers outside React; reading its snapshot does not hold the resource ([lifecycle](../../packages/client/resources/README.md#lifecycle)).
|
||||
|
||||
Streams carry metadata, not content. The `file` provider's value is `WorkspaceFileStat { absolutePath, version, bytes? }`: the first frame comes from Host `stat`, and later observations update the version. A consumer reads content through the Workspace Files Remote namespace; Preview owns refresh independently per tab ([`dsh-api-workspace-files`](../../packages/api/workspace-files/README.md)).
|
||||
Most streams carry metadata rather than content. The `file` provider's value is `WorkspaceFileStat { absolutePath, version, bytes? }`: the first frame comes from Host `stat`, and later observations update the version. A consumer reads content through the Workspace Files Remote namespace; Preview owns refresh independently per tab ([`dsh-api-workspace-files`](../../packages/api/workspace-files/README.md)). The `subagentchat` provider retains the addressed Session and yields its `SessionReference`, then releases that reference when the resource signal aborts.
|
||||
|
||||
## Limits
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
| `dsh-resource://file/session/s1/notes/a.md` | `file` | 会话 `s1` 工作区根下 `notes/a.md` 的元数据(`file` 提供方已注册时) |
|
||||
| `dsh-resource://file/absolute/home/me/notes.md` | `file` | 可解析,但没有授权 Session,以 `workspace-file/unknown-workspace` 失败;不借用当前或 Tab Session |
|
||||
| `DSH-RESOURCE://File/session/s1/a` | `file` | 另一份记录:地址按字符串比较,`openResource` 只接受 `fileAddressFor` 生成的规范小写拼写 |
|
||||
| `dsh-resource://subagentchat/session/c1?parent=p1&mode=continuable` | `subagentchat` | 已寻址的 subagent Conversation;其值持有一个 `SessionReference`,直到资源关闭 |
|
||||
| `sidebar://guide` | — | `none`:导航地址 |
|
||||
| `/home/me/notes.md` | — | `none`:不是 URL |
|
||||
|
||||
@@ -84,7 +85,7 @@ export function FileHeader({ useTabInfo, useResource, t }: Props) {
|
||||
|
||||
资源有持有者就存活:一个订阅中的 `useResource`,或一次钉住。`ctx.resources.pin(address, signal)` 在不订阅的情况下让资源保持打开直到 `signal` 中止,已中止的信号什么也不钉;右侧 Sidebar 在每条打开的 tab 记录存续期内钉住其地址,因此切 tab 卸载正文不关流。第一个持有者打开提供方的流;最后一个释放时中止它、丢弃值,并把快照回到 `loading`(有提供方)或 `none`(没有)。提供方在这次释放之后产出的帧被丢弃,迭代器被归还。`ctx.resources.source(address)` 是 hook 背后的裸 observable,按地址引用稳定,供 React 之外的调用方使用;只读它的快照不算持有([生命周期](../../packages/client/resources/README.zh.md#lifecycle))。
|
||||
|
||||
流只推元数据不推内容。`file` 提供方的值是 `WorkspaceFileStat { absolutePath, version, bytes? }`:首帧来自 Host 的 `stat`,后续观察更新版本。消费方自己经 Workspace Files Remote 命名空间读取内容;Preview 按 tab 独立刷新([`dsh-api-workspace-files`](../../packages/api/workspace-files/README.zh.md))。
|
||||
多数流只推元数据而不推内容。`file` 提供方的值是 `WorkspaceFileStat { absolutePath, version, bytes? }`:首帧来自 Host 的 `stat`,后续观察更新版本。消费方自己经 Workspace Files Remote 命名空间读取内容;Preview 按 tab 独立刷新([`dsh-api-workspace-files`](../../packages/api/workspace-files/README.zh.md))。`subagentchat` 提供方保留已寻址 Session 并产出其 `SessionReference`,在资源 signal 中止时释放该 reference。
|
||||
|
||||
## 限制
|
||||
|
||||
|
||||
@@ -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/conversation.md
|
||||
conversation.md: 61e76e1b057be7b47150bd623b3e04400b50e394
|
||||
conversation.zh.md: 5b54625fcfe9ac451e79a42c387a5cf0836ee39a
|
||||
conversation.md: 4d6324e71b4383dfc640c1873dd9ef31023a1098
|
||||
conversation.zh.md: 49f2d7dbdc67a926f88ca72ed8ae6a0622c54fb3
|
||||
@@ -24,7 +24,7 @@ Chat and Trajectory may recognize the same durable event family, but each keeps
|
||||
|
||||
Each Session keeps a monotonic set of active targets. Creating or reading a target source does not activate it. The shell explicitly activates its persisted or newly selected View, while another consumer activates a target through its first source subscription. First activation creates that target's builder and calls `replace()` once from the current target-indexed Contexts. Later flushes call `apply()` for every active target, and unsubscription does not remove one.
|
||||
|
||||
The shell owns View selection and resolves the registered preferred View or Chat fallback before rendering when a binding is created or selected as current, and after View-roster changes. The assembler receives only the resolved target id and does not select Chat or another default target. A third-party View participates through the same selection and activation operations.
|
||||
The shell owns View selection and resolves the registered preferred View or Chat fallback before rendering when a binding is created or selected as current, and after View-roster changes. The assembler receives only the resolved target id and does not select Chat or another default target. A third-party View participates through the same selection and activation operations. A View Definition may expose `toolCallFocus(callId)`; the shell supplies Inspect only for a visible target that declares this capability, and the target maps the call id to its own focus identity.
|
||||
|
||||
## Replayable event families
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ Chat 与 Trajectory 可以识别同一个持久 event family,但各自保留
|
||||
|
||||
每个 Session 都保留单调增长的 active target 集合。创建或读取 target source 不会激活它。shell 会显式激活持久化选择或新选择的 View,其他消费者则通过 target source 的首个订阅激活 target。首次激活会创建该 target 的 builder,并从当前按 target 索引的 Context 调用一次 `replace()`。后续 flush 对每个 active target 调用 `apply()`,取消订阅不会移除 target。
|
||||
|
||||
shell 拥有 View 选择,并在 binding 创建、被选为 current 或 View roster 变化时,于渲染前解析已注册的偏好 View 或 Chat fallback。assembler 只接收解析后的 target id,不自行选择 Chat 或其他默认 target。第三方 View 使用相同的选择与激活操作。
|
||||
shell 拥有 View 选择,并在 binding 创建、被选为 current 或 View roster 变化时,于渲染前解析已注册的偏好 View 或 Chat fallback。assembler 只接收解析后的 target id,不自行选择 Chat 或其他默认 target。第三方 View 使用相同的选择与激活操作。View Definition 可以提供 `toolCallFocus(callId)`;shell 仅为声明了此能力且可见的目标提供 Inspect,由目标将调用 id 映射为自己的焦点标识。
|
||||
|
||||
## 可回放 event family
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/filesystem.md
|
||||
filesystem.md: c93d5e250860c19ab41f133848f5038b78f1bd57
|
||||
filesystem.zh.md: e9011d35b9a52fd42439a23e78fe4bff7ae41c11
|
||||
filesystem.md: a4ed5460ac333b57520b241f31f5c809e574f858
|
||||
filesystem.zh.md: 6f06c140c1a9a2c685aebd6339cd1ee97d4303bb
|
||||
@@ -292,6 +292,16 @@ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnp
|
||||
Abstract filesystem provider. Targets must preserve identity across aliases; reads expose regular UTF-8 text or typed errors, listings are stable and content-free, and mutations are atomic. Optional guards add stale protection without changing the unguarded provider contract.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Observe one file or a directory's direct entries in this provider's execution world.
|
||||
* @param target - resolved file or directory, including an absent path to observe for creation.
|
||||
* @param changed - invalidation callback; errors can be reported during or after initialization.
|
||||
* @param signal - cancels watcher initialization; the caller closes an initialized watcher.
|
||||
* @returns a promise resolving once observation is active, with an asynchronous close function.
|
||||
* @throws when the provider does not support watching or cannot initialize the watcher.
|
||||
*/
|
||||
abstract watch(target: FsTarget, changed: (error?: Error) => void, signal: AbortSignal): Promise<() => Promise<void>>
|
||||
|
||||
/**
|
||||
* Resolve a model/plugin-supplied path into a stable {@link FsTarget}. May perform I/O (a
|
||||
* remote/sandboxed backend may need a round-trip to map a path to a stable identity), hence
|
||||
|
||||
@@ -292,6 +292,16 @@ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnp
|
||||
Abstract filesystem provider. Targets must preserve identity across aliases; reads expose regular UTF-8 text or typed errors, listings are stable and content-free, and mutations are atomic. Optional guards add stale protection without changing the unguarded provider contract.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Observe one file or a directory's direct entries in this provider's execution world.
|
||||
* @param target - resolved file or directory, including an absent path to observe for creation.
|
||||
* @param changed - invalidation callback; errors can be reported during or after initialization.
|
||||
* @param signal - cancels watcher initialization; the caller closes an initialized watcher.
|
||||
* @returns a promise resolving once observation is active, with an asynchronous close function.
|
||||
* @throws when the provider does not support watching or cannot initialize the watcher.
|
||||
*/
|
||||
abstract watch(target: FsTarget, changed: (error?: Error) => void, signal: AbortSignal): Promise<() => Promise<void>>
|
||||
|
||||
/**
|
||||
* Resolve a model/plugin-supplied path into a stable {@link FsTarget}. May perform I/O (a
|
||||
* remote/sandboxed backend may need a round-trip to map a path to a stable identity), hence
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/session-reference.md
|
||||
session-reference.md: 1f44e1b96e31f446ed7f3fe28b625db0958da231
|
||||
session-reference.zh.md: 4f5cccf32b0f987f47923fb104e4c66396f89ba9
|
||||
session-reference.md: a2567a6cc3f6dde9a32db770a3a5f65c35ada219
|
||||
session-reference.zh.md: 43cd567aaa94cf4f54cd286c1dfc29d6a913b3e4
|
||||
@@ -34,7 +34,7 @@ interface SessionReferenceInput {
|
||||
}
|
||||
```
|
||||
|
||||
`SessionReferenceCandidate` is host-facing discovery output. Its label uses the latest session title when present, and filtering searches that label alongside session id and cwd, never transcript text.
|
||||
`SessionReferenceCandidate` is host-facing discovery output. Its `label` uses the latest Session title when present, while its optional display text prefers a subagent's durable creation label; filtering searches both alongside Session id and cwd, never transcript text. The Remote candidate's canonical mention uses the display text when present.
|
||||
|
||||
```ts type-equiv
|
||||
/** One host-facing candidate from exact session metadata. */
|
||||
@@ -43,6 +43,8 @@ interface SessionReferenceCandidate {
|
||||
sessionId: SessionId
|
||||
/** Latest log-backed title, falling back to the opaque session id. */
|
||||
label: string
|
||||
/** Display and canonical-mention text, preferring a subagent's durable creation label over {@link label}. */
|
||||
displayTitle?: string
|
||||
/** Source session working directory, when recorded. */
|
||||
cwd?: string
|
||||
/**
|
||||
@@ -180,14 +182,13 @@ Exact-read consumer that prepares immutable cross-session message context.
|
||||
/**
|
||||
* List reference candidates, ranked by working-directory affinity.
|
||||
*
|
||||
* Discovery runs at keystroke rate, so a title only ever comes from a
|
||||
* projection read: see {@link SessionReferenceResolver.projectedTitle} for
|
||||
* which sessions can answer one and which fall back to their id.
|
||||
* Discovery runs at keystroke rate, so titles and subagent labels only ever
|
||||
* come from projection reads; sessions without either fall back to their id.
|
||||
* @param agent - target agent; self is excluded and its cwd drives ranking.
|
||||
* @param query - optional case-insensitive session-id/cwd/title substring.
|
||||
* @param query - optional case-insensitive session-id/cwd/title/display-title substring.
|
||||
* @param limit - optional positive result cap.
|
||||
* @param signal - optional cancellation boundary for host autocomplete teardown.
|
||||
* @returns candidates labeled by latest title or, when absent, session id.
|
||||
* @returns candidates with canonical mention labels and presentation titles.
|
||||
*/
|
||||
async listCandidates( agent: Agent, query: string = '', limit: number = this.config.candidateLimit, signal?: AbortSignal, ): Promise<SessionReferenceCandidate[]>
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ interface SessionReferenceInput {
|
||||
}
|
||||
```
|
||||
|
||||
`SessionReferenceCandidate` 是面向宿主的发现输出。存在最新会话标题时,它的 label 使用该标题;筛选搜索该 label 以及 session id 和 cwd,绝不搜索 transcript(文本记录)。
|
||||
`SessionReferenceCandidate` 是面向宿主的发现输出。存在最新 Session 标题时,它的 `label` 使用该标题;可选显示文本则优先使用 subagent 的持久创建 label。筛选会同时搜索两者、Session id 与 cwd,绝不搜索 transcript(文本记录)。Remote 候选在 `displayTitle` 存在时用它标记规范 mention。
|
||||
|
||||
```ts type-equiv
|
||||
/** One host-facing candidate from exact session metadata. */
|
||||
@@ -43,6 +43,8 @@ interface SessionReferenceCandidate {
|
||||
sessionId: SessionId
|
||||
/** Latest log-backed title, falling back to the opaque session id. */
|
||||
label: string
|
||||
/** Display and canonical-mention text, preferring a subagent's durable creation label over {@link label}. */
|
||||
displayTitle?: string
|
||||
/** Source session working directory, when recorded. */
|
||||
cwd?: string
|
||||
/**
|
||||
@@ -180,14 +182,13 @@ Exact-read consumer that prepares immutable cross-session message context.
|
||||
/**
|
||||
* List reference candidates, ranked by working-directory affinity.
|
||||
*
|
||||
* Discovery runs at keystroke rate, so a title only ever comes from a
|
||||
* projection read: see {@link SessionReferenceResolver.projectedTitle} for
|
||||
* which sessions can answer one and which fall back to their id.
|
||||
* Discovery runs at keystroke rate, so titles and subagent labels only ever
|
||||
* come from projection reads; sessions without either fall back to their id.
|
||||
* @param agent - target agent; self is excluded and its cwd drives ranking.
|
||||
* @param query - optional case-insensitive session-id/cwd/title substring.
|
||||
* @param query - optional case-insensitive session-id/cwd/title/display-title substring.
|
||||
* @param limit - optional positive result cap.
|
||||
* @param signal - optional cancellation boundary for host autocomplete teardown.
|
||||
* @returns candidates labeled by latest title or, when absent, session id.
|
||||
* @returns candidates with canonical mention labels and presentation titles.
|
||||
*/
|
||||
async listCandidates( agent: Agent, query: string = '', limit: number = this.config.candidateLimit, signal?: AbortSignal, ): Promise<SessionReferenceCandidate[]>
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/session.md
|
||||
session.md: 7c7e244bfca17c8e22cabe45fc69126113b685d6
|
||||
session.zh.md: fecae92809bdba93588e163447d372c7a42d0260
|
||||
session.md: 69f0ee565e47191e2468a857d12eb7d255c9ecdb
|
||||
session.zh.md: 56a0502fcbccf89625833d116cb2eb2a1fcb49f7
|
||||
@@ -818,11 +818,11 @@ inspect( sessionId: SessionId, signal?: AbortSignal, ): Promise<SessionInspectio
|
||||
workspaceDesktop(): { name: string; available: boolean; fileManager: 'finder' | 'explorer' | 'directory' | null }
|
||||
|
||||
/**
|
||||
* Open one path prepared by a Session-aware caller on the Host desktop.
|
||||
* Verify one path through the composed filesystem and open it on the Host desktop.
|
||||
* @param request - path after best-effort Session workspace resolution.
|
||||
* @param signal - caller lifetime; abort terminates the native command.
|
||||
* @returns confirmation after the native opener accepts the path.
|
||||
* @throws RemoteError when the request is invalid, cancelled, or the opener fails.
|
||||
* @throws RemoteError when the request is invalid, has no verified Host mapping, is cancelled, or the opener fails.
|
||||
*/
|
||||
@Remote('openWorkspacePath') async openWorkspacePath( request: SessionOpenWorkspacePathRequest, signal: AbortSignal, ): Promise<SessionOpenWorkspacePathValue>
|
||||
|
||||
|
||||
@@ -822,11 +822,11 @@ inspect( sessionId: SessionId, signal?: AbortSignal, ): Promise<SessionInspectio
|
||||
workspaceDesktop(): { name: string; available: boolean; fileManager: 'finder' | 'explorer' | 'directory' | null }
|
||||
|
||||
/**
|
||||
* Open one path prepared by a Session-aware caller on the Host desktop.
|
||||
* Verify one path through the composed filesystem and open it on the Host desktop.
|
||||
* @param request - path after best-effort Session workspace resolution.
|
||||
* @param signal - caller lifetime; abort terminates the native command.
|
||||
* @returns confirmation after the native opener accepts the path.
|
||||
* @throws RemoteError when the request is invalid, cancelled, or the opener fails.
|
||||
* @throws RemoteError when the request is invalid, has no verified Host mapping, is cancelled, or the opener fails.
|
||||
*/
|
||||
@Remote('openWorkspacePath') async openWorkspacePath( request: SessionOpenWorkspacePathRequest, signal: AbortSignal, ): Promise<SessionOpenWorkspacePathValue>
|
||||
|
||||
|
||||
@@ -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/sidebar-right.md
|
||||
sidebar-right.md: 470b72118ee680f84489d13668e74c0eede652b0
|
||||
sidebar-right.zh.md: 62481c4024e6647a7e620a9c8e72ed6d0c969a60
|
||||
sidebar-right.md: 9ad6bd63ed63c5c59dbe29cd1229a6412ad22de2
|
||||
sidebar-right.zh.md: d0a967f400ea80ab696e24e1b4f46d7d8664eff8
|
||||
@@ -79,6 +79,7 @@ Two opens are the navigation controller, and every way into the column calls one
|
||||
| `paneId` | Land a new tab in this pane; default is the active docked pane (the first docked pane while a floating pane is active). |
|
||||
| `replaceTab` | Take this tab's pane and strip slot, closing it in the same step; a floating tab lends no place, so the new tab lands as if unplaced. |
|
||||
| `revealIfOpened` | Default `true`: a tab already showing the same `(kind, address)` is focused and handed `params`. `false` opens another tab regardless. |
|
||||
| `preferNewPane` | Prefer a new docked pane under the normal pane budget and room rule; fall back to the target pane when it cannot split. Ignored with `replaceTab`. |
|
||||
| `kind` (`openResource` only) | Name the opening type instead of ranking claims; its implementation in force opens the address, and its `canOpen` still applies. |
|
||||
| `params` | Navigation parameters for the body, delivered as `navigation.params`. `openResource` types them by resource type through the merge-extensible `SidebarRightResourceParamsMap` (the text preview declares `{ line?: number }`); `openTab<K>` types them by kind through `SidebarRightTabParamsMap`, `undefined` for a kind that declares none; a body reads `SidebarRightNavigationParams`, the union of both. Values are JSON-shaped by convention and not validated at run time. |
|
||||
|
||||
@@ -110,11 +111,11 @@ The `text` tab is the shared Document Preview owner. Its [root registration](../
|
||||
|
||||
The [registry](../../packages/client/ui-sidebar-documentpreview/src/client/document/registry.ts) records unique `id`, `extensions`, localized `title()`, `loading`, optional `priority`, and optional `wrap`. Case-insensitive suffix matching ranks `extension` (the default) before `builtin`, then longer suffixes before shorter ones, then registration order. Unlike tab-kind replacement, the registry keeps all implementations available; the toolbar lists matching alternatives and remembers the selection per tab. Unknown extensions use plain text. Suffixes declared in `binaryExtensions` suppress the plain-text alternative, as described in the [package README](../../packages/client/ui-sidebar-documentpreview/README.md#what-it-registers). `loading` is `text-pages`, `bytes-complete`, or `renderer`; `wrap` advertises support for the shared source-wrap control.
|
||||
|
||||
[`DocumentPreviewProps`](../../packages/client/ui-sidebar-documentpreview/src/client/document/contract.ts) derives from `PropsRuntime<'sidebar.right.tab.document'>`. The owner supplies the original `resourceAddress`, `content`, and current `wrap`: text content is `{ kind: 'text', text, pages: [{ offset, text, lines }], eof }`, with cumulative `text`; complete bytes are `{ kind: 'bytes', data }`, with `Uint8Array<ArrayBuffer>` data. These transient buffers are borrowed read-only and must not enter durable layout or Session JSON. PDF copies the bytes before Worker transfer, preserving the owner's buffer. The child receives the same framework-bound `useTabInfo` and the global metadata-only `useResource`. The parent reads through ordinary inject callbacks to `remote.workspaceFiles.read`/`readAll` and owns page appends, per-tab refresh, and loading status. HTML's own inject callback uses `readRelated`; Host code resolves paths. Markdown and code retain one incremental renderer across appends and settle at EOF; HTML and PDF receive complete bytes.
|
||||
[`DocumentPreviewProps`](../../packages/client/ui-sidebar-documentpreview/src/client/document/contract.ts) derives from `PropsRuntime<'sidebar.right.tab.document'>`. The owner supplies the original `resourceAddress`, `content`, current `wrap`, and `addResource` / `setResources` dependency callbacks: text content is `{ kind: 'text', text, pages: [{ offset, text, lines }], eof }`, with cumulative `text`; complete bytes are `{ kind: 'bytes', data }`, with `Uint8Array<ArrayBuffer>` data. These transient buffers are borrowed read-only and must not enter durable layout or Session JSON. PDF copies the bytes before Worker transfer, preserving the owner's buffer. The child receives the same framework-bound `useTabInfo` and the global metadata-only `useResource`. The parent reads through ordinary inject callbacks to `remote.workspaceFiles.read`/`readAll` and owns page appends, per-tab refresh, and loading status. HTML's own inject callback uses `readRelated`; Host code resolves paths. Markdown and code retain one incremental renderer across appends and settle at EOF; HTML and PDF receive complete bytes.
|
||||
|
||||
Preview records its loaded version and the version observed when a read starts. Refresh rereads only that tab, without changing shared metadata or another tab's content. Reads are non-transactional; versions are opaque equality tokens, not ordered timestamps ([resource observation and Preview RPC](../../.agents/notes/implemented/architecture/2026-09-08-document-preview-operations.md)).
|
||||
Preview records its loaded version and the version observed when a read starts. Automatic refresh defaults to enabled; initial member metadata establishes a baseline, and later changes reload the tab. Refresh rereads only that tab, without changing shared metadata or another tab's content. Reads are non-transactional; versions are opaque equality tokens, not ordered timestamps ([resource observation and Preview RPC](../../.agents/notes/implemented/architecture/2026-09-08-document-preview-operations.md)).
|
||||
|
||||
A renderer that owns loading receives `{ kind: 'renderer', revision, loaded, reload }` instead of file bytes. The body loads through its own injected callbacks, cancels on revision changes and unmount, and reports its displayed source version through `loaded(version)`. The parent ignores stale reports and retains the shared reload and source-change controls. Office uses this mode to request [Host-rendered PDFs](office-to-pdf.md); its own store and bounded cache retain converted bytes, and its body owns font notices above a nested PDF view. The [package README](../../packages/client/ui-sidebar-documentpreview/README.md#what-it-registers) defines the loading lifecycle.
|
||||
A renderer that owns loading receives `{ kind: 'renderer', revision, loaded, failed, reload }` instead of file bytes. The body loads through its own injected callbacks, cancels on revision changes and unmount, and reports its displayed source version through `loaded(version)`. A failed load calls `failed()` so a later file change can retry. The parent ignores stale reports and retains the shared reload and source-change controls. Office uses this mode to request [Host-rendered PDFs](office-to-pdf.md); its own store and bounded cache retain converted bytes, while its body renders a nested PDF view. `OfficeFontAction` renders the missing-font warning before reload through `sidebar.right.tab.document.action`. The [package README](../../packages/client/ui-sidebar-documentpreview/README.md#what-it-registers) defines the loading lifecycle.
|
||||
|
||||
## Resource model
|
||||
|
||||
@@ -126,7 +127,7 @@ A resource stays open while it has a holder — a subscribed `useResource` or a
|
||||
|
||||
## Workspace Files
|
||||
|
||||
The Host `ctx.workspaceFiles` service and generated `workspaceFiles` Remote namespace read files allowed by the Session filesystem backend: `stat(path)` returns `{ absolutePath, version, bytes? }`; `read(path, { offset?, limit? })` returns one page of lines (`offset` 1-based, `limit` capped by the configured page size) as `{ …stat, offset, text, eof }`; `readBytes(path, { offset?, length? })` returns one raw byte window (`offset` 0-based, `length` capped by the configured byte limit) as base64 `{ …stat, offset, data, eof }` with no text decoding. `list(path)` remains inside the workspace root and returns a directory's direct children (`name`, `type: 'file' | 'directory' | 'other'`, `size?`) cut to the configured cap with `truncated` set. `changes()` likewise remains workspace-scoped and yields `{ kind: 'ready' }` once subscribed, then `{ kind: 'change', change }` frames whose payload is `{ absolutePath, version }` or `{ absolutePath, absent: true }` ([README](../../packages/api/workspace-files/README.md#use-this-package)). File operations reject final symlinks and enforce transfer caps; `read` additionally requires UTF-8 text. Failures use `workspace-file/*` codes ([failures](../../packages/api/workspace-files/README.md)).
|
||||
The Host `ctx.workspaceFiles` service and generated `workspaceFiles` Remote namespace read files allowed by the Session filesystem backend: `stat(path)` returns `{ absolutePath, version, bytes? }`; `read(path, { offset?, limit? })` returns one page of lines (`offset` 1-based, `limit` capped by the configured page size) as `{ …stat, offset, text, eof }`; `readBytes(path, { offset?, length? })` returns one raw byte window (`offset` 0-based, `length` capped by the configured byte limit) as base64 `{ …stat, offset, data, eof }` with no text decoding. `list(path)` remains inside the workspace root and returns a directory's direct children (`name`, `type: 'file' | 'directory' | 'other'`, `size?`) cut to the configured cap with `truncated` set. `changes(path)` watches one target; the Host determines its type and confines directories to the workspace. It yields `{ kind: 'ready' }` once subscribed, then `{ kind: 'change', change }` frames whose payload is `{ absolutePath, version }` or `{ absolutePath, absent: true }` ([README](../../packages/api/workspace-files/README.md#use-this-package)). File reads reject final symlinks and enforce transfer caps; `read` additionally requires UTF-8 text. Failures use `workspace-file/*` codes ([failures](../../packages/api/workspace-files/README.md)).
|
||||
|
||||
[`dsh-api-workspace-files`](../../packages/api/workspace-files/README.md) registers the `file` provider, with `ResourceProtocolMap.file` directly naming `WorkspaceFileStat`. A Session address carries the authorizing Session and a relative or absolute path, passed unchanged to the Host for resolution. The provider waits for Host `ready` before stat and filters changes by `stat.absolutePath`. Bare `absolute` addresses have no authorizing Session and fail with `workspace-file/unknown-workspace`, without borrowing current or Tab Session. Any UI, including Global components, shares the observation for the same complete address. Preview's ordinary Remote callbacks use the Session in that address; Host `readAll` and `readRelated` remain, and Preview's `rpc.ts` decodes byte results.
|
||||
|
||||
@@ -134,8 +135,9 @@ The Host `ctx.workspaceFiles` service and generated `workspaceFiles` Remote name
|
||||
|
||||
- **`guide`** — `builtin`, opened as `openTab('guide')`. A muted compass sits above one capsule per contributed `guide` entry, in `order`; short lists show registered descriptions, and every missing icon uses the shipped placeholder. Picking a capsule opens the contributing type as a page in the guide tab's place. A pane holds at most one guide tab, and the strip's add control appears only while its pane has none. A new pane receives the registered default page: the sole guide entry directly, or the guide when the entry count is not one ([guide](../../packages/client/ui-sidebar-right/README.md#the-guide)).
|
||||
- **`text`** — `fallback`, `dsh-resource://file/**`, claiming Session addresses only. Document Preview observes metadata through `useResource<'file'>`, loads content through Remote callbacks, and owns renderer selection, the toolbar, per-tab refresh, scroll, and source navigation; unknown extensions render as plain text ([README](../../packages/client/ui-sidebar-documentpreview/README.md)).
|
||||
- **`files`** — `builtin`, opened as `openTab('files')`. The workspace directory tree, listed lazily through `list`, opening a file with `tab.actions.openResource(fileAddressFor(sessionId, root, path))` into its own pane ([README](../../packages/client/ui-sidebar-files/README.md)).
|
||||
- **`files`** — `builtin`, opened as `openTab('files')`. The workspace directory tree, listed lazily through `list` and watched by expanded directory, opening a file with `tab.actions.openResource(fileAddressFor(sessionId, root, path))` into its own pane ([README](../../packages/client/ui-sidebar-files/README.md)).
|
||||
- **`browser`** — multi-instance `builtin`, opened as `openTab('browser', { params: { url? } })`. Assistant Markdown delegates HTTP(S) links to this page type. It accepts public and loopback HTTP(S) targets under the default sandbox, rejects local files in favor of Document Preview, and uses application-known iframe history ([README](../../packages/client/ui-sidebar-browser/README.md)).
|
||||
- **`subagentchat`** — `builtin`, `dsh-resource://subagentchat/session/<child>?parent=<parent>&mode=<mode>`. An explicitly addressed subagent Conversation retained by the resource provider and rendered through the shared Conversation Factory ([README](../../packages/client/ui-subagent/README.md)).
|
||||
|
||||
<a id="not-built"></a>
|
||||
## Not built
|
||||
|
||||
@@ -79,6 +79,7 @@ export function apply(ctx: Context): void {
|
||||
| `paneId` | 新 tab 落到这个 pane;缺省为活动的停靠 pane(活动的是浮窗时取第一个停靠 pane)。 |
|
||||
| `replaceTab` | 占用这个 tab 的 pane 与条上位置,并在同一步关闭它;浮窗里的 tab 让不出位置,新 tab 按未指定位置落位。 |
|
||||
| `revealIfOpened` | 缺省 `true`:已显示同一 `(kind, address)` 的 tab 被聚焦并收到 `params`。`false` 则无论如何再开一个。 |
|
||||
| `preferNewPane` | 在普通格数预算与空间规则下优先新建停靠格;不能分栏时回退到目标格。与 `replaceTab` 一起使用时忽略。 |
|
||||
| `kind`(仅 `openResource`) | 点名打开类型而不排候选;该 kind 的生效实现打开地址,它的 `canOpen` 仍生效。 |
|
||||
| `params` | 给正文的导航参数,作为 `navigation.params` 送达。`openResource` 按资源类型经声明合并表 `SidebarRightResourceParamsMap` 定型(文本预览声明 `{ line?: number }`);`openTab<K>` 按 kind 经 `SidebarRightTabParamsMap` 定型,未声明的 kind 为 `undefined`;正文读到的是二者联合 `SidebarRightNavigationParams`。值按约定为 JSON 形状,运行时不校验。 |
|
||||
|
||||
@@ -110,11 +111,11 @@ Sidebar 声明四个扩展 slot;其文档 tab 另行声明下表中的 keyed
|
||||
|
||||
[注册表](../../packages/client/ui-sidebar-documentpreview/src/client/document/registry.ts)记录唯一的 `id`、`extensions`、本地化 `title()`、`loading`,以及可选的 `priority` 和 `wrap`。后缀匹配不区分大小写,先排 `extension`(缺省值)、再排 `builtin`,随后比较后缀长度(长者优先)与注册顺序。与 tab kind 替换不同,注册表保留所有实现;工具栏列出匹配的候选,按 tab 记住选择。未知扩展名使用纯文本。`binaryExtensions` 声明的后缀不提供纯文本备选,见[包 README](../../packages/client/ui-sidebar-documentpreview/README.zh.md#what-it-registers)。`loading` 为 `text-pages`、`bytes-complete` 或 `renderer`;`wrap` 声明是否支持共享的源码换行控件。
|
||||
|
||||
[`DocumentPreviewProps`](../../packages/client/ui-sidebar-documentpreview/src/client/document/contract.ts) 派生自 `PropsRuntime<'sidebar.right.tab.document'>`。owner 提供原始 `resourceAddress`、`content` 与当前 `wrap`:文本内容为 `{ kind: 'text', text, pages: [{ offset, text, lines }], eof }`,其中 `text` 为累积文本;完整字节为 `{ kind: 'bytes', data }`,其中 `data` 为 `Uint8Array<ArrayBuffer>`。这些瞬时缓冲区按只读方式借用,不得进入持久布局或 Session JSON。PDF 在转移到 Worker 前复制字节,以保留 owner 的缓冲区。子组件收到同一个框架绑定的 `useTabInfo`,以及全局共享、仅提供元数据的 `useResource`。父组件通过普通 inject 回调调用 `remote.workspaceFiles.read`/`readAll`,拥有追加分页、逐 tab 刷新与加载状态。HTML 自己的 inject 回调使用 `readRelated`;路径由 Host 代码解析。Markdown 和代码在追加期间保留同一个增量渲染器,到 EOF 完成最终解析;HTML 和 PDF 接收完整字节。
|
||||
[`DocumentPreviewProps`](../../packages/client/ui-sidebar-documentpreview/src/client/document/contract.ts) 派生自 `PropsRuntime<'sidebar.right.tab.document'>`。owner 提供原始 `resourceAddress`、`content`、当前 `wrap`,以及声明依赖的 `addResource` / `setResources` 回调:文本内容为 `{ kind: 'text', text, pages: [{ offset, text, lines }], eof }`,其中 `text` 为累积文本;完整字节为 `{ kind: 'bytes', data }`,其中 `data` 为 `Uint8Array<ArrayBuffer>`。这些瞬时缓冲区按只读方式借用,不得进入持久布局或 Session JSON。PDF 在转移到 Worker 前复制字节,以保留 owner 的缓冲区。子组件收到同一个框架绑定的 `useTabInfo`,以及全局共享、仅提供元数据的 `useResource`。父组件通过普通 inject 回调调用 `remote.workspaceFiles.read`/`readAll`,拥有追加分页、逐 tab 刷新与加载状态。HTML 自己的 inject 回调使用 `readRelated`;路径由 Host 代码解析。Markdown 和代码在追加期间保留同一个增量渲染器,到 EOF 完成最终解析;HTML 和 PDF 接收完整字节。
|
||||
|
||||
Preview 记录已载入版本和读取开始时的观察版本。刷新只重读当前 tab,不改变共享元数据或其他 tab 的内容。读取不具备事务性;版本是不透明的相等性令牌,不是可排序的时间戳([资源观察与 Preview RPC](../../.agents/notes/implemented/architecture/2026-09-08-document-preview-operations.zh.md))。
|
||||
Preview 记录已载入版本和读取开始时的观察版本。自动刷新默认开启;成员首次元数据只建立基线,后续变化才重新加载 tab。刷新只重读当前 tab,不改变共享元数据或其他 tab 的内容。读取不具备事务性;版本是不透明的相等性令牌,不是可排序的时间戳([资源观察与 Preview RPC](../../.agents/notes/implemented/architecture/2026-09-08-document-preview-operations.zh.md))。
|
||||
|
||||
自行加载的渲染器接收 `{ kind: 'renderer', revision, loaded, reload }`,而不是文件字节。正文通过自己的注入回调加载,在 revision 变化和卸载时取消请求,并通过 `loaded(version)` 报告已展示的源版本。父组件忽略过期报告,保留共享的重新加载与源文件变更控件。Office 使用此模式请求 [Host 渲染的 PDF](office-to-pdf.zh.md);自己的 store 和有界缓存保留转换字节,正文在嵌套 PDF 视图上方管理字体提示。[包 README](../../packages/client/ui-sidebar-documentpreview/README.zh.md#what-it-registers)定义加载生命周期。
|
||||
自行加载的渲染器接收 `{ kind: 'renderer', revision, loaded, failed, reload }`,而不是文件字节。正文通过自己的注入回调加载,在 revision 变化和卸载时取消请求,并通过 `loaded(version)` 报告已展示的源版本。加载失败时调用 `failed()`,使后续文件变化能够触发重试。父组件忽略过期报告,保留共享的重新加载与源文件变更控件。Office 使用此模式请求 [Host 渲染的 PDF](office-to-pdf.zh.md);自己的 store 和有界缓存保留转换字节,正文渲染嵌套 PDF 视图,`OfficeFontAction` 通过 `sidebar.right.tab.document.action` 在刷新按钮前显示缺失字体警告。[包 README](../../packages/client/ui-sidebar-documentpreview/README.zh.md#what-it-registers)定义加载生命周期。
|
||||
|
||||
## 资源模型
|
||||
|
||||
@@ -126,7 +127,7 @@ Preview 记录已载入版本和读取开始时的观察版本。刷新只重读
|
||||
|
||||
## Workspace Files
|
||||
|
||||
Host 的 `ctx.workspaceFiles` 服务与生成的 `workspaceFiles` Remote 命名空间读取 Session 文件系统后端允许的文件:`stat(path)` 返回 `{ absolutePath, version, bytes? }`;`read(path, { offset?, limit? })` 返回一页行(`offset` 1 起,`limit` 受配置页长限制),形如 `{ …stat, offset, text, eof }`;`readBytes(path, { offset?, length? })` 返回一个原始字节窗口(`offset` 0 起,`length` 受配置字节上限限制),形如 base64 的 `{ …stat, offset, data, eof }`、不做文本解码。`list(path)` 仍限定在工作区根内,返回目录的直接子项(`name`、`type: 'file' | 'directory' | 'other'`、`size?`),按配置上限截断并置 `truncated`。`changes()` 同样限定于工作区,订阅就绪后产出 `{ kind: 'ready' }`,随后产出 `{ kind: 'change', change }` 帧,其载荷为 `{ absolutePath, version }` 或 `{ absolutePath, absent: true }`([README](../../packages/api/workspace-files/README.zh.md#use-this-package))。文件操作拒绝末端符号链接并执行传输上限;`read` 还要求 UTF-8 文本。失败使用 `workspace-file/*` 错误码([失败](../../packages/api/workspace-files/README.zh.md))。
|
||||
Host 的 `ctx.workspaceFiles` 服务与生成的 `workspaceFiles` Remote 命名空间读取 Session 文件系统后端允许的文件:`stat(path)` 返回 `{ absolutePath, version, bytes? }`;`read(path, { offset?, limit? })` 返回一页行(`offset` 1 起,`limit` 受配置页长限制),形如 `{ …stat, offset, text, eof }`;`readBytes(path, { offset?, length? })` 返回一个原始字节窗口(`offset` 0 起,`length` 受配置字节上限限制),形如 base64 的 `{ …stat, offset, data, eof }`、不做文本解码。`list(path)` 仍限定在工作区根内,返回目录的直接子项(`name`、`type: 'file' | 'directory' | 'other'`、`size?`),按配置上限截断并置 `truncated`。`changes(path)` 监听一个目标,由 Host 判断目标类型并将目录限制在工作区内;订阅就绪后产出 `{ kind: 'ready' }`,随后产出 `{ kind: 'change', change }` 帧,其载荷为 `{ absolutePath, version }` 或 `{ absolutePath, absent: true }`([README](../../packages/api/workspace-files/README.zh.md#use-this-package))。文件读取拒绝末端符号链接并执行传输上限;`read` 还要求 UTF-8 文本。失败使用 `workspace-file/*` 错误码([失败](../../packages/api/workspace-files/README.zh.md))。
|
||||
|
||||
[`dsh-api-workspace-files`](../../packages/api/workspace-files/README.zh.md) 注册 `file` 提供方,`ResourceProtocolMap.file` 直接是 `WorkspaceFileStat`。Session 地址携带授权 Session 与相对或绝对路径,Host 原样接收并解析。提供方在 stat 前等待 Host 的 `ready` 帧,并按 `stat.absolutePath` 过滤变更。裸 `absolute` 地址没有授权 Session,以 `workspace-file/unknown-workspace` 失败,不借用当前或 Tab Session。任何 UI(包括 Global)访问同一完整地址都共享观察。Preview 的普通 Remote 回调使用地址中的 Session;Host `readAll` 和 `readRelated` 保留,字节结果由 Preview 的 `rpc.ts` 解码。
|
||||
|
||||
@@ -134,8 +135,9 @@ Host 的 `ctx.workspaceFiles` 服务与生成的 `workspaceFiles` Remote 命名
|
||||
|
||||
- **`guide`**——`builtin`,以 `openTab('guide')` 打开。一枚弱化的罗盘位于各类型按 `order` 贡献的入口胶囊上方;入口较少时显示已注册的描述,未提供图标的入口统一使用内置占位符。点选胶囊即在引导 tab 的位置把贡献它的类型作为页面打开。每个 pane 最多一个引导 tab,tab 条的新增控件只在本 pane 没有引导时出现。新 pane 使用已注册的默认页:只有一个引导入口时直接使用该入口,否则使用引导页([引导](../../packages/client/ui-sidebar-right/README.zh.md#the-guide))。
|
||||
- **`text`**——`fallback`,`dsh-resource://file/**`,只认领 Session 地址。Document Preview 通过 `useResource<'file'>` 观察元数据,经 Remote 回调加载内容,并拥有渲染器选择、工具栏、逐 tab 刷新、滚动与源码定位;未知扩展名按纯文本渲染([README](../../packages/client/ui-sidebar-documentpreview/README.zh.md))。
|
||||
- **`files`**——`builtin`,以 `openTab('files')` 打开。工作区目录树,经 `list` 懒加载,用 `tab.actions.openResource(fileAddressFor(sessionId, root, path))` 在自己所在 pane 打开文件([README](../../packages/client/ui-sidebar-files/README.zh.md))。
|
||||
- **`files`**——`builtin`,以 `openTab('files')` 打开。工作区目录树,经 `list` 懒加载,按展开目录建立监听,用 `tab.actions.openResource(fileAddressFor(sessionId, root, path))` 在自己所在 pane 打开文件([README](../../packages/client/ui-sidebar-files/README.zh.md))。
|
||||
- **`browser`**——可多开的 `builtin`,以 `openTab('browser', { params: { url? } })` 打开。Assistant Markdown 会把 HTTP(S) 链接委托给该页面类型。它在默认 sandbox 下接受公共与 loopback HTTP(S) 目标,本地文件改用 Document Preview,并使用应用已知的 iframe history([README](../../packages/client/ui-sidebar-browser/README.zh.md))。
|
||||
- **`subagentchat`**——`builtin`,`dsh-resource://subagentchat/session/<child>?parent=<parent>&mode=<mode>`。资源提供方保留一个显式寻址的 subagent Conversation,并通过共享 Conversation Factory 渲染([README](../../packages/client/ui-subagent/README.zh.md))。
|
||||
|
||||
<a id="not-built"></a>
|
||||
## 不做
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/slots.md
|
||||
slots.md: 177bbc5b8f56b7276f271a2ddb7ac71ac8888363
|
||||
slots.zh.md: c746ac88704c2e22e5c50ef82a893fde9f091668
|
||||
slots.md: 1b7dbd9e8ce81d298094df8a2adf7da39178541d
|
||||
slots.zh.md: b852e3f204c0acea49f94cffcedf2eebad0e432e
|
||||
@@ -144,14 +144,16 @@ root
|
||||
│ │ │ └─ tool.view.cordis
|
||||
│ │ ├─ conversation.message.images
|
||||
│ │ └─ conversation.trajectory.images
|
||||
│ ├─ conversation.session.header
|
||||
│ │ ├─ conversation.session.header.lineage
|
||||
│ │ ├─ conversation.session.header.leading
|
||||
│ │ ├─ conversation.session.header.actions
|
||||
│ │ ├─ conversation.session.header.utilities
|
||||
│ │ └─ conversation.session.header.corner
|
||||
│ ├─ conversation.header
|
||||
│ │ ├─ conversation.header.leading
|
||||
│ │ └─ conversation.session.header
|
||||
│ │ ├─ conversation.session.header.lineage
|
||||
│ │ ├─ conversation.session.header.actions
|
||||
│ │ ├─ conversation.session.header.utilities
|
||||
│ │ └─ conversation.session.header.corner
|
||||
│ ├─ conversation.composer
|
||||
│ │ └─ conversation.approval.detail
|
||||
│ │ ├─ conversation.approval.detail
|
||||
│ │ └─ conversation.plan-review.actions
|
||||
│ ├─ conversation.composer.bar
|
||||
│ │ ├─ conversation.input.attachments
|
||||
│ │ ├─ conversation.input.permission
|
||||
|
||||
@@ -144,14 +144,16 @@ root
|
||||
│ │ │ └─ tool.view.cordis
|
||||
│ │ ├─ conversation.message.images
|
||||
│ │ └─ conversation.trajectory.images
|
||||
│ ├─ conversation.session.header
|
||||
│ │ ├─ conversation.session.header.lineage
|
||||
│ │ ├─ conversation.session.header.leading
|
||||
│ │ ├─ conversation.session.header.actions
|
||||
│ │ ├─ conversation.session.header.utilities
|
||||
│ │ └─ conversation.session.header.corner
|
||||
│ ├─ conversation.header
|
||||
│ │ ├─ conversation.header.leading
|
||||
│ │ └─ conversation.session.header
|
||||
│ │ ├─ conversation.session.header.lineage
|
||||
│ │ ├─ conversation.session.header.actions
|
||||
│ │ ├─ conversation.session.header.utilities
|
||||
│ │ └─ conversation.session.header.corner
|
||||
│ ├─ conversation.composer
|
||||
│ │ └─ conversation.approval.detail
|
||||
│ │ ├─ conversation.approval.detail
|
||||
│ │ └─ conversation.plan-review.actions
|
||||
│ ├─ conversation.composer.bar
|
||||
│ │ ├─ conversation.input.attachments
|
||||
│ │ ├─ conversation.input.permission
|
||||
|
||||
@@ -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: 2bdb618f2196e5593fcdd4448504165a641fd23e
|
||||
subagent.zh.md: 0fbde9283617cf04907f830cc8486aef284eab68
|
||||
subagent.md: 32c9d47c288a352ef234a0e555484d3826f6adf5
|
||||
subagent.zh.md: 2e39072f820e3e4c5afc2884babbde63e23af7df
|
||||
@@ -266,7 +266,7 @@ A local one-shot provider appends the descriptor inside the child's initial turn
|
||||
|
||||
## Durable enumeration: `listChildren()`, `listDescendants()`, and their entries
|
||||
|
||||
`SubagentRuntime.listChildren(parentSessionId)` enumerates the parent's direct session-backed subagents from the live-preferred merge of `ctx.sessions` and the session-query engine's `listSessions()` — no Agent is loaded or resumed. Candidates are the direct children whose durable header carries `origin: 'subagent'`; the marker classifies enumeration and coarse generic-route denial but cannot establish a valid descriptor, resumability, or authorization — the projection fold owns identity, and the Activation contract owns resume. Each row's `mode`/`label` is the registered `subagent` projection unit's value, served through a three-rung ladder: the registry's watermark cache for a live child (zero log reads); the optional projection checkpoint cache for a cold one (`cachedSnapshot` — an identity passing the own-suffix seq gate is final, because an own descriptor is immutable once appended); otherwise one `query.observeSession()` cold observation folded through the registry (bounded concurrency, recomputed per listing). The cache is a pure optional accelerator: absent, serving the `null` sentinel or missing the key, failing the seq gate, or faulting, it falls silently through to the authoritative refold. The fold is `subagent/descriptor` last-wins with no failure channel: the child's own descriptor overrides a fork-seeded ancestor's, and a malformed or unknown-version payload folds to a serializable `null` sentinel, treated as no value. The result is one `SubagentListEntry[]` in `createdAt`-then-id order: a served identity yields a `child` entry with `mode: 'one-shot' | 'continuable'` and `activity: 'running' | 'inactive'`; continuable entries always carry `label`, while one-shot entries carry it only when the start caller supplied presentation metadata. A settled candidate whose fold served no identity yields a `corrupt` diagnostic — missing, malformed, and unknown-version descriptors deliberately undistinguished (`unsupported` remains in the type but is never produced); a running candidate without an identity is omitted (the creation window before its descriptor lands); a failed cold inspection yields one `unavailable` diagnostic retried on the next listing, so one damaged sibling cannot hide healthy children. `hasChildren` marks a direct descendant with durable subagent origin, read from the same merged material. Activity snapshots only whether the logical record is live in `ctx.sessions`, not outcome or resumability. Absent persistence, enumeration is live-only rather than an error — a cold child cannot be resumed then either. `listChildren()` throws `SubagentError` with code `SUBAGENT_CONTROL_PROJECTIONS_UNAVAILABLE` when the `ctx.sessionProjections` registry is absent and `SUBAGENT_CONTROL_SESSION_STORE_UNAVAILABLE` when the session store is, both checked before any read so a deployment with zero children still fails deterministically; the list tool requires `ctx.subagents` and `ctx.agents` at plugin load. A service consumer such as a UI can display both modes and choose an unlabeled one-shot fallback, while the model-facing `list_agents` adapter (the separately loadable `/list-agents` plugin of [dsh-tool-subagent-control](../../packages/subagent/tool-subagent-control)) keeps only continuable entries and refines status through the live Agent registry into its own `running`/`idle`/`ready` vocabulary, whose `ready` names a storage-only child as resumable rather than terminal. Listing does not consult the continuation manager's Activation map, Agent registry, or provider availability; `send_message` remains the authoritative delivery-time operation, and a listed running continuable child may still reject delivery as an ownership conflict. [The archived list-identity-projection record](../../.agents/notes/archived/architecture/2026-08-06-subagent-list-identity-projection.md) documents the original read-path decision.
|
||||
`SubagentRuntime.listChildren(parentSessionId)` enumerates the parent's direct session-backed subagents from the live-preferred merge of `ctx.sessions` and the session-query engine's `listSessions()` — no Agent is loaded or resumed. Candidates are the direct children whose durable header carries `origin: 'subagent'`; the marker classifies enumeration and coarse generic-route denial but cannot establish a valid descriptor, resumability, or authorization — the projection fold owns identity, and the Activation contract owns resume. Each row's `mode`/`label` is the registered `subagent` projection unit's value, served through a three-rung ladder: the registry's watermark cache for a live child (zero log reads); the optional projection checkpoint cache for a cold one (`cachedSnapshot` — an identity passing the own-suffix seq gate is final, because an own descriptor is immutable once appended); otherwise one `query.observeSession()` cold observation folded through the registry (bounded concurrency, recomputed per listing). The cache is a pure optional accelerator: absent, serving the `null` sentinel or missing the key, failing the seq gate, or faulting, it falls silently through to the authoritative refold. The fold is `subagent/descriptor` last-wins with no failure channel: the child's own descriptor overrides a fork-seeded ancestor's, and a malformed or unknown-version payload folds to a serializable `null` sentinel, treated as no value. The result is one `SubagentListEntry[]` in `createdAt`-then-id order: a served identity yields a `child` entry with `mode: 'one-shot' | 'continuable'` and `activity: 'running' | 'inactive'`; continuable entries always carry `label`, while one-shot entries carry it only when the start caller supplied presentation metadata. A settled candidate whose fold served no identity yields a `corrupt` diagnostic — missing, malformed, and unknown-version descriptors deliberately undistinguished (`unsupported` remains in the type but is never produced); a running candidate without an identity is omitted (the creation window before its descriptor lands); a failed cold inspection yields one `unavailable` diagnostic retried on the next listing, so one damaged sibling cannot hide healthy children. `hasChildren` marks a direct descendant with durable subagent origin, read from the same merged material. Activity snapshots only whether the logical record is live in `ctx.sessions`, not outcome or resumability. Absent persistence, enumeration is live-only rather than an error — a cold child cannot be resumed then either. `listChildren()` throws `SubagentError` with code `SUBAGENT_CONTROL_PROJECTIONS_UNAVAILABLE` when the `ctx.sessionProjections` registry is absent and `SUBAGENT_CONTROL_SESSION_STORE_UNAVAILABLE` when the session store is, both checked before any read so a deployment with zero children still fails deterministically; the list tool requires `ctx.subagents` and `ctx.agents` at plugin load. A service consumer such as a UI can display both modes and choose an unlabeled one-shot fallback, while the model-facing `list_agents` adapter (the separately loadable `/list-agents` plugin of [dsh-tool-subagent-control](../../packages/subagent/tool-subagent-control)) keeps only continuable entries and refines status through the live Agent registry into `running`/`inactive`; `inactive` includes loaded and storage-only children without describing task completion or outcome. Listing does not consult the continuation manager's Activation map, Agent registry, or provider availability; `send_message` remains the authoritative delivery-time operation, and a listed running continuable child may still reject delivery as an ownership conflict. [The archived list-identity-projection record](../../.agents/notes/archived/architecture/2026-08-06-subagent-list-identity-projection.md) documents the original read-path decision.
|
||||
|
||||
`SubagentRuntime.listDescendants(rootSessionId)` applies the same live-preferred corpus and projection-backed interpretation to the root's complete descendant tree in stable pre-order. Ordinary sessions and one-shot children remain traversal nodes, so continuable descendants below them are discovered; only `origin: 'subagent'` candidates produce rows. Each returned child or diagnostic adds its position from the enumerated durable header, while a cold inspection revalidates that complete lifecycle before serving identity:
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ interface ContinuableCreateSpec {
|
||||
|
||||
## 持久化枚举:`listChildren()`、`listDescendants()` 与其条目
|
||||
|
||||
`SubagentRuntime.listChildren(parentSessionId)` 从 `ctx.sessions` 与会话查询引擎 `listSessions()` 的实时优先合并中枚举 parent 直接且由会话支撑的 subagent——不会加载或恢复任何 Agent。候选是持久 header 携带 `origin: 'subagent'` 的直接 child;该标记只负责枚举分类与粗粒度的通用路由拒绝,不能证明描述符有效、child 可恢复或操作已获授权——身份由投影折叠负责,恢复由 Activation 约定负责。每行的 `mode`/`label` 是已注册 `subagent` projection unit 的值,经三级阶梯供值:存活 child 由注册表水位缓存供值(零日志读取);冷 child 先读可选的投影 checkpoint 缓存(`cachedSnapshot`——过 own-suffix seq 门的身份即定值,own descriptor 一经追加不可变);否则在一次 `query.observeSession()` 冷观察上经注册表折叠(有界并发,每次列表重新计算)。该缓存是纯可选加速层:服务缺席、行里是 `null` 哨兵或 key 缺席、seq 门不过、读取出错,都静默落到权威重折。折叠规则是 `subagent/descriptor` last-wins 且没有失败通道:子 agent 自己的描述符覆盖 fork seed 中祖先的描述符,格式错误或版本不认识的载荷折叠为可序列化的 `null` 哨兵,视同无值。结果是按 `createdAt`、再按 id 排序的 `SubagentListEntry[]`:取到身份即生成带有 `mode: 'one-shot' | 'continuable'` 和 `activity: 'running' | 'inactive'` 的 `child` 条目;可继续条目始终携带 `label`,一次性条目则只在启动调用方提供展示元数据时携带该字段。已定局而折叠无身份的候选生成 `corrupt` diagnostic——缺失、格式错误与版本不认识的描述符有意不再细分(`unsupported` 仍保留在类型中但从不产出);运行中而无身份的候选被省略(描述符落盘前的创建窗口);冷检查失败生成一条 `unavailable` diagnostic 并在下次列表自然重试,因此一个损坏的 sibling 不会隐藏健康 child。`hasChildren` 标记存在持久 subagent origin 的直接后代,读取自同一份合并材料。活动状态只表示逻辑记录是否在 `ctx.sessions` 中存活,而不表示结果或可恢复性。缺少持久化时,枚举退化为仅存活枚举而不是报错——此时冷 child 本就无法恢复。缺少 `ctx.sessionProjections` 注册表时,`listChildren()` 抛出携带错误码 `SUBAGENT_CONTROL_PROJECTIONS_UNAVAILABLE` 的 `SubagentError`,缺少会话存储时则抛出 `SUBAGENT_CONTROL_SESSION_STORE_UNAVAILABLE`,两者都在任何读取之前检查,因此零 child 的部署同样确定失败;列表工具在插件加载时要求 `ctx.subagents` 与 `ctx.agents`。UI 等服务消费方可以展示两种模式,并为无标签的一次性 child 选择回退展示;面向模型的 `list_agents` 适配器([dsh-tool-subagent-control](../../packages/subagent/tool-subagent-control) 中可单独加载的 `/list-agents` 插件)则只保留可继续条目,并通过在线 Agent 注册表将状态细化为自己的 `running`/`idle`/`ready` 词汇,其中 `ready` 把仅存于存储的 child 命名为可恢复而非终态。枚举不会查询继续执行管理器的 Activation map、Agent 注册表或提供方可用性;`send_message` 仍是消息送达时的权威操作,列表中的运行中可继续 child 仍可能因所有权冲突而拒绝投递。[已归档的列表身份投影记录](../../.agents/notes/archived/architecture/2026-08-06-subagent-list-identity-projection.md)记录了最初的读路径决策。
|
||||
`SubagentRuntime.listChildren(parentSessionId)` 从 `ctx.sessions` 与会话查询引擎 `listSessions()` 的实时优先合并中枚举 parent 直接且由会话支撑的 subagent——不会加载或恢复任何 Agent。候选是持久 header 携带 `origin: 'subagent'` 的直接 child;该标记只负责枚举分类与粗粒度的通用路由拒绝,不能证明描述符有效、child 可恢复或操作已获授权——身份由投影折叠负责,恢复由 Activation 约定负责。每行的 `mode`/`label` 是已注册 `subagent` projection unit 的值,经三级阶梯供值:存活 child 由注册表水位缓存供值(零日志读取);冷 child 先读可选的投影 checkpoint 缓存(`cachedSnapshot`——过 own-suffix seq 门的身份即定值,own descriptor 一经追加不可变);否则在一次 `query.observeSession()` 冷观察上经注册表折叠(有界并发,每次列表重新计算)。该缓存是纯可选加速层:服务缺席、行里是 `null` 哨兵或 key 缺席、seq 门不过、读取出错,都静默落到权威重折。折叠规则是 `subagent/descriptor` last-wins 且没有失败通道:子 agent 自己的描述符覆盖 fork seed 中祖先的描述符,格式错误或版本不认识的载荷折叠为可序列化的 `null` 哨兵,视同无值。结果是按 `createdAt`、再按 id 排序的 `SubagentListEntry[]`:取到身份即生成带有 `mode: 'one-shot' | 'continuable'` 和 `activity: 'running' | 'inactive'` 的 `child` 条目;可继续条目始终携带 `label`,一次性条目则只在启动调用方提供展示元数据时携带该字段。已定局而折叠无身份的候选生成 `corrupt` diagnostic——缺失、格式错误与版本不认识的描述符有意不再细分(`unsupported` 仍保留在类型中但从不产出);运行中而无身份的候选被省略(描述符落盘前的创建窗口);冷检查失败生成一条 `unavailable` diagnostic 并在下次列表自然重试,因此一个损坏的 sibling 不会隐藏健康 child。`hasChildren` 标记存在持久 subagent origin 的直接后代,读取自同一份合并材料。活动状态只表示逻辑记录是否在 `ctx.sessions` 中存活,而不表示结果或可恢复性。缺少持久化时,枚举退化为仅存活枚举而不是报错——此时冷 child 本就无法恢复。缺少 `ctx.sessionProjections` 注册表时,`listChildren()` 抛出携带错误码 `SUBAGENT_CONTROL_PROJECTIONS_UNAVAILABLE` 的 `SubagentError`,缺少会话存储时则抛出 `SUBAGENT_CONTROL_SESSION_STORE_UNAVAILABLE`,两者都在任何读取之前检查,因此零 child 的部署同样确定失败;列表工具在插件加载时要求 `ctx.subagents` 与 `ctx.agents`。UI 等服务消费方可以展示两种模式,并为无标签的一次性 child 选择回退展示;面向模型的 `list_agents` 适配器([dsh-tool-subagent-control](../../packages/subagent/tool-subagent-control) 中可单独加载的 `/list-agents` 插件)则只保留可继续条目,并通过在线 Agent 注册表将状态细化为 `running`/`inactive`;`inactive` 包括已加载和仅存于存储的 child,不表示任务完成或结果。枚举不会查询继续执行管理器的 Activation map、Agent 注册表或提供方可用性;`send_message` 仍是消息送达时的权威操作,列表中的运行中可继续 child 仍可能因所有权冲突而拒绝投递。[已归档的列表身份投影记录](../../.agents/notes/archived/architecture/2026-08-06-subagent-list-identity-projection.md)记录了最初的读路径决策。
|
||||
|
||||
`SubagentRuntime.listDescendants(rootSessionId)` 将同一份实时优先语料与基于投影的解释应用到根的完整后代树,并按稳定 pre-order 输出。普通会话和一次性 child 仍作为遍历节点,因此其下的可继续后代仍可发现;只有 `origin: 'subagent'` 的候选会生成条目。每个返回的 child 或 diagnostic 都从枚举所得的持久 header 附加树位置;冷检查在提供身份前还会重新校验完整生命周期:
|
||||
|
||||
|
||||
@@ -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/user-questions.md
|
||||
user-questions.md: fbbfb1435586c7191e47a6eaa5b1783c9f172d48
|
||||
user-questions.zh.md: 054ca06cd3c8a85cb35d99658c325848ea780cb5
|
||||
user-questions.md: d6515464e562eb5b3d505fd3ff1dcb118c2a7ee3
|
||||
user-questions.zh.md: 87536c22ad717ee5c25f4846aee6bd6af6068e8d
|
||||
@@ -41,6 +41,8 @@ type AskUserQuestionIntent = {
|
||||
* An `approve` naming no option of its own question is rejected at `ask()`.
|
||||
*/
|
||||
approve: string
|
||||
/** Logged tool invocation whose arguments contain the reviewed plan. */
|
||||
callId?: ToolCallId
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ type AskUserQuestionIntent = {
|
||||
* An `approve` naming no option of its own question is rejected at `ask()`.
|
||||
*/
|
||||
approve: string
|
||||
/** Logged tool invocation whose arguments contain the reviewed plan. */
|
||||
callId?: ToolCallId
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -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/web-client.md
|
||||
web-client.md: 69e8c40fda4de7b9406357adf4d641b30619393d
|
||||
web-client.zh.md: 18f60eaf20e081d768344cee1a0a500ee5f62536
|
||||
web-client.md: 92e3bc4a8649f4fee81e3c3feaa026297e1cd3e5
|
||||
web-client.zh.md: 6a620e73d75f389172802fb9385ecec058bd852e
|
||||
@@ -53,6 +53,8 @@ This pairing is not a second source of business truth. Host controllers decide d
|
||||
|
||||
## Conversation and presentation
|
||||
|
||||
Web and desktop share the [developer-tool preference](../../packages/client/ui-settings/README.md#use-this-package). It controls diagnostic Views, new-session preset selection, changed-file cards, and the builtin HTML preview policy without changing Session records.
|
||||
|
||||
`ui-session` installs the Session scope adapter and publishes `useSessions`, `useSessionStatus`, `useSessionRetainInfo`, `useSession`, `sessionId`, and `useProjection`. `SessionProvider` inherits an outer binding or binds an explicit `SessionReference`, so concurrent subtrees can target different Sessions. Domain adapters add further standard sources without putting React hooks on the model objects.
|
||||
|
||||
`ui-conversation` binds once to each `SessionBinding.eventSource`. Its event registry correlates durable Session events and Client-only `assistant/live-chunk` updates into stable business Contexts, and its view registry materializes target snapshots. Chat Assistant, Trajectory Assistant, and Turn Tail interpret both live chunks and the compact streams embedded in durable settlements, so reconnect and paged history reproduce the same Assistant state without durable token rows. `ui-chat` and `ui-trajectory` register separate Definitions and builders: they may interpret the same event family, but they do not import or share each other's final display model. The shell selects a registered view and passes its snapshot through standard hooks and Slots. [Conversation](conversation.md) defines Context identity, replay, Location data, target builders, and keyed renderers.
|
||||
|
||||
@@ -53,6 +53,8 @@ Connection 拥有 request correlation、`/api` carrier、trust check、精确 Fe
|
||||
|
||||
## Conversation 与 presentation
|
||||
|
||||
Web 和桌面端共享[开发者工具偏好](../../packages/client/ui-settings/README.zh.md#use-this-package)。它控制诊断 View、新会话预设选择、改动文件卡片和内置 HTML 预览策略,不改变 Session 记录。
|
||||
|
||||
`ui-session` 安装 Session scope adapter,并提供 `useSessions`、`useSessionStatus`、`useSessionRetainInfo`、`useSession`、`sessionId` 和 `useProjection`。`SessionProvider` 可以继承外围 binding,也可以绑定显式 `SessionReference`,因此并存子树可以指向不同 Session。领域 adapter 可以继续添加标准 source,但不会把 React hook 放进 model object。
|
||||
|
||||
`ui-conversation` 对每个 `SessionBinding.eventSource` 只绑定一次。它的 event registry 把持久 Session event 与 Client-only `assistant/live-chunk` update 关联成稳定的业务 Context,view registry 则 materialize target snapshot。Chat Assistant、Trajectory Assistant 与 Turn Tail 同时解释 live chunk 和持久 settlement 中嵌入的紧凑 stream,因此重连与分页历史无需持久 token 行即可复现相同 Assistant 状态。`ui-chat` 与 `ui-trajectory` 分别注册自己的 Definition 和 builder:它们可以解释同一 event family,但不会导入或共享彼此的最终 display model。Shell 选择一个已注册 view,再通过标准 hook 与 Slot 交付其 snapshot。[Conversation](conversation.zh.md)定义 Context identity、replay、Location data、target builder 与 keyed renderer。
|
||||
|
||||
@@ -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/web-server.md
|
||||
web-server.md: 619dc8ed74ea8835aaa16b90b6e0aced5da41f3a
|
||||
web-server.zh.md: c6f77099f3f8b00b07eaeefa1b1db1cb6f388546
|
||||
web-server.md: e74d51da21682c0271c42b0a4584558e41b52b26
|
||||
web-server.zh.md: da89262e7055dbf4d6ee044def4cb5a08ce4dfe4
|
||||
@@ -92,8 +92,8 @@ authorizeIndex(request: ConnectionIndexRequest, response: ConnectionIndexRespons
|
||||
|
||||
/**
|
||||
* Add the fresh process token to an ordinary Web application URL.
|
||||
* @param baseUrl - clean canonical browser origin.
|
||||
* @returns root URL accepted by {@link authorizeIndex} for initial login.
|
||||
* @param baseUrl - clean application URL whose authority and mount are preserved.
|
||||
* @returns tokenized URL for initial login; a mount proxy strips its prefix before {@link authorizeIndex}.
|
||||
*/
|
||||
authenticatedUrl(baseUrl: string): string
|
||||
```
|
||||
|
||||
@@ -92,8 +92,8 @@ authorizeIndex(request: ConnectionIndexRequest, response: ConnectionIndexRespons
|
||||
|
||||
/**
|
||||
* Add the fresh process token to an ordinary Web application URL.
|
||||
* @param baseUrl - clean canonical browser origin.
|
||||
* @returns root URL accepted by {@link authorizeIndex} for initial login.
|
||||
* @param baseUrl - clean application URL whose authority and mount are preserved.
|
||||
* @returns tokenized URL for initial login; a mount proxy strips its prefix before {@link authorizeIndex}.
|
||||
*/
|
||||
authenticatedUrl(baseUrl: string): 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/subsystems/workspace.md
|
||||
workspace.md: 80ea3157dbd904e168e2809ce8aa0b8641c1b2d9
|
||||
workspace.zh.md: 727c612e58cdbe54b0ba0e6292803d4543e5a32e
|
||||
workspace.md: 8ecf54a2860ab5d442c4856f6efd03900de1ce9b
|
||||
workspace.zh.md: dd4aed5f271aff0256115b03c85ec8b50ad0c502
|
||||
@@ -415,15 +415,15 @@ Host Remote file reads and workspace directory observations over the composed fi
|
||||
@Remote async list(workspaceFileScope: WorkspaceFileScope, path: string, signal: AbortSignal): Promise<WorkspaceDirectoryListing>
|
||||
|
||||
/**
|
||||
* Stream every `fs/observed` observation of a file inside the Session's
|
||||
* workspace. Only instrumented filesystem operations report here; the OS is
|
||||
* not watched.
|
||||
* Watch one file or a directory's direct entries in the Session's filesystem.
|
||||
* Files use the backend's read authority; directories remain workspace-scoped.
|
||||
* @param workspaceFileScope - header-derived workspace root for the Session identity on the wire.
|
||||
* @param path - target path; the Host determines its type and confines directories to the workspace.
|
||||
* @param signal - generation cancellation.
|
||||
* @returns `ready` once the Host observation queue is active and the workspace
|
||||
* root is resolved, then queued and live observations in emission order.
|
||||
* @returns `ready` once the target watch is active, then current metadata for queued and live invalidations.
|
||||
* @throws RemoteError when watching is unavailable or a directory is outside the workspace.
|
||||
*/
|
||||
@Remote({ mode: 'stream' }) changes(workspaceFileScope: WorkspaceFileScope, signal: AbortSignal): AsyncIterable<WorkspaceFileWatchFrame>
|
||||
@Remote({ mode: 'stream' }) changes(workspaceFileScope: WorkspaceFileScope, path: string, signal: AbortSignal): AsyncIterable<WorkspaceFileWatchFrame>
|
||||
```
|
||||
|
||||
Source: [`packages/api/workspace-files/src/index.ts`](../../packages/api/workspace-files/src/index.ts)
|
||||
|
||||
@@ -415,15 +415,15 @@ Host Remote file reads and workspace directory observations over the composed fi
|
||||
@Remote async list(workspaceFileScope: WorkspaceFileScope, path: string, signal: AbortSignal): Promise<WorkspaceDirectoryListing>
|
||||
|
||||
/**
|
||||
* Stream every `fs/observed` observation of a file inside the Session's
|
||||
* workspace. Only instrumented filesystem operations report here; the OS is
|
||||
* not watched.
|
||||
* Watch one file or a directory's direct entries in the Session's filesystem.
|
||||
* Files use the backend's read authority; directories remain workspace-scoped.
|
||||
* @param workspaceFileScope - header-derived workspace root for the Session identity on the wire.
|
||||
* @param path - target path; the Host determines its type and confines directories to the workspace.
|
||||
* @param signal - generation cancellation.
|
||||
* @returns `ready` once the Host observation queue is active and the workspace
|
||||
* root is resolved, then queued and live observations in emission order.
|
||||
* @returns `ready` once the target watch is active, then current metadata for queued and live invalidations.
|
||||
* @throws RemoteError when watching is unavailable or a directory is outside the workspace.
|
||||
*/
|
||||
@Remote({ mode: 'stream' }) changes(workspaceFileScope: WorkspaceFileScope, signal: AbortSignal): AsyncIterable<WorkspaceFileWatchFrame>
|
||||
@Remote({ mode: 'stream' }) changes(workspaceFileScope: WorkspaceFileScope, path: string, signal: AbortSignal): AsyncIterable<WorkspaceFileWatchFrame>
|
||||
```
|
||||
|
||||
Source: [`packages/api/workspace-files/src/index.ts`](../../packages/api/workspace-files/src/index.ts)
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/tool-catalog.md
|
||||
tool-catalog.md: 9aa85dd4d22ba7794f0b52f8cedf000b403b5d3a
|
||||
tool-catalog.zh.md: 6ca55a890c06dc5263f9fd1e9e6eb70b633d74ab
|
||||
tool-catalog.md: 5d64924fe43ee3e660ab320204182b19a0e49785
|
||||
tool-catalog.zh.md: 46ba988c648e495ffff44eda3fd59c66200180a2
|
||||
+13
-9
@@ -84,6 +84,10 @@ List plugins or bundles in the current profile, enable or disable them, install
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"registry": {
|
||||
"type": "string",
|
||||
"description": "For install_bundle: the npm registry URL asked first, when the user names one; otherwise the configured registry is asked, and its configured fallbacks while a registry is unreachable."
|
||||
},
|
||||
"offset": {
|
||||
"type": "number",
|
||||
"description": "Zero-based list offset; defaults to 0."
|
||||
@@ -627,7 +631,7 @@ The bash tool is the model-facing consumer of the bash executor seam. A `run_in_
|
||||
|
||||
### `present`
|
||||
|
||||
Declare existing files accessible through the Session filesystem as final deliverables. When a file you create or update is an output the user asked to receive, you must call present after writing it and before your final response, including files created through Bash or code execution. Mentioning its path in your reply does not replace this call. The files must already exist. The user opens the current source files; their contents are not copied or preserved.
|
||||
Declare selected existing files accessible through the Session filesystem as final deliverables. Use present when the user needs a separate file deliverable, especially Office documents, spreadsheets, and slide decks. Prefer showing results in your final response when that is sufficient; creating or editing a file does not by itself require present. Usually select the 1-2 most important deliverables; include more when needed, but at most 4 files in a single present call. The files must already exist. The user opens the current source files; their contents are not copied or preserved.
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -1882,7 +1886,7 @@ Source: [`packages/subagent/tool-subagent-control/src/index.ts`](../packages/sub
|
||||
|
||||
### `list_agents`
|
||||
|
||||
List your continuable background subagents by durable id and label. Use it to recall which ones you started, not to poll for completion — you are told when one finishes. Status comes from the live registry: running means the agent is working right now, idle means it is loaded but between turns (it may be waiting on agents it started), and ready means it exists only in storage — resumable, not terminal, and not a result waiting to be collected; a `send_message` steers a running child at its nearest step boundary or starts a turn for an idle or ready child, and a direct child remains a `send_message` candidate in every status. The snapshot is not a delivery promise — `send_message` performs the authoritative check and may still fail. Children that could not be read are reported as diagnostics instead of being silently dropped. Scope `descendants` walks the whole tree below you in stable pre-order, annotating each entry with its durable direct-parent session id and depth. You may use `send_message` only for depth-1 entries; deeper entries are candidates for `interrupt_agent` only.
|
||||
List your continuable background subagents by durable id and label. Use it to recall which ones you started, not to poll for completion — you are told when one finishes. Status comes from the live registry: running means the agent is working right now; inactive means no turn is executing, whether the child is loaded or must be resumed. inactive does not describe task completion, success, failure, or waiting for other agents. A `send_message` steers a running child at its nearest step boundary or starts or resumes a turn for an inactive child, and a direct child remains a `send_message` candidate in every status. The snapshot is not a delivery promise — `send_message` performs the authoritative check and may still fail. Children that could not be read are reported as diagnostics instead of being silently dropped. Scope `descendants` walks the whole tree below you in stable pre-order, annotating each entry with its durable direct-parent session id and depth. You may use `send_message` only for depth-1 entries; deeper entries are candidates for `interrupt_agent` only.
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -1904,7 +1908,7 @@ Source: [`packages/subagent/tool-subagent-control/src/list-agents.ts`](../packag
|
||||
|
||||
### `send_message`
|
||||
|
||||
Send a message to a direct continuable child by its agent id. If you are a resident continuable child, you may also target your direct parent. If the target is still working, the message steers its nearest step; if it is idle, the message starts a turn. This call returns no answer from the agent — only confirmation that the message was delivered. A failure means the message was NOT delivered.
|
||||
Send a message to a direct continuable child by its agent id. If you are a resident continuable child, you may also target your direct parent. If the target is still working, the message steers its nearest step; if it is inactive, the message starts or resumes a turn. This call returns no answer from the agent — only confirmation that the message was delivered. A failure means the message was NOT delivered.
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -2017,7 +2021,7 @@ Interrupt one teammate's current turn while preserving its pending inbox. Team L
|
||||
"properties": {
|
||||
"target": {
|
||||
"type": "string",
|
||||
"description": "Teammate name."
|
||||
"description": "Teammate target returned by spawn_teammate or list_agents."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2030,7 +2034,7 @@ Source: [`packages/experimental/tool-agent-team/src/index.ts`](../packages/exper
|
||||
|
||||
### `list_agents`
|
||||
|
||||
List the Lead and every durable teammate with current runtime status.
|
||||
List the Lead and every durable teammate with an addressable target and current availability. inactive means no turn is executing, not a task result. provisioning and failed describe member creation.
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -2043,7 +2047,7 @@ Source: [`packages/experimental/tool-agent-team/src/index.ts`](../packages/exper
|
||||
|
||||
### `send_message`
|
||||
|
||||
Send one durable message to another Team member. A running target receives it at the nearest step boundary; an idle target starts a turn; an inactive teammate cold-resumes.
|
||||
Send one durable message to another Team member. A running target receives it at the nearest step boundary; an inactive target starts or resumes a turn.
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -2051,7 +2055,7 @@ Send one durable message to another Team member. A running target receives it at
|
||||
"properties": {
|
||||
"target": {
|
||||
"type": "string",
|
||||
"description": "Team member name, or lead."
|
||||
"description": "Member target returned by spawn_teammate or list_agents, including lead."
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
@@ -2186,7 +2190,7 @@ List shared tasks, including readiness, owner, revision, blockers, and write-sco
|
||||
},
|
||||
"owner": {
|
||||
"type": "string",
|
||||
"description": "Optional member-name filter; use unowned for tasks without an owner."
|
||||
"description": "Optional member target from spawn_teammate or list_agents, matching ownerName; use unowned for tasks without an owner."
|
||||
},
|
||||
"ready": {
|
||||
"type": "boolean",
|
||||
@@ -2260,7 +2264,7 @@ Compare-and-set a shared task action using the latest revision from team_task_ge
|
||||
},
|
||||
"owner": {
|
||||
"type": "string",
|
||||
"description": "Member name for Lead-only reassign; omit to unassign."
|
||||
"description": "Member target from spawn_teammate or list_agents for Lead-only reassign; omit to unassign."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
+13
-9
@@ -88,6 +88,10 @@
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"registry": {
|
||||
"type": "string",
|
||||
"description": "For install_bundle: the npm registry URL asked first, when the user names one; otherwise the configured registry is asked, and its configured fallbacks while a registry is unreachable."
|
||||
},
|
||||
"offset": {
|
||||
"type": "number",
|
||||
"description": "Zero-based list offset; defaults to 0."
|
||||
@@ -631,7 +635,7 @@ bash 工具是 bash 执行器 seam 面向模型的消费方。使用 `run_in_bac
|
||||
|
||||
### `present`
|
||||
|
||||
声明交付 Session 文件系统可访问的已有文件。如果你创建或更新的文件是用户要求接收的成果,则必须在写入完成后、最终回复前调用 present,包括通过 Bash 或代码执行创建的文件。在回复中提到文件路径不能替代这次调用。文件必须已存在。用户打开当前源文件;不复制或保存其内容。
|
||||
选择 Session 文件系统可访问的已有文件,声明为最终交付物。当用户需要独立的文件交付物时使用 present,尤其是 Office 文档、电子表格和演示文稿。如果最终回复已经足够展示结果,优先在回复中展示;创建或编辑文件本身不要求调用 present。通常选择最重要的 1 至 2 项交付物,任务需要时可以更多,但一次 present 调用最多 4 个文件。文件必须已存在。用户打开当前源文件;不复制或保存其内容。
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -1888,7 +1892,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,
|
||||
|
||||
### `list_agents`
|
||||
|
||||
按持久 id 和标签列出你的可继续后台 subagent。用它回忆你启动过哪些 subagent,而不是轮询完成情况——subagent 完成时你会被告知。状态来自实时注册表:running 表示 agent 此刻正在工作;idle 表示已加载但处于轮次之间,可能正在等待它启动的 agent;ready 表示它只存在于存储中——可恢复而非终态,也不表示有结果等待收集;`send_message` 会在运行中 child 的最近 step 边界 steer 消息,或为 idle、ready child 启动轮次,且无论处于哪种状态,直接子级都仍可作为 `send_message` 的目标。该快照并非投递承诺;`send_message` 会执行权威检查,仍可能失败。无法读取的子级会作为诊断信息报告,而不会被静默丢弃。`descendants` 作用域会按稳定的前序顺序遍历你下方的整棵树,并为每个条目标注其持久的直接父会话 id 和深度。只有深度为 1 的条目可以使用 `send_message`;更深的条目只能作为 `interrupt_agent` 的候选目标。
|
||||
按持久 id 和标签列出你的可继续后台 subagent。用它回忆你启动过哪些 subagent,而不是轮询完成情况——subagent 完成时你会被告知。状态来自实时注册表:running 表示 agent 此刻正在工作;inactive 表示没有轮次在执行,包括已加载和需要恢复的 child。inactive 不表示任务完成、成功、失败或等待其他 agent。`send_message` 会在运行中 child 的最近 step 边界 steer 消息,或为 inactive child 启动或恢复轮次,且无论处于哪种状态,直接子级都仍可作为 `send_message` 的目标。该快照并非投递承诺;`send_message` 会执行权威检查,仍可能失败。无法读取的子级会作为诊断信息报告,而不会被静默丢弃。`descendants` 作用域会按稳定的前序顺序遍历你下方的整棵树,并为每个条目标注其持久的直接父会话 id 和深度。只有深度为 1 的条目可以使用 `send_message`;更深的条目只能作为 `interrupt_agent` 的候选目标。
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -1910,7 +1914,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,
|
||||
|
||||
### `send_message`
|
||||
|
||||
根据 agent id 向直接可继续 child 发送消息。如果你是驻留的可继续 child,也可以把自己的直接 parent 作为目标。如果目标仍在工作,消息会 steer 其最近的 step;如果目标处于 idle,消息会启动一个轮次。此调用不会返回该 agent 的答案,只会确认消息已投递。调用失败表示消息**未**投递。
|
||||
根据 agent id 向直接可继续 child 发送消息。如果你是驻留的可继续 child,也可以把自己的直接 parent 作为目标。如果目标仍在工作,消息会 steer 其最近的 step;如果目标处于 inactive,消息会启动或恢复一个轮次。此调用不会返回该 agent 的答案,只会确认消息已投递。调用失败表示消息**未**投递。
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -2023,7 +2027,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,
|
||||
"properties": {
|
||||
"target": {
|
||||
"type": "string",
|
||||
"description": "Teammate name."
|
||||
"description": "Teammate target returned by spawn_teammate or list_agents."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2036,7 +2040,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,
|
||||
|
||||
### `list_agents`
|
||||
|
||||
列出 Lead 与所有持久 teammate,以及各自当前的运行时状态。
|
||||
列出 Lead 与所有持久 teammate,以及可用于寻址的 target 和当前可用状态。inactive 表示没有轮次在执行,不表示任务结果。provisioning 与 failed 描述成员创建状态。
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -2049,7 +2053,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,
|
||||
|
||||
### `send_message`
|
||||
|
||||
向另一名 Team member 发送一条持久消息。running target 会在最近的步骤边界收到消息;idle target 会启动一个 turn;inactive teammate 会冷恢复。
|
||||
向另一名 Team member 发送一条持久消息。running target 会在最近的步骤边界收到消息;inactive target 会启动或恢复一个 turn。
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -2057,7 +2061,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,
|
||||
"properties": {
|
||||
"target": {
|
||||
"type": "string",
|
||||
"description": "Team member name, or lead."
|
||||
"description": "Member target returned by spawn_teammate or list_agents, including lead."
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
@@ -2192,7 +2196,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,
|
||||
},
|
||||
"owner": {
|
||||
"type": "string",
|
||||
"description": "Optional member-name filter; use unowned for tasks without an owner."
|
||||
"description": "Optional member target from spawn_teammate or list_agents, matching ownerName; use unowned for tasks without an owner."
|
||||
},
|
||||
"ready": {
|
||||
"type": "boolean",
|
||||
@@ -2266,7 +2270,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,
|
||||
},
|
||||
"owner": {
|
||||
"type": "string",
|
||||
"description": "Member name for Lead-only reassign; omit to unassign."
|
||||
"description": "Member target from spawn_teammate or list_agents for Lead-only reassign; omit to unassign."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -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/guide/python-sdk.md
|
||||
python-sdk.md: 2cb01ffa19d173231902c5c816929fa6b4d499f0
|
||||
python-sdk.zh.md: 3db859116530e51a7c7478ab222cbc4d2435dbf2
|
||||
python-sdk.md: a14d656171f37a7feea8c091741f2175f9617cd4
|
||||
python-sdk.zh.md: 0846ed95ef3a396b468b0f50bcc176c64a963850
|
||||
@@ -14,9 +14,14 @@ This tutorial installs the published Python SDK, runs the shipped standalone min
|
||||
|
||||
## Install the SDK
|
||||
|
||||
### Linux and macOS
|
||||
<div>
|
||||
<a id="linux-and-macos"></a>
|
||||
<a id="windows-powershell"></a>
|
||||
</div>
|
||||
|
||||
```sh
|
||||
::: code-group
|
||||
|
||||
```sh [Linux/macOS]
|
||||
git clone https://github.com/deepseek-ai/deepseek-harness.git
|
||||
cd deepseek-harness
|
||||
python -m venv .venv
|
||||
@@ -24,9 +29,7 @@ python -m venv .venv
|
||||
python -m pip install deepseek-harness-sdk
|
||||
```
|
||||
|
||||
### Windows PowerShell
|
||||
|
||||
```powershell
|
||||
```powershell [Windows PowerShell]
|
||||
git clone https://github.com/deepseek-ai/deepseek-harness.git
|
||||
Set-Location deepseek-harness
|
||||
py -3.10 -m venv .venv
|
||||
@@ -34,31 +37,43 @@ py -3.10 -m venv .venv
|
||||
python -m pip install deepseek-harness-sdk
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
The installation includes a matching native runtime wheel and the `dsh` command. Normal SDK execution needs no system Node.js. Repository contributors who build the artifacts should use the [Python contributor workflow](../../../python/development.md).
|
||||
|
||||
## Run the checked-in example
|
||||
|
||||
Export the credential and, when needed, a compatible proxy endpoint:
|
||||
|
||||
### Linux and macOS
|
||||
<div>
|
||||
<a id="linux-and-macos-1"></a>
|
||||
<a id="windows-powershell-1"></a>
|
||||
</div>
|
||||
|
||||
```sh
|
||||
::: code-group
|
||||
|
||||
```sh [Linux/macOS]
|
||||
export DEEPSEEK_API_KEY=sk-your-key-here
|
||||
# export DEEPSEEK_BASE_URL=http://127.0.0.1:8000/v1
|
||||
```
|
||||
|
||||
### Windows PowerShell
|
||||
|
||||
```powershell
|
||||
```powershell [Windows PowerShell]
|
||||
$env:DEEPSEEK_API_KEY = "sk-your-key-here"
|
||||
# $env:DEEPSEEK_BASE_URL = "http://127.0.0.1:8000/v1"
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Run one task with explicit workspace and home paths:
|
||||
|
||||
### Linux and macOS
|
||||
<div>
|
||||
<a id="linux-and-macos-2"></a>
|
||||
<a id="windows-powershell-2"></a>
|
||||
</div>
|
||||
|
||||
```sh
|
||||
::: code-group
|
||||
|
||||
```sh [Linux/macOS]
|
||||
python python/sdk/examples/minimal.py \
|
||||
--workspace /absolute/path/to/disposable-workspace \
|
||||
--dsh-home /absolute/path/to/example-dsh-home \
|
||||
@@ -66,9 +81,7 @@ python python/sdk/examples/minimal.py \
|
||||
"Inspect the repository and fix the failing tests."
|
||||
```
|
||||
|
||||
### Windows PowerShell
|
||||
|
||||
```powershell
|
||||
```powershell [Windows PowerShell]
|
||||
python python/sdk/examples/minimal.py `
|
||||
--workspace C:\work\disposable-workspace `
|
||||
--dsh-home C:\work\example-dsh-home `
|
||||
@@ -76,6 +89,8 @@ python python/sdk/examples/minimal.py `
|
||||
"Inspect the repository and fix the failing tests."
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
The script prints the final assistant response. The selected home receives the generated `sdk-minimal` profile, installed plugins, and uncompressed JSONL session logs under `sessions/`. The example and SDK never silently read `~/.dsh`.
|
||||
|
||||
## Use the SDK in your program
|
||||
@@ -109,22 +124,27 @@ The SDK starts the bundled `dsh --profile sdk-minimal` process lazily and reuses
|
||||
|
||||
Use `dsh plugin` for dependencies and bundle layers that should persist in this home:
|
||||
|
||||
### Linux and macOS
|
||||
<div>
|
||||
<a id="linux-and-macos-3"></a>
|
||||
<a id="windows-powershell-3"></a>
|
||||
</div>
|
||||
|
||||
```sh
|
||||
::: code-group
|
||||
|
||||
```sh [Linux/macOS]
|
||||
export DSH_HOME=/absolute/path/to/example-dsh-home
|
||||
dsh --profile sdk-minimal --dump-default-config >/dev/null
|
||||
dsh plugin --profile sdk-minimal add file:/absolute/path/to/my-plugin-bundle
|
||||
```
|
||||
|
||||
### Windows PowerShell
|
||||
|
||||
```powershell
|
||||
```powershell [Windows PowerShell]
|
||||
$env:DSH_HOME = "C:\work\example-dsh-home"
|
||||
dsh --profile sdk-minimal --dump-default-config | Out-Null
|
||||
dsh plugin --profile sdk-minimal add file:C:/work/my-plugin-bundle
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
The first command initializes the shipped standalone profile. The second forwards package management to `pnpm`, then records any installed package that exports a `dsh.bundle` layer. Install `pnpm` only for this management command; launching the installed SDK does not need it. Edit `$DSH_HOME/profiles/sdk-minimal/cordis.patch.yml` for persistent row changes, or pass patch files from Python for per-launch changes.
|
||||
|
||||
Another `profile` is valid when it includes `@deepseek-ai/dsh-sdk-app` or another JSON-RPC server row. Missing server rows, unresolved plugins, and invalid patches fail during startup instead of falling back to another composition.
|
||||
|
||||
@@ -14,9 +14,14 @@
|
||||
|
||||
## 安装 SDK
|
||||
|
||||
### Linux 与 macOS
|
||||
<div>
|
||||
<a id="linux-与-macos"></a>
|
||||
<a id="windows-powershell"></a>
|
||||
</div>
|
||||
|
||||
```sh
|
||||
::: code-group
|
||||
|
||||
```sh [Linux/macOS]
|
||||
git clone https://github.com/deepseek-ai/deepseek-harness.git
|
||||
cd deepseek-harness
|
||||
python -m venv .venv
|
||||
@@ -24,9 +29,7 @@ python -m venv .venv
|
||||
python -m pip install deepseek-harness-sdk
|
||||
```
|
||||
|
||||
### Windows PowerShell
|
||||
|
||||
```powershell
|
||||
```powershell [Windows PowerShell]
|
||||
git clone https://github.com/deepseek-ai/deepseek-harness.git
|
||||
Set-Location deepseek-harness
|
||||
py -3.10 -m venv .venv
|
||||
@@ -34,31 +37,43 @@ py -3.10 -m venv .venv
|
||||
python -m pip install deepseek-harness-sdk
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
安装内容包含匹配的原生运行时 wheel 与 `dsh` 命令。普通 SDK 运行不需要系统 Node.js。需要构建产物的仓库贡献者应使用 [Python 贡献者工作流](../../../python/development.zh.md)。
|
||||
|
||||
## 运行检入示例
|
||||
|
||||
导出凭据;使用兼容代理时再设置 endpoint:
|
||||
|
||||
### Linux 与 macOS
|
||||
<div>
|
||||
<a id="linux-与-macos-1"></a>
|
||||
<a id="windows-powershell-1"></a>
|
||||
</div>
|
||||
|
||||
```sh
|
||||
::: code-group
|
||||
|
||||
```sh [Linux/macOS]
|
||||
export DEEPSEEK_API_KEY=sk-your-key-here
|
||||
# export DEEPSEEK_BASE_URL=http://127.0.0.1:8000/v1
|
||||
```
|
||||
|
||||
### Windows PowerShell
|
||||
|
||||
```powershell
|
||||
```powershell [Windows PowerShell]
|
||||
$env:DEEPSEEK_API_KEY = "sk-your-key-here"
|
||||
# $env:DEEPSEEK_BASE_URL = "http://127.0.0.1:8000/v1"
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
使用显式 workspace 与 home 路径运行一个任务:
|
||||
|
||||
### Linux 与 macOS
|
||||
<div>
|
||||
<a id="linux-与-macos-2"></a>
|
||||
<a id="windows-powershell-2"></a>
|
||||
</div>
|
||||
|
||||
```sh
|
||||
::: code-group
|
||||
|
||||
```sh [Linux/macOS]
|
||||
python python/sdk/examples/minimal.py \
|
||||
--workspace /absolute/path/to/disposable-workspace \
|
||||
--dsh-home /absolute/path/to/example-dsh-home \
|
||||
@@ -66,9 +81,7 @@ python python/sdk/examples/minimal.py \
|
||||
"Inspect the repository and fix the failing tests."
|
||||
```
|
||||
|
||||
### Windows PowerShell
|
||||
|
||||
```powershell
|
||||
```powershell [Windows PowerShell]
|
||||
python python/sdk/examples/minimal.py `
|
||||
--workspace C:\work\disposable-workspace `
|
||||
--dsh-home C:\work\example-dsh-home `
|
||||
@@ -76,6 +89,8 @@ python python/sdk/examples/minimal.py `
|
||||
"Inspect the repository and fix the failing tests."
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
脚本会打印最终 assistant 响应。所选 home 会保存生成的 `sdk-minimal` profile、已安装插件,以及 `sessions/` 下的未压缩 JSONL 会话日志。示例与 SDK 绝不会静默读取 `~/.dsh`。
|
||||
|
||||
## 在程序中使用 SDK
|
||||
@@ -109,22 +124,27 @@ SDK 会延迟启动内置的 `dsh --profile sdk-minimal` 进程,并复用到
|
||||
|
||||
需要在该 home 中持久保存依赖与 bundle 层时,使用 `dsh plugin`:
|
||||
|
||||
### Linux 与 macOS
|
||||
<div>
|
||||
<a id="linux-与-macos-3"></a>
|
||||
<a id="windows-powershell-3"></a>
|
||||
</div>
|
||||
|
||||
```sh
|
||||
::: code-group
|
||||
|
||||
```sh [Linux/macOS]
|
||||
export DSH_HOME=/absolute/path/to/example-dsh-home
|
||||
dsh --profile sdk-minimal --dump-default-config >/dev/null
|
||||
dsh plugin --profile sdk-minimal add file:/absolute/path/to/my-plugin-bundle
|
||||
```
|
||||
|
||||
### Windows PowerShell
|
||||
|
||||
```powershell
|
||||
```powershell [Windows PowerShell]
|
||||
$env:DSH_HOME = "C:\work\example-dsh-home"
|
||||
dsh --profile sdk-minimal --dump-default-config | Out-Null
|
||||
dsh plugin --profile sdk-minimal add file:C:/work/my-plugin-bundle
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
第一个命令初始化随附的独立 profile。第二个命令把包管理转发给 `pnpm`,然后记录所有导出 `dsh.bundle` 层的已安装包。只有执行此管理命令时才需要安装 `pnpm`;启动已安装 SDK 不需要它。持久配置项变更应编辑 `$DSH_HOME/profiles/sdk-minimal/cordis.patch.yml`;单次启动变更则从 Python 传入 patch 文件。
|
||||
|
||||
另一个 `profile` 只有包含 `@deepseek-ai/dsh-sdk-app` 或另一个 JSON-RPC server 配置项时才有效。缺失 server 配置项、无法解析的插件和非法 patch 会在启动时失败,不会回退到其他组合。
|
||||
|
||||
@@ -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/web-styling.md
|
||||
web-styling.md: 1be0b629d2ccf54c5a00cfc8091a01e3d4d09bfd
|
||||
web-styling.zh.md: 106880e964a399cba825e889b5e93048589d00e4
|
||||
web-styling.md: 1275dd7cc6f2441618ab571d180a9ccd97ca2d93
|
||||
web-styling.zh.md: 9f43829b3e2fed846584474b0fccac0d8c0e94b7
|
||||
+2
-1
@@ -22,8 +22,9 @@ Global style sheets belong in `ui-theme/src/styles/`. Component styles live besi
|
||||
- Preserve keyboard focus visibility and reduced-motion behavior when adding transitions or hover-only controls.
|
||||
- Rounded corners inherit the global superellipse smoothing from ui-theme's `corner-shape.css` on supporting engines. Pair `corner-shape: round` with every full-round `border-radius` (`50%`, `100%`, or a pill radius) so circles and capsules keep circular arcs; the ui-theme corner-shape spec enforces the pairing.
|
||||
- Elevated surfaces (menus, popovers, modals, panels, floating buttons, the composer) set `border: 0` and take `box-shadow: var(--dsw-elevation-panel)`, `var(--dsw-elevation-prominent)`, or the composer's `var(--dsw-elevation-soft)` (larger blur at lower alpha): the 0.5px hairline stroke is the first shadow layer, and `--dsw-elevation-stroke-color` rebinds or suppresses it per surface or state. Never pair a `--dsw-alias-border-*` border with an lv/elevation shadow — the ui-theme elevation spec rejects the pairing; state-colored borders (warn panels) stay real borders.
|
||||
- An elevated surface using the translucent `--dsw-specific-menu` fill applies `backdrop-filter: var(--dsw-menu-backdrop-filter)` in the same rule. A surface containing fixed-position overlays paints both values on an isolated background pseudo-element so the filter does not change those overlays' containing block. Shared dropdowns use the compact `Menu` geometry; feature-owned menu content may vary without recreating the material or scrollbar implementation ([decision](../.agents/notes/implemented/feature/2026-09-17-compact-translucent-menu-surfaces.md)).
|
||||
- Flat borders and separators that use a neutral `--dsw-alias-border-*` token draw at `0.5px` — buttons, inputs, cards, row dividers, and separators drawn as filled boxes (menu separators, the conversation header seam, markdown `hr`, vertical rails) share the hairline weight, which Chromium paints as one device pixel. Dashed affordances and state-colored borders keep 1px; spinner ring tracks keep their width through the spec's explicit allowlist. The ui-theme elevation spec rejects wider neutral solid borders.
|
||||
- Clickable artifact links (markdown anchors, prose file mentions, web source and fetch links, produced-file chips, workflow member links) color through `--dsw-alias-link` at `font-weight: 500`, with no underline at rest and a dotted 3px-offset underline on hover/focus. Compact Thinking Markdown keeps tertiary text color and a resting dotted underline ([compact presentation](../.agents/notes/implemented/bug-fix/2026-09-17-thinking-markdown.md)). Text-leading anchors also lead with the ui-primitives `LinkIcon` category glyph riding `currentColor`, which for a well-known external host is that site's own mark instead of the globe; workflow member links and image-only anchors carry no glyph, and tool-row file links keep their grey dotted affordance ([clickable-link Agent Note](../.agents/notes/implemented/feature/2026-09-04-web-clickable-link-styles.md), [known-site mark Agent Note](../.agents/notes/implemented/feature/2026-09-16-known-site-link-marks.md)).
|
||||
- Clickable artifact links (markdown anchors, prose file mentions, web source and fetch links, produced-file chips, workflow member links) color through `--dsw-alias-link` at `font-weight: 500`, with no underline at rest and a dotted 3px-offset underline on hover/focus. Compact Thinking Markdown keeps tertiary text color and a resting dotted underline ([compact presentation](../.agents/notes/implemented/bug-fix/2026-09-17-thinking-markdown.md)). Text-leading anchors also lead with the ui-primitives `LinkIconMedium` category glyph riding `currentColor`, which for a well-known external host is that site's own mark instead of the globe; workflow member links and image-only anchors carry no glyph, and tool-row file links keep their grey dotted affordance.
|
||||
|
||||
## Changing the system
|
||||
|
||||
|
||||
@@ -22,8 +22,9 @@
|
||||
- 添加过渡动画或仅悬停可见的控件时,保留清晰可见的键盘焦点和减少动态效果行为。
|
||||
- 支持的引擎上,圆角继承 ui-theme `corner-shape.css` 的全局超级椭圆平滑。每个正圆 `border-radius`(`50%`、`100%` 或胶囊半径)必须配对 `corner-shape: round`,使圆形与胶囊保持圆弧;ui-theme 的 corner-shape spec 强制这一配对。
|
||||
- 高层级表面(菜单、浮层、对话框、面板、悬浮按钮、输入框)设 `border: 0` 并使用 `box-shadow: var(--dsw-elevation-panel)`、`var(--dsw-elevation-prominent)` 或输入框专用的 `var(--dsw-elevation-soft)`(更大模糊、更低透明度):0.5px 发丝描边是第一层投影,`--dsw-elevation-stroke-color` 可按表面或状态重绑或抑制描边。不得将 `--dsw-alias-border-*` border 与 lv/elevation 投影配对——ui-theme 的 elevation spec 会拒绝;状态色 border(warn 面板)保持真 border。
|
||||
- 使用半透明 `--dsw-specific-menu` 填充的高层级表面,必须在同一规则中应用 `backdrop-filter: var(--dsw-menu-backdrop-filter)`。包含 fixed 定位浮层的表面把两个属性绘制在隔离的背景伪元素上,避免滤镜改变这些浮层的包含块。共享下拉菜单采用紧凑 `Menu` 几何;功能包自有菜单内容可以不同,但不得重新实现材质或滚动条([决定](../.agents/notes/implemented/feature/2026-09-17-compact-translucent-menu-surfaces.zh.md))。
|
||||
- 使用中性 `--dsw-alias-border-*` token 的平面边框与分割线一律 `0.5px`——按钮、输入框、卡片、行分割线,以及以填充盒绘制的分隔线(菜单分隔、对话标题栏接缝、markdown `hr`、竖向轨道线)共用发丝线粗细,Chromium 将其绘制为一个设备像素。dashed 记号与状态色 border 保持 1px;spinner 圆环经 spec 的显式豁免保留原宽度。更宽的中性 solid border 会被 ui-theme elevation spec 拒绝。
|
||||
- 可点击产物链接(Markdown 锚点、正文文件引用、网页来源与抓取链接、产物 chips、workflow 成员链接)经 `--dsw-alias-link` 着色、`font-weight: 500`,默认无下划线,hover/focus 时为 3px offset 的点状下划线。紧凑 Thinking Markdown 保持 tertiary 文字色和默认点状下划线([紧凑展示](../.agents/notes/implemented/bug-fix/2026-09-17-thinking-markdown.zh.md))。带文字的锚点另以 ui-primitives 的 `LinkIcon` 分类图形(随 `currentColor`)作前置;目的地是已知外部站点时改用该站点自己的标记而非地球;workflow 成员链接与只包图片的锚点不带图形,工具行文件链接保持其灰色点线示能([可点击链接 Agent Note](../.agents/notes/implemented/feature/2026-09-04-web-clickable-link-styles.zh.md)、[已知站点标记 Agent Note](../.agents/notes/implemented/feature/2026-09-16-known-site-link-marks.zh.md))。
|
||||
- 可点击产物链接(Markdown 锚点、正文文件引用、网页来源与抓取链接、产物 chips、workflow 成员链接)经 `--dsw-alias-link` 着色、`font-weight: 500`,默认无下划线,hover/focus 时为 3px offset 的点状下划线。紧凑 Thinking Markdown 保持 tertiary 文字色和默认点状下划线([紧凑展示](../.agents/notes/implemented/bug-fix/2026-09-17-thinking-markdown.zh.md))。带文字的锚点另以 ui-primitives 的 `LinkIconMedium` 分类图形(随 `currentColor`)作前置;目的地是已知外部站点时改用该站点自己的标记而非地球;workflow 成员链接与只包图片的锚点不带图形,工具行文件链接保持其灰色点线示能。
|
||||
|
||||
## 变更系统
|
||||
|
||||
|
||||
Reference in new issue
Block a user