Merge remote-tracking branch 'origin/master' into worktree/web-background-tasks-display-258f7e
This commit is contained in:
@@ -4,7 +4,7 @@ This file defines document structure, Markdown tiers, writing rules, and `verify
|
||||
|
||||
## Document structure
|
||||
|
||||
These rules apply to human-facing documentation; [Agent Notes](../.agents/notes/README.md) remain outside their scope. A [postmortem](postmortem/README.md) is an incident-scoped reference; chronology records evidence, not a teaching sequence. A document's subject and tree position fix its scope: describe its own subject at appropriate detail, describe direct children only by purpose, responsibility, and high-level behavior, and link to the owning descendant for lower-level detail. Document type does not widen that scope. A reference may be exhaustive only about its own subject. Testing mechanisms, fixtures, and harnesses belong at the lowest owning level; higher documents link there.
|
||||
These rules apply to human-facing documentation; [Agent Notes](../.agents/notes/README.md) remain outside their scope. A [postmortem](postmortem/README.md) is an incident-scoped reference; chronology records evidence, not a teaching sequence. A document's subject and tree position fix its scope: describe its own subject at appropriate detail and direct children only by purpose, responsibility, and high-level behavior; link to the owning descendant for lower-level detail. Document type does not widen that scope. A reference may be exhaustive only about its own subject. Testing mechanisms, fixtures, and harnesses belong at the lowest owning level; higher documents link there.
|
||||
|
||||
Classify every in-scope document as a tutorial or reference. A tutorial follows an ordered path to an outcome and introduces only what each step needs. A reference defines a lookup scope and describes current behavior without depending on a teaching sequence. Separate substantial tutorial and reference content; use a clear structural boundary when either part is small.
|
||||
|
||||
@@ -14,13 +14,13 @@ Author in this order: locate the document in the tree; set its permitted detail;
|
||||
|
||||
## The tier taxonomy: one home per fact
|
||||
|
||||
Each fact has one home: the tier whose job it is. Elsewhere, link to that home.
|
||||
Each fact has one home: the tier whose job it is; elsewhere, link there.
|
||||
|
||||
| Tier | Job | Does NOT belong there |
|
||||
|---|---|---|
|
||||
| Root `AGENTS.md` | Standing orders: rules an agent needs in context in every session, one to three lines each, linking its home | Stories, worked examples, situational procedures, anything restated from a linked home |
|
||||
| Subtree `AGENTS.md` (`packages/`, `examples/`, `docs/`, `.agents/notes/`) | Orders specific to that subtree | Repo-wide rules the root file already carries |
|
||||
| [architecture.md](architecture.md) | The system map: services, the loop, extension seams — read before changing `packages/` | Type shapes (→ subsystems), per-package detail (→ package READMEs), decision rationale (→ Agent Notes), implementation-status annotations |
|
||||
| [architecture.md](architecture.md) | System map: services, loop, capability seams, extension points — read before changing `packages/` | Type shapes (→ subsystems), per-package detail (→ package READMEs), decision rationale (→ Agent Notes), implementation-status annotations |
|
||||
| [subsystems/](subsystems/README.md) | One reference page per subsystem: type shapes, semantics, and the generated Cordis surface | Behavior narration (→ architecture.md) |
|
||||
| [Agent Notes](../.agents/notes/README.md) | Active decision records: the why, what-was-given-up, and verification contract; `implemented/` notes describe shipped reality in present tense | Migration plans, acceptance-task checklists, fixture walkthroughs, and spec-speak ("should…") once the decision has shipped; archived notes are frozen history, never current authority |
|
||||
| [postmortem/](postmortem/README.md) | Incident stories — the only tier where war-story narrative belongs | — |
|
||||
@@ -28,21 +28,21 @@ Each fact has one home: the tier whose job it is. Elsewhere, link to that home.
|
||||
| [user/](user/index.md) | Product-facing guides published by the documentation website | Generated reference tables, contributor procedures, decision history |
|
||||
| Package README | The per-package contract: config, semantics, limitations, extension points, and [Model Experience](cookbook/adding-a-package.md#4-write-the-package-readme) | JSDoc restatement, generated-catalog restatement (event/tool tables), other packages' concerns |
|
||||
| [development.md](development.md) | First-stop contributor onboarding: local setup, daily workflow, and CI shape at summary level; a bilingual pair under the [i18n contract](i18n/README.md) | Runtime/version rationale (→ Agent Notes), gate-by-gate enumerations that drift from `package.json` scripts |
|
||||
| Generated reference: the per-page `cordis-surface` regions in [subsystems/](subsystems/README.md), the [Cordis core API + inherited tier](cordis-api/context.md), [tool-catalog](tool-catalog.md), [config-catalog](config-catalog.md), [persistence-catalog](persistence-catalog.md), [module-graph.md](module-graph.md) | Exhaustive enumerations regenerated from source, freshness-gated | Hand edits of any kind (regions included) |
|
||||
| Generated reference: the per-page `cordis-surface` regions in [subsystems/](subsystems/README.md), the [Cordis core API + inherited tier](cordis-api/context.md), [tool-catalog](tool-catalog.md), [config-catalog](config-catalog.md), [persistence-catalog](persistence-catalog.md), [module-graph.md](module-graph.md) | Exhaustive English sources regenerated from source and freshness-gated; reviewed Chinese counterparts follow the [pairing workflow](i18n/README.md#scope-and-exclusions) | Hand edits to generated English sources or regions; Chinese counterparts update through pairing only |
|
||||
| Skills (`.agents/skills/`) | Reusable workflows and specialized decision standards | Product and runtime contracts (→ docs or source) |
|
||||
|
||||
Placement: bugs → postmortems; rationale → Agent Notes; procedures → cookbooks; type shapes → subsystems; package contracts → READMEs; standing orders → root `AGENTS.md` with a rationale link.
|
||||
|
||||
## Writing rules
|
||||
|
||||
- **Document current state, not change history.** Avoid "previously/now/no longer", PRs, commits, and stack positions in durable prose; name the live mechanism. Put change stories in commits, PRs, Agent Notes, or postmortems.
|
||||
- **Document current state, not change history.** Avoid "previously/now/no longer", PRs, commits, and stack positions in durable prose; name the live mechanism. Put change stories in commits, PRs, Agent Notes, or postmortems; the latter two may cite merged PRs and issues as 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)).
|
||||
- **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)).
|
||||
- **Bilingual pairs update together**: editing either side obligates the counterpart and a re-record in the same change ([i18n contract](i18n/README.md)).
|
||||
- **Comments and JSDoc state complete contracts, not reasoning transcripts.** Preserve behavior, timing, modality, exceptions, consequences, and non-obvious orientation; delete narration, test walkthroughs, review analysis, and code restatement. Keep the local contract and link its rationale. Use [dsh-prose-standard](../.agents/skills/dsh-prose-standard/SKILL.md) for details.
|
||||
- Your audience is professional programmers. Prefer concise and straight-forward English over metaphor. Do not overuse words like "gate", "vocabulary", "surface", "seams".
|
||||
- Write directly: name actors and facts plainly ([decision](../.agents/notes/implemented/process/2026-08-09-concrete-prose-names-actors-and-recorded-facts.md)). Reserve `seam` for the defined capability; avoid metaphorical "gate", "vocabulary", and "surface".
|
||||
|
||||
## Wordcount Budgets
|
||||
|
||||
@@ -52,21 +52,21 @@ When the gate goes red:
|
||||
|
||||
1. **Relocate** content that belongs in another tier; leave a one-line link if needed.
|
||||
2. **Condense** content that belongs here but can be shorter.
|
||||
3. **Raise** the ceiling only when the words truly need the space; justify the manifest diff in the PR. A too-low ceiling is a budget bug.
|
||||
3. **Raise** the ceiling only when the words need the space; justify the manifest diff in the PR. A too-low ceiling is a budget bug.
|
||||
|
||||
Ceilings are guardrails, not reduction targets. At or below target, retain at least 5% headroom; above target, freeze the ceiling until relocation or condensation brings the document under target. Lower a ceiling only when the contract still has room, and raise it when content would otherwise be deleted. Targets: root `AGENTS.md` ≤ 1,600 words; `architecture.md` ≤ 1,800; subtree `AGENTS.md` ≤ 600, except `packages/AGENTS.md` ≤ 650 and this file ≤ 1,250; `packages/README.md` ≤ 600. Review governs unbudgeted tiers.
|
||||
|
||||
## The slop checklist
|
||||
|
||||
Hunt these in any doc; the [dsh-doc-standards](../.agents/skills/dsh-doc-standards/SKILL.md) skill runs this list as an audit:
|
||||
Hunt these in any doc; [dsh-doc-standards](../.agents/skills/dsh-doc-standards/SKILL.md) runs this list as an audit:
|
||||
|
||||
- The same rule stated in more than one home. Grep a distinctive phrase; keep one home, convert the rest to links.
|
||||
- The same rule stated in more than one home. Grep a distinctive phrase; keep one home and link the rest.
|
||||
- Narrated history or war stories: "previously", "now", "no longer", "used to", "renamed", "was moved", PRs, or commits. State the current fact; link an Agent Note or postmortem when needed.
|
||||
- Implementation-status annotations in prose or diagrams ("implemented!", "future: …"). Status rots; the repo layout and package manifests carry it.
|
||||
- Hand-restated catalogs, JSDoc, or inventories of tests, packages, and status when source or a generator is authoritative.
|
||||
- Reasoning transcripts: step-by-step implementation narration, proof of obvious branches, test walkthroughs, or rejected local alternatives. Keep the resulting contract or durable rationale; delete the path used to derive it.
|
||||
- Rationale repeated beside sibling methods instead of once at the owning seam or helper.
|
||||
- Paragraph walls: one paragraph carrying several rules and parenthetical asides. Split it, or demote the detail to the linked home.
|
||||
- Rationale repeated beside sibling methods instead of once at the owning capability or helper.
|
||||
- Paragraph walls: one paragraph carrying several rules and parenthetical asides. Split it or demote the detail to its home.
|
||||
- Emphasis inflation: bold, CAPS, or "critically" everywhere means nothing stands out. Reserve emphasis for the clause that changes behavior.
|
||||
- Spec-speak in `implemented/` Agent Notes: "should", migration plans, acceptance checklists. An implemented Agent Note describes what is, per the [implemented-note instructions](../.agents/notes/implemented/AGENTS.md).
|
||||
|
||||
|
||||
6
docs/agent-lifecycle.i18n.yaml
Normal file
6
docs/agent-lifecycle.i18n.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/agent-lifecycle.md
|
||||
agent-lifecycle.md: 7e3939b7fd6e7730918e4bc05e5bfcd655422e04
|
||||
agent-lifecycle.zh.md: 259ec78431ff0ead61c66e1d8edae4d22f1bcfd0
|
||||
@@ -71,7 +71,7 @@ sequenceDiagram
|
||||
Driver-->>SDK: <code>agent/status</code> idle
|
||||
```
|
||||
|
||||
The `assistant/message` edge records every successful provider call, including content-less and `max-tokens` finishes. Empty content stays out of derived history while the durable anchor retains usage and exact chunk provenance, including an explicit empty source set.
|
||||
The `assistant/message` event records every successful provider call, including content-less and `max-tokens` finishes. Empty content stays out of derived history, while the durable event keeps usage and `sourceEventSeqs` listing the exact `assistant/chunk` events, including an explicit empty list.
|
||||
|
||||
`dsh-compact-basic` uses `agent/pre-step` for pressure before request derivation and `agent/request-error` only for canonical context overflow. Once either trigger qualifies, optional tool-result pruning runs before summary selection. Recovery works between the closed failed step and failed turn close, and opens a fresh retry turn only when pruning or summarization advances the surface replacement generation; otherwise the original request error remains authoritative.
|
||||
|
||||
|
||||
84
docs/agent-lifecycle.zh.md
Normal file
84
docs/agent-lifecycle.zh.md
Normal file
@@ -0,0 +1,84 @@
|
||||
<!-- 英文源文件由 scripts/gen-doc-graphs.ts 生成;本中文文件是通过双语配对维护的经评审对侧。
|
||||
更新时先运行 `pnpm run gen-doc-graphs` 更新英文,再更新本文件并运行 `pnpm run verify-translation-pairing --write docs/agent-lifecycle.md` 重新记录配对。 -->
|
||||
|
||||
# Agent 轮次与步骤生命周期
|
||||
|
||||
[English](agent-lifecycle.md) | 中文
|
||||
|
||||
此时序图是 [architecture.md](architecture.md#default-loop-lifecycle) 的配套图示。持久的回放事实保存在 `session/event` 中,实时控制与状态则保存在 `agent/*` 中。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant Agent
|
||||
participant Driver
|
||||
participant Hooks as hook listeners
|
||||
participant Prompt as ctx.systemPrompt
|
||||
participant LLM as ctx.llm
|
||||
participant Tools as ctx.tools
|
||||
participant Session
|
||||
participant SDK as UI or SDK listener
|
||||
User->>Agent: followup(content)
|
||||
Agent-->>SDK: <code>agent/inbox/spliced</code>
|
||||
Agent-->>SDK: <code>agent/inbox/inserted</code> { message }
|
||||
Agent->>Driver: queued work wakes driver
|
||||
Driver-->>SDK: <code>agent/status</code> running
|
||||
Note over Agent,Driver: claim pending next-step input plus one queued prompt
|
||||
Driver-->>SDK: <code>agent/inbox/spliced</code> pure deletion
|
||||
Driver-->>SDK: <code>agent/inbox/claimed</code> { message, turn } per message
|
||||
Driver->>Hooks: <code>agent/pre-step</code> waterfall
|
||||
Hooks-->>Driver: authoritative reject or enter(messages)
|
||||
alt proposed step rejected or pre-step failed
|
||||
Driver-->>Driver: claimed batch stays removed, no turn opens
|
||||
else enter proposed step
|
||||
Driver->>Session: <code>turn/start</code>
|
||||
Driver->>Session: <code>step/start</code>
|
||||
Driver->>Session: <code>user/message</code> per entered message
|
||||
Driver->>Prompt: <code>system-prompt/assemble</code> waterfall
|
||||
Driver->>LLM: <code>agent/request</code> waterfall, then <code>llm/stream</code> waterfall
|
||||
LLM-->>Driver: StreamChunk*
|
||||
Driver->>Session: <code>assistant/chunk</code>*
|
||||
Session-->>SDK: <code>session/event</code> <code>assistant/chunk</code>*
|
||||
alt final adapter or terminal in-band request failure
|
||||
Driver->>Session: <code>step/end</code>
|
||||
Driver->>Hooks: <code>agent/request-error</code> waterfall
|
||||
Hooks-->>Driver: return retry action or preserve the original error
|
||||
else model request succeeded
|
||||
Driver->>Session: <code>assistant/message</code>
|
||||
Driver->>Tools: classify pending call by executionMode
|
||||
loop barriers and bounded rolling pool, reclassify before start
|
||||
opt call starts
|
||||
Driver->>Session: <code>tool/call</code>
|
||||
Driver->>Tools: ordered pre, concurrent execute
|
||||
Tools-->>Session: tool-owned events when applicable
|
||||
end
|
||||
opt next model-order result ready
|
||||
Driver->>Tools: ordered post
|
||||
Driver->>Session: <code>tool/result</code>
|
||||
end
|
||||
end
|
||||
Driver->>Session: <code>step/end</code>
|
||||
opt natural stop and next-step inbox empty
|
||||
Driver->>Hooks: <code>agent/turn-stopping</code> serial terminal checkpoint
|
||||
end
|
||||
opt next-step input is pending
|
||||
Driver-->>Driver: claim pending next-step input
|
||||
Driver-->>SDK: <code>agent/inbox/claimed</code> { message, turn } per message
|
||||
Driver->>Hooks: <code>agent/pre-step</code> waterfall
|
||||
Hooks-->>Driver: authoritative reject or enter(messages)
|
||||
end
|
||||
end
|
||||
Driver->>Session: <code>turn/end</code>
|
||||
end
|
||||
Driver-->>SDK: <code>agent/status</code> idle
|
||||
```
|
||||
|
||||
`assistant/message` 事件会记录每次成功的提供方调用,包括返回空内容或以 `max-tokens` 结束的调用。空内容不会进入派生历史,但该持久事件仍会保留用量,并通过 `sourceEventSeqs` 精确列出对应的 `assistant/chunk` 事件,包括显式空列表。
|
||||
|
||||
`dsh-compact-basic` 在派生请求之前通过 `agent/pre-step` 处理压力,而 `agent/request-error` 仅用于规范的上下文溢出。任一触发条件满足后,系统都会先执行可选的工具结果剪枝,再选择摘要。恢复发生在失败步骤结束之后、失败轮次结束之前;只有当剪枝或摘要生成推进了 surface replacement generation 时,系统才会开启一个全新的重试轮次,否则仍以原始请求错误为准。
|
||||
|
||||
以返回的 `agent/pre-step` 决策为准;通过包装 `next()` 的监听器会保留下游消息,除非有意替换这些消息。steering(中途引导)和注入的上下文在后续边界认领其下一步骤批次后,会经过同一 waterfall(瀑布式事件)。
|
||||
|
||||
需要可回放 transcript(文本记录)数据的 SDK 用户应当消费 `session/event`;`agent/*` 是用于队列与状态、提示词拦截、请求整形、steering、继续执行和错误处理的实时协调接口。
|
||||
|
||||
维护模式:英文源文件包含人工维护的 Mermaid 时序图,并由生成器写出;本中文文件作为经评审对侧通过双语配对维护。确切的事件签名位于生成的 Cordis 目录中。
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/api-gateway.md
|
||||
api-gateway.md: e8aafc173dced3c4ead07421d92401411565ece6
|
||||
api-gateway.zh.md: 5c4f306957a65a92abe8f15159ab2d23e61ef501
|
||||
api-gateway.md: 1fdbe256afb7e870e953f05bd29923a4e1c7c22b
|
||||
api-gateway.zh.md: b9e18bf78bb5887725a5278e0b28efb86d17b944
|
||||
|
||||
@@ -75,7 +75,7 @@ await agentCtx.remote.goals.create({ objective: 'ship it' })
|
||||
|
||||
Client applications assemble only `@deepseek-ai/dsh-api-remotes`. That package imports the `/remote` subpaths of selected business packages as runtime values, mounts their contributions through `ctx.remote.$mount()`, and re-exports the declaration merges from the same files. Adding a Host Remote package is an explicit choice by the Client composition owner; business components do not need to load the TypeRT Gateway or the business package's Remote JS separately.
|
||||
|
||||
A future TUI can assemble the same React-independent `api-remotes` and `ctx.remote` contract, so the Host methods visible to it are likewise limited to the Remote methods selected at generation time. This document does not define or implement the TUI composition.
|
||||
The `api-remotes` assembly and the `ctx.remote` contract are React-independent; the Host methods visible to any Client assembly are limited to the Remote methods selected at generation time.
|
||||
|
||||
## Component responsibilities
|
||||
|
||||
@@ -88,7 +88,7 @@ A future TUI can assemble the same React-independent `api-remotes` and `ctx.remo
|
||||
| Host | `@deepseek-ai/dsh-api-gateway` | Provides `ctx.typertGateway`, claims Remote endpoints, resolves objects or Contexts, invokes live Cordis services, and validates boundaries |
|
||||
| Client | `@deepseek-ai/dsh-api-gateway/client` | Provides `ctx.remote` and `remote.<namespace>` child Services, mounts generated descriptors as concrete methods, and initiates, validates, and cancels calls through the Connection |
|
||||
| Client | `@deepseek-ai/dsh-api-remotes/client` | Explicitly selects and mounts the `/remote` contributions allowed by the application and brings the corresponding declaration merges into business code |
|
||||
| Both | `@deepseek-ai/dsh-client-connection` | Provides the RPC carrier, request correlation, trust boundary, cancellation, response envelope, and current `/api` HTTP bridge |
|
||||
| Both | `@deepseek-ai/dsh-client-connection` | Provides the RPC carrier, request correlation, trust boundary, cancellation, response envelope, and the `/api` HTTP bridge |
|
||||
|
||||
The API Gateway package owns the Host dispatcher and Client Remote endpoint as peer entries, but the two builds never enter the same `ts.Program`. The Host entry does not import the Client Cordis `Context` merge, and the Client entry does not import the Host Gateway service.
|
||||
|
||||
@@ -118,7 +118,7 @@ Strict analysis requires a Remote to be a public, non-static instance method wit
|
||||
|
||||
## Runtime invocation
|
||||
|
||||
Remote and API Proxy currently share the Connection's `/api` route; there is no separate `/api2` server or second Connection. The Client Remote calls `connection.rpc.call('/api', '<namespace>/<method>', { args }, signal)`; the current HTTP carrier maps this to `POST /api/<namespace>/<method>`, with a payload containing only a named `args` object.
|
||||
Remote and API Proxy share the Connection's `/api` route. The Client Remote calls `connection.rpc.call('/api', '<namespace>/<method>', { args }, signal)`; the HTTP carrier maps this to `POST /api/<namespace>/<method>`, with a payload containing only a named `args` object.
|
||||
|
||||
The Connection performs the unified trust check for `/api` before the HTTP bridge, then dispatches inside the shared FetchHandler in interceptor order. The TypeRT Gateway claims only two-segment endpoints that have a strict descriptor or active SRC marker; unclaimed requests fall back to the existing API Proxy. The Connection owns transport, RPC ids, response envelopes, and request cancellation, while the Gateway owns only the Remote data protocol and business dispatch. Replacing the Connection carrier in the future does not require changes to Remote descriptors or the Client programming interface.
|
||||
|
||||
@@ -165,6 +165,6 @@ The running Client watcher consumes these generated files when it rebundles. If
|
||||
|
||||
Remote handles only unary method calls with one request and one result. Session event streams, pagination, incremental reduce, projection, and entity substreams require a separate data protocol and registration model; even when they reuse the Connection, they must not masquerade as Remote methods or enter invocation descriptors.
|
||||
|
||||
The API layers are organized as `remotes → gateway → connection → webserver`. The BFF and TypeRT RPC layers live under `packages/api`; Connection and WebServer remain at `packages/client/connection` and `packages/host/webserver`, with service contracts that permit a later package-only move to `packages/api`. The legacy API Proxy remains at `packages/host/apiproxy` as the fallback for endpoints not yet migrated to Remote.
|
||||
The API layers are organized as `remotes → gateway → connection → webserver`. The BFF and TypeRT RPC layers live under `packages/api`; Connection and WebServer live at `packages/client/connection` and `packages/host/webserver`. The API Proxy at `packages/host/apiproxy` handles endpoints without Remote descriptors.
|
||||
|
||||
Lookup policy is currently configured per key, so all `agent` or `session` parameters share the cold-resume behavior. If a Remote endpoint must accept live objects only, an explicit per-parameter or per-endpoint policy must be added later; the business method must not guess whether the object came from restoration.
|
||||
Lookup policy is configured per key, so all `agent` or `session` parameters share the cold-resume behavior. Accepting live objects only would require an explicit per-parameter or per-endpoint policy, which does not exist; the business method must not guess whether the object came from restoration.
|
||||
|
||||
@@ -75,7 +75,7 @@ await agentCtx.remote.goals.create({ objective: 'ship it' })
|
||||
|
||||
Client 应用只装配 `@deepseek-ai/dsh-api-remotes`。该包以运行时值导入被选业务包的 `/remote` 子路径,通过 `ctx.remote.$mount()` 挂载贡献,同时重新导出相同文件中的声明合并。增加一个 Host Remote 包是 Client 组合所有者的显式选择;业务组件不需要分别加载 TypeRT Gateway 或业务包的 Remote JS。
|
||||
|
||||
未来的 TUI 可以装配同一个不依赖 React 的 `api-remotes` 与 `ctx.remote` 约定,因此它能看到的 Host 方法同样只限于生成时选择的 Remote 方法。本文不定义或实现 TUI 组合。
|
||||
`api-remotes` 装配与 `ctx.remote` 约定不依赖 React;任何 Client 装配能看到的 Host 方法都只限于生成时选择的 Remote 方法。
|
||||
|
||||
## 组件职责
|
||||
|
||||
@@ -88,7 +88,7 @@ Client 应用只装配 `@deepseek-ai/dsh-api-remotes`。该包以运行时值导
|
||||
| Host | `@deepseek-ai/dsh-api-gateway` | 提供 `ctx.typertGateway`,认领 Remote endpoint,解析对象或 Context,调用实时 Cordis Service 并校验边界 |
|
||||
| Client | `@deepseek-ai/dsh-api-gateway/client` | 提供 `ctx.remote` 与 `remote.<namespace>` 子 Service,把生成的描述符挂成具体方法,并通过 Connection 发起、校验和取消调用 |
|
||||
| Client | `@deepseek-ai/dsh-api-remotes/client` | 显式选择并挂载本应用允许使用的 `/remote` 贡献,向业务代码带入对应的声明合并 |
|
||||
| 双侧 | `@deepseek-ai/dsh-client-connection` | 提供 RPC carrier、请求关联、信任边界、取消、响应 envelope 与当前 `/api` HTTP bridge |
|
||||
| 双侧 | `@deepseek-ai/dsh-client-connection` | 提供 RPC carrier、请求关联、信任边界、取消、响应 envelope 与 `/api` HTTP bridge |
|
||||
|
||||
API Gateway 包同时拥有 Host dispatcher 与 Client Remote endpoint 两个对等入口,但两侧构建不会进入同一个 `ts.Program`。Host 入口不导入 Client 的 Cordis `Context` 合并,Client 入口也不导入 Host Gateway 服务。
|
||||
|
||||
@@ -118,7 +118,7 @@ Remote Client 声明中的参数名来自 wire 字段,参数和返回类型则
|
||||
|
||||
## 运行时调用
|
||||
|
||||
当前 Remote 与 API Proxy 共用 Connection 的 `/api` 路由,不存在独立 `/api2` server 或第二套 Connection。Client Remote 调用 `connection.rpc.call('/api', '<namespace>/<method>', { args }, signal)`;当前 HTTP carrier 对应 `POST /api/<namespace>/<method>`,payload 只包含一个具名 `args` 对象。
|
||||
Remote 与 API Proxy 共用 Connection 的 `/api` 路由。Client Remote 调用 `connection.rpc.call('/api', '<namespace>/<method>', { args }, signal)`;HTTP carrier 对应 `POST /api/<namespace>/<method>`,payload 只包含一个具名 `args` 对象。
|
||||
|
||||
Connection 在 HTTP bridge 之前执行 `/api` 的统一信任检查,再在共享 FetchHandler 内按 interceptor 顺序分发。TypeRT Gateway 只认领存在严格描述符或活跃 SRC marker 的两段式 endpoint;未认领的请求回退到既有 API Proxy。Connection 拥有传输、RPC id、响应 envelope 和 request cancellation,Gateway 只拥有 Remote 数据协议和业务分发。未来替换 Connection carrier 不要求改变 Remote 描述符或 Client 编程界面。
|
||||
|
||||
@@ -165,6 +165,6 @@ pnpm run build:lib
|
||||
|
||||
Remote 只处理有单个请求与单个结果的一元方法调用。Session event stream、分页、增量 reduce、projection 和实体子流需要独立的数据协议与注册模型;即使它们复用 Connection,也不应伪装成 Remote 方法或放入调用描述符。
|
||||
|
||||
API 各层按 `remotes → gateway → connection → webserver` 组织。BFF 与 TypeRT RPC 层位于 `packages/api`;Connection 与 WebServer 仍位于 `packages/client/connection` 和 `packages/host/webserver`,其服务约定允许未来只移动包,将它们放到 `packages/api`。旧 API Proxy 仍位于 `packages/host/apiproxy`,作为尚未迁移到 Remote 的 endpoint 的回退路径。
|
||||
API 各层按 `remotes → gateway → connection → webserver` 组织。BFF 与 TypeRT RPC 层位于 `packages/api`;Connection 与 WebServer 位于 `packages/client/connection` 和 `packages/host/webserver`。位于 `packages/host/apiproxy` 的 API Proxy 处理没有 Remote 描述符的 endpoint。
|
||||
|
||||
当前 lookup 策略按 key 配置,因此所有 `agent` 或 `session` 参数共享冷恢复行为。某个 Remote endpoint 若必须只接受 live 对象,需要后续增加显式的逐参数或逐 endpoint 策略,不能通过业务方法内部猜测恢复来源。
|
||||
lookup 策略按 key 配置,因此所有 `agent` 或 `session` 参数共享冷恢复行为。只接受 live 对象需要显式的逐参数或逐 endpoint 策略,而这种策略并不存在;不能通过业务方法内部猜测对象是否来自恢复。
|
||||
|
||||
@@ -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: 06c15f204b3a695de49df29938781f8f033c4a7e
|
||||
architecture.zh.md: 29fe94f5a94c317854366e811dc6ceb74d2fddfe
|
||||
architecture.md: 90d64fb0ac62020e13a7ce995c8e3273a5a9f906
|
||||
architecture.zh.md: fec9a00484c495b0eed4773f262bb44543e304bd
|
||||
|
||||
@@ -17,6 +17,7 @@ Harnesses are [Cordis](cordis-primer.md) contexts; packages contribute services,
|
||||
| `ctx.systemPrompt` | `dsh-system-prompt` | ordered prompt sections, tool schemas, and variables |
|
||||
| `ctx.tools` | `dsh-tools` | tool registry and [execution pipeline](tool-execution-pipeline.md) |
|
||||
| `ctx.agents` | `dsh-agent` | live agents, delegated creation, `agent/*` events, process-local initiator scope |
|
||||
| `ctx.agentDefaultModel` | [`dsh-agent-default-model`](../packages/core/agent-default-model/README.md) | Settings-backed model selection shared by Agent front doors |
|
||||
| `ctx.agentLoop` | `dsh-agent-loop` | concrete `Agent` driver |
|
||||
|
||||
### Capability Services
|
||||
@@ -91,7 +92,7 @@ forever:
|
||||
'step/start'
|
||||
append the returned batch as separate 'user/message' events
|
||||
assemble ordered prompt and tool schemas -> snapshot derived messages
|
||||
agent/request (config only) -> prepare adapter defaults/provenance + context capacity under turn signal -> log request/header (+ request/context on route change) -> llm/stream (frozen, registration-bound)
|
||||
agent/request (config only) -> resolve adapter defaults and mark defaulted fields + context capacity under turn signal -> log request/header (+ request/context on route change) -> llm/stream (frozen, registration-bound)
|
||||
'assistant/chunk'
|
||||
'assistant/message'
|
||||
schedule tool calls by ctx.tools.executionMode:
|
||||
@@ -143,21 +144,21 @@ The session log is authoritative. `deriveMessages()` projects model history; raw
|
||||
|
||||
Durability is a plugin concern. Backends copy synchronous `session/event` notifications into fixed-window durable batches; `session/flush` bypasses the wait before requests and top-level tool dispatch, and after `turn/end` before another turn or idle. `SessionPersistence` stores events and header metadata; JSONL defaults to checksummed Zstandard and SQLite shares the contract ([checkpoint decision](../.agents/notes/implemented/bug-fix/2026-07-21-semantic-session-checkpoints.md), [batching decision](../.agents/notes/implemented/architecture/2026-08-08-bounded-session-persistence-write-batching.md)).
|
||||
|
||||
Between turns, owners append log-only events through `Session`, flushing only for durability. `session/title` relies on bounded background persistence and lifecycle drains; manual compaction flushes its bracket before the operation completes. Title work never delays responses; latest wins with provenance. Title records are inherited fork boundaries ([decision](../.agents/notes/implemented/feature/2026-07-21-log-backed-session-titles.md)).
|
||||
Between turns, owners append log-only events through `Session`, flushing only for durability. `session/title` relies on bounded background persistence and lifecycle drains; manual compaction flushes its bracket before the operation completes. Title work never delays responses; the latest title event wins, and it records the source message seqs and whether the user, fallback, or provider supplied it. Title records are inherited fork boundaries ([decision](../.agents/notes/implemented/feature/2026-07-21-log-backed-session-titles.md)).
|
||||
|
||||
### Model Content
|
||||
|
||||
Messages use typed blocks from merge-extensible `ContentBlockMap`; the pattern also types `MessageSource`, `FinishReason`, `TurnTrigger`, and `TurnEndReason`. New blocks coordinate adapters, UI, compaction, token metering, and persistence; replay measurements live in [token-meter.md](subsystems/token-meter.md).
|
||||
|
||||
Streaming uses raw chunks and `BlockAssembler`. Each `LlmAdapter.stream()` is one provider attempt; adapters report normalized failure facts, and a handling `agent/request-error` plugin returns a retry action. The loop logs chunks, successful provenance, and replay state. Remote adapters use per-read idle watchdogs. Replay crosses routes only through a shared adapter instance ([contract](subsystems/llm-streaming.md)).
|
||||
Streaming uses raw chunks and `BlockAssembler`. Each `LlmAdapter.stream()` is one provider attempt; adapters report normalized failure facts, and a handling `agent/request-error` plugin returns a retry action. The loop logs chunks, the successful provider/model route, and replay state. Remote adapters use per-read idle watchdogs. Replay crosses routes only through a shared adapter instance ([contract](subsystems/llm-streaming.md)).
|
||||
|
||||
## Extension And Composition
|
||||
|
||||
### Capability Pattern
|
||||
|
||||
Capabilities separate **interface / implementation / consumer** layers. Filesystem and subprocess providers define one execution world; Bash, PTY, and LSP run there without provider forks. See the [capability graph](capability-seams.md).
|
||||
A **seam** is a swappable capability with **Service Definition**, **Service provider**, and **Consumer** roles. Packages may combine roles; individual roles are not seams. Filesystem and subprocess providers share one execution world; Bash, PTY, and LSP need no provider forks ([capability graph](capability-seams.md)).
|
||||
|
||||
Exceptions combine LLM interface/consumer, filesystem policy, web registries, and named skill/subagent providers. Subagents spawn fresh, fork a completed-turn prefix, use ACP children, or delegate one self-contained turn to a real product provider such as Codex ([subagent.md](subsystems/subagent.md)).
|
||||
Exceptions combine LLM Service Definition/Consumer roles, filesystem policy, web registries, and skill/subagent providers. Subagents spawn fresh, fork a completed-turn prefix, use ACP children, or delegate a self-contained turn to Codex or another product provider ([subagent.md](subsystems/subagent.md)).
|
||||
|
||||
`dsh-workspace-context` composes its baseline on the first `agent/pre-step` and folds it into the final entering batch right after the claimed prompt, so it reaches the first request with the direct prompt; rejection keeps it in the next-step inbox. When compaction removes that baseline from the visible surface, the next entering pre-step composes the current baseline and carries it in the same request. Filesystem changes projected after tools are likewise folded into the next entering pre-step instead of creating a later context-only step ([decision](../.agents/notes/implemented/feature/2026-06-24-workspace-context.md)). `dsh-paths` owns shared paths.
|
||||
|
||||
@@ -165,6 +166,10 @@ Exceptions combine LLM interface/consumer, filesystem policy, web registries, an
|
||||
|
||||
`dsh-agent-spine-demo` bundles a spine and optional goals. App packages own CLI, ACP automation, and JSON-RPC front doors ([README](../packages/examples/agent-spine-demo/README.md), [acp/](../packages/acp/README.md), [interaction/](../packages/interaction/README.md)). `dsh-jsonrpc-agent` boots external `cordis.yml`; the Python SDK defaults when config is absent ([Python SDK](../python/README.md)). Thin deployments use swappable backends and optional tools ([examples/](../examples/AGENTS.md), [runnable wirings](cookbook/extension-cookbook.md#runnable-wirings), [graph atlas](graph-atlas.md)).
|
||||
|
||||
### Agent Presets
|
||||
|
||||
A deployment may compose each session's model-facing plugin set separately. An **agent preset** is a directory holding one `agent.cordis.yml`, mounted as an `include` subtree under that agent's scope during `setup(agentCtx)`, so its tool and prompt registrations file into that agent's layer and unwind with it — no new tier in the registries. The host composition keeps what must be shared: the registries themselves, cross-session facilities, the sandbox and approval stack, the model route. `ctx.agentPresets` owns discovery and the guarded mount, rejecting a row that never activates or that publishes into the root service realm. Details: [per-session agent presets](../.agents/notes/implemented/architecture/2026-08-03-per-session-agent-presets.md), [preset/](../packages/preset/README.md).
|
||||
|
||||
### Where New Behavior Goes
|
||||
|
||||
New behavior attaches to a documented extension point; a loop change updates this map.
|
||||
@@ -173,6 +178,7 @@ New behavior attaches to a documented extension point; a loop change updates thi
|
||||
|---|---|
|
||||
| Add a model provider | register its adapter on `ctx.llm` |
|
||||
| Add a model-facing capability | register on `ctx.tools`; schemas join prompt assembly |
|
||||
| Give one session a different capability set | compose it in an agent preset; a service row there needs an `isolate` realm |
|
||||
| Add shell execution | implement and register a `ctx.bash` backend; the local backend spawns through `ctx.subprocess` |
|
||||
| Add persistent terminal execution | register a `ctx.pty` backend plus `dsh-tool-pty` |
|
||||
| Add a human command | register on `ctx.commands`; adapters discover and dispatch without a model turn |
|
||||
@@ -182,10 +188,11 @@ New behavior attaches to a documented extension point; a loop change updates thi
|
||||
| Intercept a request, tool, or turn | use its `agent/*` or `tools/*` event; `agent/turn-stopping` is the stop boundary |
|
||||
| Add model-facing context | call `agent.inject()` to queue sourced context for the next admitted request |
|
||||
| Add UI or editor integration | drive `ctx.agents` and render from `session/event` |
|
||||
| Web Client Chat node | register a `ConversationNodeDefinition` + keyed renderer |
|
||||
| Add durable session state | extend `SessionEventMap`; render and replay from the log |
|
||||
| Add asynchronous session-title generation | register the sole `ctx.sessionTitle` provider |
|
||||
| Manage a same-session objective | use `ctx.goals`; continue through `Agent` and `agent/*` |
|
||||
| Fork a live session | call `ctx.sessions.fork(source, boundary?, childSessionId?)` |
|
||||
| Scope a registration to one agent | use its `agent.ctx` (see Agent Scope) |
|
||||
|
||||
The [extension cookbook](cookbook/extension-cookbook.md) has plugin skeletons and the feature-to-seam map; guides cover [packages](cookbook/adding-a-package.md), [tools](cookbook/adding-a-tool.md), [LLM adapters](cookbook/adding-an-llm-adapter.md), and [vendored packages](cookbook/adding-a-vendored-package.md).
|
||||
[Extension cookbook](cookbook/extension-cookbook.md) maps features to capabilities; guides cover [packages](cookbook/adding-a-package.md), [tools](cookbook/adding-a-tool.md), [LLM adapters](cookbook/adding-an-llm-adapter.md), [Chat nodes](cookbook/adding-a-conversation-node.md), and [vendored packages](cookbook/adding-a-vendored-package.md).
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
## 概览
|
||||
|
||||
每个 harness 都是 [Cordis](cordis-primer.md) 上下文;各包(package)贡献服务、类型化事件和可释放的注册项。`packages/core/` 汇集默认流程;各项功能仍以插件形式存在。
|
||||
每个 harness 都是 [Cordis](cordis-primer.md) 上下文;各包贡献服务、类型化事件和可释放的注册项。`packages/core/` 汇集默认流程;各项能力仍以插件形式存在。
|
||||
|
||||
### 默认服务
|
||||
|
||||
@@ -17,18 +17,19 @@
|
||||
| `ctx.systemPrompt` | `dsh-system-prompt` | 有序的提示词片段、工具 schema 和变量 |
|
||||
| `ctx.tools` | `dsh-tools` | 工具注册表和[执行流水线](tool-execution-pipeline.md) |
|
||||
| `ctx.agents` | `dsh-agent` | 活跃 agent(智能体)、委托创建、`agent/*` 事件、进程内发起方作用域 |
|
||||
| `ctx.agentLoop` | `dsh-agent-loop` | 实体 `Agent` 驱动器 |
|
||||
| `ctx.agentDefaultModel` | [`dsh-agent-default-model`](../packages/core/agent-default-model/README.md) | 由 Settings 支撑、供 Agent 入口共享的模型选择 |
|
||||
| `ctx.agentLoop` | `dsh-agent-loop` | 具体 `Agent` 驱动器 |
|
||||
|
||||
### 功能服务
|
||||
### 能力服务
|
||||
|
||||
| ctx 键 | 包族 | 职责 |
|
||||
|---|---|---|
|
||||
| `ctx.llm` | [`llm/`](../packages/llm/README.md) | 适配器注册表和模型流式调用 |
|
||||
| `ctx.tokenMeter` | [`llm/token-meter`](../packages/llm/token-meter/README.md) | 感知回放的单实例请求压力与表面压力 |
|
||||
| `ctx.tokenMeter` | [`llm/token-meter`](../packages/llm/token-meter/README.md) | 感知回放的请求压力与表面压力 |
|
||||
| `ctx.bash` | [`bash/`](../packages/bash/README.md) | 前台和后台命令执行 |
|
||||
| `ctx.subprocess` | [`subprocess/`](../packages/subprocess/README.md) | 可执行文件查找、受管进程树、终端 |
|
||||
| `ctx.pty` | [`pty/`](../packages/pty/README.md) | 按 owner 隔离的持久化终端会话 |
|
||||
| `ctx.sandbox` | [`sandbox/`](../packages/sandbox/README.md) | 通过 argv 包装和逐调用策略限制同一执行环境内的进程 |
|
||||
| `ctx.sandbox` | [`sandbox/`](../packages/sandbox/README.md) | 通过 argv 包装和逐调用策略限制与宿主共享文件系统和内核的进程 |
|
||||
| `ctx.sandboxPolicy` | [`sandbox/`](../packages/sandbox/README.md) | 共享沙箱策略归属点 |
|
||||
| `ctx.codeRuntime` | [`code-runtime/`](../packages/code-runtime/README.md) | 执行模型编写的程序 |
|
||||
| `ctx.fs` | [`fs/`](../packages/fs/README.md) | 执行世界路径、有界 I/O 和策略事件 |
|
||||
@@ -59,7 +60,7 @@
|
||||
|
||||
- **会话事件**是通过 `session/event` 发出的持久日志事实。
|
||||
- **Agent 事件**携带活跃 `Agent`,用于 inbox、步骤、状态、请求、验证和续跑。
|
||||
- **功能事件**无需导入循环即可附加策略和适配器。
|
||||
- **能力事件**无需导入循环即可附加策略和适配器。
|
||||
|
||||
### 拦截语义
|
||||
|
||||
@@ -91,7 +92,7 @@ forever:
|
||||
'step/start'
|
||||
append the returned batch as separate 'user/message' events
|
||||
assemble ordered prompt and tool schemas -> snapshot derived messages
|
||||
agent/request (config only) -> prepare adapter defaults/provenance + context capacity under turn signal -> log request/header (+ request/context on route change) -> llm/stream (frozen, registration-bound)
|
||||
agent/request (config only) -> resolve adapter defaults and mark defaulted fields + context capacity under turn signal -> log request/header (+ request/context on route change) -> llm/stream (frozen, registration-bound)
|
||||
'assistant/chunk'
|
||||
'assistant/message'
|
||||
schedule tool calls by ctx.tools.executionMode:
|
||||
@@ -115,19 +116,19 @@ idle inject:
|
||||
|
||||
`inject()` 将不会唤醒驱动器的上下文排入 `next-step`;空闲驱动器会让它保持待处理,直至 `followup()` 或 `steer()` 唤醒。工具执行后的 `additionalContexts` 使用同一个 inbox。`agent/pre-step` 的 payload 携带独占的已领取批次,以及即将使用的轮次、步骤和信号。拒绝则不进入步骤;进入则提供在 `step/start` 后追加的完整批次。空的工具续跑仍会经过 waterfall,其最终值一次性结算所有改写。
|
||||
|
||||
裁剪先于摘要;溢出重试必须取得持久进展。`agent/request-error` 可以授权使用冻结提示词进行同步骤重试;取消优先。适配器的 `retryPolicy` 使 normal mode 保持有界,always mode 则在专门恢复后重试([压缩](../.agents/notes/implemented/architecture/2026-07-10-after-call-compaction-pressure-and-overflow-recovery.md)、[重试基础](../.agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.md)、[提供方策略](../.agents/notes/implemented/feature/2026-07-24-provider-retry-policies.md))。精确事件顺序由生成的 [agent 生命周期](agent-lifecycle.md)定义;队列、steering、重试与取消机制由 [agent-loop README](../packages/core/agent-loop/README.md)定义。
|
||||
裁剪先于摘要;溢出重试必须取得持久进展。`agent/request-error` 可以授权使用冻结提示词进行同步骤重试;取消优先。适配器的 `retryPolicy` 使 normal mode 保持有界,always mode 则在专门恢复后重试([压缩](../.agents/notes/implemented/architecture/2026-07-10-after-call-compaction-pressure-and-overflow-recovery.md)、[重试基础](../.agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.md)、[提供方策略](../.agents/notes/implemented/feature/2026-07-24-provider-retry-policies.md))。精确事件顺序由生成的 [agent 生命周期](agent-lifecycle.md)定义;队列、steering(中途引导)、重试与取消机制由 [agent-loop README](../packages/core/agent-loop/README.md)定义。
|
||||
|
||||
### 失败边界
|
||||
|
||||
适配器选择、分发与迭代失败会成为 error 或 aborted 类型的终止 `finish` 分片。`agent/request-error` 接收请求坐标、标准化 `LlmFailure`、可用的重试策略和信号;middleware 与消费方错误仍在恢复之外。失败分片既不提交消息,也不提交工具调用。
|
||||
|
||||
其他故障使用 `agent/error`;取消和资源释放优先于恢复。在提交请求头之前,轮次信号会取消功能准备;尚未分派的工具会得到合成的 `tool/call`/`ABORTED_BEFORE_DISPATCH` 对。实际生效的 `cancel(cause)` 会在清空队列和中止前报告原因;空闲调用不发事件。abort 触发后、收敛前到达的唤醒输入会在 driver 的收敛边界执行,而 `disposed` 取消则将其停放([取消收敛窗口唤醒锁存](../.agents/notes/implemented/bug-fix/2026-08-07-cancel-convergence-wake-latch.md))。持久化层以 `aborted` 区分取消,以 `disposed` 区分会等待完全停稳的拆卸([决策](../.agents/notes/implemented/architecture/2026-07-16-explicit-turn-cancellation.md))。
|
||||
其他故障使用 `agent/error`;取消和 dispose(资源释放)优先于恢复。在提交请求头之前,轮次信号会取消能力准备;尚未分派的工具会得到合成的 `tool/call`/`ABORTED_BEFORE_DISPATCH` 对。实际生效的 `cancel(cause)` 会在清空队列和中止前报告原因;空闲调用不发事件。abort 触发后、收敛前到达的唤醒输入会在 driver 的收敛边界执行,而 `disposed` 取消则将其停放([取消收敛窗口唤醒锁存](../.agents/notes/implemented/bug-fix/2026-08-07-cancel-convergence-wake-latch.md))。持久性以 `aborted` 区分取消,以 `disposed` 区分会等待完全停稳的拆卸([决策](../.agents/notes/implemented/architecture/2026-07-16-explicit-turn-cancellation.md))。
|
||||
|
||||
轮次和步骤事件均位于轮次边界内;loop 只会在轮次内从进入步骤的批次追加 `user/message`。轮次会在首次领取与 pre-step 之前打开,因此拒绝、空输入、取消或失败会关闭一个不包含任何步骤事件的持久轮次。独立的 `compact/* { turn: null }` 事件不占用轮次,其锁定时刻标记可以与 inbox splice 交错。重新加载会为中断的轮次合成结束事件;`session/end-seed` 区分陈旧的压缩遗留项与活跃锁。关闭后仅由 `agent/error` 报告故障。每个轮次有一个 [TurnEndReason](subsystems/session.md#why-a-turn-ended-turnendreasonmap)。
|
||||
|
||||
### Agent 句柄
|
||||
|
||||
`ctx.agents` 拥有 agent 并返回 `AgentHandle { agent, dispose() }`。插件使用 `send()`,或使用其 `followup()`、`steer()` 和 `inject()` 预设。`cancel()` 与 `whenIdle()` 控制生命周期,需等待完成的资源释放则负责拆卸。后续消息的 `MessageId` 跟踪持久 inbox 的插入、领取与丢弃通知,而不标识提示词输出或轮次结束;只有完整活动区间的所有方才能将其概括为一次运行结果([决策](../.agents/notes/implemented/architecture/2026-07-30-followup-enqueue-and-owned-runs.md))。
|
||||
`ctx.agents` 拥有 agent 并返回 `AgentHandle { agent, dispose() }`。插件使用 `send()`,或使用其 `followup()`、`steer()` 和 `inject()` 预设。`cancel()` 与 `whenIdle()` 控制生命周期,拆卸由需等待完成的 dispose 负责。后续消息的 `MessageId` 跟踪持久 inbox 的插入、领取与丢弃通知,而不标识提示词输出或轮次结束;只有完整活动区间的所有者才能将其概括为一次运行结果([决策](../.agents/notes/implemented/architecture/2026-07-30-followup-enqueue-and-owned-runs.md))。
|
||||
|
||||
### Agent 作用域
|
||||
|
||||
@@ -143,21 +144,21 @@ idle inject:
|
||||
|
||||
持久性由插件负责。后端会将同步的 `session/event` 通知复制到固定窗口的持久化批次中;`session/flush` 会绕过等待,在请求与顶层工具分发之前执行,并在 `turn/end` 之后、另一个轮次或空闲状态之前执行。`SessionPersistence` 存储事件和 header 元数据;JSONL 默认采用带校验和的 Zstandard,SQLite 遵循同一约定([检查点决策](../.agents/notes/implemented/bug-fix/2026-07-21-semantic-session-checkpoints.md)、[批处理决策](../.agents/notes/implemented/architecture/2026-08-08-bounded-session-persistence-write-batching.md))。
|
||||
|
||||
在轮次之间,事件所有方通过 `Session` 追加纯日志事件,仅为持久性而刷写。`session/title` 依赖有界后台持久化与生命周期排空;手动压缩会在操作完成前 flush 其标记对。标题工作绝不延迟响应;最新标题按后写覆盖并携带来源信息。标题记录是可继承的 fork 边界([决策](../.agents/notes/implemented/feature/2026-07-21-log-backed-session-titles.md))。
|
||||
在轮次之间,事件所有方通过 `Session` 追加纯日志事件,仅为持久性而刷写。`session/title` 依赖有界后台持久化与生命周期排空;手动压缩会在操作完成前 flush 其标记对。标题工作绝不延迟响应;最新的标题事件生效,并记录来源消息 seq,以及标题由用户、后备逻辑还是提供方提供。标题记录是可继承的 fork 边界([决策](../.agents/notes/implemented/feature/2026-07-21-log-backed-session-titles.md))。
|
||||
|
||||
### 模型内容
|
||||
|
||||
消息使用从可合并扩展的 `ContentBlockMap` 派生的类型化块;同一模式也为 `MessageSource`、`FinishReason`、`TurnTrigger` 和 `TurnEndReason` 定义类型。新增块会协调适配器、UI、压缩、token 计量和持久化;回放计量见 [token-meter.md](subsystems/token-meter.md)。
|
||||
|
||||
流式输出使用原始分片和 `BlockAssembler`。每次 `LlmAdapter.stream()` 调用代表一次提供方尝试;适配器报告标准化的故障事实,负责处理的 `agent/request-error` 插件会返回重试动作。循环会记录分片、成功结果的来源信息和回放状态。远程适配器使用逐次读取空闲看门狗。回放仅通过共用的适配器实例跨路由传递([约定](subsystems/llm-streaming.md))。
|
||||
流式输出使用原始分片和 `BlockAssembler`。每次 `LlmAdapter.stream()` 调用代表一次提供方尝试;适配器报告标准化的故障事实,负责处理的 `agent/request-error` 插件会返回重试动作。循环会记录分片、成功使用的提供方/模型路由和回放状态。远程适配器使用逐次读取空闲看门狗。回放仅通过共用的适配器实例跨路由传递([约定](subsystems/llm-streaming.md))。
|
||||
|
||||
## 扩展与组合
|
||||
|
||||
### 功能模式
|
||||
### 能力模式
|
||||
|
||||
能力分为**接口/实现/消费方**三层。文件系统与进程管理提供方共同定义一个执行世界;Bash、PTY 和 LSP 都在其中运行,无需提供方专用 fork。参见[功能图](capability-seams.md)。
|
||||
一个 **seam** 是一项包含 **Service Definition**、**Service provider** 和 **Consumer** 三种角色的可替换能力。包可以合并承担多个角色;任何单一角色都不是 seam。文件系统与进程管理提供方共享一个执行世界,Bash、PTY 和 LSP 都在其中运行,无需提供方专用 fork([能力图](capability-seams.md))。
|
||||
|
||||
例外情况包括 LLM(大语言模型)合并接口和消费方、文件系统整合策略、web 使用注册表、skill 和 subagent 使用具名提供方。subagent 可以通过 spawn 创建全新实例、fork 一个已完成轮次的前缀、使用 ACP(Agent Client Protocol)子 agent,或将一个独立完整的轮次委派给 Codex 等真实产品提供方([subagent.md](subsystems/subagent.md))。
|
||||
例外情况包括 LLM(大语言模型)Service Definition/消费方角色合并、文件系统策略、web 注册表,以及 skill/subagent 提供方。subagent 可以通过 spawn 创建全新实例、fork 一个已完成轮次的前缀、使用 ACP(Agent Client Protocol)子 agent,或将一个独立完整的轮次委派给 Codex 或其他产品提供方([subagent.md](subsystems/subagent.md))。
|
||||
|
||||
`dsh-workspace-context` 在第一次 `agent/pre-step` 组合基线并将它折入最终进入的批次、紧随已领取的直接提示词之后,使其与直接提示词一同抵达第一次请求;reject 则将它留在 next-step inbox。当压缩从可见表层移除该基线时,下一次进入步骤的 pre-step 会组合当前基线,并在同一请求中携带它。工具执行后投影的文件系统变更也会折入下一次进入步骤的 pre-step,而不会另外创建稍后的纯上下文步骤([决策](../.agents/notes/implemented/feature/2026-06-24-workspace-context.md))。`dsh-paths` 负责共享路径。
|
||||
|
||||
@@ -165,6 +166,10 @@ idle inject:
|
||||
|
||||
`dsh-agent-spine-demo` 组合一套主干和可选目标。应用包负责 CLI(命令行界面)、ACP 自动化入口和 JSON-RPC 入口([README](../packages/examples/agent-spine-demo/README.md)、[acp/](../packages/acp/README.md)、[interaction/](../packages/interaction/README.md))。`dsh-jsonrpc-agent` 启动外部 `cordis.yml`;Python SDK 在配置缺失时提供默认项([Python SDK](../python/README.md))。轻量部署使用可替换后端和可选工具([examples/](../examples/AGENTS.md)、[可运行接线](cookbook/extension-cookbook.md#runnable-wirings)、[图谱](graph-atlas.md))。
|
||||
|
||||
### Agent Preset
|
||||
|
||||
部署可为每个会话分别组装面向模型的插件集合。**agent preset** 是一个含 `agent.cordis.yml` 的目录,在 `setup(agentCtx)` 期间作为 `include` 子树挂到该 agent 的 scope 之下,其工具与提示词注册因而归档进该 agent 的分层并随之卸载,注册表无需新增层级。宿主组装保留必须共享的部分:注册表本身、跨会话设施、沙箱与审批栈、模型路由。`ctx.agentPresets` 负责发现与把关,拒绝未激活的行和把服务发布进根 realm 的行。详见 [按会话组装 agent preset](../.agents/notes/implemented/architecture/2026-08-03-per-session-agent-presets.md)、[preset/](../packages/preset/README.md)。
|
||||
|
||||
### 新行为的归属位置
|
||||
|
||||
新行为附加到已有文档记录的扩展点;循环发生变更时,本架构图随之更新。
|
||||
@@ -172,20 +177,22 @@ idle inject:
|
||||
| 目标 | 机制 |
|
||||
|---|---|
|
||||
| 添加模型提供方 | 在 `ctx.llm` 上注册其适配器 |
|
||||
| 添加面向模型的功能 | 在 `ctx.tools` 上注册;schema 加入提示词组装 |
|
||||
| 添加 shell 执行 | 实现并注册 `ctx.bash` 后端;本地后端通过 `ctx.subprocess` 生成进程 |
|
||||
| 添加面向模型的能力 | 在 `ctx.tools` 上注册;schema 加入提示词组装 |
|
||||
| 让某个会话拥有不同的能力集合 | 在 agent preset 中组装它;其中的 service 行需要 `isolate` realm |
|
||||
| 添加 shell 执行 | 实现并注册 `ctx.bash` 后端;本地后端通过 `ctx.subprocess` spawn 进程 |
|
||||
| 添加持久化终端执行 | 注册 `ctx.pty` 后端和 `dsh-tool-pty` |
|
||||
| 添加用户命令 | 在 `ctx.commands` 上注册;适配器无需模型轮次即可发现并分派 |
|
||||
| 添加后台工作 | 在 `ctx.tasks` 上注册;通用 `task_*` 工具负责收集或停止 |
|
||||
| 添加文件系统访问或策略 | 实现 `ctx.fs` 提供方,或监听 `fs/*` 策略事件 |
|
||||
| 限制生成的进程 | 使用 `ctx.sandbox` 后端;消费方在生成前包装 argv |
|
||||
| 限制 spawn 出的进程 | 使用 `ctx.sandbox` 后端;消费方在 spawn 前包装 argv |
|
||||
| 拦截请求、工具或轮次 | 使用相应的 `agent/*` 或 `tools/*` 事件;`agent/turn-stopping` 是停止边界 |
|
||||
| 添加模型可见上下文 | 调用 `agent.inject()`,将带来源的上下文排入下一次获准请求 |
|
||||
| 添加 UI 或编辑器集成 | 驱动 `ctx.agents` 并从 `session/event` 渲染 |
|
||||
| Web Client Chat 节点 | 注册 `ConversationNodeDefinition` + keyed renderer |
|
||||
| 添加持久会话状态 | 扩展 `SessionEventMap`;从日志渲染和回放 |
|
||||
| 添加异步会话标题生成 | 注册唯一的 `ctx.sessionTitle` 提供方 |
|
||||
| 管理同会话目标 | 使用 `ctx.goals`;通过 `Agent` 和 `agent/*` 续跑 |
|
||||
| fork 活跃会话 | 调用 `ctx.sessions.fork(source, boundary?, childSessionId?)` |
|
||||
| 将注册项限定到单个 agent | 使用其 `agent.ctx`(参见 Agent 作用域) |
|
||||
|
||||
[扩展实操手册(cookbook)](cookbook/extension-cookbook.md)提供插件骨架和功能到服务边界的映射;指南涵盖[包](cookbook/adding-a-package.md)、[工具](cookbook/adding-a-tool.md)、[LLM 适配器](cookbook/adding-an-llm-adapter.md)和 [vendored 包](cookbook/adding-a-vendored-package.md)。
|
||||
[扩展实操手册](cookbook/extension-cookbook.md)将功能映射到能力;指南涵盖[包](cookbook/adding-a-package.md)、[工具](cookbook/adding-a-tool.md)、[LLM 适配器](cookbook/adding-an-llm-adapter.md)、[Chat 节点](cookbook/adding-a-conversation-node.md)和 [vendored 包](cookbook/adding-a-vendored-package.md)。
|
||||
|
||||
6
docs/capability-seams.i18n.yaml
Normal file
6
docs/capability-seams.i18n.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/capability-seams.md
|
||||
capability-seams.md: 05788eb8044f91e31c82dc4b78af0421e2b11030
|
||||
capability-seams.zh.md: ae182cfeeb1d7461122d791eedb818160a772e9b
|
||||
@@ -81,6 +81,8 @@ flowchart LR
|
||||
svc_userInteraction["ctx.userInteraction<br/>Human question/answer seam"]
|
||||
pkg_plan_mode["plan-mode"]
|
||||
svc_planMode["ctx.planMode<br/>Plan collaboration state"]
|
||||
pkg_agent_presets["agent-presets"]
|
||||
svc_agentPresets["ctx.agentPresets<br/>Per-session agent composition"]
|
||||
pkg_commands["commands"]
|
||||
svc_commands["ctx.commands<br/>Human command registry"]
|
||||
pkg_session_projection["session-projection"]
|
||||
@@ -94,6 +96,9 @@ flowchart LR
|
||||
pkg_skill_local["skill-local"]
|
||||
svc_agents["ctx.agents<br/>Agent service"]
|
||||
pkg_acp["acp"]
|
||||
pkg_agent_default_model["agent-default-model"]
|
||||
svc_agentDefaultModel["ctx.agentDefaultModel<br/>Default Agent model selection"]
|
||||
pkg_headless["headless"]
|
||||
svc_agentLoop["ctx.agentLoop<br/>Concrete loop driver"]
|
||||
pkg_agent_spine_demo["agent-spine-demo"]
|
||||
pkg_goal["goal"]
|
||||
@@ -176,7 +181,9 @@ flowchart LR
|
||||
pkg_tool_workflow["tool-workflow"]
|
||||
pkg_acp --> svc_approval
|
||||
pkg_agent --> svc_agents
|
||||
pkg_agent_default_model --> svc_agentDefaultModel
|
||||
pkg_agent_loop --> svc_agentLoop
|
||||
pkg_agent_presets --> svc_agentPresets
|
||||
pkg_api_gateway --> svc_typertGateway
|
||||
pkg_approval --> svc_approval
|
||||
pkg_bash --> svc_bash
|
||||
@@ -265,6 +272,8 @@ flowchart LR
|
||||
pkg_workflow --> svc_workflows
|
||||
pkg_workflow_workerthread --> svc_workflows
|
||||
pkg_workspace --> svc_workspace
|
||||
svc_agentDefaultModel --> pkg_headless
|
||||
svc_agentDefaultModel --> pkg_host_apiproxy
|
||||
svc_agentLoop --> pkg_agent_spine_demo
|
||||
svc_agents --> pkg_acp
|
||||
svc_agents --> pkg_agent_loop
|
||||
@@ -392,11 +401,13 @@ flowchart LR
|
||||
| `ctx.tools` | `core` | [`tools`](../packages/core/tools) | - | [`agent-loop`](../packages/core/agent-loop), [`tool-ask-user`](../packages/interaction/tool-ask-user), [`tool-bash`](../packages/bash/tool-bash), [`tool-cordis`](../packages/self-modification/tool-cordis), [`tool-fs`](../packages/fs/tool-fs), [`tool-pty`](../packages/pty/tool-pty), [`tool-skill`](../packages/skill/tool-skill), [`tool-subagent`](../packages/subagent/tool-subagent), [`tool-todo`](../packages/todo/tool-todo), [`tool-web`](../packages/web/tool-web) | - | Registers capabilities, owns Code Mode transport, and routes calls through pre-policy, monotonic guards, around dispatch, post-policy, and final-result observation. |
|
||||
| `ctx.userInteraction` | `seam` | [`user-interaction`](../packages/interaction/user-interaction) | - | [`tool-ask-user`](../packages/interaction/tool-ask-user) | - | UI front doors provide the active human-answer provider; tool-ask-user pauses a tool call on the provider-neutral ask() promise. |
|
||||
| `ctx.planMode` | `core` | [`plan-mode`](../packages/plan/plan-mode) | - | - | - | Folds logged plan/mode state, flushes user selections at turn boundaries, renders deployment-owned guidance, registers /plan, and keeps the plan-exit schema stable across transitions. |
|
||||
| `ctx.agentPresets` | `core` | [`agent-presets`](../packages/preset/agent-presets) | - | - | - | Discovers preset directories over trusted and user-authored roots and mounts one preset cordis.yml under an agent scope during creation, rejecting a row that never activates or that publishes into the root service realm. |
|
||||
| `ctx.commands` | `core` | [`commands`](../packages/interaction/commands) | - | - | - | Plugins register direct human commands without sending invocations to the model. |
|
||||
| `ctx.sessionProjections` | `core` | [`session-projection`](../packages/session/session-projection) | - | [`tool-todo`](../packages/todo/tool-todo), [`session-title`](../packages/session/session-title), [`host-apiproxy`](../packages/host/apiproxy) | - | Domains register state-driven fold units; the eager drive keeps per-session watermark states and api-proxy serves baselines and pushes changed values. |
|
||||
| `ctx.sessionProjectionCache` | `core` | [`session-projection-cache`](../packages/session/session-projection-cache) | - | [`host-apiproxy`](../packages/host/apiproxy) | - | Durably checkpoints projection unit states per session (throttled + turn/end/detach mandatory points) and serves the cold-read ladder: cache row + persistence tail replay, so listings never load full logs. |
|
||||
| `ctx.skills` | `seam` | [`skill`](../packages/skill/skill) | [`skill-badge`](../packages/skill/skill-badge), [`skill-local`](../packages/skill/skill-local) | [`tool-skill`](../packages/skill/tool-skill) | - | Merges provider skill catalogs; tool-skill renders the session-prefix catalog and loads complete skill bodies. |
|
||||
| `ctx.agents` | `core` | [`agent`](../packages/core/agent) | - | [`agent-loop`](../packages/core/agent-loop), [`acp`](../packages/acp/acp), [`subagent-inprocess`](../packages/subagent/subagent-inprocess) | - | Owns live Agent handles, the create/resume factory seam, and process-local initiator propagation. |
|
||||
| `ctx.agentDefaultModel` | `core` | [`agent-default-model`](../packages/core/agent-default-model) | - | [`headless`](../packages/bundle/headless), [`host-apiproxy`](../packages/host/apiproxy) | - | Layers the default ModelSelection through settings so direct and Host-backed Agent front doors share one state owner. |
|
||||
| `ctx.agentLoop` | `bundle` | [`agent-loop`](../packages/core/agent-loop) | - | [`agent-spine-demo`](../packages/examples/agent-spine-demo) | - | The one concrete loop plugin; extension packages depend on dsh-agent events and services, not on this package. |
|
||||
| `ctx.goals` | `core` | [`goal`](../packages/goal/goal) | - | - | - | Folds revisioned objective state from the session log and keeps live continuation activation process-local. |
|
||||
| `ctx.e2b` | `core` | [`e2b`](../packages/e2b/e2b) | - | [`fs-e2b`](../packages/e2b/fs-e2b), [`subprocess-e2b`](../packages/e2b/subprocess-e2b) | - | Owns one shared E2B SDK handle, remote working directory, and final sandbox disposition so both fundamental E2B providers inhabit the same Linux runtime. |
|
||||
@@ -410,7 +421,7 @@ flowchart LR
|
||||
| `ctx.permission` | `core` | [`permission`](../packages/interaction/permission) | - | - | - | User-facing preset table (`workspace-write`/`danger-full-access`) bundling the sandbox-mode and approval-policy knobs; a switch writes one `permission/preset` event through to both knob events. |
|
||||
| `ctx.codeRuntime` | `seam` | [`code-runtime`](../packages/code-runtime/code-runtime) | [`code-runtime-worker`](../packages/code-runtime/code-runtime-worker) | [`tools`](../packages/core/tools) | - | Runs one model-written program against host-provided async bindings; backends differ by substrate and language (the tool registry consumes it for Code Mode). |
|
||||
| `ctx.fs` | `seam` | [`fs`](../packages/fs/fs) | [`fs-local`](../packages/fs/fs-local), [`fs-sandbox`](../packages/fs/fs-sandbox), [`fs-e2b`](../packages/e2b/fs-e2b) | [`tool-fs`](../packages/fs/tool-fs) | [`fs-policy`](../packages/fs/fs-policy) | tool-fs executes read/write/edit through ctx.fs; fs-sandbox fences mutations by the shared sandbox mode; fs-policy contributes observed-state checks through the fs/* event gate. |
|
||||
| `ctx.compact` | `seam` | [`compact`](../packages/compact/compact) | [`compact-basic`](../packages/compact/compact-basic) | [`compact-basic`](../packages/compact/compact-basic) | - | The basic backend consumes post-step pressure and request-error recovery events; a model-facing compact tool remains deferred. |
|
||||
| `ctx.compact` | `seam` | [`compact`](../packages/compact/compact) | [`compact-basic`](../packages/compact/compact-basic) | [`compact-basic`](../packages/compact/compact-basic) | - | The basic backend consumes post-step pressure and request-error recovery events; there is no model-facing compact tool. |
|
||||
| `ctx.subagents` | `seam` | [`subagent`](../packages/subagent/subagent) | [`subagent-spawn`](../packages/subagent/subagent-spawn), [`subagent-fork`](../packages/subagent/subagent-fork), [`subagent-acp`](../packages/subagent/subagent-acp), [`subagent-codex`](../packages/subagent/subagent-codex), [`subagent-claude-code`](../packages/subagent/subagent-claude-code), [`subagent-dsh-sdk`](../packages/subagent/subagent-dsh-sdk) | [`tool-subagent`](../packages/subagent/tool-subagent), [`tool-subagent-control`](../packages/subagent/tool-subagent-control), [`tool-ralph`](../packages/workflow/tool-ralph) | - | Providers implement transports; the service also owns optional Activation-based continuation orchestration, tool-subagent selects one-shot or continuable delegation, tool-subagent-control delivers follow-ups, and tool-ralph requires one fresh structured-output route. |
|
||||
| `ctx.tasks` | `seam` | [`tasks`](../packages/tasks/tasks) | [`tasks-local`](../packages/tasks/tasks-local) | [`tool-bash`](../packages/bash/tool-bash), [`tool-pty`](../packages/pty/tool-pty), [`tool-subagent`](../packages/subagent/tool-subagent), [`tool-tasks`](../packages/tasks/tool-tasks) | - | Producers (background bash, PTY sends, and subagent delegations) register running work; tool-tasks is the model-facing control surface that reads, lists, and kills it; tasks-local is the process-local registry. |
|
||||
| `ctx.web` | `seam` | [`web`](../packages/web/web) | [`web-search-exa`](../packages/web/web-search-exa), [`web-search-perplexity`](../packages/web/web-search-perplexity), [`web-search-deepseek`](../packages/web/web-search-deepseek), [`web-fetch-local`](../packages/web/web-fetch-local) | [`tool-web`](../packages/web/tool-web) | - | Search and fetch providers register into one ctx.web seam; tool-web owns the stable model-facing names. |
|
||||
|
||||
436
docs/capability-seams.zh.md
Normal file
436
docs/capability-seams.zh.md
Normal file
@@ -0,0 +1,436 @@
|
||||
<!-- 英文源文件由 scripts/gen-doc-graphs.ts 生成;本中文文件是通过双语配对维护的经评审对侧。
|
||||
更新时先运行 `pnpm run gen-doc-graphs` 更新英文,再更新本文件并运行 `pnpm run verify-translation-pairing --write docs/capability-seams.md` 重新记录配对。 -->
|
||||
|
||||
# 能力 Seams 与核心服务
|
||||
|
||||
[English](capability-seams.md) | 中文
|
||||
|
||||
服务可以是核心主干服务、可替换的能力 seam,也可以是组合包/组合点。下图展示了拥有服务声明的包、已知实现包,以及直接消费该服务的包。
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
pkg_llm["llm"]
|
||||
svc_llm["ctx.llm<br/>LLM adapter registry"]
|
||||
pkg_llm_deepseek["llm-deepseek"]
|
||||
pkg_llm_pi_ai["llm-pi-ai"]
|
||||
pkg_llm_replay["llm-replay"]
|
||||
pkg_agent_loop["agent-loop"]
|
||||
pkg_compact_basic["compact-basic"]
|
||||
pkg_token_meter["token-meter"]
|
||||
svc_tokenMeter["ctx.tokenMeter<br/>Replay token measurement"]
|
||||
pkg_compact_tool_result_prune["compact-tool-result-prune"]
|
||||
svc_toolResultPrune["ctx.toolResultPrune<br/>Model-free tool-result pruning"]
|
||||
pkg_session["session"]
|
||||
svc_sessions["ctx.sessions<br/>In-memory session store"]
|
||||
pkg_agent["agent"]
|
||||
pkg_session_persistence["session-persistence"]
|
||||
pkg_session_query["session-query"]
|
||||
pkg_session_query_sqlite["session-query-sqlite"]
|
||||
pkg_subagent_inprocess["subagent-inprocess"]
|
||||
pkg_invariants["invariants"]
|
||||
svc_invariants["ctx.invariants<br/>Package-owned invariant registry"]
|
||||
pkg_scope["scope"]
|
||||
pkg_typert_registry["typert-registry"]
|
||||
svc_typert["ctx.typert<br/>Runtime type registry"]
|
||||
pkg_typert_loader["typert-loader"]
|
||||
pkg_api_gateway["api-gateway"]
|
||||
svc_typertGateway["ctx.typertGateway<br/>TypeRT Host invocation gateway"]
|
||||
svc_sessionPersistence["ctx.sessionPersistence<br/>Durable session persistence seam"]
|
||||
pkg_session_persistence_jsonl["session-persistence-jsonl"]
|
||||
pkg_session_persistence_sqlite["session-persistence-sqlite"]
|
||||
pkg_tool_bash["tool-bash"]
|
||||
pkg_hooks_claude["hooks-claude"]
|
||||
pkg_hooks_codex["hooks-codex"]
|
||||
pkg_settings["settings"]
|
||||
svc_settings["ctx.settings<br/>User-settings seam"]
|
||||
pkg_settings_local["settings-local"]
|
||||
pkg_apiproxy["apiproxy"]
|
||||
pkg_credentials["credentials"]
|
||||
svc_credentials["ctx.credentials<br/>Credential seam"]
|
||||
pkg_credentials_local["credentials-local"]
|
||||
pkg_session_telemetry["session-telemetry"]
|
||||
svc_telemetry["ctx.telemetry<br/>Session telemetry seam"]
|
||||
pkg_session_telemetry_otel["session-telemetry-otel"]
|
||||
pkg_storage["storage"]
|
||||
svc_storage["ctx.storage<br/>Non-session storage hub"]
|
||||
pkg_storage_json["storage-json"]
|
||||
pkg_storage_sqlite["storage-sqlite"]
|
||||
pkg_storage_domain["storage-domain"]
|
||||
svc_storageDomain["ctx.storageDomain<br/>Domain data facility"]
|
||||
pkg_workspace["workspace"]
|
||||
svc_workspace["ctx.workspace<br/>Workspace entity registry"]
|
||||
svc_sessionQuery["ctx.sessionQuery<br/>Session reads, traces, filters, and search"]
|
||||
pkg_session_reference["session-reference"]
|
||||
pkg_tool_session_query["tool-session-query"]
|
||||
svc_sessionReferences["ctx.sessionReferences<br/>Cross-session snapshot preparation"]
|
||||
pkg_session_title["session-title"]
|
||||
svc_sessionTitle["ctx.sessionTitle<br/>Log-backed session titles"]
|
||||
pkg_session_title_first_message_llm["session-title-first-message-llm"]
|
||||
pkg_session_title_all_messages_llm["session-title-all-messages-llm"]
|
||||
pkg_system_prompt["system-prompt"]
|
||||
svc_systemPrompt["ctx.systemPrompt<br/>System prompt assembly registry"]
|
||||
pkg_tools["tools"]
|
||||
pkg_tool_fs["tool-fs"]
|
||||
pkg_tool_pty["tool-pty"]
|
||||
pkg_tool_web["tool-web"]
|
||||
svc_tools["ctx.tools<br/>Tool registry and guarded execution pipeline"]
|
||||
pkg_tool_ask_user["tool-ask-user"]
|
||||
pkg_tool_cordis["tool-cordis"]
|
||||
pkg_tool_skill["tool-skill"]
|
||||
pkg_tool_subagent["tool-subagent"]
|
||||
pkg_tool_todo["tool-todo"]
|
||||
pkg_user_interaction["user-interaction"]
|
||||
svc_userInteraction["ctx.userInteraction<br/>Human question/answer seam"]
|
||||
pkg_plan_mode["plan-mode"]
|
||||
svc_planMode["ctx.planMode<br/>Plan collaboration state"]
|
||||
pkg_agent_presets["agent-presets"]
|
||||
svc_agentPresets["ctx.agentPresets<br/>Per-session agent composition"]
|
||||
pkg_commands["commands"]
|
||||
svc_commands["ctx.commands<br/>Human command registry"]
|
||||
pkg_session_projection["session-projection"]
|
||||
svc_sessionProjections["ctx.sessionProjections<br/>Session projection units"]
|
||||
pkg_host_apiproxy["host-apiproxy"]
|
||||
pkg_session_projection_cache["session-projection-cache"]
|
||||
svc_sessionProjectionCache["ctx.sessionProjectionCache<br/>Persisted projection cache"]
|
||||
pkg_skill["skill"]
|
||||
svc_skills["ctx.skills<br/>Skill provider registry"]
|
||||
pkg_skill_badge["skill-badge"]
|
||||
pkg_skill_local["skill-local"]
|
||||
svc_agents["ctx.agents<br/>Agent service"]
|
||||
pkg_acp["acp"]
|
||||
pkg_agent_default_model["agent-default-model"]
|
||||
svc_agentDefaultModel["ctx.agentDefaultModel<br/>Default Agent model selection"]
|
||||
pkg_headless["headless"]
|
||||
svc_agentLoop["ctx.agentLoop<br/>Concrete loop driver"]
|
||||
pkg_agent_spine_demo["agent-spine-demo"]
|
||||
pkg_goal["goal"]
|
||||
svc_goals["ctx.goals<br/>Same-session goal domain"]
|
||||
pkg_e2b["e2b"]
|
||||
svc_e2b["ctx.e2b<br/>E2B sandbox lifecycle owner"]
|
||||
pkg_fs_e2b["fs-e2b"]
|
||||
pkg_subprocess_e2b["subprocess-e2b"]
|
||||
pkg_subprocess["subprocess"]
|
||||
svc_subprocess["ctx.subprocess<br/>Subprocess seam"]
|
||||
pkg_subprocess_local["subprocess-local"]
|
||||
pkg_bash_local["bash-local"]
|
||||
pkg_bash_sandbox["bash-sandbox"]
|
||||
pkg_pty_local["pty-local"]
|
||||
pkg_lsp_local["lsp-local"]
|
||||
pkg_subagent_acp["subagent-acp"]
|
||||
pkg_subagent_codex["subagent-codex"]
|
||||
pkg_subagent_claude_code["subagent-claude-code"]
|
||||
pkg_bash["bash"]
|
||||
svc_bash["ctx.bash<br/>Bash executor seam"]
|
||||
pkg_pwsh_local["pwsh-local"]
|
||||
pkg_tool_pwsh["tool-pwsh"]
|
||||
pkg_bash_env["bash-env"]
|
||||
svc_bashEnv["ctx.bashEnv<br/>Managed bash environment registry"]
|
||||
pkg_pty["pty"]
|
||||
svc_pty["ctx.pty<br/>Persistent PTY session registry"]
|
||||
pkg_sandbox["sandbox"]
|
||||
svc_sandbox["ctx.sandbox<br/>Process-sandbox seam"]
|
||||
pkg_sandbox_local["sandbox-local"]
|
||||
pkg_sandbox_policy["sandbox-policy"]
|
||||
svc_sandboxPolicy["ctx.sandboxPolicy<br/>Sandbox policy home"]
|
||||
pkg_fs_sandbox["fs-sandbox"]
|
||||
pkg_approval["approval"]
|
||||
svc_approval["ctx.approval<br/>Approval seam"]
|
||||
pkg_permission["permission"]
|
||||
svc_permission["ctx.permission<br/>Permission presets"]
|
||||
pkg_code_runtime["code-runtime"]
|
||||
svc_codeRuntime["ctx.codeRuntime<br/>Code-execution seam"]
|
||||
pkg_code_runtime_worker["code-runtime-worker"]
|
||||
pkg_fs["fs"]
|
||||
svc_fs["ctx.fs<br/>Filesystem provider seam"]
|
||||
pkg_fs_local["fs-local"]
|
||||
pkg_fs_policy["fs-policy"]
|
||||
pkg_compact["compact"]
|
||||
svc_compact["ctx.compact<br/>Compaction seam"]
|
||||
pkg_subagent["subagent"]
|
||||
svc_subagents["ctx.subagents<br/>Subagent provider and continuation service"]
|
||||
pkg_subagent_spawn["subagent-spawn"]
|
||||
pkg_subagent_fork["subagent-fork"]
|
||||
pkg_subagent_dsh_sdk["subagent-dsh-sdk"]
|
||||
pkg_tool_subagent_control["tool-subagent-control"]
|
||||
pkg_tool_ralph["tool-ralph"]
|
||||
pkg_tasks["tasks"]
|
||||
svc_tasks["ctx.tasks<br/>Background task registry"]
|
||||
pkg_tasks_local["tasks-local"]
|
||||
pkg_tool_tasks["tool-tasks"]
|
||||
pkg_web["web"]
|
||||
svc_web["ctx.web<br/>Web access provider registry"]
|
||||
pkg_web_search_exa["web-search-exa"]
|
||||
pkg_web_search_perplexity["web-search-perplexity"]
|
||||
pkg_web_search_deepseek["web-search-deepseek"]
|
||||
pkg_web_fetch_local["web-fetch-local"]
|
||||
pkg_spill["spill"]
|
||||
svc_spillStore["ctx.spillStore<br/>Spill storage seam"]
|
||||
pkg_spill_local["spill-local"]
|
||||
pkg_spill_policy["spill-policy"]
|
||||
pkg_directory_picker["directory-picker"]
|
||||
svc_directoryPicker["ctx.directoryPicker<br/>Workspace-directory picking seam"]
|
||||
pkg_directory_picker_native["directory-picker-native"]
|
||||
pkg_directory_picker_browse["directory-picker-browse"]
|
||||
pkg_webserver["webserver"]
|
||||
svc_httpServer["ctx.httpServer<br/>HTTP route registration"]
|
||||
pkg_connection["connection"]
|
||||
pkg_modules["modules"]
|
||||
pkg_hmr["hmr"]
|
||||
svc_clientModuleHost["ctx.clientModuleHost<br/>Client plugin graph host"]
|
||||
pkg_workflow["workflow"]
|
||||
svc_workflows["ctx.workflows<br/>Workflow script engine"]
|
||||
pkg_workflow_workerthread["workflow-workerthread"]
|
||||
pkg_tool_workflow["tool-workflow"]
|
||||
pkg_acp --> svc_approval
|
||||
pkg_agent --> svc_agents
|
||||
pkg_agent_default_model --> svc_agentDefaultModel
|
||||
pkg_agent_loop --> svc_agentLoop
|
||||
pkg_agent_presets --> svc_agentPresets
|
||||
pkg_api_gateway --> svc_typertGateway
|
||||
pkg_approval --> svc_approval
|
||||
pkg_bash --> svc_bash
|
||||
pkg_bash_env --> svc_bashEnv
|
||||
pkg_bash_local --> svc_bash
|
||||
pkg_bash_sandbox --> svc_bash
|
||||
pkg_code_runtime --> svc_codeRuntime
|
||||
pkg_code_runtime_worker --> svc_codeRuntime
|
||||
pkg_commands --> svc_commands
|
||||
pkg_compact --> svc_compact
|
||||
pkg_compact_basic --> svc_compact
|
||||
pkg_compact_tool_result_prune --> svc_toolResultPrune
|
||||
pkg_credentials --> svc_credentials
|
||||
pkg_credentials_local --> svc_credentials
|
||||
pkg_directory_picker --> svc_directoryPicker
|
||||
pkg_directory_picker_browse --> svc_directoryPicker
|
||||
pkg_directory_picker_native --> svc_directoryPicker
|
||||
pkg_e2b --> svc_e2b
|
||||
pkg_fs --> svc_fs
|
||||
pkg_fs_e2b --> svc_fs
|
||||
pkg_fs_local --> svc_fs
|
||||
pkg_fs_sandbox --> svc_fs
|
||||
pkg_goal --> svc_goals
|
||||
pkg_invariants --> svc_invariants
|
||||
pkg_llm --> svc_llm
|
||||
pkg_llm_deepseek --> svc_llm
|
||||
pkg_llm_pi_ai --> svc_llm
|
||||
pkg_llm_replay --> svc_llm
|
||||
pkg_modules --> svc_clientModuleHost
|
||||
pkg_permission --> svc_permission
|
||||
pkg_plan_mode --> svc_planMode
|
||||
pkg_pty --> svc_pty
|
||||
pkg_pty_local --> svc_pty
|
||||
pkg_pwsh_local --> svc_bash
|
||||
pkg_sandbox --> svc_sandbox
|
||||
pkg_sandbox_local --> svc_sandbox
|
||||
pkg_sandbox_policy --> svc_sandboxPolicy
|
||||
pkg_session --> svc_sessions
|
||||
pkg_session_persistence --> svc_sessionPersistence
|
||||
pkg_session_persistence_jsonl --> svc_sessionPersistence
|
||||
pkg_session_persistence_sqlite --> svc_sessionPersistence
|
||||
pkg_session_projection --> svc_sessionProjections
|
||||
pkg_session_projection_cache --> svc_sessionProjectionCache
|
||||
pkg_session_query --> svc_sessionQuery
|
||||
pkg_session_query_sqlite --> svc_sessionQuery
|
||||
pkg_session_reference --> svc_sessionReferences
|
||||
pkg_session_telemetry --> svc_telemetry
|
||||
pkg_session_telemetry_otel --> svc_telemetry
|
||||
pkg_session_title --> svc_sessionTitle
|
||||
pkg_session_title_all_messages_llm --> svc_sessionTitle
|
||||
pkg_session_title_first_message_llm --> svc_sessionTitle
|
||||
pkg_settings --> svc_settings
|
||||
pkg_settings_local --> svc_settings
|
||||
pkg_skill --> svc_skills
|
||||
pkg_skill_badge --> svc_skills
|
||||
pkg_skill_local --> svc_skills
|
||||
pkg_spill --> svc_spillStore
|
||||
pkg_spill_local --> svc_spillStore
|
||||
pkg_storage --> svc_storage
|
||||
pkg_storage_domain --> svc_storageDomain
|
||||
pkg_storage_json --> svc_storage
|
||||
pkg_storage_sqlite --> svc_storage
|
||||
pkg_subagent --> svc_subagents
|
||||
pkg_subagent_acp --> svc_subagents
|
||||
pkg_subagent_claude_code --> svc_subagents
|
||||
pkg_subagent_codex --> svc_subagents
|
||||
pkg_subagent_dsh_sdk --> svc_subagents
|
||||
pkg_subagent_fork --> svc_subagents
|
||||
pkg_subagent_spawn --> svc_subagents
|
||||
pkg_subprocess --> svc_subprocess
|
||||
pkg_subprocess_e2b --> svc_subprocess
|
||||
pkg_subprocess_local --> svc_subprocess
|
||||
pkg_system_prompt --> svc_systemPrompt
|
||||
pkg_tasks --> svc_tasks
|
||||
pkg_tasks_local --> svc_tasks
|
||||
pkg_token_meter --> svc_tokenMeter
|
||||
pkg_tools --> svc_tools
|
||||
pkg_typert_registry --> svc_typert
|
||||
pkg_user_interaction --> svc_userInteraction
|
||||
pkg_web --> svc_web
|
||||
pkg_web_fetch_local --> svc_web
|
||||
pkg_web_search_deepseek --> svc_web
|
||||
pkg_web_search_exa --> svc_web
|
||||
pkg_web_search_perplexity --> svc_web
|
||||
pkg_webserver --> svc_httpServer
|
||||
pkg_workflow --> svc_workflows
|
||||
pkg_workflow_workerthread --> svc_workflows
|
||||
pkg_workspace --> svc_workspace
|
||||
svc_agentDefaultModel --> pkg_headless
|
||||
svc_agentDefaultModel --> pkg_host_apiproxy
|
||||
svc_agentLoop --> pkg_agent_spine_demo
|
||||
svc_agents --> pkg_acp
|
||||
svc_agents --> pkg_agent_loop
|
||||
svc_agents --> pkg_subagent_inprocess
|
||||
svc_approval --> pkg_tool_bash
|
||||
svc_approval --> pkg_tools
|
||||
svc_bash --> pkg_hooks_claude
|
||||
svc_bash --> pkg_hooks_codex
|
||||
svc_bash --> pkg_tool_bash
|
||||
svc_bash --> pkg_tool_pwsh
|
||||
svc_bashEnv --> pkg_tool_bash
|
||||
svc_bashEnv --> pkg_tool_pwsh
|
||||
svc_clientModuleHost --> pkg_hmr
|
||||
svc_codeRuntime --> pkg_tools
|
||||
svc_compact --> pkg_compact_basic
|
||||
svc_credentials --> pkg_apiproxy
|
||||
svc_credentials --> pkg_llm_deepseek
|
||||
svc_credentials --> pkg_llm_pi_ai
|
||||
svc_directoryPicker --> pkg_apiproxy
|
||||
svc_e2b --> pkg_fs_e2b
|
||||
svc_e2b --> pkg_subprocess_e2b
|
||||
svc_fs --> pkg_tool_fs
|
||||
svc_httpServer --> pkg_connection
|
||||
svc_httpServer --> pkg_hmr
|
||||
svc_httpServer --> pkg_modules
|
||||
svc_invariants --> pkg_agent
|
||||
svc_invariants --> pkg_agent_loop
|
||||
svc_invariants --> pkg_scope
|
||||
svc_invariants --> pkg_session
|
||||
svc_llm --> pkg_agent_loop
|
||||
svc_llm --> pkg_compact_basic
|
||||
svc_pty --> pkg_tool_pty
|
||||
svc_sandbox --> pkg_bash_sandbox
|
||||
svc_sandbox --> pkg_pty_local
|
||||
svc_sandboxPolicy --> pkg_bash_sandbox
|
||||
svc_sandboxPolicy --> pkg_fs_sandbox
|
||||
svc_sandboxPolicy --> pkg_pty_local
|
||||
svc_sessionPersistence --> pkg_agent_loop
|
||||
svc_sessionPersistence --> pkg_hooks_claude
|
||||
svc_sessionPersistence --> pkg_hooks_codex
|
||||
svc_sessionPersistence --> pkg_session_query
|
||||
svc_sessionPersistence --> pkg_session_query_sqlite
|
||||
svc_sessionPersistence --> pkg_tool_bash
|
||||
svc_sessionProjectionCache --> pkg_host_apiproxy
|
||||
svc_sessionProjections --> pkg_host_apiproxy
|
||||
svc_sessionProjections --> pkg_session_title
|
||||
svc_sessionProjections --> pkg_tool_todo
|
||||
svc_sessionQuery --> pkg_session_reference
|
||||
svc_sessionQuery --> pkg_tool_session_query
|
||||
svc_sessions --> pkg_agent
|
||||
svc_sessions --> pkg_agent_loop
|
||||
svc_sessions --> pkg_invariants
|
||||
svc_sessions --> pkg_session_persistence
|
||||
svc_sessions --> pkg_session_query
|
||||
svc_sessions --> pkg_session_query_sqlite
|
||||
svc_sessions --> pkg_subagent_inprocess
|
||||
svc_settings --> pkg_apiproxy
|
||||
svc_settings --> pkg_llm_deepseek
|
||||
svc_settings --> pkg_llm_pi_ai
|
||||
svc_skills --> pkg_tool_skill
|
||||
svc_spillStore --> pkg_spill_policy
|
||||
svc_storage --> pkg_storage_domain
|
||||
svc_storageDomain --> pkg_workspace
|
||||
svc_subagents --> pkg_tool_ralph
|
||||
svc_subagents --> pkg_tool_subagent
|
||||
svc_subagents --> pkg_tool_subagent_control
|
||||
svc_subprocess --> pkg_bash_local
|
||||
svc_subprocess --> pkg_bash_sandbox
|
||||
svc_subprocess --> pkg_lsp_local
|
||||
svc_subprocess --> pkg_pty_local
|
||||
svc_subprocess --> pkg_subagent_acp
|
||||
svc_subprocess --> pkg_subagent_claude_code
|
||||
svc_subprocess --> pkg_subagent_codex
|
||||
svc_systemPrompt --> pkg_agent_loop
|
||||
svc_systemPrompt --> pkg_tool_fs
|
||||
svc_systemPrompt --> pkg_tool_pty
|
||||
svc_systemPrompt --> pkg_tool_web
|
||||
svc_systemPrompt --> pkg_tools
|
||||
svc_tasks --> pkg_tool_bash
|
||||
svc_tasks --> pkg_tool_pty
|
||||
svc_tasks --> pkg_tool_subagent
|
||||
svc_tasks --> pkg_tool_tasks
|
||||
svc_tokenMeter --> pkg_compact_basic
|
||||
svc_toolResultPrune --> pkg_compact_basic
|
||||
svc_tools --> pkg_agent_loop
|
||||
svc_tools --> pkg_tool_ask_user
|
||||
svc_tools --> pkg_tool_bash
|
||||
svc_tools --> pkg_tool_cordis
|
||||
svc_tools --> pkg_tool_fs
|
||||
svc_tools --> pkg_tool_pty
|
||||
svc_tools --> pkg_tool_skill
|
||||
svc_tools --> pkg_tool_subagent
|
||||
svc_tools --> pkg_tool_todo
|
||||
svc_tools --> pkg_tool_web
|
||||
svc_typert --> pkg_api_gateway
|
||||
svc_typert --> pkg_typert_loader
|
||||
svc_userInteraction --> pkg_tool_ask_user
|
||||
svc_web --> pkg_tool_web
|
||||
svc_workflows --> pkg_tool_ralph
|
||||
svc_workflows --> pkg_tool_workflow
|
||||
svc_workspace --> pkg_apiproxy
|
||||
svc_fs -. event gate .-> pkg_fs_policy
|
||||
```
|
||||
|
||||
| ctx 键 | 角色 | 所属包 | 实现 | 直接消费方 | 配套插件 | 说明 |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| `ctx.llm` | `seam` | [`llm`](../packages/llm/llm) | [`llm-deepseek`](../packages/llm/llm-deepseek)、[`llm-pi-ai`](../packages/llm/llm-pi-ai)、[`llm-replay`](../packages/support/llm-replay) | [`agent-loop`](../packages/core/agent-loop)、[`compact-basic`](../packages/compact/compact-basic) | - | 适配器注册提供方实现;agent loop(智能体循环)与压缩功能调用提供方无关的流服务。 |
|
||||
| `ctx.tokenMeter` | `core` | [`token-meter`](../packages/llm/token-meter) | - | [`compact-basic`](../packages/compact/compact-basic) | - | 拥有按会话隔离的回放折叠区;压力消费方共享不可变且带修订版本的测量结果。 |
|
||||
| `ctx.toolResultPrune` | `core` | [`compact-tool-result-prune`](../packages/compact/compact-tool-result-prune) | - | [`compact-basic`](../packages/compact/compact-basic) | - | 在摘要压缩前,通过可回放的单节点表层替换来改写过大的当前工具结果。 |
|
||||
| `ctx.sessions` | `core` | [`session`](../packages/core/session) | - | [`agent-loop`](../packages/core/agent-loop)、[`agent`](../packages/core/agent)、[`session-persistence`](../packages/session/session-persistence)、[`session-query`](../packages/session-query/session-query)、[`session-query-sqlite`](../packages/session-query/session-query-sqlite)、[`subagent-inprocess`](../packages/subagent/subagent-inprocess)、[`invariants`](../packages/support/invariants) | - | 拥有仅追加的 Session 实例,并发出持久的会话事件流。 |
|
||||
| `ctx.invariants` | `core` | [`invariants`](../packages/support/invariants) | - | [`session`](../packages/core/session)、[`agent`](../packages/core/agent)、[`scope`](../packages/core/scope)、[`agent-loop`](../packages/core/agent-loop) | - | 配套子路径注册所属包本地的检查;该服务负责选择、唯一性、子 fiber,以及标明所属包的失败。 |
|
||||
| `ctx.typert` | `core` | [`typert-registry`](../packages/typert/registry) | - | [`typert-loader`](../packages/typert/loader)、[`api-gateway`](../packages/api/gateway) | - | 插件直接或通过 dsh-typert-loader 注册实时 zod 贡献;API 网关消费调用描述符和提供方,其他运行时消费方则在各自边界查询 schema 与反射元数据。 |
|
||||
| `ctx.typertGateway` | `core` | [`api-gateway`](../packages/api/gateway) | - | - | - | 将生成的 Remote 描述符与实时 Cordis 服务关联,解析已注册的身份,并通过共享的 Connection RPC 载体提供一元调用。 |
|
||||
| `ctx.sessionPersistence` | `seam` | [`session-persistence`](../packages/session/session-persistence) | [`session-persistence-jsonl`](../packages/session/session-persistence-jsonl)、[`session-persistence-sqlite`](../packages/session/session-persistence-sqlite) | [`agent-loop`](../packages/core/agent-loop)、[`tool-bash`](../packages/bash/tool-bash)、[`hooks-claude`](../packages/hooks/hooks-claude)、[`hooks-codex`](../packages/hooks/hooks-codex)、[`session-query`](../packages/session-query/session-query)、[`session-query-sqlite`](../packages/session-query/session-query-sqlite) | - | 各后端持久化同一套 SessionEvent 词汇;应用在组合时选择后端。 |
|
||||
| `ctx.settings` | `seam` | [`settings`](../packages/settings/settings) | [`settings-local`](../packages/settings/settings-local) | [`llm-deepseek`](../packages/llm/llm-deepseek)、[`llm-pi-ai`](../packages/llm/llm-pi-ai)、`apiproxy` | - | 插件注册命名空间 schema 并解析分层值;提供方存储原始文档。LLM(大语言模型)适配器在用户分区下将其入口配置注册为组合基础;Web 网关提供经过脱敏的分层描述符,并写入用户层。 |
|
||||
| `ctx.credentials` | `seam` | [`credentials`](../packages/credentials/credentials) | [`credentials-local`](../packages/credentials/credentials-local) | [`llm-deepseek`](../packages/llm/llm-deepseek)、[`llm-pi-ai`](../packages/llm/llm-pi-ai)、`apiproxy` | - | 配置携带对机密信息的引用;提供方拥有实际值。消费方按操作解析,因此轮换后的凭据会在紧接着的下一次请求中生效;Web 网关提供不含实际值的视图和只写存储。 |
|
||||
| `ctx.telemetry` | `seam` | [`session-telemetry`](../packages/session/session-telemetry) | [`session-telemetry-otel`](../packages/session/session-telemetry-otel) | - | - | 该 seam 捕获会话记录、进行脱敏并交给一个后端;没有其他组件消费该服务,其输出会离开当前进程。 |
|
||||
| `ctx.storage` | `seam` | [`storage`](../packages/storage/storage) | [`storage-json`](../packages/storage/storage-json)、[`storage-sqlite`](../packages/storage/storage-sqlite) | [`storage-domain`](../packages/storage/storage-domain) | - | 各后端以不同名称并列注册;数据形态(领域优先)挂载到枢纽上,并将类型化操作转换为不透明的 KV 单元原语。 |
|
||||
| `ctx.storageDomain` | `core` | [`storage-domain`](../packages/storage/storage-domain) | - | [`workspace`](../packages/workspace/workspace) | - | 等待所有已配置后端就绪,然后将领域形态发布为一个受生命周期约束的服务,用于类型化持久状态。 |
|
||||
| `ctx.workspace` | `core` | [`workspace`](../packages/workspace/workspace) | - | `apiproxy` | - | 通过领域设施拥有带 WorkspaceId 品牌类型的记录;稳定的 sessionIds 账户驱动 Host RPC 与 GUI 投影。 |
|
||||
| `ctx.sessionQuery` | `seam` | [`session-query`](../packages/session-query/session-query) | [`session-query-sqlite`](../packages/session-query/session-query-sqlite) | [`session-reference`](../packages/context/session-reference)、[`tool-session-query`](../packages/session-query/tool-session-query) | - | 该接口提供精确读取、过滤和追踪;具体后端还提供全文协调、排序、摘要片段和游标世代,而模型消费方负责工作区权限与不含游标的渲染。 |
|
||||
| `ctx.sessionReferences` | `core` | [`session-reference`](../packages/context/session-reference) | - | - | - | 将当前表层中有界的对话快照投影为持久但不可信的消息上下文;Host 适配器负责提及语法。 |
|
||||
| `ctx.sessionTitle` | `seam` | [`session-title`](../packages/session/session-title) | [`session-title-first-message-llm`](../packages/session/session-title-first-message-llm)、[`session-title-all-messages-llm`](../packages/session/session-title-all-messages-llm) | - | - | 负责确定性回退、最新标题折叠区,以及唯一的可选异步提供方注册。 |
|
||||
| `ctx.systemPrompt` | `core` | [`system-prompt`](../packages/core/system-prompt) | - | [`agent-loop`](../packages/core/agent-loop)、[`tools`](../packages/core/tools)、[`tool-fs`](../packages/fs/tool-fs)、[`tool-pty`](../packages/pty/tool-pty)、[`tool-web`](../packages/web/tool-web) | - | 为每个步骤收集提示词各部分和面向模型的工具 schema。 |
|
||||
| `ctx.tools` | `core` | [`tools`](../packages/core/tools) | - | [`agent-loop`](../packages/core/agent-loop)、[`tool-ask-user`](../packages/interaction/tool-ask-user)、[`tool-bash`](../packages/bash/tool-bash)、[`tool-cordis`](../packages/self-modification/tool-cordis)、[`tool-fs`](../packages/fs/tool-fs)、[`tool-pty`](../packages/pty/tool-pty)、[`tool-skill`](../packages/skill/tool-skill)、[`tool-subagent`](../packages/subagent/tool-subagent)、[`tool-todo`](../packages/todo/tool-todo)、[`tool-web`](../packages/web/tool-web) | - | 注册能力,负责 Code Mode 传输,并让调用依次经过策略前处理、单调守卫、环绕分派、策略后处理和最终结果观测。 |
|
||||
| `ctx.userInteraction` | `seam` | [`user-interaction`](../packages/interaction/user-interaction) | - | [`tool-ask-user`](../packages/interaction/tool-ask-user) | - | UI 入口提供当前生效的人工回答提供方;tool-ask-user 在提供方无关的 ask() promise 上暂停工具调用。 |
|
||||
| `ctx.planMode` | `core` | [`plan-mode`](../packages/plan/plan-mode) | - | - | - | 折叠已记录的计划/模式状态,在轮次边界刷新用户选择,渲染由部署方拥有的指导信息,注册 /plan,并在状态转换期间保持计划退出 schema 稳定。 |
|
||||
| `ctx.agentPresets` | `core` | [`agent-presets`](../packages/preset/agent-presets) | - | - | - | 在受信任根目录与用户创作根目录上发现 preset 目录,并在创建期把一份 preset cordis.yml 挂载到 agent 作用域之下,拒绝始终未激活或向根服务 realm 发布服务的行。 |
|
||||
| `ctx.commands` | `core` | [`commands`](../packages/interaction/commands) | - | - | - | 插件注册直接面向人的命令,而不会把调用发送给模型。 |
|
||||
| `ctx.sessionProjections` | `core` | [`session-projection`](../packages/session/session-projection) | - | [`tool-todo`](../packages/todo/tool-todo)、[`session-title`](../packages/session/session-title)、[`host-apiproxy`](../packages/host/apiproxy) | - | 各领域注册由状态驱动的折叠单元;主动驱动过程维护每个会话的水位状态,api-proxy 提供基线并推送发生变化的值。 |
|
||||
| `ctx.sessionProjectionCache` | `core` | [`session-projection-cache`](../packages/session/session-projection-cache) | - | [`host-apiproxy`](../packages/host/apiproxy) | - | 按会话持久保存投影单元状态的检查点(节流检查点,以及轮次/结束/分离时的必选检查点),并提供冷读取阶梯:缓存行加持久化尾部回放,因此列表读取永远不需要加载完整日志。 |
|
||||
| `ctx.skills` | `seam` | [`skill`](../packages/skill/skill) | [`skill-badge`](../packages/skill/skill-badge)、[`skill-local`](../packages/skill/skill-local) | [`tool-skill`](../packages/skill/tool-skill) | - | 合并提供方的 skill(技能)目录;tool-skill 渲染会话前缀目录,并加载完整的 skill 正文。 |
|
||||
| `ctx.agents` | `core` | [`agent`](../packages/core/agent) | - | [`agent-loop`](../packages/core/agent-loop)、[`acp`](../packages/acp/acp)、[`subagent-inprocess`](../packages/subagent/subagent-inprocess) | - | 拥有实时 Agent 句柄、创建/恢复工厂 seam,以及进程本地的发起方传播。 |
|
||||
| `ctx.agentDefaultModel` | `core` | [`agent-default-model`](../packages/core/agent-default-model) | - | [`headless`](../packages/bundle/headless)、[`host-apiproxy`](../packages/host/apiproxy) | - | 通过 settings 分层默认 `ModelSelection`,让直接前门与 Host 支撑的 Agent 前门共享同一个状态所有者。 |
|
||||
| `ctx.agentLoop` | `bundle` | [`agent-loop`](../packages/core/agent-loop) | - | [`agent-spine-demo`](../packages/examples/agent-spine-demo) | - | 唯一的具体循环插件;扩展包依赖 dsh-agent 的事件和服务,而不依赖此包。 |
|
||||
| `ctx.goals` | `core` | [`goal`](../packages/goal/goal) | - | - | - | 从会话日志折叠带修订版本的目标状态,并将实时延续激活保留在进程本地。 |
|
||||
| `ctx.e2b` | `core` | [`e2b`](../packages/e2b/e2b) | - | [`fs-e2b`](../packages/e2b/fs-e2b)、[`subprocess-e2b`](../packages/e2b/subprocess-e2b) | - | 拥有一个共享的 E2B SDK 句柄、远程工作目录和最终沙箱处置,使两个基础 E2B 提供方处于同一个 Linux 运行时中。 |
|
||||
| `ctx.subprocess` | `seam` | [`subprocess`](../packages/subprocess/subprocess) | [`subprocess-local`](../packages/subprocess/subprocess-local)、[`subprocess-e2b`](../packages/e2b/subprocess-e2b) | [`bash-local`](../packages/bash/bash-local)、[`bash-sandbox`](../packages/bash/bash-sandbox)、[`pty-local`](../packages/pty/pty-local)、[`lsp-local`](../packages/lsp/lsp-local)、[`subagent-acp`](../packages/subagent/subagent-acp)、[`subagent-codex`](../packages/subagent/subagent-codex)、[`subagent-claude-code`](../packages/subagent/subagent-claude-code) | - | Bash 执行器、PTY shell 后端、LSP Host,以及进程外 ACP、Codex 和 Claude Code subagent 后端都通过 ctx.subprocess 执行 spawn;该服务负责进程坐标、进程树/会话生命周期、stdio 处置、终端机制和 kill 升级。 |
|
||||
| `ctx.bash` | `seam` | [`bash`](../packages/bash/bash) | [`bash-local`](../packages/bash/bash-local)、[`bash-sandbox`](../packages/bash/bash-sandbox)、[`pwsh-local`](../packages/bash/pwsh-local) | [`tool-bash`](../packages/bash/tool-bash)、[`tool-pwsh`](../packages/bash/tool-pwsh)、[`hooks-claude`](../packages/hooks/hooks-claude)、[`hooks-codex`](../packages/hooks/hooks-codex) | - | 面向模型的 shell 工具和钩子桥接消费此 seam;沙箱、远程或 PowerShell 执行器可以替换 bash-local,而无需改动这些消费方。 |
|
||||
| `ctx.bashEnv` | `core` | [`bash-env`](../packages/bash/bash-env) | - | [`tool-bash`](../packages/bash/tool-bash)、[`tool-pwsh`](../packages/bash/tool-pwsh) | - | 插件声明限定于 effect 作用域的 DSH_* 事实;每个 shell 工具在每次执行时收集一份可信快照,其执行器据此重建命名空间。 |
|
||||
| `ctx.pty` | `seam` | [`pty`](../packages/pty/pty) | [`pty-local`](../packages/pty/pty-local) | [`tool-pty`](../packages/pty/tool-pty) | - | 注册表负责精确到 Agent 的会话身份和清理;后端负责终端机制,tool-pty 则提供限定于所有者作用域的模型接口。 |
|
||||
| `ctx.sandbox` | `seam` | [`sandbox`](../packages/sandbox/sandbox) | [`sandbox-local`](../packages/sandbox/sandbox-local) | [`bash-sandbox`](../packages/bash/bash-sandbox)、[`pty-local`](../packages/pty/pty-local) | - | 消费方交出即将执行 spawn 的确切 argv;与宿主共享文件系统和内核的后端按每次调用的策略包装该 argv,并报告强制执行情况。 |
|
||||
| `ctx.sandboxPolicy` | `core` | [`sandbox-policy`](../packages/sandbox/sandbox-policy) | - | [`bash-sandbox`](../packages/bash/bash-sandbox)、[`fs-sandbox`](../packages/fs/fs-sandbox)、[`pty-local`](../packages/pty/pty-local) | - | 统一保存部署默认模式和工作区根目录;只有沙箱执行器和提供方读取该服务(工具层使用它同时导出的纯 `sandbox/mode` 折叠区)。两类强制执行组件都读取该服务,因此 bash 与 fs 不会限制到不同的根目录。 |
|
||||
| `ctx.approval` | `seam` | `approval` | [`acp`](../packages/acp/acp) | [`tools`](../packages/core/tools)、[`tool-bash`](../packages/bash/tool-bash) | - | 一次性权限决策通过 `approval/request` waterfall(瀑布式事件)分派;回答方是监听器(即 ACP 为自身 agent 提供的桥接),没有回答方时以 `unavailable` 关闭失败。 |
|
||||
| `ctx.permission` | `core` | [`permission`](../packages/interaction/permission) | - | - | - | 面向用户的预设表(`workspace-write`/`danger-full-access`),将沙箱模式与审批策略选项组合在一起;一次切换会写入一个 `permission/preset` 事件,并贯通到两个选项事件。 |
|
||||
| `ctx.codeRuntime` | `seam` | [`code-runtime`](../packages/code-runtime/code-runtime) | [`code-runtime-worker`](../packages/code-runtime/code-runtime-worker) | [`tools`](../packages/core/tools) | - | 使用 Host 提供的异步绑定运行一段由模型编写的程序;各后端采用不同的基础环境和语言(工具注册表在 Code Mode 下消费该服务)。 |
|
||||
| `ctx.fs` | `seam` | [`fs`](../packages/fs/fs) | [`fs-local`](../packages/fs/fs-local)、[`fs-sandbox`](../packages/fs/fs-sandbox)、[`fs-e2b`](../packages/e2b/fs-e2b) | [`tool-fs`](../packages/fs/tool-fs) | [`fs-policy`](../packages/fs/fs-policy) | tool-fs 通过 ctx.fs 执行读取/写入/编辑;fs-sandbox 按共享沙箱模式限制变更;fs-policy 通过 fs/* 事件门禁贡献基于观测状态的检查。 |
|
||||
| `ctx.compact` | `seam` | [`compact`](../packages/compact/compact) | [`compact-basic`](../packages/compact/compact-basic) | [`compact-basic`](../packages/compact/compact-basic) | - | 基础后端消费步骤后的压力事件和请求错误恢复事件;不存在面向模型的压缩工具。 |
|
||||
| `ctx.subagents` | `seam` | [`subagent`](../packages/subagent/subagent) | [`subagent-spawn`](../packages/subagent/subagent-spawn)、[`subagent-fork`](../packages/subagent/subagent-fork)、[`subagent-acp`](../packages/subagent/subagent-acp)、[`subagent-codex`](../packages/subagent/subagent-codex)、[`subagent-claude-code`](../packages/subagent/subagent-claude-code)、[`subagent-dsh-sdk`](../packages/subagent/subagent-dsh-sdk) | [`tool-subagent`](../packages/subagent/tool-subagent)、[`tool-subagent-control`](../packages/subagent/tool-subagent-control)、[`tool-ralph`](../packages/workflow/tool-ralph) | - | 提供方实现传输;该服务还负责可选的、基于 Activation 的延续编排,tool-subagent 选择一次性或可延续委派,tool-subagent-control 传递后续消息,而 tool-ralph 要求一条全新的结构化输出路由。 |
|
||||
| `ctx.tasks` | `seam` | [`tasks`](../packages/tasks/tasks) | [`tasks-local`](../packages/tasks/tasks-local) | [`tool-bash`](../packages/bash/tool-bash)、[`tool-pty`](../packages/pty/tool-pty)、[`tool-subagent`](../packages/subagent/tool-subagent)、[`tool-tasks`](../packages/tasks/tool-tasks) | - | 生产方(后台 bash、PTY 发送和 subagent 委派)登记正在运行的工作;tool-tasks 是面向模型的控制接口,用于读取、列出和终止这些工作;tasks-local 是进程本地注册表。 |
|
||||
| `ctx.web` | `seam` | [`web`](../packages/web/web) | [`web-search-exa`](../packages/web/web-search-exa)、[`web-search-perplexity`](../packages/web/web-search-perplexity)、[`web-search-deepseek`](../packages/web/web-search-deepseek)、[`web-fetch-local`](../packages/web/web-fetch-local) | [`tool-web`](../packages/web/tool-web) | - | 搜索和抓取提供方注册到同一个 ctx.web seam;tool-web 负责稳定的面向模型名称。 |
|
||||
| `ctx.spillStore` | `seam` | [`spill`](../packages/spill/spill) | [`spill-local`](../packages/spill/spill-local) | [`spill-policy`](../packages/spill/spill-policy) | - | 后端保存过大的工具文本,并返回面向模型的定位信息和取回提示;spill-policy 是 tools/post-execute 消费方,负责决定何时 spill。 |
|
||||
| `ctx.directoryPicker` | `seam` | `directory-picker` | `directory-picker-native`、`directory-picker-browse` | `apiproxy` | - | 带判别标记的交互能力:原生后端在 Host 显示设备上打开一个操作系统选择器,浏览后端为应用内浏览器提供列表与创建原语;双端后端通过其浏览器侧填充 ui-workspace 目录流程的 slot(不通过协议发布)。 |
|
||||
| `ctx.httpServer` | `core` | `webserver` | - | `connection`、`modules`、`hmr` | - | 普通的 node:http 载体:具名路由注册表、索引转换 tap,以及静态 dist 回退;Web 传输插件注册自己的路由。 |
|
||||
| `ctx.clientModuleHost` | `core` | `modules` | - | `hmr` | - | 通过增量 dshClient 扫描组合 __DSH_BOOT__ 入口图,提供插件组合包,并通知重建/图变更订阅方。 |
|
||||
| `ctx.workflows` | `seam` | [`workflow`](../packages/workflow/workflow) | [`workflow-workerthread`](../packages/workflow/workflow-workerthread) | [`tool-workflow`](../packages/workflow/tool-workflow)、[`tool-ralph`](../packages/workflow/tool-ralph) | - | 每个上下文使用一个引擎(bash 形态,无具名提供方注册表);通用工作流与固定 Ralph 消费方启动运行,其中的 agent() 调用通过 ctx.subagents 扇出。 |
|
||||
|
||||
维护模式:混合模式。服务从 Cordis 声明中发现;接口、实现和消费方角色在 `scripts/gen-doc-graphs.ts` 中分类,并设有完整性守卫。
|
||||
6
docs/config-catalog.i18n.yaml
Normal file
6
docs/config-catalog.i18n.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/config-catalog.md
|
||||
config-catalog.md: bfb7af770db9414a6605a261ad66ca8f270898fc
|
||||
config-catalog.zh.md: de8a51f29d4752fab1a0c226e64e60a74f6830c4
|
||||
@@ -14,7 +14,7 @@ A `Requires:` line lists the service keys the plugin `inject`s: its `cordis.yml`
|
||||
Requires: `agents`
|
||||
|
||||
```ts config-catalog
|
||||
/** Plugin config: the provider/model target used for each ACP-created agent. */
|
||||
/** Plugin config: the provider/model selection used for each ACP-created agent. */
|
||||
export interface AcpConfig {
|
||||
/** Provider route for created agents. */
|
||||
provider?: string
|
||||
@@ -80,6 +80,20 @@ Depends on: [`agentCore`](../packages/examples/agent-spine-demo/src/index.ts) ·
|
||||
|
||||
Source: [`packages/examples/acp-demo/src/index.ts:39`](../packages/examples/acp-demo/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-agent-default-model`
|
||||
|
||||
```ts config-catalog
|
||||
/** Composition entry for the default model selection. */
|
||||
export interface Config {
|
||||
/** Registered provider route. */
|
||||
provider: string
|
||||
/** Provider-owned model id. */
|
||||
model: string
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/core/agent-default-model/src/index.ts:41`](../packages/core/agent-default-model/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-agent-loop`
|
||||
|
||||
Requires: `agents` · `sessions` · `llm` · `tools` · `systemPrompt`
|
||||
@@ -110,6 +124,37 @@ Depends on: [`AgentOptions`](subsystems/core.md) · [`SessionId`](subsystems/cor
|
||||
|
||||
Source: [`packages/core/agent-loop/src/index.ts:236`](../packages/core/agent-loop/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-agent-presets`
|
||||
|
||||
Requires: `loader`
|
||||
|
||||
```ts config-catalog
|
||||
/** Plugin config: which preset is the default, and where presets live. */
|
||||
export interface Config {
|
||||
/** Preset id mounted when a caller names none. Missing at mount time fails loud. */
|
||||
default: string
|
||||
/** Scanned roots in precedence order; an earlier root wins a duplicate id. */
|
||||
roots: PresetRoot[]
|
||||
}
|
||||
|
||||
/** One directory scanned for preset subdirectories. */
|
||||
export interface PresetRoot {
|
||||
/** Directory holding one subdirectory per preset; a leading `~` expands. */
|
||||
path: string
|
||||
/** Trust recorded on every preset discovered under this root. */
|
||||
trust: PresetTrust
|
||||
}
|
||||
|
||||
/**
|
||||
* Where a preset's composition came from. A `system` preset ships with the
|
||||
* deployment; a `user` preset was authored locally, by a person or by an
|
||||
* agent, and therefore carries the same trust as shell access.
|
||||
*/
|
||||
export type PresetTrust = 'system' | 'user'
|
||||
```
|
||||
|
||||
Source: [`packages/preset/agent-presets/src/types.ts:52`](../packages/preset/agent-presets/src/types.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-agent-spine-demo`
|
||||
|
||||
```ts config-catalog
|
||||
@@ -194,6 +239,28 @@ Depends on: [`AgentLoopConfig`](#deepseek-aidsh-agent-loop) · [`GoalDomainConfi
|
||||
|
||||
Source: [`packages/examples/agent-spine-demo/src/index.ts:90`](../packages/examples/agent-spine-demo/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-agent-tool-mode`
|
||||
|
||||
Requires: `tools`
|
||||
|
||||
```ts config-catalog
|
||||
/** Plugin config. */
|
||||
export interface Config {
|
||||
/**
|
||||
* The form this agent's model sees. `native` sends every visible schema,
|
||||
* `code` sends only `run_code` plus a generated SDK, `both` sends both.
|
||||
* Required rather than defaulted: the deployment default is what a preset
|
||||
* without this row already gets, so an omitted value would mean the row was
|
||||
* composed for nothing.
|
||||
*/
|
||||
mode: ToolPresentationMode
|
||||
}
|
||||
```
|
||||
|
||||
Depends on: [`ToolPresentationMode`](subsystems/tools.md)
|
||||
|
||||
Source: [`packages/core/agent-tool-mode/src/index.ts:36`](../packages/core/agent-tool-mode/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-bash-env`
|
||||
|
||||
```ts config-catalog
|
||||
@@ -397,7 +464,7 @@ export interface Config {
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/credentials/credentials-local/src/index.ts:54`](../packages/credentials/credentials-local/src/index.ts)
|
||||
Source: [`packages/credentials/credentials-local/src/index.ts:55`](../packages/credentials/credentials-local/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-e2b`
|
||||
|
||||
@@ -475,17 +542,17 @@ Source: [`packages/goal/goal/src/index.ts:116`](../packages/goal/goal/src/index.
|
||||
|
||||
## `@deepseek-ai/dsh-headless`
|
||||
|
||||
Requires: `apiProxy` · `httpServer`
|
||||
Requires: `agentDefaultModel` · `agents` · `sessions`
|
||||
|
||||
```ts config-catalog
|
||||
/** Plugin config: the task, patched in by the launcher. */
|
||||
export interface Config {
|
||||
/** The prompt text for the single turn. */
|
||||
/** The prompt text for the single run. */
|
||||
task: string
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/bundle/headless/src/index.ts:32`](../packages/bundle/headless/src/index.ts)
|
||||
Source: [`packages/bundle/headless/src/index.ts:29`](../packages/bundle/headless/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-hooks-claude`
|
||||
|
||||
@@ -499,7 +566,7 @@ export interface Config {
|
||||
* Process-level: read once at load, a relative path resolves against the process
|
||||
* launch cwd, so one config applies to the whole process.
|
||||
* TODO(per-session-hook-config): per-session discovery of a project-local
|
||||
* `hooks.json` from each `session/new.cwd` is not yet implemented.
|
||||
* `hooks.json` from each `session/new.cwd`.
|
||||
*/
|
||||
configPath: string
|
||||
/**
|
||||
@@ -534,7 +601,7 @@ export interface Config {
|
||||
* Path to a Codex `hooks.json`. Process-level: read once at load, a relative
|
||||
* path resolves against the process launch cwd.
|
||||
* TODO(per-session-hook-config): per-session project-local discovery from each
|
||||
* `session/new.cwd` is not yet implemented.
|
||||
* `session/new.cwd`.
|
||||
*/
|
||||
configPath: string
|
||||
/** The model name stamped on every payload (Codex includes `model` on each event). */
|
||||
@@ -550,32 +617,25 @@ Source: [`packages/hooks/hooks-codex/src/index.ts:44`](../packages/hooks/hooks-c
|
||||
|
||||
## `@deepseek-ai/dsh-host-apiproxy`
|
||||
|
||||
Requires: `agents` · `directoryPicker` · `llm` · `sessions` · `subagents` · `sessionQuery` · `tools` · `userInteraction` · `workspace`
|
||||
Requires: `agentDefaultModel` · `agents` · `directoryPicker` · `llm` · `sessions` · `subagents` · `sessionQuery` · `tools` · `userInteraction` · `workspace`
|
||||
|
||||
```ts config-catalog
|
||||
/**
|
||||
* Gateway plugin config: host-level agent routing and Workspace creation root.
|
||||
*
|
||||
* `reasoningEffort` is deliberately absent, so the section carries one field
|
||||
* the composition cannot. The seam resolves a section by MERGING the user
|
||||
* layer over the composition entry per field, and an absent key cannot
|
||||
* override a present one — so a composition-set effort would survive every
|
||||
* later switch to a model that has none, and strand it for the next session
|
||||
* to fail on. Effort is a per-model fact anyway: a deployment default belongs
|
||||
* on the adapter profile (`llm-pi-ai`'s `reasoning`, `llm-deepseek`'s own),
|
||||
* which resolves per model rather than per gateway.
|
||||
*/
|
||||
/** Gateway plugin config: the Host-only Workspace creation root. */
|
||||
export interface Config {
|
||||
/** Default provider route for created agents. */
|
||||
provider: string
|
||||
/** Default model id. */
|
||||
model: string
|
||||
/** Parent directory for name-created Workspaces; defaults to the Host cwd. */
|
||||
workspaceRoot?: string
|
||||
/**
|
||||
* Whether this deployment can hand paths to a native desktop opener —
|
||||
* the `hasDocument` capability the agent-preset roster reports. Absent,
|
||||
* the platform is asked (macOS/Windows/WSL yes; Linux only with a display
|
||||
* server); set it explicitly where detection misleads, e.g. `false` in a
|
||||
* container whose DISPLAY points nowhere a user can see.
|
||||
*/
|
||||
nativeOpen?: boolean
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/host/apiproxy/src/index.ts:67`](../packages/host/apiproxy/src/index.ts)
|
||||
Source: [`packages/host/apiproxy/src/index.ts:38`](../packages/host/apiproxy/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-host-directory-picker-browse`
|
||||
|
||||
@@ -624,7 +684,7 @@ Source: [`packages/support/invariants/src/index.ts:15`](../packages/support/inva
|
||||
Requires: `agents`
|
||||
|
||||
```ts config-catalog
|
||||
/** JSON-RPC deployment config plus runtime-only test seams. */
|
||||
/** JSON-RPC deployment config plus runtime-only test hooks. */
|
||||
export interface JsonRpcConfig {
|
||||
/** Report max-token turn/subagent termination as a successful SDK result. */
|
||||
maxTokensAsSuccess?: boolean
|
||||
@@ -847,8 +907,7 @@ type PiThinkingFormat = NonNullable<OpenAICompletionsCompat['thinkingFormat']>
|
||||
|
||||
/**
|
||||
* pi-ai thinking formats a profile cannot name: both drive the request through
|
||||
* `chatTemplateKwargs`, which this configuration does not expose, so offering
|
||||
* them would hand back a format with nothing to say.
|
||||
* `chatTemplateKwargs`, which this configuration does not expose.
|
||||
*/
|
||||
type WithheldThinkingFormat = 'chat-template' | 'qwen-chat-template'
|
||||
```
|
||||
@@ -918,7 +977,7 @@ Requires: `agents`
|
||||
export type Config = Readonly<Record<string, never>>
|
||||
```
|
||||
|
||||
Source: [`packages/llm/llm-retry/src/index.ts:46`](../packages/llm/llm-retry/src/index.ts)
|
||||
Source: [`packages/llm/llm-retry/src/index.ts:24`](../packages/llm/llm-retry/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-lsp-local`
|
||||
|
||||
@@ -1052,6 +1111,24 @@ Depends on: [`ApprovalPolicy`](subsystems/approval.md) · [`SandboxMode`](subsys
|
||||
|
||||
Source: [`packages/interaction/permission/src/index.ts:140`](../packages/interaction/permission/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-persona`
|
||||
|
||||
Requires: `systemPrompt`
|
||||
|
||||
```ts config-catalog
|
||||
/** Plugin config: the persona text this composition contributes. */
|
||||
export interface Config {
|
||||
/**
|
||||
* Persona prose rendered as the `deployment:persona` section. A template:
|
||||
* complete `{{…}}` groups interpolate strictly against registered prompt
|
||||
* variables. Empty text drops the section at render, matching the registry.
|
||||
*/
|
||||
text: string
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/preset/persona/src/index.ts:34`](../packages/preset/persona/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-plan-mode`
|
||||
|
||||
Requires: `tools` · `systemPrompt`
|
||||
@@ -1140,6 +1217,26 @@ export interface Config {
|
||||
|
||||
Source: [`packages/bash/pwsh-local/src/index.ts:54`](../packages/bash/pwsh-local/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-pwsh-sandbox`
|
||||
|
||||
Requires: `subprocess` · `sandbox` · `sandboxPolicy`
|
||||
|
||||
```ts config-catalog
|
||||
/**
|
||||
* Plugin config: the local executor's knobs, verbatim. The sandbox policy —
|
||||
* the default mode and fallback `workspace-write` root — is NOT here: it lives
|
||||
* on `ctx.sandboxPolicy` (`@deepseek-ai/dsh-sandbox-policy`), which resolves
|
||||
* each calling session's mode and cwd for every enforcing capability. The
|
||||
* runner choice is likewise the `ctx.sandbox` provider's config, not this
|
||||
* executor's.
|
||||
*/
|
||||
export type Config = LocalConfig
|
||||
```
|
||||
|
||||
Depends on: [`LocalConfig`](#deepseek-aidsh-pwsh-local)
|
||||
|
||||
Source: [`packages/bash/pwsh-sandbox/src/index.ts:40`](../packages/bash/pwsh-sandbox/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-repeat-tool-guard`
|
||||
|
||||
```ts config-catalog
|
||||
@@ -1197,9 +1294,10 @@ export interface Config {
|
||||
* Override the runner argv; bwrap-shaped profile arguments are appended. A
|
||||
* non-empty override asserts full enforcement and skips built-in selection and
|
||||
* probing. A runner that starts but refuses its profile must be identifiable by
|
||||
* {@link runnerFailureSignatures}. Consumers classify spawn rejection; only
|
||||
* attributable `ENOENT` or `EACCES` with runner argv[0] provenance becomes an
|
||||
* infrastructure failure.
|
||||
* {@link runnerFailureSignatures}. Consumers classify a spawn rejection only after
|
||||
* confirming the workdir is usable. `ENOENT` or `EACCES` identifies the runner when
|
||||
* `error.path` equals argv[0] and `error.syscall` is `spawn` or `spawn <runner>`, or
|
||||
* when `error.path` is absent and `error.syscall` is exactly `spawn <runner>`.
|
||||
*/
|
||||
runnerCommand?: string[]
|
||||
/**
|
||||
@@ -1215,7 +1313,7 @@ export interface Config {
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/sandbox/sandbox-local/src/index.ts:24`](../packages/sandbox/sandbox-local/src/index.ts)
|
||||
Source: [`packages/sandbox/sandbox-local/src/index.ts:43`](../packages/sandbox/sandbox-local/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-sandbox-policy`
|
||||
|
||||
@@ -1515,7 +1613,7 @@ export interface Config {
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/skill/skill/src/index.ts:265`](../packages/skill/skill/src/index.ts)
|
||||
Source: [`packages/skill/skill/src/index.ts:279`](../packages/skill/skill/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-skill-local`
|
||||
|
||||
@@ -1689,7 +1787,7 @@ export interface Config {
|
||||
/**
|
||||
* How to auto-answer the child's `session/request_permission` prompts:
|
||||
* `reject` (default — decline every prompt) or `allow` (approve via the first
|
||||
* allow-shaped option). The first cut surfaces no prompt to a human.
|
||||
* allow-shaped option). No prompt is surfaced to a human.
|
||||
*/
|
||||
permission: PermissionPolicy
|
||||
/**
|
||||
@@ -1868,7 +1966,7 @@ export interface Config {
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/core/system-prompt/src/index.ts:166`](../packages/core/system-prompt/src/index.ts)
|
||||
Source: [`packages/core/system-prompt/src/index.ts:177`](../packages/core/system-prompt/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-time-context`
|
||||
|
||||
@@ -2071,7 +2169,7 @@ export interface Config {
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/bash/tool-pwsh/src/index.ts:43`](../packages/bash/tool-pwsh/src/index.ts)
|
||||
Source: [`packages/bash/tool-pwsh/src/index.ts:52`](../packages/bash/tool-pwsh/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-tool-ralph`
|
||||
|
||||
@@ -2137,7 +2235,7 @@ export interface Config {
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/fs/tool-str-replace-editor/src/index.ts:496`](../packages/fs/tool-str-replace-editor/src/index.ts)
|
||||
Source: [`packages/fs/tool-str-replace-editor/src/index.ts:497`](../packages/fs/tool-str-replace-editor/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-tool-subagent`
|
||||
|
||||
@@ -2304,11 +2402,16 @@ Requires: `systemPrompt`
|
||||
/** Plugin config: how the registered tools are presented to the model. */
|
||||
export interface Config {
|
||||
/**
|
||||
* Model presentation. `native` (default) sends every visible schema; `code`
|
||||
* sends only `run_code` plus a generated SDK prompt; `both` sends both forms.
|
||||
* Code modes require a `ctx.codeRuntime` whose `language` has a registered
|
||||
* SDK renderer (TypeScript or Python) and fail prompt assembly when it is
|
||||
* absent or has no renderer. Under `code`, native names in `toolOrder` are invalid.
|
||||
* Model presentation for agents that declare none of their own. `native`
|
||||
* (default) sends every visible schema; `code` sends only `run_code` plus a
|
||||
* generated SDK prompt; `both` sends both forms. Code modes require a
|
||||
* `ctx.codeRuntime` whose `language` has a registered SDK renderer
|
||||
* (TypeScript or Python) and fail prompt assembly when it is absent or has
|
||||
* no renderer. Under `code`, native names in `toolOrder` are invalid.
|
||||
*
|
||||
* One agent overrides this for itself with {@link ToolRegistry.presentAs},
|
||||
* which is how an agent preset composes a Code Mode agent beside native
|
||||
* ones in the same process.
|
||||
*/
|
||||
mode?: ToolPresentationMode
|
||||
/**
|
||||
@@ -2325,7 +2428,7 @@ export interface Config {
|
||||
export type ToolPresentationMode = 'native' | 'code' | 'both'
|
||||
```
|
||||
|
||||
Source: [`packages/core/tools/src/index.ts:616`](../packages/core/tools/src/index.ts)
|
||||
Source: [`packages/core/tools/src/index.ts:624`](../packages/core/tools/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-typert-loader`
|
||||
|
||||
@@ -2360,8 +2463,7 @@ export interface Config {
|
||||
* ask BEFORE any interactive answerer sees it:
|
||||
*
|
||||
* - `'ask'` (the default) — delegate to the composed answerers; with none
|
||||
* composed the chain falls through to the fail-closed `'unavailable'`
|
||||
* (exactly today's behavior).
|
||||
* composed the chain falls through to the fail-closed `'unavailable'`.
|
||||
* - `'never'` — never prompt anyone: every ask resolves `'rejected'`
|
||||
* deterministically. The strict headless stance (CI, unattended runs) and
|
||||
* the policy whose outcome is knowable without asking.
|
||||
@@ -2369,7 +2471,7 @@ export interface Config {
|
||||
export type ApprovalPolicy = 'ask' | 'never'
|
||||
```
|
||||
|
||||
Source: [`packages/interaction/user-approval/src/index.ts:178`](../packages/interaction/user-approval/src/index.ts)
|
||||
Source: [`packages/interaction/user-approval/src/index.ts:177`](../packages/interaction/user-approval/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-web`
|
||||
|
||||
@@ -2583,6 +2685,7 @@ These load from a `cordis.yml` entry with no `config:` block; they declare no co
|
||||
- `@deepseek-ai/dsh-client-locale` ([`packages/client/locale/src/index.ts`](../packages/client/locale/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-modules` — requires `httpServer` · `loader` ([`packages/client/modules/src/index.ts`](../packages/client/modules/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-runtime` ([`packages/client/runtime/src/index.ts`](../packages/client/runtime/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-agent-preset` ([`packages/client/ui-agent-preset/src/index.ts`](../packages/client/ui-agent-preset/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-command` ([`packages/client/ui-command/src/index.ts`](../packages/client/ui-command/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-conversation` ([`packages/client/ui-conversation/src/index.ts`](../packages/client/ui-conversation/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-deliverables` ([`packages/client/ui-deliverables/src/index.ts`](../packages/client/ui-deliverables/src/index.ts))
|
||||
@@ -2592,7 +2695,7 @@ These load from a `cordis.yml` entry with no `config:` block; they declare no co
|
||||
- `@deepseek-ai/dsh-client-ui-models` ([`packages/client/ui-models/src/index.ts`](../packages/client/ui-models/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-permission` ([`packages/client/ui-permission/src/index.ts`](../packages/client/ui-permission/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-plan` ([`packages/client/ui-plan/src/index.ts`](../packages/client/ui-plan/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-question` — requires `tools` · `userInteraction` ([`packages/client/ui-question/src/index.ts`](../packages/client/ui-question/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-question` ([`packages/client/ui-question/src/index.ts`](../packages/client/ui-question/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-settings` ([`packages/client/ui-settings/src/index.ts`](../packages/client/ui-settings/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-settings-general` ([`packages/client/ui-settings-general/src/index.ts`](../packages/client/ui-settings-general/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-sidebar` ([`packages/client/ui-sidebar/src/index.ts`](../packages/client/ui-sidebar/src/index.ts))
|
||||
@@ -2675,6 +2778,7 @@ Imported as libraries by other packages; a `cordis.yml` cannot load them.
|
||||
- `@deepseek-ai/dsh-native-command` ([`packages/util/native-command/src/index.ts`](../packages/util/native-command/src/index.ts))
|
||||
- `@deepseek-ai/dsh-paths` ([`packages/util/paths/src/index.ts`](../packages/util/paths/src/index.ts))
|
||||
- `@deepseek-ai/dsh-retention` ([`packages/util/retention/src/index.ts`](../packages/util/retention/src/index.ts))
|
||||
- `@deepseek-ai/dsh-sandbox-windows-acl` ([`packages/sandbox/sandbox-windows-acl/src/index.ts`](../packages/sandbox/sandbox-windows-acl/src/index.ts))
|
||||
- `@deepseek-ai/dsh-scope` ([`packages/core/scope/src/index.ts`](../packages/core/scope/src/index.ts))
|
||||
- `@deepseek-ai/dsh-scripts` ([`packages/scaffold/scripts/src/index.ts`](../packages/scaffold/scripts/src/index.ts))
|
||||
- `@deepseek-ai/dsh-sdk-client` ([`packages/scaffold/client/src/index.ts`](../packages/scaffold/client/src/index.ts))
|
||||
|
||||
2793
docs/config-catalog.zh.md
Normal file
2793
docs/config-catalog.zh.md
Normal file
File diff suppressed because it is too large
Load Diff
6
docs/cookbook/adding-a-conversation-node.i18n.yaml
Normal file
6
docs/cookbook/adding-a-conversation-node.i18n.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cookbook/adding-a-conversation-node.md
|
||||
adding-a-conversation-node.md: ea4ec73eb109af6b0e4c7cf50fc8692942c75dd4
|
||||
adding-a-conversation-node.zh.md: 4b9a8049e2f1d060ec4bc3334036559b989ea562
|
||||
232
docs/cookbook/adding-a-conversation-node.md
Normal file
232
docs/cookbook/adding-a-conversation-node.md
Normal file
@@ -0,0 +1,232 @@
|
||||
# Add a Web Client conversation node
|
||||
|
||||
English | [中文](adding-a-conversation-node.zh.md)
|
||||
|
||||
This tutorial adds one business-owned row to the Web Client Chat view. The finished plugin correlates a durable Session event family into one Context, incrementally builds business State, publishes typed Step data, and renders a keyed Chat Node without scanning the Session window or other rendered nodes. It assumes the Host already records the events and the client plugin is composed into the Web bundle; external Host-side UIs and additional view targets such as Trajectory are outside this tutorial.
|
||||
|
||||
The [Conversation Node assembly decision](../../.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.md) owns the rationale and complete engine model. This guide covers the implementation path.
|
||||
|
||||
## 1. Design a replayable event family
|
||||
|
||||
Choose one stable business id before writing the Definition. Every event that contributes to the same Node must carry that id or derive it independently from its own payload; the client must never assign an update to “the latest unfinished” Context.
|
||||
|
||||
For a review job, the event contract could be:
|
||||
|
||||
| Event | Role | Required durable facts |
|
||||
|---|---|---|
|
||||
| `review/start` | unique start | `reviewId`, Turn/Step coordinates, title |
|
||||
| `review/progress` | update | the same `reviewId`, coordinates, replayable progress |
|
||||
| `review/end` | update | the same `reviewId`, coordinates, final summary |
|
||||
|
||||
Use the producer-owned branded id type across the process boundary. Put the `SessionEventMap` merge and payload types on the producer's type-only export, then import that export for side effects from the client package. Each `(kind, id)` may have at most one start event. A single-event business can use the event's stable identity, such as `event.seq`, as its Definition-local id.
|
||||
|
||||
Incremental events are supported. Prefer whole-value checkpoints when the producer can emit them cheaply, because they remain useful when the start is outside the loaded window. Each delta must carry the stable id and produce deterministic State when replayed in ascending log `seq`; it must not depend on live-only memory. If the current history window contains only updates, the assembler keeps a pending Context and builds no State until an older page supplies the start. If the product must render before the start is loaded, a terminal or checkpoint event must carry enough whole fallback state for the Definition to build that result directly; do not recover it by scanning unrelated events.
|
||||
|
||||
## 2. Implement the Definition and typed Chat payload
|
||||
|
||||
The example keeps the producer declarations and client contribution in one block so the complete relationship is visible. In a package family, keep the branded id and `SessionEventMap` declaration with the event producer, and keep the Definition, Chat data merge, and renderer in the client plugin.
|
||||
|
||||
```ts ignore-check
|
||||
import { createElement } from 'react'
|
||||
import type { Branded } from '@deepseek-ai/dsh-brand'
|
||||
import type {
|
||||
ClientContext, ConversationLocation, ConversationNodeContext,
|
||||
ConversationNodeDefinition,
|
||||
} from '@deepseek-ai/dsh-client-runtime/client'
|
||||
import type { ChatNodeViewProps } from '@deepseek-ai/dsh-client-ui-conversation/client'
|
||||
|
||||
type ReviewId = Branded<'ReviewId'>
|
||||
|
||||
interface ReviewStartData {
|
||||
readonly reviewId: ReviewId
|
||||
readonly turn: number
|
||||
readonly step: number
|
||||
readonly title: string
|
||||
}
|
||||
|
||||
interface ReviewProgressData {
|
||||
readonly reviewId: ReviewId
|
||||
readonly turn: number
|
||||
readonly step: number
|
||||
readonly completed: number
|
||||
}
|
||||
|
||||
interface ReviewEndData {
|
||||
readonly reviewId: ReviewId
|
||||
readonly turn: number
|
||||
readonly step: number
|
||||
readonly summary: string
|
||||
}
|
||||
|
||||
declare module '@deepseek-ai/dsh-session/types' {
|
||||
interface SessionEventMap {
|
||||
/**
|
||||
* Opens one durable review job.
|
||||
* @mode emit
|
||||
* @param data - stable identity, location, and initial display state.
|
||||
*/
|
||||
'review/start': ReviewStartData
|
||||
/**
|
||||
* Records replayable progress for one review job.
|
||||
* @mode emit
|
||||
* @param data - stable identity, location, and latest progress.
|
||||
*/
|
||||
'review/progress': ReviewProgressData
|
||||
/**
|
||||
* Closes one review job with its final summary.
|
||||
* @mode emit
|
||||
* @param data - stable identity, location, and final display state.
|
||||
*/
|
||||
'review/end': ReviewEndData
|
||||
}
|
||||
}
|
||||
|
||||
interface ReviewChatData {
|
||||
readonly title: string
|
||||
readonly completed: number
|
||||
readonly status: 'running' | 'completed'
|
||||
readonly summary?: string
|
||||
}
|
||||
|
||||
declare module '@deepseek-ai/dsh-client-ui-conversation/client' {
|
||||
interface ChatNodeDataMap {
|
||||
'review-job': ReviewChatData
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@deepseek-ai/dsh-client-runtime/client' {
|
||||
interface ConversationStepDataMap {
|
||||
'review-job': ReviewChatData
|
||||
}
|
||||
}
|
||||
|
||||
interface ReviewState extends ReviewChatData {
|
||||
readonly turn: number
|
||||
readonly step: number
|
||||
}
|
||||
|
||||
function locationOf(context: ConversationNodeContext): ConversationLocation {
|
||||
return context.start?.location ?? context.matches[0]?.location ?? { kind: 'unresolved' }
|
||||
}
|
||||
|
||||
function viewData(state: ReviewState): ReviewChatData {
|
||||
return {
|
||||
title: state.title,
|
||||
completed: state.completed,
|
||||
status: state.status,
|
||||
...state.summary === undefined ? {} : { summary: state.summary },
|
||||
}
|
||||
}
|
||||
|
||||
const reviewDefinition: ConversationNodeDefinition<ReviewState> = {
|
||||
kind: 'review-job',
|
||||
match: (event) => {
|
||||
if (event.type === 'review/start') {
|
||||
return { id: String(event.data.reviewId), role: 'start' }
|
||||
}
|
||||
if (event.type === 'review/progress' || event.type === 'review/end') {
|
||||
return { id: String(event.data.reviewId), role: 'update' }
|
||||
}
|
||||
return null
|
||||
},
|
||||
start: (_context, match) => {
|
||||
if (match.event.type !== 'review/start') throw new Error('review-job requires review/start')
|
||||
return {
|
||||
turn: match.event.data.turn,
|
||||
step: match.event.data.step,
|
||||
title: match.event.data.title,
|
||||
completed: 0,
|
||||
status: 'running',
|
||||
}
|
||||
},
|
||||
update: (context, match) => {
|
||||
if (match.event.type === 'review/progress') {
|
||||
return { ...context.state, completed: match.event.data.completed }
|
||||
}
|
||||
if (match.event.type === 'review/end') {
|
||||
return { ...context.state, completed: 100, status: 'completed', summary: match.event.data.summary }
|
||||
}
|
||||
return context.state
|
||||
},
|
||||
publication: match => match.event.type === 'review/progress'
|
||||
? 'animation-frame'
|
||||
: 'immediate',
|
||||
buildLocationData: (context, scope) => {
|
||||
if (scope !== 'step' || context.state === undefined) return null
|
||||
return {
|
||||
kind: 'step',
|
||||
turn: context.state.turn,
|
||||
step: context.state.step,
|
||||
key: 'review-job',
|
||||
value: viewData(context.state),
|
||||
}
|
||||
},
|
||||
buildViewNode: (context, target) => {
|
||||
if (target !== 'chat' || context.state === undefined) return null
|
||||
return {
|
||||
key: context.key,
|
||||
kind: 'review-job',
|
||||
id: context.id,
|
||||
target: 'chat',
|
||||
anchorSeq: context.start?.event.seq ?? context.matches[0]?.event.seq ?? 0,
|
||||
location: locationOf(context),
|
||||
visibility: 'visible',
|
||||
data: viewData(context.state),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
function ReviewNodeView({ node }: ChatNodeViewProps<'review-job'>) {
|
||||
const text = node.data.summary ?? `${node.data.title}: ${node.data.completed}%`
|
||||
return createElement('p', null, text)
|
||||
}
|
||||
|
||||
export const inject = ['conversationEvents', 'slots']
|
||||
|
||||
export function apply(ctx: ClientContext): void {
|
||||
ctx.conversationEvents.register(reviewDefinition)
|
||||
ctx.slots.inject('conversation.chat.node', () => ctx.slots.register({
|
||||
name: 'conversation.chat.node',
|
||||
key: 'review-job',
|
||||
}, ReviewNodeView))
|
||||
}
|
||||
```
|
||||
|
||||
`match(event)` is an identity extractor, not a fold: it receives only the current event and returns the Definition-local id and lifecycle role. After a match, the assembler locates the Context by `(kind, id)` and calls `start` once or `update` with the current State. Both functions return the State that the engine adopts; returning a new immutable value is preferred, but a function that mutates and returns the same object has the same adoption semantics.
|
||||
|
||||
`buildLocationData(context, scope)` optionally publishes Definition-owned data onto an engine-owned Turn or Step. Use declaration merging to give each key a precise value type. Another Node in the same Location can consume that value through its constrained slot hook, such as `useTurnData(key)`, without receiving the Session or scanning `snapshot.chat.nodes`.
|
||||
|
||||
`buildViewNode(context, target)` materializes the final target-specific Node. Preserve `context.key` as the React-facing identity, choose `anchorSeq` from durable ordering evidence, and return only renderer-ready data. Once a target Node has been published, keep returning the same key; use `visibility: 'hidden'` when it must temporarily leave the visible flow rather than withdrawing it with `null`.
|
||||
|
||||
## 3. Query an earlier business Context only at start
|
||||
|
||||
Some Definitions need the latest earlier State of another business kind. `start` receives a `ConversationContextReader`; call `reader.previous<State>(kind)` there instead of accepting a Context collection or scanning events. The reader returns the nearest started Context before the current start `seq` as read-only data.
|
||||
|
||||
The assembler records that dependency. If an older prepend later supplies a nearer predecessor, closes a previously unknown window gap, or revises the predecessor State, it reruns the dependent Context from `start` and replays its updates in ascending `seq`. The queried Definition remains responsible for writing useful State; the reader exposes no business-specific query methods and grants no mutation authority over another Context.
|
||||
|
||||
## 4. Understand the three ingestion paths
|
||||
|
||||
History may be requested from the tail backward one page at a time, but every accepted page is normalized into ascending `seq` before State replay.
|
||||
|
||||
| Path | Engine work | Definition-visible behavior |
|
||||
|---|---|---|
|
||||
| Replace on open, resync, or gap repair | Rebuild the loaded window, match every event once per Definition, then replay each started Context | `start`, followed by its updates in ascending `seq`; pending update-only Contexts remain without State |
|
||||
| Prepend one older page | Match only fresh older events, merge them into Contexts by `(kind, id)`, preserve existing keyed nodes, and replay only affected Contexts and dependencies | A newly found start activates its collected updates; a changed Location or predecessor may rerun the Context |
|
||||
| Append one live event | Call each Definition's `match` once, look up the matched Context by key, and update only that Context | One `update` and one requested publication for a matching post-start event; no existing Context scan |
|
||||
|
||||
With `D` registered Definitions, one incoming event performs `D` current-event matches and constant-time Context-key lookup after a match. Definition code must preserve that property: do not traverse the complete event window, every Context, `context.matches`, or the rendered Node collection on the normal append path. Use State for accumulated facts, Location data for same-Turn/Step sharing, and `reader.previous()` for indexed predecessor dependencies.
|
||||
|
||||
`publication` controls when changed State is materialized. Use `immediate` for structural or terminal changes, `animation-frame` for high-frequency visible deltas, and `none` when the State change feeds only a later publication. The engine still applies every update in log order; cadence only coalesces view publication.
|
||||
|
||||
## 5. Verify replay, pagination, and rendering
|
||||
|
||||
Add focused tests that establish these outcomes:
|
||||
|
||||
1. A complete window passed through replace produces the expected final State, Location data, Node payload, and `anchorSeq`.
|
||||
2. An update-only tail stays pending; prepending the unique start produces the same result as a complete replace.
|
||||
3. Initial history followed by live append produces the same result as replaying the combined window.
|
||||
4. Prepending an older page adds earlier rows without replacing existing keyed Node values whose data did not change.
|
||||
5. Repeated visible deltas preserve `context.key` and publish at most once per animation frame when requested.
|
||||
6. The keyed renderer consumes `node.data` and constrained Location hooks only; it does not scan the Session event window, Contexts, or Chat Nodes.
|
||||
|
||||
Use [`packages/client/ui-conversation/src/client/conversation-nodes/assistant.ts`](../../packages/client/ui-conversation/src/client/conversation-nodes/assistant.ts) for streaming and interruption, [`inbox.ts`](../../packages/client/ui-conversation/src/client/conversation-nodes/inbox.ts) plus [`message.ts`](../../packages/client/ui-conversation/src/client/conversation-nodes/message.ts) for predecessor queries, and [`packages/client/ui-deliverables`](../../packages/client/ui-deliverables) for a Definition that publishes Turn data without creating its own Node.
|
||||
232
docs/cookbook/adding-a-conversation-node.zh.md
Normal file
232
docs/cookbook/adding-a-conversation-node.zh.md
Normal file
@@ -0,0 +1,232 @@
|
||||
# 添加 Web Client Conversation Node
|
||||
|
||||
[English](adding-a-conversation-node.md) | 中文
|
||||
|
||||
本教程为 Web Client Chat 视图添加一行由业务自行拥有的内容。完成后的插件会把一个持久 Session 事件族关联成一个 Context,增量构造业务 State,发布类型化 Step 数据,再渲染 keyed Chat Node;整个过程不扫描 Session 窗口或其他已渲染节点。本教程假设 Host 已经记录这些事件,且该 Client 插件已组装进 Web bundle;Host 侧外部 UI 和 Trajectory 等额外视图目标不在本文范围内。
|
||||
|
||||
[Conversation Node 组装决策](../../.agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.md)记录完整的引擎模型和设计理由;本文只说明实现路径。
|
||||
|
||||
## 1. 设计可回放的事件族
|
||||
|
||||
编写 Definition 前先选定稳定的业务 id。构成同一个 Node 的每条事件都必须携带该 id,或只凭自身 payload 独立推导出该 id;Client 绝不能把 update 猜测为属于“最近一个未完成”的 Context。
|
||||
|
||||
以一个 review job 为例,事件约定可以是:
|
||||
|
||||
| 事件 | 角色 | 必须持久化的事实 |
|
||||
|---|---|---|
|
||||
| `review/start` | 唯一 start | `reviewId`、Turn/Step 坐标、标题 |
|
||||
| `review/progress` | update | 相同的 `reviewId`、坐标、可回放进度 |
|
||||
| `review/end` | update | 相同的 `reviewId`、坐标、最终摘要 |
|
||||
|
||||
跨进程边界使用生产方拥有的 branded id 类型。把 `SessionEventMap` 合并和 payload 类型放在生产方的纯类型导出中,再由 Client 包通过仅类型副作用导入该导出。每个 `(kind, id)` 最多只能有一条 start 事件。单事件业务可以把事件自身的稳定身份(例如 `event.seq`)作为 Definition 内部 id。
|
||||
|
||||
系统支持增量事件。如果生产方能以较低成本发出 whole-value checkpoint,应优先采用,因为 start 位于已加载窗口之外时它仍可直接使用。每条 delta 都必须携带稳定 id,并且按照日志 `seq` 升序回放时能够确定性地产生 State;它不能依赖只存在于实时内存中的状态。如果当前历史窗口只有 update,Assembler 会保留一个 pending Context,并在更早分页补齐 start 前不构造 State。如果产品必须在 start 尚未加载时渲染,terminal 或 checkpoint 事件就必须携带足够的完整 fallback 状态,让 Definition 能直接构造结果;不要通过扫描无关事件恢复它。
|
||||
|
||||
## 2. 实现 Definition 与类型化 Chat payload
|
||||
|
||||
为了完整展示关联关系,下面把生产方声明和 Client 贡献写在同一个代码块里。实际的包族中,branded id 与 `SessionEventMap` 声明留在事件生产方,Definition、Chat data 合并与 renderer 留在 Client 插件。
|
||||
|
||||
```ts ignore-check
|
||||
import { createElement } from 'react'
|
||||
import type { Branded } from '@deepseek-ai/dsh-brand'
|
||||
import type {
|
||||
ClientContext, ConversationLocation, ConversationNodeContext,
|
||||
ConversationNodeDefinition,
|
||||
} from '@deepseek-ai/dsh-client-runtime/client'
|
||||
import type { ChatNodeViewProps } from '@deepseek-ai/dsh-client-ui-conversation/client'
|
||||
|
||||
type ReviewId = Branded<'ReviewId'>
|
||||
|
||||
interface ReviewStartData {
|
||||
readonly reviewId: ReviewId
|
||||
readonly turn: number
|
||||
readonly step: number
|
||||
readonly title: string
|
||||
}
|
||||
|
||||
interface ReviewProgressData {
|
||||
readonly reviewId: ReviewId
|
||||
readonly turn: number
|
||||
readonly step: number
|
||||
readonly completed: number
|
||||
}
|
||||
|
||||
interface ReviewEndData {
|
||||
readonly reviewId: ReviewId
|
||||
readonly turn: number
|
||||
readonly step: number
|
||||
readonly summary: string
|
||||
}
|
||||
|
||||
declare module '@deepseek-ai/dsh-session/types' {
|
||||
interface SessionEventMap {
|
||||
/**
|
||||
* Opens one durable review job.
|
||||
* @mode emit
|
||||
* @param data - stable identity, location, and initial display state.
|
||||
*/
|
||||
'review/start': ReviewStartData
|
||||
/**
|
||||
* Records replayable progress for one review job.
|
||||
* @mode emit
|
||||
* @param data - stable identity, location, and latest progress.
|
||||
*/
|
||||
'review/progress': ReviewProgressData
|
||||
/**
|
||||
* Closes one review job with its final summary.
|
||||
* @mode emit
|
||||
* @param data - stable identity, location, and final display state.
|
||||
*/
|
||||
'review/end': ReviewEndData
|
||||
}
|
||||
}
|
||||
|
||||
interface ReviewChatData {
|
||||
readonly title: string
|
||||
readonly completed: number
|
||||
readonly status: 'running' | 'completed'
|
||||
readonly summary?: string
|
||||
}
|
||||
|
||||
declare module '@deepseek-ai/dsh-client-ui-conversation/client' {
|
||||
interface ChatNodeDataMap {
|
||||
'review-job': ReviewChatData
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@deepseek-ai/dsh-client-runtime/client' {
|
||||
interface ConversationStepDataMap {
|
||||
'review-job': ReviewChatData
|
||||
}
|
||||
}
|
||||
|
||||
interface ReviewState extends ReviewChatData {
|
||||
readonly turn: number
|
||||
readonly step: number
|
||||
}
|
||||
|
||||
function locationOf(context: ConversationNodeContext): ConversationLocation {
|
||||
return context.start?.location ?? context.matches[0]?.location ?? { kind: 'unresolved' }
|
||||
}
|
||||
|
||||
function viewData(state: ReviewState): ReviewChatData {
|
||||
return {
|
||||
title: state.title,
|
||||
completed: state.completed,
|
||||
status: state.status,
|
||||
...state.summary === undefined ? {} : { summary: state.summary },
|
||||
}
|
||||
}
|
||||
|
||||
const reviewDefinition: ConversationNodeDefinition<ReviewState> = {
|
||||
kind: 'review-job',
|
||||
match: (event) => {
|
||||
if (event.type === 'review/start') {
|
||||
return { id: String(event.data.reviewId), role: 'start' }
|
||||
}
|
||||
if (event.type === 'review/progress' || event.type === 'review/end') {
|
||||
return { id: String(event.data.reviewId), role: 'update' }
|
||||
}
|
||||
return null
|
||||
},
|
||||
start: (_context, match) => {
|
||||
if (match.event.type !== 'review/start') throw new Error('review-job requires review/start')
|
||||
return {
|
||||
turn: match.event.data.turn,
|
||||
step: match.event.data.step,
|
||||
title: match.event.data.title,
|
||||
completed: 0,
|
||||
status: 'running',
|
||||
}
|
||||
},
|
||||
update: (context, match) => {
|
||||
if (match.event.type === 'review/progress') {
|
||||
return { ...context.state, completed: match.event.data.completed }
|
||||
}
|
||||
if (match.event.type === 'review/end') {
|
||||
return { ...context.state, completed: 100, status: 'completed', summary: match.event.data.summary }
|
||||
}
|
||||
return context.state
|
||||
},
|
||||
publication: match => match.event.type === 'review/progress'
|
||||
? 'animation-frame'
|
||||
: 'immediate',
|
||||
buildLocationData: (context, scope) => {
|
||||
if (scope !== 'step' || context.state === undefined) return null
|
||||
return {
|
||||
kind: 'step',
|
||||
turn: context.state.turn,
|
||||
step: context.state.step,
|
||||
key: 'review-job',
|
||||
value: viewData(context.state),
|
||||
}
|
||||
},
|
||||
buildViewNode: (context, target) => {
|
||||
if (target !== 'chat' || context.state === undefined) return null
|
||||
return {
|
||||
key: context.key,
|
||||
kind: 'review-job',
|
||||
id: context.id,
|
||||
target: 'chat',
|
||||
anchorSeq: context.start?.event.seq ?? context.matches[0]?.event.seq ?? 0,
|
||||
location: locationOf(context),
|
||||
visibility: 'visible',
|
||||
data: viewData(context.state),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
function ReviewNodeView({ node }: ChatNodeViewProps<'review-job'>) {
|
||||
const text = node.data.summary ?? `${node.data.title}: ${node.data.completed}%`
|
||||
return createElement('p', null, text)
|
||||
}
|
||||
|
||||
export const inject = ['conversationEvents', 'slots']
|
||||
|
||||
export function apply(ctx: ClientContext): void {
|
||||
ctx.conversationEvents.register(reviewDefinition)
|
||||
ctx.slots.inject('conversation.chat.node', () => ctx.slots.register({
|
||||
name: 'conversation.chat.node',
|
||||
key: 'review-job',
|
||||
}, ReviewNodeView))
|
||||
}
|
||||
```
|
||||
|
||||
`match(event)` 是身份提取器,不是 fold:它只能收到当前事件,并返回 Definition 内部 id 与生命周期角色。命中后,Assembler 通过 `(kind, id)` 定位 Context,再调用一次 `start`,或把当前 State 交给 `update`。两个函数都必须返回引擎随后采用的 State;推荐返回新的 immutable value,但函数原地修改后返回同一对象时,采用语义也相同。
|
||||
|
||||
`buildLocationData(context, scope)` 可以把 Definition 拥有的数据发布到引擎拥有的 Turn 或 Step 上。通过 declaration merging 为每个 key 指定精确 value 类型。同一 Location 内的另一个 Node 可以使用受限 slot hook(例如 `useTurnData(key)`)读取该值,无须取得 Session,也无须扫描 `snapshot.chat.nodes`。
|
||||
|
||||
`buildViewNode(context, target)` 物化最终的目标专用 Node。把 `context.key` 保留为 React 侧身份,根据持久排序证据选择 `anchorSeq`,并且只返回 renderer 可以直接使用的数据。某个 target Node 一旦发布,就要继续返回同一个 key;需要暂时离开可见流时使用 `visibility: 'hidden'`,不要改为返回 `null` 撤回它。
|
||||
|
||||
## 3. 只在 start 时查询更早的业务 Context
|
||||
|
||||
有些 Definition 需要另一个业务 kind 在当前位置之前的最新 State。`start` 会收到 `ConversationContextReader`;应在这里调用 `reader.previous<State>(kind)`,不要接收 Context 集合或扫描事件。Reader 返回当前 start `seq` 之前最近一个已启动 Context 的只读数据。
|
||||
|
||||
Assembler 会记录这项依赖。如果后续 older prepend 带来了更近的前序 Context、补齐了原先未知的窗口缺口,或者前序 State 被修订,引擎会从 `start` 重新运行依赖方 Context,并按 `seq` 升序回放其 update。被查询的 Definition 仍负责把有用信息写入自身 State;Reader 不提供业务专用查询方法,也不授予修改其他 Context 的权限。
|
||||
|
||||
## 4. 理解三条摄入路径
|
||||
|
||||
历史可能从尾部开始一页一页向前请求,但每个已接收分页都会先按 `seq` 升序归一化,再进入 State 回放。
|
||||
|
||||
| 路径 | 引擎工作 | Definition 可观察到的行为 |
|
||||
|---|---|---|
|
||||
| open、resync 或 gap repair 时 replace | 重建已加载窗口,每条事件对每个 Definition 匹配一次,再回放每个已有 start 的 Context | 先执行 `start`,再按 `seq` 升序执行其 update;只有 update 的 pending Context 仍没有 State |
|
||||
| prepend 一页更早历史 | 只匹配新增的更早事件,按 `(kind, id)` 合并进 Context,保留现有 keyed node,并只重放受影响的 Context 与依赖 | 新发现的 start 会激活已收集 update;Location 或前序依赖变化也可能重跑 Context |
|
||||
| append 一条实时事件 | 每个 Definition 各调用一次 `match`,按 key 查找命中的 Context,只更新该 Context | 对 start 之后的匹配事件执行一次 `update` 并请求一次发布;不扫描已有 Context |
|
||||
|
||||
注册 `D` 个 Definition 时,一条新事件会进行 `D` 次仅当前事件匹配;命中后的 Context key 查询是常数时间。Definition 代码必须维持这个性质:正常 append 热路径不得遍历完整事件窗口、所有 Context、`context.matches` 或已渲染 Node 集合。累计事实放进 State,同 Turn/Step 共享信息放进 Location data,有索引的前序依赖使用 `reader.previous()`。
|
||||
|
||||
`publication` 控制发生 State 变更后何时物化。结构或 terminal 变化使用 `immediate`,高频可见 delta 使用 `animation-frame`,只为后续发布积累 State 时使用 `none`。引擎仍会按日志顺序应用每条 update;该选项只合并视图发布频率。
|
||||
|
||||
## 5. 验证回放、分页与渲染
|
||||
|
||||
添加聚焦测试,证明以下结果:
|
||||
|
||||
1. 完整窗口通过 replace 后产生预期的最终 State、Location data、Node payload 与 `anchorSeq`。
|
||||
2. 只有 update 的尾部窗口保持 pending;prepend 唯一 start 后,结果与完整 replace 相同。
|
||||
3. 初始历史后继续实时 append,与回放合并后的完整窗口得到相同结果。
|
||||
4. prepend 更早分页只增加更早的行;数据未变化的既有 keyed Node value 不被替换。
|
||||
5. 重复的可见 delta 保持 `context.key`,并在请求 `animation-frame` 时每帧最多发布一次。
|
||||
6. keyed renderer 只消费 `node.data` 与受限 Location hook,不扫描 Session 事件窗口、Context 或 Chat Node。
|
||||
|
||||
流式与中断处理可参考 [`packages/client/ui-conversation/src/client/conversation-nodes/assistant.ts`](../../packages/client/ui-conversation/src/client/conversation-nodes/assistant.ts),前序查询可参考 [`inbox.ts`](../../packages/client/ui-conversation/src/client/conversation-nodes/inbox.ts) 与 [`message.ts`](../../packages/client/ui-conversation/src/client/conversation-nodes/message.ts),只发布 Turn data 而不创建自有 Node 的例子见 [`packages/client/ui-deliverables`](../../packages/client/ui-deliverables)。
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cookbook/adding-a-package.md
|
||||
adding-a-package.md: 8ab603ea7b235bd2a582c9232afaca281a969448
|
||||
adding-a-package.zh.md: 400bd080b04ff5791393b56e67c1e3b9ade987de
|
||||
adding-a-package.md: 79e8604a47a4bdbb7e2912990a8b1c8be300b3b0
|
||||
adding-a-package.zh.md: 5fcdf03f52dfdfe375aeb2b6fd41e50ee406d043
|
||||
|
||||
@@ -40,7 +40,7 @@ Covered automatically by globs or package-manifest discovery — no edits needed
|
||||
|
||||
## 3. Decide the package topology
|
||||
|
||||
For a swappable capability, split interface / implementation / consumer into separate packages (see docs/architecture.md § "Capability seams" — the bash trio is the template). A single-purpose plugin stays one package.
|
||||
For a swappable capability, separate Service Definition / Service provider / Consumer roles into packages when they evolve independently (see docs/architecture.md § "Capability seams" — the bash trio is the template). A single-purpose plugin stays one package.
|
||||
|
||||
## 4. Write the package README
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ package.json 不变式(由 `pnpm run constraints` / `scripts/check-workspace-c
|
||||
|
||||
## 3. 确定包拓扑
|
||||
|
||||
对于可替换的能力,将接口、实现、消费方拆分为独立的包(见 docs/architecture.md § "Capability seams"——bash 三组件是模板)。单一用途的插件保持为一个包。
|
||||
对于可替换的能力,当 Service Definition/Service provider/Consumer 角色需要独立演进时,将它们拆分到不同包中(见 docs/architecture.md § "Capability seams"——bash 三组件是模板)。单一用途的插件保持为一个包。
|
||||
|
||||
## 4. 编写包 README
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cookbook/extension-cookbook.md
|
||||
extension-cookbook.md: e04f6ffcf9a32ba3ee7344db18cad113b347c667
|
||||
extension-cookbook.zh.md: c3370a519bb09435749d608fe7c63a5330c24f62
|
||||
extension-cookbook.md: aba220ec6dc3cf3d0f99edd0e47ffa6069499b47
|
||||
extension-cookbook.zh.md: 34e8fc0fa3d2d57136616d66cfb4f3f6de20605e
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
English | [中文](extension-cookbook.zh.md)
|
||||
|
||||
Reference shapes for the harness extension surface. The snippets omit imports and helper implementations and are not copy-paste-complete. For concrete authoring paths, see the [package checklist](adding-a-package.md), [first-tool tutorial](../user/develop/basic/tool.md), [tool reference](adding-a-tool.md), and [LLM adapter guide](adding-an-llm-adapter.md); the [architecture](../architecture.md) owns the system and extension-seam map.
|
||||
Reference shapes for the harness extension surface. The snippets omit imports and helper implementations and are not copy-paste-complete. For concrete authoring paths, see the [package checklist](adding-a-package.md), [first-tool tutorial](../user/develop/basic/tool.md), [tool reference](adding-a-tool.md), and [LLM adapter guide](adding-an-llm-adapter.md); the [architecture](../architecture.md) owns the system and extension-point map.
|
||||
|
||||
## A tool plugin
|
||||
|
||||
@@ -10,7 +10,7 @@ A tool registers on `ctx.tools`. The annotated `defineTool` example (typed `exec
|
||||
|
||||
## A hook plugin (permission-gate example)
|
||||
|
||||
This permission gate is one example of a hook plugin. It returns a typed decision from the `tools/pre-execute` gate to allow or deny a call; sandbox, permission, and plan-mode plugins can use this seam. Hook plugins can intercept other seams and are not inherently permission gates. A "native hook" is an ordinary Cordis plugin on an interception seam; it needs no external protocol.
|
||||
This permission gate is one example of a hook plugin. It returns a typed decision from the `tools/pre-execute` gate to allow or deny a call; sandbox, permission, and plan-mode plugins can use this extension point. Hook plugins can intercept other extension points and are not inherently permission gates. A "native hook" is an ordinary Cordis plugin on an interception point; it needs no external protocol.
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
@@ -34,7 +34,7 @@ This waterfall is the reorderable policy layer. Use `ctx.tools.guard()` when an
|
||||
|
||||
## A UI plugin
|
||||
|
||||
A UI plugin renders from the `session/event` feed (the assistant token stream as `assistant/chunk`, plus turn/step boundaries and tool activity), and drives input back in via `agent.followup()` / `agent.steer()`.
|
||||
A UI plugin renders from the `session/event` feed (the assistant token stream as `assistant/chunk`, plus turn/step boundaries and tool activity), and drives input back in via `agent.followup()` / `agent.steer()`. A browser plugin contributing a business row to the built-in Web Client instead registers a `ConversationNodeDefinition` and keyed Chat renderer; follow the [Conversation Node guide](adding-a-conversation-node.md).
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
@@ -94,18 +94,18 @@ Runnable leaves load their plugin trees from `examples/*/cordis.yml`; the root `
|
||||
|
||||
## The feature → mechanism map
|
||||
|
||||
Every product feature maps to a listener on a documented extension seam — the microkernel claim made checkable ([microkernel Agent Note](../../.agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.md)). No row modifies the loop.
|
||||
Every product feature maps to a listener on a documented extension point — the microkernel claim made checkable ([microkernel Agent Note](../../.agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.md)). No row modifies the loop.
|
||||
|
||||
`system-prompt/assemble` is an expert cooperative whole-assembly transform: its returned assembly is authoritative, so listener authors own preserving active Code Mode and structured-output protocol contributions. Prefer `ctx.tools.restrict()` for tool filtering that must stay aligned across presentation, lookup, and execution.
|
||||
|
||||
| Product feature | Plugin mechanism |
|
||||
|---|---|
|
||||
| Hook system (user + project level) | listeners on `agent/session-start`, `agent/pre-step`, `agent/request`, `tools/pre-execute`, `tools/post-execute`, and `agent/turn-stopping`; the waterfall seams return typed decisions, while `agent/turn-stopping` may steer another step; the `dsh-hooks-claude` / `dsh-hooks-codex` bridges map hook config files onto these seams |
|
||||
| Hook system (user + project level) | listeners on `agent/session-start`, `agent/pre-step`, `agent/request`, `tools/pre-execute`, `tools/post-execute`, and `agent/turn-stopping`; the waterfalls return typed decisions, while `agent/turn-stopping` may steer another step; the `dsh-hooks-claude` / `dsh-hooks-codex` bridges map hook config files onto these extension points |
|
||||
| `/goal` | `ctx.goals` owns durable state, `dsh-goal-session` schedules same-session rounds through the public `Agent`, and separate command/tool producers expose human/model control |
|
||||
| `/loop` | on the `turn/end` session event, `followup()` the next iteration; or force-continue |
|
||||
| Dynamic workflow | `ctx.workflows` + the worker-thread engine + the `workflow` tool; structured in-process children enforce output with scoped prompt/tool registrations, a monotonic tool guard, final `tools/result` commit (including enclosing `run_code`), and the structured-output execution's monotonic `concludeTurn()` marker |
|
||||
| Queued + steering messages | core `Agent.followup()` / `Agent.steer()` |
|
||||
| Context compaction (auto + manual) | the `ctx.compact` seam + `dsh-compact-basic`; automatic pressure runs on serial `agent/pre-step`, canonical overflow recovery runs on `agent/request-error`, and manual callers use the same compact service ([compaction Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md) — the model-facing `/compact` consumer tool is deferred) |
|
||||
| Context compaction (auto + manual) | the `ctx.compact` seam + `dsh-compact-basic`; automatic pressure runs on serial `agent/pre-step`, canonical overflow recovery runs on `agent/request-error`, and manual callers use the same compact service ([compaction Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md)) |
|
||||
| System prompt configurability | `ctx.systemPrompt.section()` with ordering and scope-local shadowing |
|
||||
| AGENTS.md (root) | a section provider reading the file |
|
||||
| AGENTS.md (subdir, on-touch) + file-change notices | `agent.inject()` from a watcher / tool-result listener |
|
||||
@@ -116,13 +116,14 @@ Every product feature maps to a listener on a documented extension seam — the
|
||||
| Monotonic terminal turn policy | call `ToolExecution.concludeTurn()` from the successful terminal tool; later tool calls in the same response remain guardable, and the loop stops after the step |
|
||||
| Subprocess sandbox (landlock / sandbox-exec) | use a `ctx.sandbox` backend through `dsh-bash-sandbox`; use `tools/pre-execute` for capability-level denial |
|
||||
| Permission system / AskUserQuestion | return `ask` from `tools/pre-execute` and answer through `ctx.approval`; register a separate model-facing ask tool for ordinary user questions |
|
||||
| Plan mode | Shipped: [`@deepseek-ai/dsh-plan-mode`](../../packages/plan/plan-mode/README.md) — logged `plan/mode` state, the `plan:policy` guidance section, `/plan [message]` entry, `/plan off` direct exit, and the user-reviewed `exit_plan_mode` exit; enforcement stays on the independent sandbox/approval axes |
|
||||
| Plan mode | [`@deepseek-ai/dsh-plan-mode`](../../packages/plan/plan-mode/README.md) — logged `plan/mode` state, the `plan:policy` guidance section, `/plan [message]` entry, `/plan off` direct exit, and the user-reviewed `exit_plan_mode` exit; enforcement stays on the independent sandbox/approval axes |
|
||||
| Sub-agent delegation | the `ctx.subagents` provider registry (`dsh-subagent-spawn`/`-fork`/`-acp`/`-codex`/`-claude-code`/`-dsh-sdk`) + `dsh-tool-subagent` exposing one configured provider to the model |
|
||||
| MCP | one plugin per server: discover tools → `ctx.tools.register()` |
|
||||
| Skills | section + tool registration; `inject()` skill content on invocation |
|
||||
| Memory | section provider + tool |
|
||||
| Scheduled tasks (cron) | a plugin registers model-callable scheduling tools; timer fires → `followup(…, {source: {kind: 'cron', …}})` when idle / `inject()` notification when busy |
|
||||
| UI (GUI; CLI emits JSONL) | listen `session/event` (assistant chunks, boundaries, tool activity); input → `followup()` |
|
||||
| Web Client Chat business node | register a `ConversationNodeDefinition` and `conversation.chat.node` keyed renderer |
|
||||
| Telemetry / replayable trace | `session/event` → JSONL; replay = `sessions.create(id, { seed })` |
|
||||
| Model adapters | `LlmAdapter` subclass via `registerAdapter` (`dsh-llm-deepseek`, `dsh-llm-pi-ai`) |
|
||||
| Plugin hot-reload | every registration is a `ctx.effect` → vendored HMR just works |
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
[English](extension-cookbook.md) | 中文
|
||||
|
||||
harness 扩展表面的参考形态。代码片段省略了 import 和辅助实现,无法直接复制运行。具体编写路径见[包检查清单](adding-a-package.md)、[第一个工具教程](../user/develop/basic/tool.md)、[工具参考](adding-a-tool.md)和 [LLM(大语言模型)适配器指南](adding-an-llm-adapter.md);系统与扩展 seam 映射由[架构文档](../architecture.md)负责。
|
||||
harness 扩展表面的参考形态。代码片段省略了 import 和辅助实现,无法直接复制运行。具体编写路径见[包检查清单](adding-a-package.md)、[第一个工具教程](../user/develop/basic/tool.md)、[工具参考](adding-a-tool.md)和 [LLM(大语言模型)适配器指南](adding-an-llm-adapter.md);系统与扩展点映射由[架构文档](../architecture.md)负责。
|
||||
|
||||
## 工具插件
|
||||
|
||||
工具在 `ctx.tools` 上注册。带注解的 `defineTool` 示例(类型化的 `execute` 参数、结果塑形、`run_in_background` 模式)见 [adding-a-tool.md](adding-a-tool.md)——该指南是工具形态的真源。`ctx.tools.register()` 也直接接受原始 JSON-Schema `ToolDefinition`(MCP 来源的工具就是这样到达的);`defineTool` 是为第一方工具提供的类型化语法糖。
|
||||
工具在 `ctx.tools` 上注册。带注解的 `defineTool` 示例(类型化的 `execute` 参数、结果塑形、`run_in_background` 模式)见 [adding-a-tool.md](adding-a-tool.md)——该指南是工具形态的真源。`ctx.tools.register()` 也直接接受原始 JSON Schema `ToolDefinition`(MCP 来源的工具就是这样到达的);`defineTool` 是为第一方工具提供的类型化语法糖。
|
||||
|
||||
## 钩子插件(以权限门禁为例)
|
||||
|
||||
这个权限门禁是钩子插件的一个示例。它从 `tools/pre-execute` 门禁返回一个类型化的决策,用于允许或拒绝一次调用;沙箱、权限和 plan-mode 插件都可以使用该 seam。钩子插件也可以拦截其他 seam,本身并不等同于权限门禁。「原生钩子」是在拦截 seam 上运行的普通 Cordis 插件,不需要外部协议。
|
||||
这个权限门禁是钩子插件的一个示例。它从 `tools/pre-execute` 门禁返回一个类型化的决策,用于允许或拒绝一次调用;沙箱、权限和 plan-mode 插件都可以使用该扩展点。钩子插件也可以拦截其他扩展点,本身并不等同于权限门禁。「原生钩子」是在拦截点上运行的普通 Cordis 插件,不需要外部协议。
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
@@ -34,7 +34,7 @@ export function apply(ctx: Context) {
|
||||
|
||||
## UI 插件
|
||||
|
||||
UI 插件从 `session/event` 事件流渲染(助手 token 流以 `assistant/chunk` 形式到达,加上轮次/步骤边界与工具活动),并通过 `agent.followup()` / `agent.steer()` 将输入驱动回去。
|
||||
UI 插件从 `session/event` 事件流渲染(助手 token 流以 `assistant/chunk` 形式到达,加上轮次/步骤边界与工具活动),并通过 `agent.followup()` / `agent.steer()` 将输入驱动回去。如果浏览器插件要向内建 Web Client 贡献业务行,则应注册 `ConversationNodeDefinition` 与 keyed Chat renderer;具体步骤见 [Conversation Node 指南](adding-a-conversation-node.md)。
|
||||
|
||||
```ts
|
||||
import type { Context } from 'cordis'
|
||||
@@ -94,35 +94,36 @@ export function apply(ctx: Context) {
|
||||
|
||||
## 功能→机制映射
|
||||
|
||||
每个产品功能都映射到一个文档化扩展 seam 上的监听器——微内核声明由此可验证([微内核 Agent Note](../../.agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.md))。没有任何一行修改循环本身。
|
||||
每个产品功能都映射到一个文档化扩展点上的监听器——微内核声明由此可验证([微内核 Agent Note](../../.agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.md))。没有任何一行修改循环本身。
|
||||
|
||||
`system-prompt/assemble` 是一个专家协作式的整体装配变换:其返回的装配结果具有权威性,因此监听器作者有责任保留活跃的 Code Mode 和结构化输出协议的贡献。对于需要在展示、查找和执行之间保持对齐的工具过滤,优先使用 `ctx.tools.restrict()`。
|
||||
|
||||
| 产品功能 | 插件机制 |
|
||||
|---|---|
|
||||
| 钩子系统(用户级 + 项目级) | `agent/session-start`、`agent/pre-step`、`agent/request`、`tools/pre-execute`、`tools/post-execute` 和 `agent/turn-stopping` 上的监听器;waterfall seam 返回类型化决策,`agent/turn-stopping` 则可通过 steering 触发下一步;`dsh-hooks-claude` / `dsh-hooks-codex` 桥接器将钩子配置文件映射到这些 seam 上 |
|
||||
| `/goal` | `ctx.goals` 管理持久状态,`dsh-goal-session` 通过公共 `Agent` 调度同会话回合,独立的命令/工具生产方分别提供人类/模型控制 |
|
||||
| 钩子系统(用户级 + 项目级) | `agent/session-start`、`agent/pre-step`、`agent/request`、`tools/pre-execute`、`tools/post-execute` 和 `agent/turn-stopping` 上的监听器;waterfall 返回类型化决策,`agent/turn-stopping` 则可通过 steering(中途引导)触发下一步;`dsh-hooks-claude` / `dsh-hooks-codex` 桥接器将钩子配置文件映射到这些扩展点上 |
|
||||
| `/goal` | `ctx.goals` 管理持久状态,`dsh-goal-session` 通过公共 `Agent` 调度同会话 Round,独立的命令/工具生产方分别提供人类/模型控制 |
|
||||
| `/loop` | 在 `turn/end` 会话事件上 `followup()` 下一次迭代;或强制继续 |
|
||||
| 动态工作流 | `ctx.workflows` + worker-thread 引擎 + `workflow` 工具;结构化的进程内子任务通过作用域化的 prompt/工具注册、单调工具守卫、最终 `tools/result` 提交(包括外层 `run_code`)和结构化输出执行的单调 `concludeTurn()` 标记来强制输出 |
|
||||
| 排队消息 + steering(中途引导) | 核心 `Agent.followup()` / `Agent.steer()` |
|
||||
| 上下文压缩(context compaction)(自动 + 手动) | `ctx.compact` seam + `dsh-compact-basic`;自动压力检查运行在串行 `agent/pre-step`,规范化溢出恢复运行在 `agent/request-error`,手动调用方使用同一个压缩服务([压缩 Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md)——面向模型的 `/compact` 消费方工具已推迟) |
|
||||
| 动态工作流 | `ctx.workflows` + worker-thread 引擎 + `workflow` 工具;结构化的进程内子任务通过作用域化的提示词/工具注册、单调工具守卫、最终 `tools/result` 提交(包括外层 `run_code`)和结构化输出执行的单调 `concludeTurn()` 标记来强制输出 |
|
||||
| 排队消息 + steering | 核心 `Agent.followup()` / `Agent.steer()` |
|
||||
| 上下文压缩(context compaction)(自动 + 手动) | `ctx.compact` seam + `dsh-compact-basic`;自动压力检查运行在串行 `agent/pre-step`,规范化溢出恢复运行在 `agent/request-error`,手动调用方使用同一个压缩服务([压缩 Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md)) |
|
||||
| 系统提示词可配置性 | `ctx.systemPrompt.section()`,支持排序与作用域局部覆盖 |
|
||||
| AGENTS.md(根目录) | 一个读取该文件的 section provider |
|
||||
| AGENTS.md(子目录,按需触发)+ 文件变更通知 | 从 watcher / tool-result 监听器调用 `agent.inject()` |
|
||||
| AGENTS.md(根目录) | 一个读取该文件的 section 提供方 |
|
||||
| AGENTS.md(子目录,按需触发)+ 文件变更通知 | 从 watcher / 工具结果监听器调用 `agent.inject()` |
|
||||
| 内置工具 | `ctx.tools.register()`;schema 自动流入装配——`dsh-tool-*` 系列(bash、fs、web、subagent、todo)是已交付的示例 |
|
||||
| ToolSearch / 渐进式披露 | 当可见集变化时替换一个作用域化的 `ctx.tools.restrict()` 注册;注册表保持展示、查找和执行三者对齐 |
|
||||
| 工具截止时间 / 重试 / 指标 | 用 `tools/execute` 包裹核心分发;包装器可替换 `exec.signal`、委托执行,并在同一词法生命周期内检视规范化结果 |
|
||||
| 工具截止时间 / 重试 / 指标 | 用 `tools/execute` 包裹核心分发;包装层可替换 `exec.signal`、委托执行,并在同一词法生命周期内检视规范化结果 |
|
||||
| 最终工具结果指标 / 审计 / 捕获 | 用 `tools/result` 观察不可变的权威结果;仅当插件需要变换结果或附加上下文时才使用 `tools/post-execute` |
|
||||
| 单调终端轮次策略 | 从成功的终端工具调用 `ToolExecution.concludeTurn()`;同一响应中后续工具调用仍可由守卫阻止,循环在该步骤后停止 |
|
||||
| 子进程沙箱(landlock / sandbox-exec) | 通过 `dsh-bash-sandbox` 使用 `ctx.sandbox` 后端;能力级别的拒绝使用 `tools/pre-execute` |
|
||||
| 权限系统 / AskUserQuestion | 从 `tools/pre-execute` 返回 `ask` 并通过 `ctx.approval` 应答;为普通用户提问注册一个独立的面向模型的 ask 工具 |
|
||||
| Plan mode | 已交付:[`@deepseek-ai/dsh-plan-mode`](../../packages/plan/plan-mode/README.md) — 落日志的 `plan/mode` 状态、`plan:policy` 引导段、`/plan [message]` 入口、`/plan off` 直接退出,以及经用户评审的 `exit_plan_mode` 出口;强制约束留在独立的沙箱/审批轴上 |
|
||||
| 子 agent 委派 | `ctx.subagents` 提供方注册表(`dsh-subagent-spawn`/`-fork`/`-acp`/`-codex`/`-claude-code`/`-dsh-sdk`)+ `dsh-tool-subagent` 向模型暴露一个已配置的提供方 |
|
||||
| Plan mode | [`@deepseek-ai/dsh-plan-mode`](../../packages/plan/plan-mode/README.md):落日志的 `plan/mode` 状态、`plan:policy` 引导段、`/plan [message]` 入口、`/plan off` 直接退出,以及经用户评审的 `exit_plan_mode` 出口;强制约束留在独立的沙箱/审批轴上 |
|
||||
| subagent 委派 | `ctx.subagents` 提供方注册表(`dsh-subagent-spawn`/`-fork`/`-acp`/`-codex`/`-claude-code`/`-dsh-sdk`)+ `dsh-tool-subagent` 向模型暴露一个已配置的提供方 |
|
||||
| MCP | 每个服务器一个插件:发现工具 → `ctx.tools.register()` |
|
||||
| Skill(技能) | section + 工具注册;调用时通过 `inject()` 注入 skill 内容 |
|
||||
| 记忆 | section provider + 工具 |
|
||||
| skill(技能) | section + 工具注册;调用时通过 `inject()` 注入 skill 内容 |
|
||||
| 记忆 | section 提供方 + 工具 |
|
||||
| 定时任务(cron) | 插件注册面向模型的调度工具;定时器触发 → 空闲时 `followup(…, {source: {kind: 'cron', …}})`/忙碌时 `inject()` 通知 |
|
||||
| UI(GUI;CLI(命令行界面)输出 JSONL) | 监听 `session/event`(助手分片、边界、工具活动);输入 → `followup()` |
|
||||
| Web Client Chat 业务节点 | 注册 `ConversationNodeDefinition` 与 `conversation.chat.node` keyed renderer |
|
||||
| 遥测 / 可回放 trace | `session/event` → JSONL;回放 = `sessions.create(id, { seed })` |
|
||||
| 模型适配器 | 通过 `registerAdapter` 注册 `LlmAdapter` 子类(`dsh-llm-deepseek`、`dsh-llm-pi-ai`) |
|
||||
| 插件热重载 | 每个注册都是一个 `ctx.effect` → vendor 的 HMR(热模块替换)直接生效 |
|
||||
| 插件热重载 | 每个注册都是一个 `ctx.effect` → 随仓库提供的 HMR(热模块替换)直接生效 |
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cookbook/maintaining-dsh-code-review.md
|
||||
maintaining-dsh-code-review.md: 2b5d0d926ae922f2650daac33cf35991cb71c5e5
|
||||
maintaining-dsh-code-review.zh.md: 4466565b294ede89fa34da9e76b88f4ac39748eb
|
||||
maintaining-dsh-code-review.md: c8517054434f4b090c67455cda0a992c2c3173ee
|
||||
maintaining-dsh-code-review.zh.md: 3d26d540a41661aa45b41d6738118f36d904ccf3
|
||||
|
||||
@@ -6,11 +6,11 @@ The [`dsh-code-review`](../../.agents/skills/dsh-code-review/SKILL.md) skill is
|
||||
|
||||
## What the maintainer receives
|
||||
|
||||
Run the private tool daily with a two-UTC-day overlap; until the proposed scheduler has completed its acceptance run, the operator invokes the wrapper manually at the same cadence. A manual weekly recovery run uses a seven-day window. The workflow:
|
||||
The operator invokes the wrapper manually, daily with a two-UTC-day overlap; a manual weekly recovery run uses a seven-day window. The workflow:
|
||||
|
||||
1. It selects PRs merged in the chosen window (default two UTC days for the daily cadence, seven for weekly) whose merge commit is reachable from `origin/master`. PRs whose merge commit is not reachable (stacked branches whose parent was squashed) or that exceed a 250-commit acquisition cap are logged to `skipped-pulls.json` and skipped rather than aborting the run.
|
||||
2. It collects pre-merge human review feedback with commit anchors (inline comments and review submissions), then compares feedback-time and final landed PR patches. It does not acquire PR conversation comments because current GitHub state cannot give them a force-push-safe feedback-time baseline, and it excludes target-branch-only changes from adoption evidence.
|
||||
3. Two independently configured reviewer adapters classify provenance and adoption, then classify agreed-adopted items against the current skill.
|
||||
3. Two independently configured reviewer adapters classify who wrote each item and whether the change adopted it, then classify agreed-adopted items against the current skill.
|
||||
4. The primary adapter drafts a complete revised `SKILL.md`; both adapters review the same diff; blocking findings loop until both approve.
|
||||
5. `pnpm run doc-sync` and `pnpm run lint` run against the candidate before the tool declares success.
|
||||
|
||||
@@ -38,7 +38,7 @@ When a run produces a candidate, a macOS notification arrives with a `dsh-code-r
|
||||
rm ~/dsh-code-review-outputs/2026-07-16T02-00-00Z.{diff,SKILL.md,manifest.json}
|
||||
```
|
||||
- **Batch.** Keep the candidate aside if the update is small and could combine with a future one. The source-skill check still applies; rerun the analysis or manually rebase and re-review the diff if `master` changes first.
|
||||
- **Promote.** From a clean `master` checkout of the repo, run the promote helper. It refreshes `master`, verifies that the current skill matches the recorded source blob, applies the saved diff, and opens a draft PR whose body carries the manifest's provenance summary. It stops on skill drift rather than overwriting newer guidance; the operator still reviews the PR on GitHub and either merges it or closes it.
|
||||
- **Promote.** From a clean `master` checkout of the repo, run the promote helper. It refreshes `master`, verifies that the current skill matches the recorded source blob, applies the saved diff, and opens a draft PR whose body lists the source feedback URLs or IDs, landed commit range, originating run, checks, and operator edits. It stops on skill drift rather than overwriting newer guidance; the operator still reviews the PR on GitHub and either merges it or closes it.
|
||||
|
||||
```sh
|
||||
cd ~/path/to/deepseek-harness # clean master
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
## 维护者会收到什么
|
||||
|
||||
每天运行私有工具,并使用 2 个 UTC 日的重叠窗口;在拟议的调度器完成验收运行之前,操作员按相同频率手动调用包装脚本。每周手动恢复运行使用 7 日窗口。工作流会:
|
||||
操作员每天手动调用包装脚本,并使用 2 个 UTC 日的重叠窗口;每周手动恢复运行使用 7 日窗口。工作流会:
|
||||
|
||||
1. 选择指定窗口内合并、且合并 commit 可从 `origin/master` 到达的 PR(每天运行默认选择 2 个 UTC 日,每周运行选择 7 日)。合并 commit 无法到达的 PR(例如父分支被 squash 的堆叠分支),或超出 250 个 commit 获取上限的 PR,会记录到 `skipped-pulls.json` 并跳过,不会中止本次运行。
|
||||
2. 收集合并前带 commit 锚点的人工评审反馈(行内评论和评审提交),然后比较反馈时与最终落地的 PR patch。它不获取 PR 会话评论,因为 GitHub 当前状态无法为这些评论提供可抵抗 force-push 的反馈时基线;它也不会把只存在于目标分支的变更作为采纳证据。
|
||||
3. 两个独立配置的评审适配器先对来源和采纳情况分类,再根据当前 skill 对双方一致认定已采纳的条目分类。
|
||||
3. 两个独立配置的评审适配器先对每个条目的作者以及更改是否采纳了它进行分类,再根据当前 skill 对双方一致认定已采纳的条目分类。
|
||||
4. 主适配器起草完整修订版 `SKILL.md`;两个适配器评审同一份 diff;只要仍有阻塞性问题,循环就会继续,直到双方批准。
|
||||
5. 工具声明成功前,会针对候选版本运行 `pnpm run doc-sync` 和 `pnpm run lint`。
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
rm ~/dsh-code-review-outputs/2026-07-16T02-00-00Z.{diff,SKILL.md,manifest.json}
|
||||
```
|
||||
- **留待成批处理。** 如果更新很小,可以把候选版本留待与后续版本合并。源 skill 检查仍然适用;如果 `master` 先发生变化,请重新运行分析,或手动 rebase 并重新评审 diff。
|
||||
- **提升。** 在仓库的干净 `master` checkout 中运行提升辅助工具。它会刷新 `master`、验证当前 skill 与记录的源 blob 一致、应用保存的 diff,并创建一份 draft PR,其正文包含 manifest 的来源摘要。如果 skill 已发生漂移,它会停止而不是覆盖更新后的指导;操作员仍需在 GitHub 上评审 PR,并选择合并或关闭。
|
||||
- **提升。** 在仓库的干净 `master` checkout 中运行提升辅助工具。它会刷新 `master`、验证当前 skill 与记录的源 blob 一致、应用保存的 diff,并创建一份 draft PR,其正文列出原始反馈的 URL 或 ID、已落地的 commit 范围、发起这次更改的运行、检查以及操作员编辑。如果 skill 已发生漂移,它会停止而不是覆盖更新后的指导;操作员仍需在 GitHub 上评审 PR,并选择合并或关闭。
|
||||
|
||||
```sh
|
||||
cd ~/path/to/deepseek-harness # clean master
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cookbook/responding-to-pr-review-on-a-stack.md
|
||||
responding-to-pr-review-on-a-stack.md: 6bb7be3daf8613666f02f21e96bf7b1ac8cb3606
|
||||
responding-to-pr-review-on-a-stack.zh.md: 94c2bd2cdd03b9eeca1e180b09bb71471db91c0a
|
||||
responding-to-pr-review-on-a-stack.zh.md: cd4984a09a8bdc1ab38fe2bbe54e669bff18230f
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
## 沿堆叠解决评审意见
|
||||
|
||||
1. 在行动之前先就事论事地审视每条评论:对照代码验证其论断——评审者指出了正确的症状,但仍可能误诊原因。
|
||||
2. 将每个被接受的发现映射到其发起 PR,并在那里修复。
|
||||
2. 将每个被接受的发现映射到引入该问题的 PR,并在那里修复。
|
||||
3. 将修复后的层按顺序传播到每个受影响的子 PR:
|
||||
- **Merge-forward:** 将修复后的父分支合并到其子分支,验证子分支,然后继续沿堆叠向上传播。依照[增量更新 base 的决策](../../.agents/notes/implemented/process/2026-07-26-incremental-pr-base-retargeting.md),保留每个正在处理的检查点。
|
||||
- **原生级联 rebase:** 使用 `gh stack rebase`,验证所有已改写的层,然后通过 `gh stack push` 发布;也可以使用 `gh stack sync`,该命令可能先发布,因此必须按照 [dsh-pre-push-checks](../../.agents/skills/dsh-pre-push-checks/SKILL.md) 在同步后立即验证。
|
||||
4. 委派的修复需要信任但验证:子 agent(智能体)的报告描述的是意图,不一定是实际落地的内容。请亲自在实际代码树上重新运行门禁;对于回归守卫,要证明它在未修复的代码上**失败**(引入回归、观察变红、再还原)——两种情况都通过的守卫什么也守不住。子 agent 将问题重新定性为「已处理」时,这是一个需要亲自深入的信号。
|
||||
4. 委派的修复需要信任但验证:subagent 的报告描述的是意图,不一定是实际落地的内容。请亲自在实际代码树上重新运行门禁;对于回归守卫,要证明它在未修复的代码上**失败**(引入回归、观察变红、再还原)——两种情况都通过的守卫什么也守不住。subagent 将问题重新定性为「已处理」时,这是一个需要亲自深入的信号。
|
||||
5. 在评审线程中回复(`gh api repos/{owner}/{repo}/pulls/{pr}/comments/{id}/replies`),而非发顶层评论;说明修复内容及当前承载修复的 commit 或 head。
|
||||
6. 每次改写推送后,都要重新读取未解决线程、批准状态、可合并性和检查结果。经 force-push 改写的 commit OID 或已过时的内联锚点,都不足以证明该发现当前仍处于已解决状态。
|
||||
7. 仅可通过官方堆叠流程落地。如果这些 PR 尚未关联,落地 skill 会自动关联作者相同的链;如果作者不同,则先询问用户;如果原生堆叠支持不可用,则硬性停止流程。
|
||||
|
||||
6
docs/cordis-api/context.i18n.yaml
Normal file
6
docs/cordis-api/context.i18n.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-api/context.md
|
||||
context.md: 320b23de1c8d19e2dacdf0ec9f2361037bcf8048
|
||||
context.zh.md: 9b1f92a329ff4d75b3fafe7bf6bc8db317bcc267
|
||||
366
docs/cordis-api/context.zh.md
Normal file
366
docs/cordis-api/context.zh.md
Normal file
@@ -0,0 +1,366 @@
|
||||
<!-- 英文源文件由 scripts/gen-cordis-catalog.ts 生成;本中文文件是通过双语配对维护的经评审对侧。
|
||||
更新时先运行 `pnpm run gen-cordis-catalog` 更新英文,再更新本文件并运行 `pnpm run verify-translation-pairing --write docs/cordis-api/context.md` 重新记录配对。 -->
|
||||
|
||||
# 上下文
|
||||
|
||||
[English](context.md) | 中文
|
||||
|
||||
上下文是 Cordis 的核心对象:所有服务、事件和生命周期 API 都通过 `ctx` 访问。事件方法见[事件](events.md),副作用与当前 fiber 见 [Fiber](fiber.md),插件加载见[注册表](registry.md)。
|
||||
|
||||
Cordis 插件的根依赖容器和子依赖容器。
|
||||
|
||||
上下文是一个代理:普通属性读取通过服务解析器进行,而 `extend()`、`isolate()` 和 `intercept()` 会创建有作用域的子上下文,且不修改其父上下文。
|
||||
|
||||
[源码](../../vendor/cordis/src/context.ts#L42)
|
||||
|
||||
### ctx.extend(meta?)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Create a child context with extra metadata on top of the current scope.
|
||||
*
|
||||
* The child prototypally inherits every property of this context; own
|
||||
* properties of `meta` shadow the inherited ones. The parent is not mutated.
|
||||
*
|
||||
* @param meta — own properties (including symbol keys) to define on the child.
|
||||
* @returns a child context inheriting from this one.
|
||||
*/
|
||||
extend(meta = {}): this
|
||||
```
|
||||
|
||||
在当前作用域之上创建一个带有额外元数据的子上下文。
|
||||
|
||||
子上下文通过原型继承当前上下文的所有属性;`meta` 的自有属性会遮蔽继承的同名属性。父上下文不会被修改。
|
||||
|
||||
- `meta`:要在子上下文上定义的自有属性,包括以 symbol 为键的属性。
|
||||
|
||||
**返回**继承自当前上下文的子上下文。
|
||||
|
||||
[源码](../../vendor/cordis/src/context.ts#L99)
|
||||
|
||||
### ctx.isolate(name, label?)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Create a child context with an independent service scope for `name`.
|
||||
*
|
||||
* Below the returned context, reads and writes of the service `name`
|
||||
* resolve against the new label instead of the parent's, so a different
|
||||
* implementation can be provided without affecting the parent scope.
|
||||
* Passing the same `label` to two `isolate()` calls joins their scopes.
|
||||
*
|
||||
* @param name — the service name to isolate.
|
||||
* @param label — scope label to join; defaults to a fresh unique symbol.
|
||||
* @returns a child context whose `name` service resolves in the new scope.
|
||||
*/
|
||||
isolate(name: string, label?: symbol)
|
||||
```
|
||||
|
||||
创建一个子上下文,使 `name` 拥有独立的服务作用域。
|
||||
|
||||
在返回的上下文之下,对服务 `name` 的读写会根据新标签解析,而不再根据父上下文的标签解析,因此可以提供不同的实现而不影响父作用域。将同一个 `label` 传给两次 `isolate()` 调用,可使二者加入同一作用域。
|
||||
|
||||
- `name`:要隔离的服务名称。
|
||||
- `label`:要加入的作用域标签;默认为一个新建的唯一 symbol。
|
||||
|
||||
**返回**一个子上下文,其 `name` 服务在新作用域中解析。
|
||||
|
||||
[源码](../../vendor/cordis/src/context.ts#L121)
|
||||
|
||||
### ctx.intercept(name, config)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Add service-specific intercept config for plugins started below this
|
||||
* context.
|
||||
*
|
||||
* Plugins loaded under the returned context see `config` merged into the
|
||||
* service's resolved config (ancestor entries first; see
|
||||
* `Service[symbols.resolveConfig]`). The parent context is not affected.
|
||||
*
|
||||
* @param name — the service name whose config to intercept.
|
||||
* @param config — the intercept config to merge for that service.
|
||||
* @returns a child context carrying the additional intercept entry.
|
||||
*/
|
||||
intercept<K extends InjectKey>(name: K, config: Context[K] extends { [symbols.config]: infer T } ? T : never): this
|
||||
intercept(name: string, config: any): this
|
||||
```
|
||||
|
||||
为在此上下文之下启动的插件添加服务专属的拦截配置。
|
||||
|
||||
在返回的上下文下加载的插件会看到 `config` 已合并到服务解析后的配置中(祖先条目在前;见 `Service[symbols.resolveConfig]`)。父上下文不受影响。
|
||||
|
||||
- `name`:要拦截其配置的服务名称。
|
||||
- `config`:要为该服务合并的拦截配置。
|
||||
|
||||
**返回**一个携带额外拦截条目的子上下文。
|
||||
|
||||
[源码](../../vendor/cordis/src/context.ts#L139)
|
||||
|
||||
### ctx.root
|
||||
|
||||
```ts cordis-catalog
|
||||
/** The root context of the application (every child context shares it). @experimental */
|
||||
root: this
|
||||
```
|
||||
|
||||
应用的根上下文,所有子上下文均共享它。@experimental
|
||||
|
||||
[源码](../../vendor/cordis/src/context.ts#L22)
|
||||
|
||||
### ctx.baseUrl
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Base URL used to resolve relative plugin/module specifiers, if the runtime sets one. */
|
||||
baseUrl?: string
|
||||
```
|
||||
|
||||
用于解析相对插件/模块说明符的基础 URL,前提是运行时设置了该值。
|
||||
|
||||
[源码](../../vendor/cordis/src/context.ts#L24)
|
||||
|
||||
### ctx.events
|
||||
|
||||
```ts cordis-catalog
|
||||
/** The event bus. Its methods are also mixed onto `ctx` (`ctx.on`, `ctx.emit`, ...). */
|
||||
events: EventsService
|
||||
```
|
||||
|
||||
事件总线。它的方法也会混入 `ctx`(`ctx.on`、`ctx.emit` 等)。
|
||||
|
||||
[源码](../../vendor/cordis/src/context.ts#L26)
|
||||
|
||||
### ctx.logger
|
||||
|
||||
```ts cordis-catalog
|
||||
/** The logging service. Call `ctx.logger(name)` for a named logger. */
|
||||
logger: LoggerService
|
||||
```
|
||||
|
||||
日志服务。调用 `ctx.logger(name)` 可获取具名 logger。
|
||||
|
||||
[源码](../../vendor/cordis/src/context.ts#L28)
|
||||
|
||||
### ctx.reflect
|
||||
|
||||
```ts cordis-catalog
|
||||
/** The reflection layer backing the context proxy (`ctx.get`, `ctx.provide`, ...). */
|
||||
reflect: ReflectService
|
||||
```
|
||||
|
||||
为上下文代理提供支持的反射层(`ctx.get`、`ctx.provide` 等)。
|
||||
|
||||
[源码](../../vendor/cordis/src/context.ts#L30)
|
||||
|
||||
### ctx.registry
|
||||
|
||||
```ts cordis-catalog
|
||||
/** The plugin registry. Its methods are mixed onto `ctx` (`ctx.plugin`, `ctx.inject`). */
|
||||
registry: RegistryService
|
||||
```
|
||||
|
||||
插件注册表。它的方法会混入 `ctx`(`ctx.plugin`、`ctx.inject`)。
|
||||
|
||||
[源码](../../vendor/cordis/src/context.ts#L32)
|
||||
|
||||
## 静态成员
|
||||
|
||||
### Context.effect
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Symbol key under which a disposer exposes its {@link EffectMeta} diagnostics tree. */
|
||||
static readonly effect: unique symbol
|
||||
```
|
||||
|
||||
资源释放函数用于公开其 EffectMeta 诊断树的 symbol 键。
|
||||
|
||||
[源码](../../vendor/cordis/src/context.ts#L44)
|
||||
|
||||
### Context.filter
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Symbol key for a context's listener filter, consulted on every event dispatch. */
|
||||
static readonly filter: unique symbol
|
||||
```
|
||||
|
||||
上下文监听器过滤器的 symbol 键,每次分派事件时都会查询该过滤器。
|
||||
|
||||
[源码](../../vendor/cordis/src/context.ts#L46)
|
||||
|
||||
### Context.isolate
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Symbol key of the isolation map (see the `Context[symbols.isolate]` property). */
|
||||
static readonly isolate: unique symbol
|
||||
```
|
||||
|
||||
隔离映射的 symbol 键(见 `Context[symbols.isolate]` 属性)。
|
||||
|
||||
[源码](../../vendor/cordis/src/context.ts#L48)
|
||||
|
||||
### Context.intercept
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Symbol key of the intercept map (see the `Context[symbols.intercept]` property). */
|
||||
static readonly intercept: unique symbol
|
||||
```
|
||||
|
||||
拦截映射的 symbol 键(见 `Context[symbols.intercept]` 属性)。
|
||||
|
||||
[源码](../../vendor/cordis/src/context.ts#L50)
|
||||
|
||||
### Context.is(value)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Returns true for Cordis context proxies and context prototypes.
|
||||
*
|
||||
* Works across realms and across multiple copies of cordis, because the
|
||||
* brand is keyed by a global symbol rather than by `instanceof`.
|
||||
*
|
||||
* @param value — the value to test.
|
||||
* @returns `true` if `value` is a Cordis context, narrowing its type.
|
||||
*/
|
||||
static is(value: any): value is Context
|
||||
```
|
||||
|
||||
对于 Cordis 上下文代理和上下文原型,返回 true。
|
||||
|
||||
此方法可跨 realm 和多个 cordis 副本工作,因为其品牌标识以全局 symbol 为键,而不是通过 `instanceof` 判断。
|
||||
|
||||
- `value`:要测试的值。
|
||||
|
||||
如果返回 `true`,则 `value` 是 Cordis 上下文,并会收窄其类型。
|
||||
|
||||
[源码](../../vendor/cordis/src/context.ts#L61)
|
||||
|
||||
## 服务存储与混入
|
||||
|
||||
### ctx.get(name, strict?)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Read a service from the store without the inject requirement.
|
||||
*
|
||||
* @param name — the service name.
|
||||
* @param strict — when `true` (default), only return implementations
|
||||
* whose providing fiber is currently active.
|
||||
* @returns the service value, or `undefined` when not (yet) provided.
|
||||
*/
|
||||
get<K extends string & keyof this>(name: K, strict?: boolean): undefined | this[K]
|
||||
get(name: string, strict?: boolean): any
|
||||
```
|
||||
|
||||
从存储中读取服务,无需满足注入要求。
|
||||
|
||||
- `name`:服务名称。
|
||||
- `strict`:设为 `true`(默认值)时,仅返回其提供方 fiber 当前处于活动状态的实现。
|
||||
|
||||
**返回**服务值;如果尚未提供,则返回 `undefined`。
|
||||
|
||||
[源码](../../vendor/cordis/src/reflect.ts#L17)
|
||||
|
||||
### ctx.set(name, value)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Overwrite a provided service's value.
|
||||
*
|
||||
* Only the fiber that provided the service may set it; setting an
|
||||
* unprovided name throws.
|
||||
*
|
||||
* @param name — the service name.
|
||||
* @param value — the new service value.
|
||||
*/
|
||||
set<K extends string & keyof this>(name: K, value: undefined | this[K]): void
|
||||
set(name: string, value: any): void
|
||||
```
|
||||
|
||||
覆盖已提供服务的值。
|
||||
|
||||
只有提供该服务的 fiber 才能设置它;设置尚未提供的名称会抛出异常。
|
||||
|
||||
- `name`:服务名称。
|
||||
- `value`:新的服务值。
|
||||
|
||||
[源码](../../vendor/cordis/src/reflect.ts#L29)
|
||||
|
||||
### ctx.provide(name, value)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Register a service implementation owned by the current fiber.
|
||||
*
|
||||
* The service becomes visible to dependents in the same isolation scope
|
||||
* once the fiber is active; it is unregistered (waking dependents) when
|
||||
* the returned disposer runs or the fiber unloads. Throws if the name is
|
||||
* already provided in this scope or declared as an accessor.
|
||||
*
|
||||
* @param name — the service name.
|
||||
* @param value — the service value.
|
||||
* @returns a disposer that unregisters the service.
|
||||
*/
|
||||
provide<K extends string & keyof this>(name: K, value: undefined | this[K]): () => void
|
||||
provide(name: string, value?: any): () => void
|
||||
```
|
||||
|
||||
注册一个归当前 fiber 所有的服务实现。
|
||||
|
||||
fiber 激活后,该服务对同一隔离作用域内的依赖方可见;当返回的资源释放函数运行或 fiber 卸载时,该服务会被取消注册,并唤醒依赖方。如果该名称已在此作用域中被提供,或已声明为访问器,则抛出异常。
|
||||
|
||||
- `name`:服务名称。
|
||||
- `value`:服务值。
|
||||
|
||||
**返回**一个用于取消注册该服务的资源释放函数。
|
||||
|
||||
[源码](../../vendor/cordis/src/reflect.ts#L44)
|
||||
|
||||
### ctx.accessor(name, options)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Define a computed context property backed by get/set hooks.
|
||||
*
|
||||
* The accessor is removed when the current fiber unloads. Throws if the
|
||||
* name is already declared.
|
||||
*
|
||||
* @param name — the context property name.
|
||||
* @param options — the `get` hook and optional `set` hook.
|
||||
*/
|
||||
accessor(name: string, options: Omit<Property.Accessor, 'type'>): void
|
||||
```
|
||||
|
||||
定义一个由 get/set 钩子支持的计算型上下文属性。
|
||||
|
||||
当前 fiber 卸载时会移除该访问器。如果该名称已被声明,则抛出异常。
|
||||
|
||||
- `name`:上下文属性名称。
|
||||
- `options`:`get` 钩子和可选的 `set` 钩子。
|
||||
|
||||
[源码](../../vendor/cordis/src/reflect.ts#L56)
|
||||
|
||||
### ctx.mixin(name, mixins)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Expose selected members of a service directly on `ctx`.
|
||||
*
|
||||
* Each mixed-in key becomes an accessor that forwards to the service
|
||||
* (binding methods to it), so e.g. `ctx.on` forwards to `ctx.events.on`.
|
||||
* Mixins are removed when the current fiber unloads.
|
||||
*
|
||||
* @param name — the context property holding the source service.
|
||||
* @param mixins — keys to forward, or a source-key → ctx-key map.
|
||||
*/
|
||||
mixin<K extends string & keyof this>(name: K, mixins: (keyof this & keyof this[K])[] | Dict<string>): void
|
||||
mixin<T extends {}>(source: T, mixins: (keyof this & keyof T)[] | Dict<string>): void
|
||||
```
|
||||
|
||||
直接在 `ctx` 上公开服务的指定成员。
|
||||
|
||||
每个混入的键都会成为一个转发到该服务的访问器,并将方法绑定到该服务。例如,`ctx.on` 会转发到 `ctx.events.on`。当前 fiber 卸载时会移除这些混入。
|
||||
|
||||
- `name`:存放源服务的上下文属性。
|
||||
- `mixins`:要转发的键,或从源键到 ctx 键的映射。
|
||||
|
||||
[源码](../../vendor/cordis/src/reflect.ts#L67)
|
||||
6
docs/cordis-api/events.i18n.yaml
Normal file
6
docs/cordis-api/events.i18n.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-api/events.md
|
||||
events.md: 8b8eb2358e10a250f581aecc725ba32360d338d3
|
||||
events.zh.md: 366f78fbe5d9bb5ff6f95c79c307237aaa97967a
|
||||
209
docs/cordis-api/events.zh.md
Normal file
209
docs/cordis-api/events.zh.md
Normal file
@@ -0,0 +1,209 @@
|
||||
<!-- 英文源文件由 scripts/gen-cordis-catalog.ts 生成;本中文文件是通过双语配对维护的经评审对侧。
|
||||
更新时先运行 `pnpm run gen-cordis-catalog` 更新英文,再更新本文件并运行 `pnpm run verify-translation-pairing --write docs/cordis-api/events.md` 重新记录配对。 -->
|
||||
|
||||
# 事件
|
||||
|
||||
[English](events.md) | 中文
|
||||
|
||||
每个上下文中都混入了事件分发 API。Harness 事件声明及其分发模式会生成到各自所属的[子系统页面](../subsystems/core.md)。
|
||||
|
||||
### ctx.parallel(name, ...args)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Dispatch an event, running all listeners concurrently.
|
||||
*
|
||||
* @param name — the event name.
|
||||
* @param args — arguments passed to every listener.
|
||||
* @returns a promise resolving once every listener has settled.
|
||||
*/
|
||||
parallel<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): Promise<void>
|
||||
parallel<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): Promise<void>
|
||||
```
|
||||
|
||||
分发一个事件,并发运行所有监听器。
|
||||
|
||||
- `name`:事件名称。
|
||||
- `args`:传递给每个监听器的参数。
|
||||
|
||||
**返回值**:一个 Promise,在所有监听器均已完成后兑现。
|
||||
|
||||
[源码](../../vendor/cordis/src/events.ts#L44)
|
||||
|
||||
### ctx.emit(name, ...args)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Dispatch an event synchronously, ignoring listener return values.
|
||||
*
|
||||
* @param name — the event name.
|
||||
* @param args — arguments passed to every listener.
|
||||
*/
|
||||
emit<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): void
|
||||
emit<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): void
|
||||
```
|
||||
|
||||
同步分发一个事件,忽略监听器的返回值。
|
||||
|
||||
- `name`:事件名称。
|
||||
- `args`:传递给每个监听器的参数。
|
||||
|
||||
[源码](../../vendor/cordis/src/events.ts#L53)
|
||||
|
||||
### ctx.serial(name, ...args)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Dispatch an event, awaiting listeners in order until one bails.
|
||||
*
|
||||
* @param name — the event name.
|
||||
* @param args — arguments passed to each listener.
|
||||
* @returns the first bail value (non-null, non-false, non-undefined), if any.
|
||||
*/
|
||||
serial<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): Promisify<ReturnType<Events[K]>>
|
||||
serial<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): Promisify<ReturnType<Events[K]>>
|
||||
```
|
||||
|
||||
分发一个事件,依次等待各监听器,直到其中一个提前终止分发。
|
||||
|
||||
- `name`:事件名称。
|
||||
- `args`:传递给每个监听器的参数。
|
||||
|
||||
**返回值**:第一个提前终止值(非 null、非 false 且非 undefined);如果没有,则不返回此类值。
|
||||
|
||||
[源码](../../vendor/cordis/src/events.ts#L63)
|
||||
|
||||
### ctx.bail(name, ...args)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Dispatch an event, calling listeners in order until one bails.
|
||||
*
|
||||
* @param name — the event name.
|
||||
* @param args — arguments passed to each listener.
|
||||
* @returns the first bail value (non-null, non-false, non-undefined), if any.
|
||||
*/
|
||||
bail<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>
|
||||
bail<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>
|
||||
```
|
||||
|
||||
分发一个事件,依次调用各监听器,直到其中一个提前终止分发。
|
||||
|
||||
- `name`:事件名称。
|
||||
- `args`:传递给每个监听器的参数。
|
||||
|
||||
**返回值**:第一个提前终止值(非 null、非 false 且非 undefined);如果没有,则不返回此类值。
|
||||
|
||||
[源码](../../vendor/cordis/src/events.ts#L73)
|
||||
|
||||
### ctx.waterfall(name, ...args)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Dispatch an event whose last argument is a `next` continuation.
|
||||
*
|
||||
* Each listener wraps the rest of the chain: calling `next()` invokes the
|
||||
* next listener (finally the built-in behavior); not calling it vetoes.
|
||||
*
|
||||
* @param name — the event name.
|
||||
* @param args — listener arguments; the final one is the innermost `next`.
|
||||
* @returns the outermost listener's return value.
|
||||
*/
|
||||
waterfall<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>
|
||||
waterfall<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>
|
||||
```
|
||||
|
||||
分发一个事件,其最后一个参数是续接执行的 `next` 回调。
|
||||
|
||||
每个监听器都会包装调用链的其余部分:调用 `next()` 会执行下一个监听器,最终执行内置行为;不调用则会否决后续执行。
|
||||
|
||||
- `name`:事件名称。
|
||||
- `args`:监听器参数;最后一个参数是最内层的 `next`。
|
||||
|
||||
**返回值**:最外层监听器的返回值。
|
||||
|
||||
[源码](../../vendor/cordis/src/events.ts#L86)
|
||||
|
||||
### ctx.on(name, listener, options?)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Register an event listener owned by the current fiber.
|
||||
*
|
||||
* @param name — the event name to listen for.
|
||||
* @param listener — called with the dispatch arguments.
|
||||
* @param options — listener options; a boolean is shorthand for `prepend`.
|
||||
* @returns a disposer removing the listener; `true` if it was still registered.
|
||||
*/
|
||||
on<K extends keyof Events>(name: K, listener: Events[K], options?: boolean | EventOptions): () => boolean
|
||||
```
|
||||
|
||||
注册一个归当前 fiber 所有的事件监听器。
|
||||
|
||||
- `name`:要监听的事件名称。
|
||||
- `listener`:使用分发参数调用的监听器。
|
||||
- `options`:监听器选项;布尔值可作为 `prepend` 的简写。
|
||||
|
||||
**返回值**:一个用于移除监听器的资源释放函数;如果调用该函数时监听器仍处于注册状态,则返回 `true`。
|
||||
|
||||
[源码](../../vendor/cordis/src/events.ts#L97)
|
||||
|
||||
### ctx.once(name, listener, options?)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Same as `on()`, but the listener disposes itself after its first call.
|
||||
*
|
||||
* @param name — the event name to listen for.
|
||||
* @param listener — called at most once with the dispatch arguments.
|
||||
* @param options — listener options; a boolean is shorthand for `prepend`.
|
||||
* @returns a disposer removing the listener; `true` if it was still registered.
|
||||
*/
|
||||
once<K extends keyof Events>(name: K, listener: Events[K], options?: boolean | EventOptions): () => boolean
|
||||
```
|
||||
|
||||
与 `on()` 相同,但监听器在首次调用后会自行注销。
|
||||
|
||||
- `name`:要监听的事件名称。
|
||||
- `listener`:使用分发参数调用,最多调用一次。
|
||||
- `options`:监听器选项;布尔值可作为 `prepend` 的简写。
|
||||
|
||||
**返回值**:一个用于移除监听器的资源释放函数;如果调用该函数时监听器仍处于注册状态,则返回 `true`。
|
||||
|
||||
[源码](../../vendor/cordis/src/events.ts#L106)
|
||||
|
||||
## EventOptions
|
||||
|
||||
`ctx.on()` 和 `ctx.once()` 接受的选项。
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Options accepted by `ctx.on()` and `ctx.once()`. */
|
||||
interface EventOptions {
|
||||
/** Add the listener before existing listeners for the same event. */
|
||||
prepend?: boolean
|
||||
/** Receive the event regardless of context filter checks. */
|
||||
global?: boolean
|
||||
}
|
||||
```
|
||||
|
||||
[源码](../../vendor/cordis/src/events.ts#L112)
|
||||
|
||||
## DispatchMode
|
||||
|
||||
事件服务使用的事件分发策略。
|
||||
|
||||
`emit` 运行同步监听器但不等待它们,`parallel` 同时等待所有监听器,`serial` 依次等待监听器直至其中一个提前终止分发,`bail` 遇到第一个同步提前终止值时停止,`waterfall` 则围绕最终的 `next` 回调组合监听器。
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Event dispatch strategy used by the event service.
|
||||
*
|
||||
* `emit` runs synchronous listeners without awaiting them, `parallel` awaits
|
||||
* all listeners together, `serial` awaits them in order until one bails,
|
||||
* `bail` stops on the first synchronous bail value, and `waterfall` composes
|
||||
* listeners around a final `next` callback.
|
||||
*/
|
||||
type DispatchMode = 'emit' | 'parallel' | 'serial' | 'bail' | 'waterfall'
|
||||
```
|
||||
|
||||
[源码](../../vendor/cordis/src/events.ts#L32)
|
||||
6
docs/cordis-api/fiber.i18n.yaml
Normal file
6
docs/cordis-api/fiber.i18n.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-api/fiber.md
|
||||
fiber.md: 36d2861ac6a53e8186a92d86c65ba228d4b59ee5
|
||||
fiber.zh.md: fafa559ca911677c43893862190009d82c39c56b
|
||||
377
docs/cordis-api/fiber.zh.md
Normal file
377
docs/cordis-api/fiber.zh.md
Normal file
@@ -0,0 +1,377 @@
|
||||
<!-- 英文源文件由 scripts/gen-cordis-catalog.ts 生成;本中文文件是通过双语配对维护的经评审对侧。
|
||||
更新时先运行 `pnpm run gen-cordis-catalog` 更新英文,再更新本文件并运行 `pnpm run verify-translation-pairing --write docs/cordis-api/fiber.md` 重新记录配对。 -->
|
||||
|
||||
# Fiber
|
||||
|
||||
[English](fiber.md) | 中文
|
||||
|
||||
fiber 是一个已加载的插件实例,包含其生命周期状态、经过校验的配置以及已注册的作用。`ctx.fiber` 是当前 fiber,`ctx.effect()` 会将调用委托给它。
|
||||
|
||||
### ctx.effect(execute, label?)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Register a cleanup-aware effect on this fiber.
|
||||
*
|
||||
* `execute` runs immediately; the disposers it produces are collected and
|
||||
* run (in reverse order) either when the returned disposer is called or
|
||||
* when the fiber unloads, whichever comes first. Calling the disposer twice
|
||||
* is a no-op. Throws `CordisError('INACTIVE_EFFECT')` if the fiber is
|
||||
* already disposed, and `TypeError` if `execute` returns an invalid shape.
|
||||
*
|
||||
* @param execute — the effect body; see {@link Effect} for accepted shapes.
|
||||
* @param label — effect label shown in `getEffects()` diagnostics.
|
||||
* @returns a disposer that tears the effect down and settles once done.
|
||||
*/
|
||||
effect(execute: () => SyncEffect, label?: string): Disposable<Promise<void>>
|
||||
effect(execute: () => Effect, label?: string): AsyncDisposable<Promise<void>>
|
||||
```
|
||||
|
||||
在此 fiber 上注册一个支持清理的作用。
|
||||
|
||||
`execute` 会立即运行;它产生的清理函数将被收集,并在调用返回的清理函数或卸载 fiber 时按相反顺序运行,以先发生者为准。重复调用清理函数不会产生任何效果。如果 fiber 已经 dispose(资源释放),则抛出 `CordisError('INACTIVE_EFFECT')`;如果结构无效,则抛出 `TypeError`,表示 `execute` 返回了不受支持的结果。
|
||||
|
||||
- `execute`:作用主体;可接受的结构见 `Effect`。
|
||||
- `label`:在 `getEffects()` 诊断信息中显示的作用标签。
|
||||
|
||||
**返回**一个用于撤销该作用的清理函数,并在清理完成后结算。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L420)
|
||||
|
||||
### ctx.fiber
|
||||
|
||||
```ts cordis-catalog
|
||||
/** The fiber (plugin runtime instance) that owns this context. */
|
||||
fiber: Fiber
|
||||
```
|
||||
|
||||
拥有此上下文的 fiber(插件运行时实例)。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L12)
|
||||
|
||||
## Fiber 类
|
||||
|
||||
单次插件应用的运行时实例。
|
||||
|
||||
fiber 会跟踪 `ctx.plugin()` 返回的插件上下文所对应的依赖状态、经过校验的配置、生命周期作用和清理操作。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L184)
|
||||
|
||||
### fiber.uid
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Unique id within the registry; 0 for the root fiber, `null` once disposed. */
|
||||
public uid: number | null
|
||||
```
|
||||
|
||||
在注册表中的唯一 id;根 fiber 的 id 为 0,dispose 后为 `null`。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L186)
|
||||
|
||||
### fiber.ctx
|
||||
|
||||
```ts cordis-catalog
|
||||
/** The context this fiber's plugin runs in (extends the parent context). */
|
||||
public readonly ctx: Context
|
||||
```
|
||||
|
||||
此 fiber 的插件运行所在的上下文(扩展自父上下文)。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L188)
|
||||
|
||||
### fiber.config
|
||||
|
||||
```ts cordis-catalog
|
||||
/** The validated plugin config (updated by `update()`). */
|
||||
public config: any
|
||||
```
|
||||
|
||||
经过校验的插件配置(由 `update()` 更新)。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L190)
|
||||
|
||||
### fiber.state
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Current lifecycle state; transitions emit `internal/status`. */
|
||||
public state
|
||||
```
|
||||
|
||||
当前生命周期状态;状态转换会发出 `internal/status`。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L192)
|
||||
|
||||
### fiber.dispose
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Dispose this fiber: unload the plugin, then settle once cleanup finished. */
|
||||
public readonly dispose: () => Promise<void>
|
||||
```
|
||||
|
||||
dispose 此 fiber:卸载插件,并在清理完成后结算。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L194)
|
||||
|
||||
### fiber.store
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Snapshot of required service implementations while loaded; `undefined` otherwise. */
|
||||
public store: Dict<Impl> | undefined
|
||||
```
|
||||
|
||||
加载期间所需服务实现的快照;其他情况下为 `undefined`。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L196)
|
||||
|
||||
### fiber.inertia
|
||||
|
||||
```ts cordis-catalog
|
||||
/** The in-flight load/unload transition, if one is currently running. */
|
||||
public inertia: Promise<void> | undefined
|
||||
```
|
||||
|
||||
当前正在进行的加载或卸载转换;如果没有此类转换,则为 undefined。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L198)
|
||||
|
||||
### fiber.name
|
||||
|
||||
```ts cordis-catalog
|
||||
/** The plugin's display name, inherited from the nearest named ancestor, else `'root'`. */
|
||||
get name()
|
||||
```
|
||||
|
||||
插件的显示名称,继承自最近的具名祖先;如果不存在,则为 `'root'`。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L341)
|
||||
|
||||
### fiber.assertActive()
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Throw if the fiber has already been disposed.
|
||||
*
|
||||
* @returns nothing when the fiber is still active.
|
||||
* @throws {CordisError} `INACTIVE_EFFECT` when the fiber's uid has been cleared.
|
||||
*/
|
||||
assertActive()
|
||||
```
|
||||
|
||||
如果 fiber 已经 dispose,则抛出异常。
|
||||
|
||||
**返回**:fiber 仍处于活动状态时不返回任何内容。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L356)
|
||||
|
||||
### fiber.effect(execute, label?)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Register a cleanup-aware effect on this fiber.
|
||||
*
|
||||
* `execute` runs immediately; the disposers it produces are collected and
|
||||
* run (in reverse order) either when the returned disposer is called or
|
||||
* when the fiber unloads, whichever comes first. Calling the disposer twice
|
||||
* is a no-op. Throws `CordisError('INACTIVE_EFFECT')` if the fiber is
|
||||
* already disposed, and `TypeError` if `execute` returns an invalid shape.
|
||||
*
|
||||
* @param execute — the effect body; see {@link Effect} for accepted shapes.
|
||||
* @param label — effect label shown in `getEffects()` diagnostics.
|
||||
* @returns a disposer that tears the effect down and settles once done.
|
||||
*/
|
||||
effect(execute: () => SyncEffect, label?: string): Disposable<Promise<void>>
|
||||
effect(execute: () => Effect, label?: string): AsyncDisposable<Promise<void>>
|
||||
```
|
||||
|
||||
在此 fiber 上注册一个支持清理的作用。
|
||||
|
||||
`execute` 会立即运行;它产生的清理函数将被收集,并在调用返回的清理函数或卸载 fiber 时按相反顺序运行,以先发生者为准。重复调用清理函数不会产生任何效果。如果 fiber 已经 dispose,则抛出 `CordisError('INACTIVE_EFFECT')`;如果结构无效,则抛出 `TypeError`,表示 `execute` 返回了不受支持的结果。
|
||||
|
||||
- `execute`:作用主体;可接受的结构见 `Effect`。
|
||||
- `label`:在 `getEffects()` 诊断信息中显示的作用标签。
|
||||
|
||||
**返回**一个用于撤销该作用的清理函数,并在清理完成后结算。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L420)
|
||||
|
||||
### fiber.getEffects()
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Return metadata for currently registered effects.
|
||||
*
|
||||
* @returns one {@link EffectMeta} tree per labeled live effect.
|
||||
*/
|
||||
getEffects()
|
||||
```
|
||||
|
||||
返回当前已注册作用的元数据。
|
||||
|
||||
**返回**:每个带标签的活动作用对应一棵 `EffectMeta` 树。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L573)
|
||||
|
||||
### fiber.await()
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Wait for current lifecycle work and rethrow startup errors.
|
||||
*
|
||||
* @returns this fiber, once it has settled into a stable state.
|
||||
* @throws the config-validation or plugin-startup error, if any.
|
||||
*/
|
||||
async await()
|
||||
```
|
||||
|
||||
等待当前生命周期工作完成,并重新抛出启动错误。
|
||||
|
||||
**返回**:进入稳定状态后的此 fiber。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L702)
|
||||
|
||||
### fiber.restart()
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Dispose and immediately reload this plugin with its current config.
|
||||
*
|
||||
* @returns a promise resolving once the reload settled.
|
||||
* @throws {CordisError} `INACTIVE_EFFECT` when the fiber is already disposed.
|
||||
*/
|
||||
async restart()
|
||||
```
|
||||
|
||||
dispose 此插件,并立即使用其当前配置重新加载。
|
||||
|
||||
**返回**一个在重新加载完成后兑现的 promise。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L716)
|
||||
|
||||
### fiber.update(config, noSave?)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Validate and apply new config, then restart the plugin.
|
||||
*
|
||||
* Runs the `internal/update` waterfall first, so update hooks (and HMR)
|
||||
* can veto or replace the restart.
|
||||
*
|
||||
* @param config — the new raw config; validated before anything restarts.
|
||||
* @param noSave — hint for persistence hooks not to write the change back.
|
||||
* @returns the update waterfall result; the default restart returns a promise.
|
||||
* @throws when validation, an update listener, or the restarted plugin fails.
|
||||
*/
|
||||
update(config: any, noSave = false)
|
||||
```
|
||||
|
||||
校验并应用新配置,然后重新启动插件。
|
||||
|
||||
首先运行 `internal/update` waterfall(瀑布式事件),因此更新钩子(以及 HMR(热模块替换))可以否决或取代重新启动操作。
|
||||
|
||||
- `config`:新的原始配置;在任何内容重新启动前进行校验。
|
||||
- `noSave`:提示持久化钩子不要写回此变更。
|
||||
|
||||
**返回**更新 waterfall 的结果;默认的重新启动操作返回一个 promise。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L734)
|
||||
|
||||
## Effect
|
||||
|
||||
`ctx.effect()` 和插件启动所接受的作用主体结果。
|
||||
|
||||
可以是单个清理函数、兑现为清理函数的 promise,或生成多个清理函数的(可能为异步的)可迭代对象。生成器作用会在每个清理函数产生时将其注册。
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Effect body result accepted by `ctx.effect()` and plugin startup.
|
||||
*
|
||||
* Either a single disposer, a promise of one, or a (possibly async) iterable
|
||||
* yielding several — generator effects register each yielded disposer as it
|
||||
* is produced.
|
||||
*/
|
||||
type Effect<T = any> =
|
||||
| SyncEffect<T>
|
||||
| AsyncEffect<T>
|
||||
```
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L83)
|
||||
|
||||
## Disposable
|
||||
|
||||
作用返回的函数,用于在资源释放期间释放资源。
|
||||
|
||||
拥有该函数的 fiber 卸载时,清理函数会按注册的相反顺序运行;清理函数可以是异步的,此时卸载过程会等待其完成。
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Function returned by an effect to release resources during disposal.
|
||||
*
|
||||
* Disposers run in reverse registration order when the owning fiber unloads;
|
||||
* they may be async, in which case unloading awaits them.
|
||||
*/
|
||||
type Disposable<T = any> = () => T
|
||||
```
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L74)
|
||||
|
||||
## EffectMeta
|
||||
|
||||
用于在诊断信息中公开嵌套作用标签的树节点。
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Tree node used to expose nested effect labels for diagnostics. */
|
||||
interface EffectMeta {
|
||||
/** Human-readable effect label, e.g. `ctx.on("event")` or `ctx.provide("name")`. */
|
||||
label: string
|
||||
/** Metadata of nested effects registered while this effect ran. */
|
||||
children: EffectMeta[]
|
||||
}
|
||||
```
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L96)
|
||||
|
||||
## CordisError
|
||||
|
||||
具有稳定机器可读错误码的框架错误。
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Framework error with a stable machine-readable code. */
|
||||
class CordisError extends Error {
|
||||
/**
|
||||
* @param code — the stable error code; also the default message.
|
||||
* @param message — optional human-readable override.
|
||||
*/
|
||||
constructor(public code: CordisError.Code, message?: string)
|
||||
}
|
||||
|
||||
/** Cordis error code definitions. */
|
||||
namespace CordisError {
|
||||
export type Code = keyof typeof Code
|
||||
|
||||
export const Code = {
|
||||
INACTIVE_EFFECT: 'cannot create effect on inactive context',
|
||||
} as const
|
||||
}
|
||||
```
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L157)
|
||||
|
||||
## ValidationError
|
||||
|
||||
插件配置未通过 standard-schema 校验时抛出的错误。
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Error raised when plugin configuration fails standard-schema validation. */
|
||||
class ValidationError extends TypeError {
|
||||
name = 'ValidationError'
|
||||
|
||||
/**
|
||||
* Build the aggregated message from schema issues.
|
||||
*
|
||||
* @param issues — the standard-schema issues, one message line each.
|
||||
*/
|
||||
constructor(issues: readonly StandardSchemaV1.Issue[])
|
||||
}
|
||||
```
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L19)
|
||||
6
docs/cordis-api/registry.i18n.yaml
Normal file
6
docs/cordis-api/registry.i18n.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-api/registry.md
|
||||
registry.md: e6ddce5700ab071c2a4fedae19d99e2cb6e994ec
|
||||
registry.zh.md: c10509f569adfe65b4dbee4ca5b7139085dce1f7
|
||||
154
docs/cordis-api/registry.zh.md
Normal file
154
docs/cordis-api/registry.zh.md
Normal file
@@ -0,0 +1,154 @@
|
||||
<!-- 英文源文件由 scripts/gen-cordis-catalog.ts 生成;本中文文件是通过双语配对维护的经评审对侧。
|
||||
更新时先运行 `pnpm run gen-cordis-catalog` 更新英文,再更新本文件并运行 `pnpm run verify-translation-pairing --write docs/cordis-api/registry.md` 重新记录配对。 -->
|
||||
|
||||
# 注册表
|
||||
|
||||
[English](registry.md) | 中文
|
||||
|
||||
插件加载与依赖注入。
|
||||
|
||||
### ctx.inject(deps, callback)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Run a callback once the requested services are available.
|
||||
*
|
||||
* Shorthand for `ctx.plugin({ inject, apply: callback })`: the callback
|
||||
* is unloaded and re-run whenever a required service changes.
|
||||
*
|
||||
* @param deps — required services, as an array or a name → config map.
|
||||
* @param callback — plugin body called with `(ctx, config)`.
|
||||
* @returns the fiber; awaiting it settles once loading finished.
|
||||
*/
|
||||
inject(deps: Inject, callback: Plugin.Function<void>): Fiber & PromiseLike<Fiber>
|
||||
```
|
||||
|
||||
当请求的服务可用后,运行一次回调。
|
||||
|
||||
这是 `ctx.plugin({ inject, apply: callback })` 的简写形式:每当某个必需服务发生变化时,系统都会卸载并重新运行该回调。
|
||||
|
||||
- `deps`:必需服务,形式可以是数组,也可以是从名称到配置的映射。
|
||||
- `callback`:以 `(ctx, config)` 调用的插件主体。
|
||||
|
||||
**返回** fiber;对其执行 await 会在加载完成后结束等待。
|
||||
|
||||
[源码](../../vendor/cordis/src/registry.ts#L176)
|
||||
|
||||
### ctx.plugin(plugin, ...args)
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Load a plugin in the current context.
|
||||
*
|
||||
* @param plugin — a function, class, or `{ apply }` object plugin.
|
||||
* @param args — the plugin config, validated against its `Config` schema.
|
||||
* @returns the fiber; awaiting it settles once loading finished
|
||||
* (rejecting on config or startup errors).
|
||||
*/
|
||||
plugin<P extends Plugin>(plugin: P, ...args: Spread<GetPluginConfig<P>>): Fiber & PromiseLike<Fiber>
|
||||
```
|
||||
|
||||
在当前上下文中加载插件。
|
||||
|
||||
- `plugin`:函数、类或 `{ apply }` 对象形式的插件。
|
||||
- `args`:插件配置,会根据其 `Config` schema 进行校验。
|
||||
|
||||
**返回** fiber;对其执行 await 会在加载完成后结束等待(如果发生配置错误或启动错误,则会被拒绝)。
|
||||
|
||||
[源码](../../vendor/cordis/src/registry.ts#L185)
|
||||
|
||||
## Plugin
|
||||
|
||||
支持的插件入口点形式。
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Supported plugin entrypoint shapes. */
|
||||
type Plugin<T = any> =
|
||||
| Plugin.Function<T>
|
||||
| Plugin.Constructor<T>
|
||||
| Plugin.Object<T>
|
||||
|
||||
/** Types associated with plugin entrypoints and runtime records. */
|
||||
namespace Plugin {
|
||||
/** Shared metadata understood by the plugin registry and related tooling. */
|
||||
export interface Base<T = any> {
|
||||
/** Display name used for fiber diagnostics and logger names. */
|
||||
name?: string
|
||||
/** Standard-schema validator applied to config before the plugin starts. */
|
||||
Config?: StandardSchemaV1<any, T>
|
||||
/** Services the plugin requires; it only loads while all are available. */
|
||||
inject?: Inject
|
||||
/** Service name(s) the plugin provides (read by `Service` and by loaders). */
|
||||
provide?: string | string[]
|
||||
/** Service names whose intercept config the plugin declares it consumes. */
|
||||
intercept?: Dict<boolean>
|
||||
}
|
||||
|
||||
export interface Transform<S, T> {
|
||||
/** Marks the transform object as a schema/config transform. */
|
||||
schema?: true
|
||||
/** Convert user-facing config to runtime config. */
|
||||
Config: (config: S) => T
|
||||
}
|
||||
|
||||
/** Function plugin called with `(ctx, config)`. */
|
||||
export interface Function<T = any> extends Base<T> {
|
||||
(ctx: Context, config: T): any
|
||||
}
|
||||
|
||||
/** Class plugin constructed with `(ctx, config)`. */
|
||||
export interface Constructor<T = any> extends Base<T> {
|
||||
new (ctx: Context, config: T): any
|
||||
}
|
||||
|
||||
/** Object plugin with an `apply(ctx, config)` method. */
|
||||
export interface Object<T = any> extends Base<T> {
|
||||
apply(ctx: Context, config: T): any
|
||||
}
|
||||
|
||||
/** Mutable registry record shared by all fibers of one plugin callback. */
|
||||
export interface Runtime {
|
||||
/** Display name copied from the first registered plugin shape. */
|
||||
name?: string
|
||||
/** Every live fiber of this plugin (one per `ctx.plugin()` call). */
|
||||
fibers: DisposableList<Fiber>
|
||||
/** The executable entrypoint all fibers share (registry identity key). */
|
||||
callback: globalThis.Function
|
||||
/** Standard-schema validator applied to each fiber's config. */
|
||||
Config?: StandardSchemaV1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
[源码](../../vendor/cordis/src/registry.ts#L92)
|
||||
|
||||
## Inject
|
||||
|
||||
插件和 `@Inject` 装饰器接受的服务依赖声明。
|
||||
|
||||
数组形式请求不带拦截配置的服务。对象形式将每个服务名称映射到插件上下文中可选的拦截配置。
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Service dependency declaration accepted by plugins and the `@Inject`
|
||||
* decorator.
|
||||
*
|
||||
* Array form requests services without intercept config. Object form maps each
|
||||
* service name to optional intercept config for the plugin context.
|
||||
*/
|
||||
type Inject<M = Dict> = (keyof M)[] | { [K in keyof M]?: M[K] }
|
||||
|
||||
/** Utilities for normalizing plugin dependency declarations. */
|
||||
namespace Inject {
|
||||
/**
|
||||
* Convert array/object/class-inherited inject metadata into a plain map.
|
||||
*
|
||||
* @param inject — the declaration to normalize; `null`/`undefined` add nothing.
|
||||
* @param result — the map to fill (service name → intercept config or `null`).
|
||||
* @returns `result`.
|
||||
*/
|
||||
export function resolve(inject: Inject | null | undefined, result: Dict = Object.create(null))
|
||||
}
|
||||
```
|
||||
|
||||
[源码](../../vendor/cordis/src/registry.ts#L19)
|
||||
6
docs/cordis-api/service.i18n.yaml
Normal file
6
docs/cordis-api/service.i18n.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-api/service.md
|
||||
service.md: d4b0f06da16decf31e0d348a88e0360b46ee9d35
|
||||
service.zh.md: ec0b443a0eae2787e0a3db919583d8092414c52d
|
||||
104
docs/cordis-api/service.zh.md
Normal file
104
docs/cordis-api/service.zh.md
Normal file
@@ -0,0 +1,104 @@
|
||||
<!-- 英文源文件由 scripts/gen-cordis-catalog.ts 生成;本中文文件是通过双语配对维护的经评审对侧。
|
||||
更新时先运行 `pnpm run gen-cordis-catalog` 更新英文,再更新本文件并运行 `pnpm run verify-translation-pairing --write docs/cordis-api/service.md` 重新记录配对。 -->
|
||||
|
||||
# Service
|
||||
|
||||
[English](service.md) | 中文
|
||||
|
||||
上下文服务的基类。以插件形式加载的子类会将自身注册为 `ctx.<name>`。
|
||||
|
||||
用于在 `ctx` 上公开具名 API 的服务基类。
|
||||
|
||||
子类在构造函数中调用 `super(ctx, name)`。服务会立即注册,并随所属 fiber 自动移除。
|
||||
|
||||
[源码](../../vendor/cordis/src/service.ts#L11)
|
||||
|
||||
### service.name
|
||||
|
||||
```ts cordis-catalog
|
||||
/** The service name this instance is registered under. */
|
||||
public name!: string
|
||||
```
|
||||
|
||||
此实例注册时使用的服务名称。
|
||||
|
||||
[源码](../../vendor/cordis/src/service.ts#L30)
|
||||
|
||||
## 静态成员
|
||||
|
||||
### Service.init
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Symbol key of an instance method run after construction (class plugins). */
|
||||
static readonly init: unique symbol
|
||||
```
|
||||
|
||||
构造完成后运行的实例方法所使用的符号键(类插件)。
|
||||
|
||||
[源码](../../vendor/cordis/src/service.ts#L13)
|
||||
|
||||
### Service.check
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Symbol key of the availability predicate passed to `ctx.provide()`. */
|
||||
static readonly check: unique symbol
|
||||
```
|
||||
|
||||
传给 `ctx.provide()` 的可用性谓词所使用的符号键。
|
||||
|
||||
[源码](../../vendor/cordis/src/service.ts#L15)
|
||||
|
||||
### Service.config
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Symbol key of the phantom intercept-config type parameter. */
|
||||
static readonly config: unique symbol
|
||||
```
|
||||
|
||||
虚设拦截配置类型参数所使用的符号键。
|
||||
|
||||
[源码](../../vendor/cordis/src/service.ts#L17)
|
||||
|
||||
### Service.invoke
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Symbol key of the call body making a service callable (e.g. `ctx.logger()`). */
|
||||
static readonly invoke: unique symbol
|
||||
```
|
||||
|
||||
使服务可被调用的调用体所使用的符号键(例如 `ctx.logger()`)。
|
||||
|
||||
[源码](../../vendor/cordis/src/service.ts#L19)
|
||||
|
||||
### Service.extend
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Symbol key of the helper deriving an extended service instance. */
|
||||
static readonly extend: unique symbol
|
||||
```
|
||||
|
||||
用于派生扩展服务实例的辅助方法所使用的符号键。
|
||||
|
||||
[源码](../../vendor/cordis/src/service.ts#L21)
|
||||
|
||||
### Service.tracker
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Symbol key of the tracker metadata used for context tracing. */
|
||||
static readonly tracker: unique symbol
|
||||
```
|
||||
|
||||
上下文追踪所用跟踪器元数据的符号键。
|
||||
|
||||
[源码](../../vendor/cordis/src/service.ts#L23)
|
||||
|
||||
### Service.resolveConfig
|
||||
|
||||
```ts cordis-catalog
|
||||
/** Symbol key of the intercept-config resolution helper below. */
|
||||
static readonly resolveConfig: unique symbol
|
||||
```
|
||||
|
||||
下述拦截配置解析辅助方法所使用的符号键。
|
||||
|
||||
[源码](../../vendor/cordis/src/service.ts#L25)
|
||||
@@ -3,4 +3,4 @@
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/01-first-plugin.md
|
||||
01-first-plugin.md: 4359dfe4883f12e9cb242cf3009827fd7864768c
|
||||
01-first-plugin.zh.md: 62ccb7e5d37beb5b9636439e563cea6eaa1044a0
|
||||
01-first-plugin.zh.md: 9965f4ddb75fa338ba7fd9d564bd4a32fced7b93
|
||||
|
||||
@@ -28,7 +28,7 @@ export function apply(ctx: Context) {
|
||||
- name: './hello.ts'
|
||||
```
|
||||
|
||||
该文件是一组 Cordis 配置项的列表。`name` 是模块指定符,可以是相对路径或 NPM 包(package)名;loader 会挂载每个配置项。各项会并发启动,因此它们在列表中的位置不保证插件的加载先后;顺序由服务依赖(`inject`,参见[第 3 章](03-services.md))决定,而非文件中的位置。
|
||||
该文件是一组 Cordis 配置项的列表。`name` 是模块指定符,可以是相对路径或 NPM 包名;loader 会挂载每个配置项。各项会并发启动,因此它们在列表中的位置不保证插件的加载先后;顺序由服务依赖(`inject`,参见[第 3 章](03-services.md))决定,而非文件中的位置。
|
||||
|
||||
## 运行
|
||||
|
||||
@@ -86,7 +86,7 @@ export function apply(ctx: Context) {
|
||||
}
|
||||
```
|
||||
|
||||
再次运行:进程会因该错误而终止。插件加载失败必须明确报错,不会仅跳过该配置项。
|
||||
再次运行:进程会因该错误而终止。插件加载失败会明确报错,不会仅跳过该配置项。
|
||||
|
||||
还需要尽早了解一个例外:如果某个配置项的模块无法被 **解析**,例如路径或包名拼写错误,Cordis 会通过 logger 服务报告错误,而不会使进程崩溃。在启动阶段,这条报告可能在 console 导出器开始观察之前丢失。如果新增配置项似乎没有任何效果,请先检查拼写。
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/04-events.md
|
||||
04-events.md: b0563c71fada3efc760ff7183bc7a82e7e86934e
|
||||
04-events.zh.md: 66b52fcb1d7ec4a81c823a7c8e016c5b17d45993
|
||||
04-events.md: e77641dffcb82fcb50a24ca2e3e764d152218094
|
||||
04-events.zh.md: 00cce854e9a54fddb594ffa8e306f60a725ac012
|
||||
|
||||
@@ -135,7 +135,7 @@ HELLO
|
||||
|
||||
Walk through the second line: listener 1 runs first, calls `next()`, which invokes listener 2; listener 2 sees `blocked` and returns without calling `next()` — the innermost default (the function passed to `ctx.waterfall`) never runs — and listener 1 uppercases the replacement message on the way out.
|
||||
|
||||
The discipline that follows: **a waterfall listener that only observes or annotates must call `next()`**; returning without it is a deliberate short-circuit. Forgetting `next()` in a logging listener silently swallows the default behavior for everyone downstream. This is important enough that it is a standing rule of this repository ([waterfall semantics](../cordis-primer.md#cordis-waterfall-semantics)).
|
||||
The discipline that follows: **a waterfall listener that only observes or annotates must call `next()`**; returning without it is a deliberate short-circuit. Forgetting `next()` in a logging listener silently swallows the default behavior for everyone downstream. It is a standing rule of this repository ([waterfall semantics](../cordis-primer.md#cordis-waterfall-semantics)).
|
||||
|
||||
The harness uses waterfalls for decisions that cooperating plugins may wrap or answer: [`agent/request`](../subsystems/core.md#agentrequest--waterfall) lets a plugin replace the model-call config, and [`approval/request`](../subsystems/approval.md#approvalrequest--waterfall) lets a policy answer instead of the user.
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ HELLO
|
||||
|
||||
按顺序看第二行如何产生:监听器 1 先运行并调用 `next()`,从而调用监听器 2;监听器 2 看到 `blocked` 后直接返回而不调用 `next()`,因此最内层默认逻辑(传给 `ctx.waterfall` 的函数)从未运行;返回途中,监听器 1 再把替换消息转换为大写。
|
||||
|
||||
由此得到一项纪律:**只负责观察或标注的 waterfall 监听器必须调用 `next()`**;不调用就直接返回代表有意短路。如果日志监听器忘记调用 `next()`,会悄无声息地吞掉所有下游的默认行为。这一点极其重要,已成为本仓库的常设规则([waterfall 语义](../cordis-primer.md#cordis-waterfall-semantics))。
|
||||
由此得到一项纪律:**只负责观察或标注的 waterfall 监听器必须调用 `next()`**;不调用就直接返回代表有意短路。如果日志监听器忘记调用 `next()`,会悄无声息地吞掉所有下游的默认行为。这是本仓库的常设规则([waterfall 语义](../cordis-primer.md#cordis-waterfall-semantics))。
|
||||
|
||||
harness 使用 waterfall 处理协作插件可以包装或回答的决策:[`agent/request`](../subsystems/core.md#agentrequest--waterfall) 允许插件替换模型调用配置,[`approval/request`](../subsystems/approval.md#approvalrequest--waterfall) 允许策略代替用户作答。
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/06-composition-and-hmr.md
|
||||
06-composition-and-hmr.md: f138918a2d217ed98fdfd4e56dffddc14e3397f0
|
||||
06-composition-and-hmr.zh.md: a678e86735c6d9e3b4f3cd0dfa46a2a64079c762
|
||||
06-composition-and-hmr.md: a169d7a164be63c939e352e4e5b0bf9bce43da29
|
||||
06-composition-and-hmr.zh.md: 07ae46555c390d625a4397933e2ec5ac059bd270
|
||||
|
||||
@@ -18,7 +18,7 @@ A config entry accepts metadata beyond `name` and `config`:
|
||||
|
||||
`id` gives the entry a stable identity so the loader can tell an edit to an existing entry apart from a removal plus an addition. `disabled: true` unmounts a plugin without deleting its entry — flip it back and the plugin (and everything PENDING on its services) loads again.
|
||||
|
||||
Groups nest a sub-list of entries that load and unload as one unit, and `isolate` gives a group its own instance of a service name — two groups can each see a differently-configured `bash` without affecting each other. Those are worth knowing about before you need them; the [Cordis primer](../cordis-primer.md) and the [service isolation example](../user/develop/framework/service.md#service-isolation) cover the details.
|
||||
Groups nest a sub-list of entries that load and unload as one unit, and `isolate` gives a group its own instance of a service name — two groups can each see a differently-configured `bash` without affecting each other. The [Cordis primer](../cordis-primer.md) and the [service isolation example](../user/develop/framework/service.md#service-isolation) cover the details.
|
||||
|
||||
## Hot module replacement
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ Cordis 配置项除了 `name` 和 `config`,还接受其他元数据:
|
||||
|
||||
`id` 为 Cordis 配置项提供稳定标识,使 loader 能区分修改现有 Cordis 配置项与先删除再添加。`disabled: true` 会卸载插件而不删除其 Cordis 配置项;改回原值后,插件以及所有因依赖其服务而处于 PENDING 的插件都会再次加载。
|
||||
|
||||
组可以嵌套一份 Cordis 配置项子列表,并将其作为一个单元加载和卸载;`isolate` 则为一个组提供某项服务名称的独立实例,因此两个组可以各自看到配置不同的 `bash`,互不影响。这些概念值得在用到之前先了解;[Cordis 入门](../cordis-primer.md)和[服务隔离示例](../user/develop/framework/service.md#service-isolation)介绍了详细内容。
|
||||
组可以嵌套一份 Cordis 配置项子列表,并将其作为一个单元加载和卸载;`isolate` 则为一个组提供某项服务名称的独立实例,因此两个组可以各自看到配置不同的 `bash`,互不影响。[Cordis 入门](../cordis-primer.md)和[服务隔离示例](../user/develop/framework/service.md#service-isolation)介绍了详细内容。
|
||||
|
||||
## 热模块替换
|
||||
|
||||
|
||||
@@ -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/defensive-patterns.md
|
||||
defensive-patterns.md: 6dc1708f0b9bbcb00ad4774006d6d60059accf6a
|
||||
defensive-patterns.zh.md: 587d09a812857e6cf61f64bfd0e17e3386d1a772
|
||||
defensive-patterns.md: afb462e120892eafe676d8b7feef273c2d0e42df
|
||||
defensive-patterns.zh.md: ab5f689d47f89b6930b749824c69325490bd4586
|
||||
|
||||
@@ -8,9 +8,9 @@ Hard-won bug-class rules: each pattern below is a class of defect that actually
|
||||
|
||||
A result can be several things at once — a process can time out AND exit 0 because it trapped the signal. Surface each independent fact (`timedOut`, `signal`, `exitCode`) on its own; never nest one flag's report inside another's branch, or a caller reads a cut-short run as a clean success.
|
||||
|
||||
## Honor cross-seam contracts on BOTH sides
|
||||
## Honor public contracts on BOTH sides
|
||||
|
||||
When an implementation boundary receives several representations of one outcome, normalize them before crossing the public seam. `LlmAdapter.stream()` implementations may throw or emit `finish {kind:'error'|'aborted'}`, but `LlmService.stream()` exposes model-request failures only as terminal finish chunks; middleware and consumer defects remain thrown. This keeps consumers from guessing whether a caught exception came from the provider, a wrapper, chunk logging, or their own assembly. Document the normalized contract where the type is defined; exercise every source form through the real consumer.
|
||||
When an implementation boundary receives several representations of one outcome, normalize them before crossing the public contract. `LlmAdapter.stream()` implementations may throw or emit `finish {kind:'error'|'aborted'}`, but `LlmService.stream()` exposes model-request failures only as terminal finish chunks; middleware and consumer defects remain thrown. This keeps consumers from guessing whether a caught exception came from the provider, a wrapper, chunk logging, or their own assembly. Document the normalized contract where the type is defined; exercise every source form through the real consumer.
|
||||
|
||||
## Async state is not synchronous state
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
|
||||
一个结果可以同时具有多种性质:进程可能已经超时,却仍以退出码 0 结束,因为它捕获了终止信号。每个独立事实(`timedOut`、`signal`、`exitCode`)都应单独上报;切勿把一个标志的上报嵌套在另一个标志的分支中,否则调用方可能把提前终止的运行误判为正常成功。
|
||||
|
||||
## 跨 seam 约定两侧都要遵守
|
||||
## 公共约定两侧都要遵守
|
||||
|
||||
当一个实现边界接收到同一结果的多种表示时,应在跨越公共 seam 前将其规范化。`LlmAdapter.stream()` 的实现可以抛出异常或发出 `finish {kind:'error'|'aborted'}`,但 `LlmService.stream()` 只会通过终止型 finish 分片暴露模型请求失败;middleware 缺陷与消费方缺陷仍会以异常形式抛出。这使消费方不必猜测捕获的异常究竟来自提供方、包装层、chunk 日志记录还是自身组装逻辑。请在类型定义处记录规范化后的约定;通过真实消费方覆盖每种来源形式。
|
||||
当一个实现边界接收到同一结果的多种表示时,应在跨越公共约定前将其规范化。`LlmAdapter.stream()` 的实现可以抛出异常或发出 `finish {kind:'error'|'aborted'}`,但 `LlmService.stream()` 只会通过终止 finish chunk 暴露模型请求失败;middleware 与消费方缺陷仍会抛出。这使消费方不必猜测捕获的异常究竟来自提供方、包装层、chunk 日志记录还是自身组装逻辑。请在类型定义处记录规范化约定;通过真实消费方覆盖每种来源形式。
|
||||
|
||||
## 异步状态不是同步状态
|
||||
|
||||
`agent.followup()` 没有逐消息的完成状态或结果;后台任务的完成与轮次边界存在竞争;`reader.close()` 在 EOF 和 dispose(资源释放)两种情况下都会触发。切勿把 `agent/status` 或 `whenIdle()` 当作某次 `followup()` 的结果:多条已排队的后续消息、steering(中途引导)和注入工作可能共用同一个 `running` 区间,而取消或资源释放可能丢弃尚未启动的项。真正拥有一次运行的自动化调用方必须显式定义其区间——例如从消息的持久 inbox 回执到整个 agent(智能体)下一次进入 `idle`——并将选取的任何输出描述为整个区间的输出,而不是把因果关系归于该消息。这条守则是双向的:如果等待的转换永远不会发生,等待就会挂起,因此应显式处理「无需等待」的分支。
|
||||
`agent.followup()` 没有逐消息的完成状态或结果;后台任务的完成与轮次边界存在竞争;`reader.close()` 在 EOF 和 dispose(资源释放)两种情况下都会触发。切勿把 `agent/status` 或 `whenIdle()` 当作某次 `followup()` 的结果:多条已排队的后续消息、steering(中途引导)和注入工作可能共用同一个 `running` 区间,而取消或资源释放可能丢弃尚未启动的项。真正拥有一次运行的自动化调用方必须显式定义其区间——例如从消息的持久 inbox 回执到整个 agent 下一次进入 `idle`——并将选取的任何输出描述为整个区间的输出,而不是把因果关系归于该消息。这条守则是双向的:如果等待的转换永远不会发生,等待就会挂起,因此应显式处理「无需等待」的分支。
|
||||
|
||||
## Dispose 必须达到完全停稳,而不仅仅是请求停止
|
||||
|
||||
|
||||
@@ -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/development.md
|
||||
development.md: f7084403b30e8a6d12c4ef2b886f8fb61ed39b26
|
||||
development.zh.md: 56df93beddbb128cac8e0bcf2adaa9dcfb72c751
|
||||
development.md: 8b6c148d87fdd6288695b0029b9dfcc0139d2144
|
||||
development.zh.md: 55ca013cc0dd901500e340a7447057de27665f61
|
||||
|
||||
@@ -106,7 +106,7 @@ The installer probes the exact Node/tsx driver entrypoint before publishing its
|
||||
|
||||
lefthook is configured in `lefthook.yml` as a fast local checkpoint:
|
||||
|
||||
- `pre-commit` verifies staged pairing records against the staged owner blobs, applies formatting-only ESLint fixes, validates the staged files with the project-free `.oxlintrc.staged.json` profile and applies Oxlint's native fixes, regenerates `THIRD_PARTY_NOTICES.md` when a staged file is one of its inputs, checks the staged diff for whitespace errors, and runs the vendor manifest guard.
|
||||
- `pre-commit` verifies staged pairing records against the staged owner blobs, validates staged files with the project-free `.oxlintrc.staged.json` profile and applies Oxlint fixes with one bounded retry, regenerates `THIRD_PARTY_NOTICES.md` when a staged file is one of its inputs, checks the staged diff for whitespace errors, and runs the vendor manifest guard.
|
||||
- `pre-merge-commit` performs the same index-backed pairing check before Git creates an automatic merge commit.
|
||||
- `pre-push` runs `pnpm run typecheck`, which completes the Host lib phase, including generated TypeRT contracts, before the Client TypeScript check.
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ DEEPSEEK_BASE_URL=https://... # optional
|
||||
|
||||
lefthook 在 `lefthook.yml` 中配置,作为快速的本地检查点:
|
||||
|
||||
- `pre-commit` 对照暂存的配对文档 blob 校验暂存的配对记录,应用仅用于格式化的 ESLint 修复,使用不加载项目的 `.oxlintrc.staged.json` 配置验证暂存文件并应用 Oxlint 的原生修复,在暂存文件属于 `THIRD_PARTY_NOTICES.md` 的输入时重新生成该文件,然后检查暂存 diff 中的空白错误,并运行 vendor manifest(元数据清单)守卫;
|
||||
- `pre-commit` 对照暂存的配对文档 blob 校验暂存的配对记录,使用不加载项目的 `.oxlintrc.staged.json` 配置验证暂存文件,并通过一次有界重试应用 Oxlint 修复,在暂存文件属于 `THIRD_PARTY_NOTICES.md` 的输入时重新生成该文件,然后检查暂存 diff 中的空白错误,并运行 vendor manifest(元数据清单)守卫;
|
||||
- `pre-merge-commit` 在 Git 创建自动合并提交前执行同样以索引为准的配对检查;
|
||||
- `pre-push` 运行 `pnpm run typecheck`;该命令会先完成包含 TypeRT 约定生成的完整 Host lib 阶段,再运行 Client TypeScript 检查。
|
||||
|
||||
|
||||
6
docs/event-producer-consumer.i18n.yaml
Normal file
6
docs/event-producer-consumer.i18n.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/event-producer-consumer.md
|
||||
event-producer-consumer.md: 3b8a6b1dd155fd1350b164f1dd2d2bf0ec26a4a5
|
||||
event-producer-consumer.zh.md: 12de167fcd1217f00a8ae719ef3191a4873a2799
|
||||
@@ -3,30 +3,30 @@
|
||||
|
||||
# Event Producer And Consumer Matrix
|
||||
|
||||
This matrix shows which packages dispatch each harness-owned event and which packages listen to it. It is intentionally a table rather than one large graph: events are many-to-many, and dense relation data is easier to review in rows. Receiver and event-name types also cover contained dispatch sites that deliberately bypass `ctx.emit`, such as subagent lifecycle containment.
|
||||
This matrix shows which packages dispatch each harness-owned event and which packages listen to it. Events are many-to-many, so the dense relation data is presented as a table rather than one large graph. Receiver and event-name types also cover contained dispatch sites that deliberately bypass `ctx.emit`, such as subagent lifecycle containment.
|
||||
|
||||
| Event | Mode | Declared in | Dispatchers | Listeners |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `agent-loop/config-start-failed` | `emit` | [`packages/core/agent-loop/src/index.ts:182`](../packages/core/agent-loop/src/index.ts) | [`agent-loop`](../packages/core/agent-loop) (`events.dispatch`) | - |
|
||||
| `agent/created` | `emit` | [`packages/core/agent/src/types.ts:158`](../packages/core/agent/src/types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`goal-session`](../packages/goal/goal-session) |
|
||||
| `agent/disposed` | `emit` | [`packages/core/agent/src/types.ts:167`](../packages/core/agent/src/types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), [`goal-session`](../packages/goal/goal-session), [`subagent`](../packages/subagent/subagent) |
|
||||
| `agent/error` | `emit` | [`packages/core/agent/src/types.ts:289`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`acp`](../packages/acp/acp), `apiproxy`, [`goal-session`](../packages/goal/goal-session), [`session-telemetry`](../packages/session/session-telemetry) |
|
||||
| `agent/inbox/claimed` | `emit` | [`packages/core/agent/src/types.ts:196`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`acp`](../packages/acp/acp), [`goal-session`](../packages/goal/goal-session), [`subagent`](../packages/subagent/subagent) |
|
||||
| `agent/inbox/discarded` | `emit` | [`packages/core/agent/src/types.ts:204`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`goal-session`](../packages/goal/goal-session), [`subagent`](../packages/subagent/subagent) |
|
||||
| `agent/inbox/inserted` | `emit` | [`packages/core/agent/src/types.ts:185`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`goal-session`](../packages/goal/goal-session) |
|
||||
| `agent/pre-step` | `waterfall` | [`packages/core/agent/src/types.ts:230`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compact-basic`](../packages/compact/compact-basic), [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`plan-mode`](../packages/plan/plan-mode), [`repeat-tool-guard`](../packages/guard/repeat-tool-guard), [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), [`subagent-inprocess`](../packages/subagent/subagent-inprocess), [`time-context`](../packages/context/time-context), [`tmux-context`](../packages/context/tmux-context), [`tool-skill`](../packages/skill/tool-skill), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `agent/request` | `waterfall` | [`packages/core/agent/src/types.ts:243`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`agent`](../packages/core/agent) |
|
||||
| `agent/request-error` | `waterfall` | [`packages/core/agent/src/types.ts:259`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compact-basic`](../packages/compact/compact-basic), [`llm-retry`](../packages/llm/llm-retry) |
|
||||
| `agent/session-start` | `emit` | [`packages/core/agent/src/types.ts:216`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex) |
|
||||
| `agent/status` | `emit` | [`packages/core/agent/src/types.ts:177`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`agent`](../packages/core/agent), `apiproxy`, [`compact-basic`](../packages/compact/compact-basic), [`goal-session`](../packages/goal/goal-session), [`headless`](../packages/bundle/headless), `server` |
|
||||
| `agent/turn-stopping` | `serial` | [`packages/core/agent/src/types.ts:277`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex) |
|
||||
| `agent/created` | `emit` | [`packages/core/agent/src/runtime-types.ts:159`](../packages/core/agent/src/runtime-types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`goal-session`](../packages/goal/goal-session) |
|
||||
| `agent/disposed` | `emit` | [`packages/core/agent/src/runtime-types.ts:168`](../packages/core/agent/src/runtime-types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), [`goal-session`](../packages/goal/goal-session), [`subagent`](../packages/subagent/subagent) |
|
||||
| `agent/error` | `emit` | [`packages/core/agent/src/runtime-types.ts:290`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`acp`](../packages/acp/acp), `apiproxy`, [`goal-session`](../packages/goal/goal-session), [`session-telemetry`](../packages/session/session-telemetry) |
|
||||
| `agent/inbox/claimed` | `emit` | [`packages/core/agent/src/runtime-types.ts:197`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`acp`](../packages/acp/acp), [`goal-session`](../packages/goal/goal-session), [`subagent`](../packages/subagent/subagent) |
|
||||
| `agent/inbox/discarded` | `emit` | [`packages/core/agent/src/runtime-types.ts:205`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`goal-session`](../packages/goal/goal-session), [`subagent`](../packages/subagent/subagent) |
|
||||
| `agent/inbox/inserted` | `emit` | [`packages/core/agent/src/runtime-types.ts:186`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`goal-session`](../packages/goal/goal-session) |
|
||||
| `agent/pre-step` | `waterfall` | [`packages/core/agent/src/runtime-types.ts:231`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compact-basic`](../packages/compact/compact-basic), [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`plan-mode`](../packages/plan/plan-mode), [`repeat-tool-guard`](../packages/guard/repeat-tool-guard), [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), [`subagent-inprocess`](../packages/subagent/subagent-inprocess), [`time-context`](../packages/context/time-context), [`tmux-context`](../packages/context/tmux-context), [`tool-skill`](../packages/skill/tool-skill), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `agent/request` | `waterfall` | [`packages/core/agent/src/runtime-types.ts:244`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`agent`](../packages/core/agent) |
|
||||
| `agent/request-error` | `waterfall` | [`packages/core/agent/src/runtime-types.ts:260`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compact-basic`](../packages/compact/compact-basic), [`llm-retry`](../packages/llm/llm-retry) |
|
||||
| `agent/session-start` | `emit` | [`packages/core/agent/src/runtime-types.ts:217`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex) |
|
||||
| `agent/status` | `emit` | [`packages/core/agent/src/runtime-types.ts:178`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`agent`](../packages/core/agent), `apiproxy`, [`compact-basic`](../packages/compact/compact-basic), [`goal-session`](../packages/goal/goal-session), `server` |
|
||||
| `agent/turn-stopping` | `serial` | [`packages/core/agent/src/runtime-types.ts:278`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex) |
|
||||
| `approval/request` | `waterfall` | [`packages/interaction/user-approval/src/index.ts:30`](../packages/interaction/user-approval/src/index.ts) | [`user-approval`](../packages/interaction/user-approval) (`waterfall`) | [`acp`](../packages/acp/acp), `apiproxy` |
|
||||
| `commands/change` | `emit` | [`packages/interaction/commands/src/index.ts:172`](../packages/interaction/commands/src/index.ts) | [`commands`](../packages/interaction/commands) (`events.dispatch`) | `apiproxy` |
|
||||
| `commands/change` | `emit` | [`packages/interaction/commands/src/index.ts:134`](../packages/interaction/commands/src/index.ts) | [`commands`](../packages/interaction/commands) (`events.dispatch`) | `apiproxy` |
|
||||
| `credentials/updated` | `emit` | [`packages/credentials/credentials/src/index.ts:67`](../packages/credentials/credentials/src/index.ts) | [`credentials`](../packages/credentials/credentials) (`events.dispatch`) | `apiproxy`, [`credentials`](../packages/credentials/credentials) |
|
||||
| `domain/changed` | `emit` | [`packages/storage/storage-domain/src/events.ts:46`](../packages/storage/storage-domain/src/events.ts) | [`storage-domain`](../packages/storage/storage-domain) (`emit`) | `apiproxy`, [`storage-domain`](../packages/storage/storage-domain), [`workspace`](../packages/workspace/workspace) |
|
||||
| `fs/edit-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:64`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`), [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) (`waterfall`) | [`fs-policy`](../packages/fs/fs-policy) |
|
||||
| `fs/observed` | `emit` | [`packages/fs/fs/src/index.ts:73`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`emit`), [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) (`emit`) | [`fs-policy`](../packages/fs/fs-policy), [`skill-local`](../packages/skill/skill-local) |
|
||||
| `fs/write-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:56`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`), [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) (`waterfall`) | [`fs-policy`](../packages/fs/fs-policy) |
|
||||
| `fs/edit-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:66`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`), [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) (`waterfall`) | [`fs-policy`](../packages/fs/fs-policy) |
|
||||
| `fs/observed` | `emit` | [`packages/fs/fs/src/index.ts:76`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`emit`), [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) (`emit`) | [`fs-policy`](../packages/fs/fs-policy), [`skill-local`](../packages/skill/skill-local) |
|
||||
| `fs/write-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:58`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`), [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) (`waterfall`) | [`fs-policy`](../packages/fs/fs-policy) |
|
||||
| `goal/changed` | `emit` | [`packages/goal/goal/src/domain.ts:114`](../packages/goal/goal/src/domain.ts) | [`goal`](../packages/goal/goal) (`emit`) | [`goal-session`](../packages/goal/goal-session) |
|
||||
| `llm/adapters-updated` | `emit` | [`packages/llm/llm/src/index.ts:73`](../packages/llm/llm/src/index.ts) | [`llm`](../packages/llm/llm) (`events.dispatch`) | `apiproxy`, [`llm`](../packages/llm/llm) |
|
||||
| `llm/stream` | `waterfall` | [`packages/llm/llm/src/index.ts:62`](../packages/llm/llm/src/index.ts) | [`llm`](../packages/llm/llm) (`waterfall`) | [`agent-loop`](../packages/core/agent-loop), [`llm`](../packages/llm/llm), [`llm-replay`](../packages/support/llm-replay), [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), [`session-title`](../packages/session/session-title) |
|
||||
@@ -36,7 +36,7 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `session/flush` | `parallel` | [`packages/core/session/src/index.ts:105`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`session-persistence`](../packages/session/session-persistence), [`session-telemetry`](../packages/session/session-telemetry) |
|
||||
| `settings/document-updated` | `emit` | [`packages/settings/settings/src/index.ts:170`](../packages/settings/settings/src/index.ts) | [`settings`](../packages/settings/settings) (`events.dispatch`) | `apiproxy` |
|
||||
| `settings/updated` | `emit` | [`packages/settings/settings/src/index.ts:157`](../packages/settings/settings/src/index.ts) | [`settings`](../packages/settings/settings) (`events.dispatch`) | [`settings`](../packages/settings/settings) |
|
||||
| `skills/change` | `emit` | [`packages/skill/skill/src/index.ts:283`](../packages/skill/skill/src/index.ts) | [`skill`](../packages/skill/skill) (`events.dispatch`) | - |
|
||||
| `skills/change` | `emit` | [`packages/skill/skill/src/index.ts:297`](../packages/skill/skill/src/index.ts) | [`skill`](../packages/skill/skill) (`events.dispatch`) | - |
|
||||
| `subagent/end` | `emit` | [`packages/subagent/subagent/src/index.ts:162`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude`](../packages/hooks/hooks-claude), `server`, [`subagent`](../packages/subagent/subagent) |
|
||||
| `subagent/provider-added` | `emit` | [`packages/subagent/subagent/src/index.ts:136`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`emit`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `subagent/provider-removed` | `emit` | [`packages/subagent/subagent/src/index.ts:142`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
@@ -44,12 +44,12 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `system-prompt/assemble` | `waterfall` | [`packages/core/system-prompt/src/index.ts:29`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`waterfall`) | [`agent`](../packages/core/agent), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| `system-prompt/change` | `emit` | [`packages/core/system-prompt/src/index.ts:35`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`emit`) | - |
|
||||
| `telemetry/record` | `waterfall` | [`packages/session/session-telemetry/src/index.ts:43`](../packages/session/session-telemetry/src/index.ts) | [`session-telemetry`](../packages/session/session-telemetry) (`waterfall`) | - |
|
||||
| `tools/change` | `emit` | [`packages/core/tools/src/index.ts:191`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`emit`) | - |
|
||||
| `tools/code-dispatch-log` | `waterfall` | [`packages/core/tools/src/index.ts:173`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`spill-policy`](../packages/spill/spill-policy) |
|
||||
| `tools/execute` | `waterfall` | [`packages/core/tools/src/index.ts:148`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), [`timeout-policy`](../packages/guard/timeout-policy) |
|
||||
| `tools/post-execute` | `waterfall` | [`packages/core/tools/src/index.ts:160`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`repeat-tool-guard`](../packages/guard/repeat-tool-guard), [`spill-policy`](../packages/spill/spill-policy), [`tool-fs-search`](../packages/fs/tool-fs-search) |
|
||||
| `tools/pre-execute` | `waterfall` | [`packages/core/tools/src/index.ts:137`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`tool-tasks`](../packages/tasks/tool-tasks) |
|
||||
| `tools/result` | `emit` | [`packages/core/tools/src/index.ts:181`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`events.dispatch`) | [`subagent-inprocess`](../packages/subagent/subagent-inprocess), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `tools/change` | `emit` | [`packages/core/tools/src/index.ts:192`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`emit`) | - |
|
||||
| `tools/code-dispatch-log` | `waterfall` | [`packages/core/tools/src/index.ts:174`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`spill-policy`](../packages/spill/spill-policy) |
|
||||
| `tools/execute` | `waterfall` | [`packages/core/tools/src/index.ts:149`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), [`timeout-policy`](../packages/guard/timeout-policy) |
|
||||
| `tools/post-execute` | `waterfall` | [`packages/core/tools/src/index.ts:161`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`repeat-tool-guard`](../packages/guard/repeat-tool-guard), [`spill-policy`](../packages/spill/spill-policy), [`tool-fs-search`](../packages/fs/tool-fs-search) |
|
||||
| `tools/pre-execute` | `waterfall` | [`packages/core/tools/src/index.ts:138`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`tool-tasks`](../packages/tasks/tool-tasks) |
|
||||
| `tools/result` | `emit` | [`packages/core/tools/src/index.ts:182`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`events.dispatch`) | [`subagent-inprocess`](../packages/subagent/subagent-inprocess), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `workflow/agent-end` | `emit` | [`packages/workflow/workflow/src/index.ts:81`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | [`workflow`](../packages/workflow/workflow) |
|
||||
| `workflow/agent-start` | `emit` | [`packages/workflow/workflow/src/index.ts:70`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | [`workflow`](../packages/workflow/workflow) |
|
||||
| `workflow/end` | `emit` | [`packages/workflow/workflow/src/index.ts:91`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | [`workflow`](../packages/workflow/workflow) |
|
||||
@@ -66,7 +66,7 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `credentials/changed` | `runtime` (`emit`) | `ui-models` |
|
||||
| `internal/dispatch` | - | [`commands`](../packages/interaction/commands), [`compact`](../packages/compact/compact), [`fs`](../packages/fs/fs), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`llm-retry`](../packages/llm/llm-retry), [`permission`](../packages/interaction/permission), [`plan-mode`](../packages/plan/plan-mode), [`pty-local`](../packages/pty/pty-local), `runtime`, [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-title`](../packages/session/session-title), [`subagent`](../packages/subagent/subagent), [`time-context`](../packages/context/time-context), [`tool-todo`](../packages/todo/tool-todo), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval), [`workflow`](../packages/workflow/workflow) |
|
||||
| `internal/plugin` | - | `hmr`, `loader`, [`lsp-local`](../packages/lsp/lsp-local), `modules`, `webserver` |
|
||||
| `internal/service` | - | `gateway` |
|
||||
| `internal/service` | - | [`agent-presets`](../packages/preset/agent-presets), `gateway` |
|
||||
| `internal/status` | - | [`agent`](../packages/core/agent) |
|
||||
| `locale/change` | `locale` (`emit`) | `locale` |
|
||||
| `models/changed` | `runtime` (`emit`) | `ui-models` |
|
||||
|
||||
83
docs/event-producer-consumer.zh.md
Normal file
83
docs/event-producer-consumer.zh.md
Normal file
@@ -0,0 +1,83 @@
|
||||
<!-- 英文源文件由 scripts/gen-doc-graphs.ts 生成;本中文文件是通过双语配对维护的经评审对侧。
|
||||
更新时先运行 `pnpm run gen-doc-graphs` 更新英文,再更新本文件并运行 `pnpm run verify-translation-pairing --write docs/event-producer-consumer.md` 重新记录配对。 -->
|
||||
|
||||
# 事件生产方与消费方矩阵
|
||||
|
||||
[English](event-producer-consumer.md) | 中文
|
||||
|
||||
本矩阵展示哪些包会派发各个 harness 自有事件,以及哪些包会监听这些事件。事件之间存在多对多关系,因此密集的关系数据以表格而非一张大型关系图呈现。接收方和事件名称类型还涵盖有意绕过 `ctx.emit` 的内含派发位置,例如 subagent 生命周期封装。
|
||||
|
||||
| 事件 | 模式 | 声明位置 | 派发方 | 监听方 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `agent-loop/config-start-failed` | `emit` | [`packages/core/agent-loop/src/index.ts:182`](../packages/core/agent-loop/src/index.ts) | [`agent-loop`](../packages/core/agent-loop) (`events.dispatch`) | - |
|
||||
| `agent/created` | `emit` | [`packages/core/agent/src/runtime-types.ts:159`](../packages/core/agent/src/runtime-types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`goal-session`](../packages/goal/goal-session) |
|
||||
| `agent/disposed` | `emit` | [`packages/core/agent/src/runtime-types.ts:168`](../packages/core/agent/src/runtime-types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), [`goal-session`](../packages/goal/goal-session), [`subagent`](../packages/subagent/subagent) |
|
||||
| `agent/error` | `emit` | [`packages/core/agent/src/runtime-types.ts:290`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`acp`](../packages/acp/acp), `apiproxy`, [`goal-session`](../packages/goal/goal-session), [`session-telemetry`](../packages/session/session-telemetry) |
|
||||
| `agent/inbox/claimed` | `emit` | [`packages/core/agent/src/runtime-types.ts:197`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`acp`](../packages/acp/acp), [`goal-session`](../packages/goal/goal-session), [`subagent`](../packages/subagent/subagent) |
|
||||
| `agent/inbox/discarded` | `emit` | [`packages/core/agent/src/runtime-types.ts:205`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`goal-session`](../packages/goal/goal-session), [`subagent`](../packages/subagent/subagent) |
|
||||
| `agent/inbox/inserted` | `emit` | [`packages/core/agent/src/runtime-types.ts:186`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`goal-session`](../packages/goal/goal-session) |
|
||||
| `agent/pre-step` | `waterfall` | [`packages/core/agent/src/runtime-types.ts:231`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compact-basic`](../packages/compact/compact-basic), [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`plan-mode`](../packages/plan/plan-mode), [`repeat-tool-guard`](../packages/guard/repeat-tool-guard), [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), [`subagent-inprocess`](../packages/subagent/subagent-inprocess), [`time-context`](../packages/context/time-context), [`tmux-context`](../packages/context/tmux-context), [`tool-skill`](../packages/skill/tool-skill), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `agent/request` | `waterfall` | [`packages/core/agent/src/runtime-types.ts:244`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`agent`](../packages/core/agent) |
|
||||
| `agent/request-error` | `waterfall` | [`packages/core/agent/src/runtime-types.ts:260`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compact-basic`](../packages/compact/compact-basic), [`llm-retry`](../packages/llm/llm-retry) |
|
||||
| `agent/session-start` | `emit` | [`packages/core/agent/src/runtime-types.ts:217`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex) |
|
||||
| `agent/status` | `emit` | [`packages/core/agent/src/runtime-types.ts:178`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`agent`](../packages/core/agent), `apiproxy`, [`compact-basic`](../packages/compact/compact-basic), [`goal-session`](../packages/goal/goal-session), `server` |
|
||||
| `agent/turn-stopping` | `serial` | [`packages/core/agent/src/runtime-types.ts:278`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex) |
|
||||
| `approval/request` | `waterfall` | [`packages/interaction/user-approval/src/index.ts:30`](../packages/interaction/user-approval/src/index.ts) | [`user-approval`](../packages/interaction/user-approval) (`waterfall`) | [`acp`](../packages/acp/acp), `apiproxy` |
|
||||
| `commands/change` | `emit` | [`packages/interaction/commands/src/index.ts:134`](../packages/interaction/commands/src/index.ts) | [`commands`](../packages/interaction/commands) (`events.dispatch`) | `apiproxy` |
|
||||
| `credentials/updated` | `emit` | [`packages/credentials/credentials/src/index.ts:67`](../packages/credentials/credentials/src/index.ts) | [`credentials`](../packages/credentials/credentials) (`events.dispatch`) | `apiproxy`, [`credentials`](../packages/credentials/credentials) |
|
||||
| `domain/changed` | `emit` | [`packages/storage/storage-domain/src/events.ts:46`](../packages/storage/storage-domain/src/events.ts) | [`storage-domain`](../packages/storage/storage-domain) (`emit`) | `apiproxy`, [`storage-domain`](../packages/storage/storage-domain), [`workspace`](../packages/workspace/workspace) |
|
||||
| `fs/edit-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:66`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`), [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) (`waterfall`) | [`fs-policy`](../packages/fs/fs-policy) |
|
||||
| `fs/observed` | `emit` | [`packages/fs/fs/src/index.ts:76`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`emit`), [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) (`emit`) | [`fs-policy`](../packages/fs/fs-policy), [`skill-local`](../packages/skill/skill-local) |
|
||||
| `fs/write-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:58`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`), [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) (`waterfall`) | [`fs-policy`](../packages/fs/fs-policy) |
|
||||
| `goal/changed` | `emit` | [`packages/goal/goal/src/domain.ts:114`](../packages/goal/goal/src/domain.ts) | [`goal`](../packages/goal/goal) (`emit`) | [`goal-session`](../packages/goal/goal-session) |
|
||||
| `llm/adapters-updated` | `emit` | [`packages/llm/llm/src/index.ts:73`](../packages/llm/llm/src/index.ts) | [`llm`](../packages/llm/llm) (`events.dispatch`) | `apiproxy`, [`llm`](../packages/llm/llm) |
|
||||
| `llm/stream` | `waterfall` | [`packages/llm/llm/src/index.ts:62`](../packages/llm/llm/src/index.ts) | [`llm`](../packages/llm/llm) (`waterfall`) | [`agent-loop`](../packages/core/agent-loop), [`llm`](../packages/llm/llm), [`llm-replay`](../packages/support/llm-replay), [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), [`session-title`](../packages/session/session-title) |
|
||||
| `session/created` | `emit` | [`packages/core/session/src/index.ts:74`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | `apiproxy`, [`compact`](../packages/compact/compact), [`goal`](../packages/goal/goal), [`hook-protocol`](../packages/hooks/hook-protocol), [`llm-retry`](../packages/llm/llm-retry), [`permission`](../packages/interaction/permission), [`plan-mode`](../packages/plan/plan-mode), `server`, [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-telemetry`](../packages/session/session-telemetry), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| `session/disposed` | `emit` | [`packages/core/session/src/index.ts:84`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), `apiproxy`, [`session-persistence`](../packages/session/session-persistence), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-telemetry`](../packages/session/session-telemetry), [`session-title`](../packages/session/session-title) |
|
||||
| `session/event` | `emit` | [`packages/core/session/src/index.ts:96`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`acp`](../packages/acp/acp), [`agent-loop`](../packages/core/agent-loop), `apiproxy`, [`compact`](../packages/compact/compact), [`compact-basic`](../packages/compact/compact-basic), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`loader-smoke`](../packages/support/loader-smoke), `server`, [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-telemetry`](../packages/session/session-telemetry), [`session-telemetry-otel`](../packages/session/session-telemetry-otel), [`session-title`](../packages/session/session-title), [`token-meter`](../packages/llm/token-meter), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `session/flush` | `parallel` | [`packages/core/session/src/index.ts:105`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`session-persistence`](../packages/session/session-persistence), [`session-telemetry`](../packages/session/session-telemetry) |
|
||||
| `settings/document-updated` | `emit` | [`packages/settings/settings/src/index.ts:170`](../packages/settings/settings/src/index.ts) | [`settings`](../packages/settings/settings) (`events.dispatch`) | `apiproxy` |
|
||||
| `settings/updated` | `emit` | [`packages/settings/settings/src/index.ts:157`](../packages/settings/settings/src/index.ts) | [`settings`](../packages/settings/settings) (`events.dispatch`) | [`settings`](../packages/settings/settings) |
|
||||
| `skills/change` | `emit` | [`packages/skill/skill/src/index.ts:297`](../packages/skill/skill/src/index.ts) | [`skill`](../packages/skill/skill) (`events.dispatch`) | - |
|
||||
| `subagent/end` | `emit` | [`packages/subagent/subagent/src/index.ts:162`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude`](../packages/hooks/hooks-claude), `server`, [`subagent`](../packages/subagent/subagent) |
|
||||
| `subagent/provider-added` | `emit` | [`packages/subagent/subagent/src/index.ts:136`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`emit`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `subagent/provider-removed` | `emit` | [`packages/subagent/subagent/src/index.ts:142`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
| `subagent/start` | `emit` | [`packages/subagent/subagent/src/index.ts:153`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`subagent`](../packages/subagent/subagent) |
|
||||
| `system-prompt/assemble` | `waterfall` | [`packages/core/system-prompt/src/index.ts:29`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`waterfall`) | [`agent`](../packages/core/agent), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| `system-prompt/change` | `emit` | [`packages/core/system-prompt/src/index.ts:35`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`emit`) | - |
|
||||
| `telemetry/record` | `waterfall` | [`packages/session/session-telemetry/src/index.ts:43`](../packages/session/session-telemetry/src/index.ts) | [`session-telemetry`](../packages/session/session-telemetry) (`waterfall`) | - |
|
||||
| `tools/change` | `emit` | [`packages/core/tools/src/index.ts:192`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`emit`) | - |
|
||||
| `tools/code-dispatch-log` | `waterfall` | [`packages/core/tools/src/index.ts:174`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`spill-policy`](../packages/spill/spill-policy) |
|
||||
| `tools/execute` | `waterfall` | [`packages/core/tools/src/index.ts:149`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), [`timeout-policy`](../packages/guard/timeout-policy) |
|
||||
| `tools/post-execute` | `waterfall` | [`packages/core/tools/src/index.ts:161`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`repeat-tool-guard`](../packages/guard/repeat-tool-guard), [`spill-policy`](../packages/spill/spill-policy), [`tool-fs-search`](../packages/fs/tool-fs-search) |
|
||||
| `tools/pre-execute` | `waterfall` | [`packages/core/tools/src/index.ts:138`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`tool-tasks`](../packages/tasks/tool-tasks) |
|
||||
| `tools/result` | `emit` | [`packages/core/tools/src/index.ts:182`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`events.dispatch`) | [`subagent-inprocess`](../packages/subagent/subagent-inprocess), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `workflow/agent-end` | `emit` | [`packages/workflow/workflow/src/index.ts:81`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | [`workflow`](../packages/workflow/workflow) |
|
||||
| `workflow/agent-start` | `emit` | [`packages/workflow/workflow/src/index.ts:70`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | [`workflow`](../packages/workflow/workflow) |
|
||||
| `workflow/end` | `emit` | [`packages/workflow/workflow/src/index.ts:91`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | [`workflow`](../packages/workflow/workflow) |
|
||||
| `workflow/log` | `emit` | [`packages/workflow/workflow/src/index.ts:60`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | - |
|
||||
| `workflow/phase` | `emit` | [`packages/workflow/workflow/src/index.ts:53`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | - |
|
||||
| `workflow/start` | `emit` | [`packages/workflow/workflow/src/index.ts:45`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | [`workflow`](../packages/workflow/workflow) |
|
||||
|
||||
## Non-harness or undeclared event strings seen in package source
|
||||
|
||||
| Event string | Dispatchers | Listeners |
|
||||
| --- | --- | --- |
|
||||
| `commands/changed` | `runtime` (`emit`) | `ui-command` |
|
||||
| `connection/reset` | `runtime` (`emit`) | `ui-command`, `ui-models`, `ui-permission`, `ui-settings-general` |
|
||||
| `credentials/changed` | `runtime` (`emit`) | `ui-models` |
|
||||
| `internal/dispatch` | - | [`commands`](../packages/interaction/commands), [`compact`](../packages/compact/compact), [`fs`](../packages/fs/fs), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`llm-retry`](../packages/llm/llm-retry), [`permission`](../packages/interaction/permission), [`plan-mode`](../packages/plan/plan-mode), [`pty-local`](../packages/pty/pty-local), `runtime`, [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-title`](../packages/session/session-title), [`subagent`](../packages/subagent/subagent), [`time-context`](../packages/context/time-context), [`tool-todo`](../packages/todo/tool-todo), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval), [`workflow`](../packages/workflow/workflow) |
|
||||
| `internal/plugin` | - | `hmr`, `loader`, [`lsp-local`](../packages/lsp/lsp-local), `modules`, `webserver` |
|
||||
| `internal/service` | - | [`agent-presets`](../packages/preset/agent-presets)、`gateway` |
|
||||
| `internal/status` | - | [`agent`](../packages/core/agent) |
|
||||
| `locale/change` | `locale` (`emit`) | `locale` |
|
||||
| `models/changed` | `runtime` (`emit`) | `ui-models` |
|
||||
| `settings/changed` | `runtime` (`emit`) | `ui-models`, `ui-permission`, `ui-settings-general` |
|
||||
| `slash/input-begin-command` | - | `ui-conversation` |
|
||||
| `slash/input-consume-token` | - | `ui-conversation` |
|
||||
| `slash/input-insert-reference` | - | `ui-conversation` |
|
||||
| `slash/input-insert-text` | - | `ui-conversation` |
|
||||
| `slots/changed` | `runtime` (`emit`) | - |
|
||||
| `theme/change` | `ui-theme` (`emit`) | `ui-layout`, `ui-theme` |
|
||||
|
||||
Maintenance mode: generated: Cordis event declarations and producer/listener edges are resolved from the repository TypeScript Program.
|
||||
@@ -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/glossary.md
|
||||
glossary.md: 16409517bff623a80d6e1e00888d95f63b42f780
|
||||
glossary.zh.md: a84447dd067a3364033601742c116583661cdf45
|
||||
glossary.md: d556e760dd2f07ab640aafca06b2757b47935406
|
||||
glossary.zh.md: d6a8e423ff2a6324ce0cdd65dd3edde573fac5b1
|
||||
|
||||
@@ -4,6 +4,10 @@ English | [中文](glossary.zh.md)
|
||||
|
||||
Domain vocabulary for the DeepSeek Harness SDK uses one canonical term per concept. Terms link to their entries with standard Markdown anchors; implementation detail stays in package READMEs and Agent Notes.
|
||||
|
||||
## capability-seam
|
||||
|
||||
- **seam** — a *swappable capability* with three roles: a **Service Definition** (the Cordis `Service` that owns its `ctx.<key>` and vocabulary types — an abstract class such as `BashExecutor`, or a concrete registry such as `WebService`, never a TypeScript `interface`), one or more **Service providers**, and one or more **Consumers** that inject the service. `packages/bash` is the canonical example: `dsh-bash` (Service Definition), `dsh-bash-local` / `dsh-bash-sandbox` (providers), and `dsh-tool-bash` (Consumer). Roles normally occupy separate packages when they evolve independently, but a package may own multiple roles when they are one concern (`dsh-llm` owns its Service Definition and Consumer). The seam is the complete capability, never one role; reserve the term for that meaning and name a constituent by its role, class, service, contract, or extension point.
|
||||
|
||||
## agent-scope
|
||||
|
||||
- **scope** — the unit of per-agent registration: a contribution (tool, prompt section, variable, restriction, listener) is either *global* (visible to every agent) or *scoped* (owned by exactly one [scope key](#scope-key)). Two levels, flat: scoped registrations do not inherit down to subagents; subtree behavior is expressed with [lineage](#lineage) data, never scope structure.
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
|
||||
DeepSeek Harness SDK 的领域词汇为每个概念规定一个规范术语。各术语通过标准 Markdown 锚点链接到相应条目;实现细节留在各包的 README 与 Agent Note 中。
|
||||
|
||||
## capability-seam
|
||||
|
||||
- **seam**:一种包含三种角色的*可替换能力*:**Service Definition**(拥有自身 `ctx.<key>` 和词汇类型的 Cordis `Service`——可以是 `BashExecutor` 这样的抽象类,也可以是 `WebService` 这样的具体注册表,从不是 TypeScript `interface`)、一个或多个 **Service provider**,以及一个或多个注入该服务的 **Consumer**。`packages/bash` 是规范范例:`dsh-bash`(Service Definition)、`dsh-bash-local` / `dsh-bash-sandbox`(提供方),以及 `dsh-tool-bash`(Consumer)。角色需要独立演进时通常位于不同包,但属于同一关注点时,一个包也可以承担多个角色(`dsh-llm` 同时承担 Service Definition 和 Consumer)。seam 是完整能力,绝不是其中一个角色;该术语仅保留此义,能力成员应按其角色、类、服务、约定或扩展点命名。
|
||||
|
||||
## agent-scope
|
||||
|
||||
- **scope**:按 agent(智能体)划分的注册单位。一项贡献(工具、提示词片段、变量、限制、监听器)要么是*全局的*(对所有 agent 可见),要么是*带作用域的*(归属于恰好一个 [scope key](#scope-key))。只有两层,采用扁平结构:带作用域的注册不会向下继承给 subagent;子树行为通过 [lineage](#lineage) 数据表达,从不通过 scope 结构。
|
||||
|
||||
6
docs/graph-atlas.i18n.yaml
Normal file
6
docs/graph-atlas.i18n.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/graph-atlas.md
|
||||
graph-atlas.md: 5b831520fb4e1c5d49d83738ba979ce04ce4f69f
|
||||
graph-atlas.zh.md: 1f9a30124284549248bbb21f926772d5cdc2598a
|
||||
26
docs/graph-atlas.zh.md
Normal file
26
docs/graph-atlas.zh.md
Normal file
@@ -0,0 +1,26 @@
|
||||
<!-- 英文源文件由 scripts/gen-doc-graphs.ts 生成;本中文文件是通过双语配对维护的经评审对侧。
|
||||
更新时先运行 `pnpm run gen-doc-graphs` 更新英文,再更新本文件并运行 `pnpm run verify-translation-pairing --write docs/graph-atlas.md` 重新记录配对。 -->
|
||||
|
||||
# 文档图索引
|
||||
|
||||
[English](graph-atlas.md) | 中文
|
||||
|
||||
这些图构成生成目录之上的关系层。你可以借助它们了解包拓扑、能力 seam、事件流、面向模型的工具、应用组合以及运行时生命周期路径。精确签名和类型结构仍以[子系统页面](subsystems/core.md)(类型和生成的 `cordis-surface` 区域)及[工具目录](tool-catalog.md)为准。
|
||||
|
||||
本索引背后的流程决策记录在[文档图 Agent Note](../.agents/notes/archived/process/2026-07-03-documentation-graph-atlas.md)中。
|
||||
|
||||
| 图 | 模式 |
|
||||
| --- | --- |
|
||||
| [模块依赖图](module-graph.md) | `generated` |
|
||||
| [工具 schema 目录与包映射](tool-catalog.md) | `generated` |
|
||||
| [能力 seam 与核心服务](capability-seams.md) | `hybrid generated` |
|
||||
| [dsh 共享基础组合](../apps/cli/composition.md) | `hybrid generated` |
|
||||
| [headless-agent 应用组合](../examples/headless-agent/composition.md) | `hybrid generated` |
|
||||
| [acp-agent 应用组合](../examples/acp-agent/composition.md) | `hybrid generated` |
|
||||
| [事件生产方/消费方矩阵](event-producer-consumer.md) | `hybrid generated` |
|
||||
| [agent(智能体)轮次与步骤生命周期](agent-lifecycle.md) | `curated` |
|
||||
| [工具执行流水线](tool-execution-pipeline.md) | `curated` |
|
||||
|
||||
运行 `pnpm run gen-doc-graphs` 可重新生成英文源文件;运行 `pnpm run verify-doc-graphs` 可验证英文源的新鲜度,中文对侧则通过双语配对维护。
|
||||
|
||||
英文源文件的维护模式为混合。每个链接页面都会声明其英文源模式为生成、混合或人工编写;本中文文件是通过双语配对维护的经评审对侧。
|
||||
@@ -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/i18n/README.md
|
||||
README.md: 30f56eeebf15a3edec559e3080247dab9ab14178
|
||||
README.zh.md: 52d0061fc6b7edd6ecbcab0798380f7202fd4981
|
||||
README.md: 042fe71e796340c5c653e1f671c53a95a8496a38
|
||||
README.zh.md: d2d3b84e98cf4b761ae0174459b91236a71fb187
|
||||
|
||||
@@ -17,8 +17,8 @@ This repo's documentation is read by people and agents both inside and outside t
|
||||
|
||||
Blob hashes, not commit hashes, so the record is computable for files edited in the same PR (`git hash-object foo.md`) and consistency is a pure content comparison. `--write` stores those snapshots in the local Git object database before recording them, including uncommitted working-tree contents, and pins every distinct stored blob under a content-addressed `refs/dsh/translation-pairing/snapshots/` ref so garbage collection cannot invalidate a recorded recovery pointer. The recorded hashes therefore recover the exact last-confirmed text of either side, so an out-of-sync pair is updated by patching the counterpart minimally against the edited side's diff — never by re-translating whole files. `pnpm run gen-translation-brief <pair>` assembles that update's working set mechanically at the narrowest safely aligned granularity — changed Markdown units, then heading sections, then whole document — with the edited side's diff since last confirmation, each changed span's three-way text, the terminology rows the change touches, and the binding update rules; a change confined to the pair's byte-identical code fences is computed outright, and `--apply` splices it into the counterpart after structural validation ([briefed-updates Agent Note](../../.agents/notes/implemented/process/2026-07-26-briefed-minimal-translation-updates.md)). After bringing the pair back in line, `pnpm run verify-translation-pairing --write <pair>` re-records both hashes; that yaml diff is the reviewable act of confirming consistency, which is why `--write` requires naming the pairs you confirmed (`--write --all` is the explicit corpus-wide form).
|
||||
|
||||
When two branches contain valid confirmations of the same pair, the installed `dsh-translation-pairing` Git merge driver composes a new record only if Git's default text merge succeeds for both recorded owner-blob triplets and the merged pair retains its switchers and structural signature. Any uncertain shape remains an ordinary conflict; `pnpm run resolve-translation-pairing-conflicts` applies the same fail-closed operation to a merge that has already stopped, stages every safe pairing record, and exits unsuccessfully when other pairing conflicts remain. The [automatic pairing merges Agent Note](../../.agents/notes/implemented/process/2026-08-08-automatic-translation-pairing-merges.md) owns the mechanism and alternatives.
|
||||
- **Language switcher.** Both files link to each other immediately after their H1 heading: the English file carries `English | [中文](foo.zh.md)` and the Chinese file carries `[English](foo.md) | 中文`.
|
||||
When two branches contain valid confirmations of the same pair, the installed `dsh-translation-pairing` Git merge driver composes a new record only if Git's default text merge succeeds for both recorded owner-blob triplets and the merged pair retains its required switchers and structural signature. The Chinese file must retain its English backlink; an authored English source must retain its Chinese link, while a listed generated English source is exempt. Any uncertain shape remains an ordinary conflict; `pnpm run resolve-translation-pairing-conflicts` applies the same fail-closed operation to a merge that has already stopped, stages every safe pairing record, and exits unsuccessfully when other pairing conflicts remain. The [automatic pairing merges Agent Note](../../.agents/notes/implemented/process/2026-08-08-automatic-translation-pairing-merges.md) owns the mechanism and alternatives.
|
||||
- **Language switcher.** The Chinese file always links back immediately after its H1 heading with `[English](foo.md) | 中文`. An authored English file reciprocates there with `English | [中文](foo.zh.md)`; a listed generated English source omits that line so it remains byte-identical to generator output.
|
||||
- **Structure mirrors the counterpart.** Heading depths and order, list kinds, ordered-list starts, list item counts, table row and column counts, link targets, and verbatim code blocks match one to one across the pair — see [translation-rules.md](translation-rules.md) for the full preservation rules. Existing Markdown gates apply to `.zh.md` files unchanged (`verify-md-wrap`, `verify-md-links`).
|
||||
|
||||
## The gate: verify-translation-pairing
|
||||
@@ -26,7 +26,7 @@ This repo's documentation is read by people and agents both inside and outside t
|
||||
`pnpm run verify-translation-pairing` (part of `doc-sync`, which contributors run locally for documentation changes and CI runs exhaustively) enforces the contract mechanically:
|
||||
|
||||
1. Every document in scope has a complete pair. README discovery is case-insensitive on the basename, so `missions/readme.md` is in scope alongside the other documentation roots.
|
||||
2. Every pair artifact that exists at all is complete and consistent: all three files present, each side's current blob hash equals the recorded one (editing either side without re-confirming the pair goes red), both sides carry the language switcher, and the structural signatures match in order — heading depths, verbatim code blocks (info string and content), table row and column counts, list kinds, ordered-list starts, item counts, and every link target apart from the switcher.
|
||||
2. Every pair artifact that exists at all is complete and consistent: all three files present, each side's current blob hash equals the recorded one (editing either side without re-confirming the pair goes red), the Chinese side and every authored English source carry their language switchers (listed generated English sources are exempt), and the structural signatures match in order — heading depths, verbatim code blocks (info string and content), table row and column counts, list kinds, ordered-list starts, item counts, and every link target apart from the switcher.
|
||||
3. Files listed as `excluded` have no `.zh.md` and no `.i18n.yaml` at all. Frozen Agent Notes under `.agents/notes/archived/` are outside this evolving gate; their dedicated verifier requires and seals the complete existing triplet instead.
|
||||
|
||||
Source-oriented code gates consume an exact `.zh.md` fence sequence as a derivative of its unsuffixed sibling instead of compiling or manifesting the same code twice. The sequence must match in length, order, fence kind, and byte-exact body; otherwise both copies remain independently checked and the pairing gate reports the structural mismatch.
|
||||
@@ -43,9 +43,11 @@ The gate's limit, stated plainly: **a green gate means the pair was confirmed co
|
||||
|
||||
**Scope**: every non-vendor README, plus every active document under `.agents/notes/**`, `docs/**`, and `python/**`. README matching is case-insensitive on the basename and covers future directories without another manifest edit. Dependency and ignored build-output trees and the frozen `.agents/notes/archived/` tree are discovery exclusions, not evolving translation source.
|
||||
|
||||
Generated English references and graphs participate in pairing when a reviewed Chinese counterpart is available. Their generators remain the English source of truth, and freshness and pairing gates enforce their respective invariants independently; regeneration that changes English leaves the pair out of sync until the reviewed Chinese counterpart is updated and re-recorded. Generated English sources omit the language switcher that ordinary authored sources carry, because adding it would make the generator stale; their Chinese counterparts still link back to the English source. A generated page's Chinese counterpart may rewrite only self-referential generation and maintenance statements that would otherwise be false for the reviewed translation; all technical content remains subject to the ordinary faithfulness rules.
|
||||
|
||||
**Excluded** (never paired, and the gate rejects a `.zh.md` or `.i18n.yaml` for them):
|
||||
|
||||
- `docs/cordis-catalog/`, `docs/tool-catalog/`, `docs/config-catalog.md`, `docs/persistence-catalog.md`, `docs/module-graph.md`, `docs/agent-lifecycle.md`, `docs/capability-seams.md`, `docs/event-producer-consumer.md`, `docs/graph-atlas.md`, and `docs/tool-execution-pipeline.md` — generated files whose generators emit English only; a hand-written translation would go stale on regeneration.
|
||||
- [cordis-api/inherited.md](../cordis-api/inherited.md) — generated without a reviewed Chinese counterpart, so both website locales project the English source.
|
||||
- `docs/AGENTS.md`, `.agents/notes/**/AGENTS.md`, and their `CLAUDE.md` instruction symlinks — agent instructions, maintained in English only like the root `AGENTS.md`.
|
||||
- `docs/i18n/terminology.md` and [style-samples.md](style-samples.md) — both are bilingual by construction.
|
||||
- [translation-prompt.md](translation-prompt.md) — the automated pipeline's prompt template; its body is machine-consumed verbatim, so a paired translation would change pipeline behavior.
|
||||
@@ -55,4 +57,4 @@ The gate's limit, stated plainly: **a green gate means the pair was confirmed co
|
||||
|
||||
## Division of labor
|
||||
|
||||
Counterparts here are produced by an agent running [dsh-translate-docs](../../.agents/skills/dsh-translate-docs/SKILL.md) and reviewed by a human — inference is cheap here, review attention is the scarce resource. The gate checks pair completeness, recorded hashes, switchers, and its documented structural signature. Review still owns translation quality, terminology, and structural requirements that the signature does not encode. The prompt contract is executable: [scripts/translation-prompt.ts](../../scripts/translation-prompt.ts) renders the committed template (terminology injected; the template carries its own calibrated rules) into either direction and parses the three-section response, while `verify-translation-prompt` exercises both render directions and the checked-in example in `doc-sync`.
|
||||
Counterparts here are produced by an agent running [dsh-translate-docs](../../.agents/skills/dsh-translate-docs/SKILL.md) and reviewed by a human — inference is cheap here, review attention is the scarce resource. The gate checks pair completeness, recorded hashes, the Chinese backlink and authored-source switcher (with the documented generated-source exception), and its documented structural signature. Review still owns translation quality, terminology, and structural requirements that the signature does not encode. The prompt contract is executable: [scripts/translation-prompt.ts](../../scripts/translation-prompt.ts) renders the committed template (terminology injected; the template carries its own calibrated rules) into either direction and parses the three-section response, while `verify-translation-prompt` exercises both render directions and the checked-in example in `doc-sync`.
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
用 blob hash 而不是 commit hash,这样同一个 PR 里改动的文件也能算出记录(`git hash-object foo.md`),一致性是纯内容比较。`--write` 会先把这些快照存入本地 Git 对象库再写下记录,未提交的工作树内容也不例外;它还会在内容寻址的 `refs/dsh/translation-pairing/snapshots/` ref 下固定每个不同的已存 blob,使垃圾回收无法让已记录的恢复指针失效。因此记录的 hash 能还原任一侧上次确认时的确切文本,所以失去同步的配对是「按被改一侧的 diff 最小化地修补另一侧」,从不整篇重译。`pnpm run gen-translation-brief <pair>` 会以能安全对齐的最窄粒度——先是有改动的 Markdown 单元,再是标题小节,最后是整篇文档——机械地汇集这次更新的工作集:被改一侧自上次确认以来的 diff、每个改动块的三方文本、改动触及的术语表行,以及有约束力的更新规则;仅落在配对中逐字节一致的围栏代码块内的改动可以直接算出,`--apply` 则经结构签名校验后把它拼接进对侧文件([briefed-updates Agent Note](../../.agents/notes/implemented/process/2026-07-26-briefed-minimal-translation-updates.md))。两侧对齐后,`pnpm run verify-translation-pairing --write <pair>` 重新记录两个 hash;那份 yaml diff 就是「确认一致」这个动作本身,可以被评审,也正因如此,`--write` 要求点名你确认过的配对(`--write --all` 是显式的全语料形式)。
|
||||
|
||||
当两个分支都包含同一配对的有效确认时,已安装的 `dsh-translation-pairing` Git 合并驱动只会在 Git 默认文本合并能分别干净合并记录所指向的英文三方 blob 与中文三方 blob,且合并后的配对仍保留两侧的语言切换行和结构签名时,组合出一份新记录。任何无法确定的情形都保留为普通冲突;`pnpm run resolve-translation-pairing-conflicts` 会对已经停止的合并执行同一套遇错即保留冲突的操作,暂存每份可安全生成的配对记录,并在还有其他配对冲突时以非零状态退出。[自动配对合并 Agent Note](../../.agents/notes/implemented/process/2026-08-08-automatic-translation-pairing-merges.md) 负责记录该机制与备选方案。
|
||||
- **语言切换行。** 两个文件在各自 H1 标题之后立即互链:英文文件带 `English | [中文](foo.zh.md)`,中文文件带 `[English](foo.md) | 中文`。
|
||||
当两个分支都包含同一配对的有效确认时,已安装的 `dsh-translation-pairing` Git 合并驱动只会在 Git 默认文本合并能分别干净合并记录所指向的英文三方 blob 与中文三方 blob,且合并后的配对仍保留必需的语言切换行和结构签名时,组合出一份新记录。中文文件必须保留指向英文的反向链接;普通撰写的英文源必须保留指向中文的链接,而清单内的生成英文源不作此要求。任何无法确定的情形都保留为普通冲突;`pnpm run resolve-translation-pairing-conflicts` 会对已经停止的合并执行同一套遇错即保留冲突的操作,暂存每份可安全生成的配对记录,并在还有其他配对冲突时以非零状态退出。[自动配对合并 Agent Note](../../.agents/notes/implemented/process/2026-08-08-automatic-translation-pairing-merges.md) 负责记录该机制与备选方案。
|
||||
- **语言切换行。** 中文文件一律在 H1 标题后立即以 `[English](foo.md) | 中文` 链回英文。普通撰写的英文文件在同一位置以 `English | [中文](foo.zh.md)` 互链;清单内的生成英文源省略此行,以便与生成器输出逐字节一致。
|
||||
- **结构与另一侧一一对应。** 标题深度与顺序、列表类型、有序列表起始编号、列表项数量、表格行列数、链接目标与逐字节一致的代码块在配对两侧一一对应;完整保持规则见 [translation-rules.md](translation-rules.md)。既有 Markdown 门禁对 `.zh.md` 文件原样生效(`verify-md-wrap`、`verify-md-links`)。
|
||||
|
||||
## 门禁:verify-translation-pairing
|
||||
@@ -26,7 +26,7 @@
|
||||
`pnpm run verify-translation-pairing`(`doc-sync`(文档同步门禁)的一环,贡献者会针对文档变更在本地运行,CI 则会完整运行)机械地强制执行这份约定:
|
||||
|
||||
1. 范围内的每篇文档都有完整配对。发现 README 时,basename 不区分大小写,因此 `missions/readme.md` 与其他文档根一样属于范围。
|
||||
2. 任何已存在的配对产物都完整且一致:三个文件齐全、每一侧的当前 blob hash 等于记录值(改了任一侧而没重新确认配对就变红)、双方都带语言切换行、结构签名按序一致:标题深度、逐字节一致的代码块(信息字符串与内容)、表格行列数、列表类型、有序列表起始编号、列表项数量,以及除切换行之外的每个链接目标。
|
||||
2. 任何已存在的配对产物都完整且一致:三个文件齐全、每一侧的当前 blob hash 等于记录值(改了任一侧而没重新确认配对就变红)、中文侧和所有普通撰写的英文源都带语言切换行(清单内的生成英文源除外)、结构签名按序一致:标题深度、逐字节一致的代码块(信息字符串与内容)、表格行列数、列表类型、有序列表起始编号、列表项数量,以及除切换行之外的每个链接目标。
|
||||
3. 列为 `excluded` 的文件完全没有 `.zh.md`,也没有 `.i18n.yaml`。`.agents/notes/archived/` 下冻结的 Agent Note 不受这个持续演进的门禁约束;专用校验器会要求其现有的三个配对文件完整,并将其封存。
|
||||
|
||||
面向源码的代码门禁会把精确的 `.zh.md` 围栏序列视为其无后缀兄弟文件的派生内容,而不会再次编译相同代码或在 manifest 中重复登记。该序列必须在长度、顺序、围栏类型和按字节精确的正文上一致;否则两份副本仍会独立受检,配对门禁也会报告结构不匹配。
|
||||
@@ -43,9 +43,11 @@
|
||||
|
||||
**范围**:除 vendor 源码外的全部 README,以及 `.agents/notes/**`、`docs/**` 与 `python/**` 下的全部活跃文档。匹配 README 时只看文件名且不区分大小写,因此今后新增的目录无需再修改 manifest。依赖目录、被忽略的构建产物目录以及冻结的 `.agents/notes/archived/` 目录树只在发现阶段排除,不属于持续演进的翻译源文档。
|
||||
|
||||
有经评审中文对侧的生成英文参考文档和图文档遵循配对规则。生成器仍是英文真源,新鲜度门禁与配对门禁各自独立强制其约束;重新生成导致英文变化后,配对会保持失去同步状态,直至经评审的中文对侧完成更新并重新记录。生成的英文源文件不含普通撰写文档所带的语言切换行,因为添加该行会使生成器新鲜度检查失败;中文对侧仍链接回英文源。生成页的中文对侧只能改写若直译便不再符合经评审译文事实的自指生成与维护说明;所有技术内容仍受普通忠实性规则约束。
|
||||
|
||||
**排除**(永不配对,门禁拒绝为它们建 `.zh.md` 或 `.i18n.yaml`):
|
||||
|
||||
- `docs/cordis-catalog/`、`docs/tool-catalog/`、`docs/config-catalog.md`、`docs/persistence-catalog.md`、`docs/module-graph.md`、`docs/agent-lifecycle.md`、`docs/capability-seams.md`、`docs/event-producer-consumer.md`、`docs/graph-atlas.md` 与 `docs/tool-execution-pipeline.md`:生成文件,其生成器只输出英文;手写译文会在重新生成时变得陈旧。
|
||||
- [cordis-api/inherited.md](../cordis-api/inherited.md):该生成文档没有经评审的中文对侧,因此网站的两个 locale 都投影英文源文件。
|
||||
- `docs/AGENTS.md`、`.agents/notes/**/AGENTS.md` 以及指向它们的 `CLAUDE.md` 指令符号链接:agent 指令,与根 `AGENTS.md` 一样只以英文维护。
|
||||
- `docs/i18n/terminology.md` 与 [style-samples.md](style-samples.md):二者本身即为中英对照文档。
|
||||
- [translation-prompt.md](translation-prompt.md):自动翻译流水线的提示词模板;正文逐字进入模型请求,配对翻译会改变流水线行为。
|
||||
@@ -55,4 +57,4 @@
|
||||
|
||||
## 分工
|
||||
|
||||
这里的对侧文件由运行 [dsh-translate-docs](../../.agents/skills/dsh-translate-docs/SKILL.md) 的 agent 生成,再由人评审:在这里推理(inference)很便宜,评审注意力才是稀缺资源。门禁负责检查配对是否完整、记录的 hash、语言切换行以及本文列出的结构签名;翻译质量、术语和签名未涵盖的结构要求仍由评审把关。提示词约定也有可执行实现:[scripts/translation-prompt.ts](../../scripts/translation-prompt.ts) 会把仓库内置的模板(注入术语表;模板自带经人工校准的规则)渲染为英译中或中译英两个方向的提示词,并解析三段式响应;`doc-sync` 中的 `verify-translation-prompt` 会检查两个渲染方向与仓库内示例。
|
||||
这里的对侧文件由运行 [dsh-translate-docs](../../.agents/skills/dsh-translate-docs/SKILL.md) 的 agent 生成,再由人评审:在这里推理(inference)很便宜,评审注意力才是稀缺资源。门禁负责检查配对是否完整、记录的 hash、中文反向链接和普通撰写源的切换行(生成源按本文规则例外),以及本文列出的结构签名;翻译质量、术语和签名未涵盖的结构要求仍由评审把关。提示词约定也有可执行实现:[scripts/translation-prompt.ts](../../scripts/translation-prompt.ts) 会把仓库内置的模板(注入术语表;模板自带经人工校准的规则)渲染为英译中或中译英两个方向的提示词,并解析三段式响应;`doc-sync` 中的 `verify-translation-prompt` 会检查两个渲染方向与仓库内示例。
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
| Round | Round | | 回合、目标回合、Ralph 回合 | 外层策略使用 Round 时,领域层级为 Session > Round > Turn(轮次) > Step(步骤);Round 是可选的外层策略迭代,并非每个会话轮次都具有的通用层级。Goal Round 与 Ralph Round 均保留英文。一个 Round 承载一个轮次,步骤隶属于该轮次;明确的零步骤轮次仍保持原义。 |
|
||||
| schema | schema | | | |
|
||||
| schema DSL | schema DSL | | | |
|
||||
| seam | seam | | 接缝 | 本仓库的命名架构概念,正文保留英文;与 `extension point` 是不同概念 |
|
||||
| seam | seam | | 接缝 | 一个可替换能力的整体,包含 Service Definition / Service provider / Consumer 三种角色;角色需要独立演化时才拆包,也可由同一包承担多个角色。以 `packages/bash` 为范例;Service Definition 是 Cordis `Service`(抽象类或具体 registry 服务),不是 TypeScript interface。任何单一角色、普通边界或扩展点都不能称为 seam。本仓库正文保留英文;与 `extension point` 是不同概念 |
|
||||
| skill | skill | skill(技能) | | |
|
||||
| slot | slot | | 坑位、孔位 | 客户端架构中的具名可注册位置,保留英文 |
|
||||
| spill | spill | | | 工具输出超限落盘机制;组合词写 `spill 文件`、`spill 路径` |
|
||||
@@ -84,7 +84,7 @@
|
||||
| cancel | 取消 | | | |
|
||||
| canary test | canary 测试 | | 金丝雀测试 | 本仓库保留 `canary` |
|
||||
| capability | 能力 | | | 必须与 `feature` → `功能` 区分 |
|
||||
| capability seam | 能力 seam | | 功能 seam、能力接缝 | 本仓库接口、实现与消费方分离的命名架构概念;普通 `seam` 仍按其词条处理 |
|
||||
| capability seam | 能力 seam | | 功能 seam、能力接缝 | 本仓库 Service Definition、Service provider 与 Consumer 三种角色组成完整可替换能力的命名架构概念;普通 `seam` 仍按其词条处理 |
|
||||
| feature | 功能 | | 能力 | SDK 产品与工程模型中的可管理产品单元 |
|
||||
| feature option | 功能选项 | | variant | 一项 SDK 功能内有限、可选择的实现或配置 |
|
||||
| checkpoint | 检查点 | | | |
|
||||
@@ -137,6 +137,7 @@
|
||||
| message | 消息 | | | |
|
||||
| mod | 模组 | | | |
|
||||
| model provider | 模型提供方 | | | |
|
||||
| model selection | 模型选择 | | 模型目标 | 面向 Agent 的提供方、模型和可选推理强度选择。 |
|
||||
| module | 模块 | | | |
|
||||
| non-escalation | 非升权 | | 非升级、不可升级 | 仅用于安全与权限语境,指主体不得获得超出既有授权的权限;普通升级不适用此行 |
|
||||
| npm dependency | NPM 依赖 | | | `package.json` 中的包关系;`dependencies`、`devDependencies` 等字段保持原样 |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Translation prompt (pipeline asset)
|
||||
|
||||
本文件是自动翻译流水线的 prompt 模板;从 `# Translation Prompt` 开始的正文会逐字进入模型请求,因此本文件不参与双语配对(见 [README.md](README.md) 排除清单)。模板正文与内嵌 few-shot 正误例由 jingtingxiang 基于对存量译文的质量评审撰写,是流水线行为的拍板基线。渲染时把 [terminology.md](terminology.md) 整表填入 `{{terminology}}`;除此之外不注入任何其他仓库文件(translation-rules.md 约束人和 agent 的翻译工作,不注入本模板)。[style-samples.md](style-samples.md) 定义文体,模板中的 Examples 只用于说明典型问题,两者冲突时以文体样例为准。[提示词 v4 约定 Agent Note](../../.agents/notes/implemented/process/2026-07-23-translation-prompt-v4-contract.md) 记录兼容协议;v7 保留该协议并选择性吸收经评估的生成质量改进。修改本文件会改变翻译行为,需正常经过 PR 评审。
|
||||
本文件是自动翻译流水线的 prompt 模板;从 `# Translation Prompt` 开始的正文会逐字进入模型请求,因此本文件不参与双语配对(见 [README.md](README.md) 排除清单)。模板正文与内嵌 few-shot 正误例由 jingtingxiang 基于对存量译文的质量评审撰写,是流水线行为的拍板基线。渲染时把 [terminology.md](terminology.md) 整表填入 `{{terminology}}`;除此之外不注入任何其他仓库文件(translation-rules.md 约束人和 agent 的翻译工作,不注入本模板)。[style-samples.md](style-samples.md) 定义文体,模板中的 Examples 只用于说明典型问题,两者冲突时以文体样例为准。本模板遵循 [提示词 v4 约定 Agent Note](../../.agents/notes/implemented/process/2026-07-23-translation-prompt-v4-contract.md) 记录的兼容协议。修改本文件会改变翻译行为,需正常经过 PR 评审。
|
||||
|
||||
## 占位符约定
|
||||
|
||||
@@ -91,7 +91,7 @@ A lower-priority rule may refine but never override a higher-priority requiremen
|
||||
- Avoid repeating the same ordinary verb in close proximity when a natural equivalent preserves the exact meaning. Never vary a terminology-table form, defined concept, or contract verb merely for stylistic variety.
|
||||
|
||||
#### When translating into Chinese
|
||||
- When a number modifies a noun, include a natural Chinese classifier or measure word when Chinese grammar requires one. For example: "three-package seam" → "由三个包构成的 seam", not "三包 seam". Do not add classifiers to code, identifiers, versions, units, or fixed names.
|
||||
- When a number modifies a noun, include a natural Chinese classifier or measure word when Chinese grammar requires one. For example: "three-role capability seam" → "包含三种角色的能力 seam", not "三角色 seam". Do not add classifiers to code, identifiers, versions, units, or fixed names.
|
||||
|
||||
### Punctuation
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write
|
||||
# pnpm run verify-translation-pairing --write docs/i18n/translation-rules.md
|
||||
translation-rules.md: fb6aa9ac05bebe68ff9213af99f64457bdb1ad6f
|
||||
translation-rules.zh.md: 04dd0a704e19502c676ea0966437870c5af0624f
|
||||
|
||||
6
docs/module-graph.i18n.yaml
Normal file
6
docs/module-graph.i18n.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/module-graph.md
|
||||
module-graph.md: 26e542f613e78a2c6069570d3918eb042ab82580
|
||||
module-graph.zh.md: 5010bcadadf78c0184adbe2960322f3c704c4b4e
|
||||
@@ -25,7 +25,9 @@ flowchart TD
|
||||
end
|
||||
subgraph group_core["packages/core"]
|
||||
pkg_agent["agent"]
|
||||
pkg_agent_default_model["agent-default-model"]
|
||||
pkg_agent_loop["agent-loop"]
|
||||
pkg_agent_tool_mode["agent-tool-mode"]
|
||||
pkg_scope["scope"]
|
||||
pkg_session["session"]
|
||||
pkg_system_prompt["system-prompt"]
|
||||
@@ -43,6 +45,7 @@ flowchart TD
|
||||
pkg_bash_local["bash-local"]
|
||||
pkg_bash_sandbox["bash-sandbox"]
|
||||
pkg_pwsh_local["pwsh-local"]
|
||||
pkg_pwsh_sandbox["pwsh-sandbox"]
|
||||
pkg_tool_bash["tool-bash"]
|
||||
pkg_tool_pwsh["tool-pwsh"]
|
||||
end
|
||||
@@ -140,6 +143,7 @@ flowchart TD
|
||||
pkg_client_runtime["client-runtime"]
|
||||
pkg_client_schema_form["client-schema-form"]
|
||||
pkg_client_test_runtime["client-test-runtime"]
|
||||
pkg_client_ui_agent_preset["client-ui-agent-preset"]
|
||||
pkg_client_ui_command["client-ui-command"]
|
||||
pkg_client_ui_conversation["client-ui-conversation"]
|
||||
pkg_client_ui_deliverables["client-ui-deliverables"]
|
||||
@@ -221,6 +225,10 @@ flowchart TD
|
||||
subgraph group_mcp["packages/mcp"]
|
||||
pkg_mcp_client["mcp-client"]
|
||||
end
|
||||
subgraph group_preset["packages/preset"]
|
||||
pkg_agent_presets["agent-presets"]
|
||||
pkg_persona["persona"]
|
||||
end
|
||||
subgraph group_pty["packages/pty"]
|
||||
pkg_pty["pty"]
|
||||
pkg_pty_local["pty-local"]
|
||||
@@ -231,6 +239,7 @@ flowchart TD
|
||||
pkg_sandbox["sandbox"]
|
||||
pkg_sandbox_local["sandbox-local"]
|
||||
pkg_sandbox_policy["sandbox-policy"]
|
||||
pkg_sandbox_windows_acl["sandbox-windows-acl"]
|
||||
end
|
||||
subgraph group_scaffold["packages/scaffold"]
|
||||
pkg_helper["helper"]
|
||||
@@ -311,9 +320,9 @@ flowchart TD
|
||||
pkg_code_runtime --> pkg_invariants
|
||||
pkg_e2b --> pkg_invariants
|
||||
pkg_jsonrpc_demo --> pkg_invariants
|
||||
pkg_host_apiproxy --> pkg_invariants
|
||||
pkg_host_directory_picker --> pkg_invariants
|
||||
pkg_host_webserver --> pkg_invariants
|
||||
pkg_sandbox_windows_acl --> pkg_invariants
|
||||
pkg_storage --> pkg_invariants
|
||||
pkg_subprocess --> pkg_invariants
|
||||
pkg_type_meta --> pkg_invariants
|
||||
@@ -379,6 +388,7 @@ flowchart TD
|
||||
pkg_system_prompt --> pkg_scope
|
||||
pkg_skill --> pkg_invariants
|
||||
pkg_skill --> pkg_llm
|
||||
pkg_skill --> pkg_scope
|
||||
pkg_web --> pkg_invariants
|
||||
pkg_web --> pkg_llm
|
||||
pkg_api_gateway --> pkg_client_connection
|
||||
@@ -388,11 +398,6 @@ flowchart TD
|
||||
pkg_client_locale --> pkg_client_ui_primitives
|
||||
pkg_client_locale --> pkg_client_ui_slots
|
||||
pkg_client_locale --> pkg_invariants
|
||||
pkg_client_test_runtime --> pkg_client_runtime
|
||||
pkg_client_test_runtime --> pkg_client_ui_slots
|
||||
pkg_client_test_runtime --> pkg_client_web_react
|
||||
pkg_client_test_runtime --> pkg_host_apiproxy
|
||||
pkg_client_test_runtime --> pkg_invariants
|
||||
pkg_client_ui_models --> pkg_client_connection
|
||||
pkg_client_ui_models --> pkg_client_runtime
|
||||
pkg_client_ui_models --> pkg_client_schema_form
|
||||
@@ -415,8 +420,6 @@ flowchart TD
|
||||
pkg_lsp --> pkg_brand
|
||||
pkg_lsp --> pkg_invariants
|
||||
pkg_lsp --> pkg_llm
|
||||
pkg_sandbox --> pkg_invariants
|
||||
pkg_sandbox --> pkg_llm
|
||||
pkg_settings_local --> pkg_atomic_write
|
||||
pkg_settings_local --> pkg_invariants
|
||||
pkg_settings_local --> pkg_paths
|
||||
@@ -427,18 +430,8 @@ flowchart TD
|
||||
pkg_agent --> pkg_session
|
||||
pkg_agent --> pkg_system_prompt
|
||||
pkg_agent --> pkg_type_meta
|
||||
pkg_bash --> pkg_invariants
|
||||
pkg_bash --> pkg_sandbox
|
||||
pkg_bash --> pkg_subprocess
|
||||
pkg_fs --> pkg_brand
|
||||
pkg_fs --> pkg_invariants
|
||||
pkg_fs --> pkg_llm
|
||||
pkg_fs --> pkg_sandbox
|
||||
pkg_skill_badge --> pkg_invariants
|
||||
pkg_skill_badge --> pkg_skill
|
||||
pkg_compact --> pkg_invariants
|
||||
pkg_compact --> pkg_llm
|
||||
pkg_compact --> pkg_session
|
||||
pkg_web_fetch_local --> pkg_invariants
|
||||
pkg_web_fetch_local --> pkg_timeout
|
||||
pkg_web_fetch_local --> pkg_web
|
||||
@@ -492,9 +485,17 @@ flowchart TD
|
||||
pkg_code_runtime_worker --> pkg_invariants
|
||||
pkg_code_runtime_worker --> pkg_session
|
||||
pkg_code_runtime_worker --> pkg_timeout
|
||||
pkg_sandbox_local --> pkg_invariants
|
||||
pkg_sandbox_local --> pkg_llm
|
||||
pkg_sandbox_local --> pkg_sandbox
|
||||
pkg_agent_presets --> pkg_atomic_write
|
||||
pkg_agent_presets --> pkg_invariants
|
||||
pkg_agent_presets --> pkg_paths
|
||||
pkg_agent_presets --> pkg_scope
|
||||
pkg_agent_presets --> pkg_session
|
||||
pkg_agent_presets --> pkg_settings
|
||||
pkg_persona --> pkg_invariants
|
||||
pkg_persona --> pkg_system_prompt
|
||||
pkg_sandbox --> pkg_invariants
|
||||
pkg_sandbox --> pkg_llm
|
||||
pkg_sandbox --> pkg_session
|
||||
pkg_session_persistence --> pkg_brand
|
||||
pkg_session_persistence --> pkg_invariants
|
||||
pkg_session_persistence --> pkg_session
|
||||
@@ -502,15 +503,15 @@ flowchart TD
|
||||
pkg_session_projection --> pkg_invariants
|
||||
pkg_session_projection --> pkg_session
|
||||
pkg_llm_retry --> pkg_agent
|
||||
pkg_llm_retry --> pkg_brand
|
||||
pkg_llm_retry --> pkg_invariants
|
||||
pkg_llm_retry --> pkg_llm
|
||||
pkg_llm_retry --> pkg_session
|
||||
pkg_llm_retry --> pkg_timeout
|
||||
pkg_token_meter --> pkg_compact
|
||||
pkg_token_meter --> pkg_invariants
|
||||
pkg_token_meter --> pkg_llm
|
||||
pkg_token_meter --> pkg_session
|
||||
pkg_token_meter --> pkg_session_projection
|
||||
pkg_agent_default_model --> pkg_agent
|
||||
pkg_agent_default_model --> pkg_invariants
|
||||
pkg_agent_default_model --> pkg_llm
|
||||
pkg_agent_default_model --> pkg_settings
|
||||
pkg_goal --> pkg_agent
|
||||
pkg_goal --> pkg_brand
|
||||
pkg_goal --> pkg_invariants
|
||||
@@ -519,22 +520,13 @@ flowchart TD
|
||||
pkg_goal --> pkg_session
|
||||
pkg_goal --> pkg_session_projection
|
||||
pkg_goal --> pkg_type_meta
|
||||
pkg_bash_local --> pkg_bash
|
||||
pkg_bash_local --> pkg_invariants
|
||||
pkg_bash_local --> pkg_subprocess
|
||||
pkg_bash_local --> pkg_timeout
|
||||
pkg_pwsh_local --> pkg_bash
|
||||
pkg_pwsh_local --> pkg_invariants
|
||||
pkg_pwsh_local --> pkg_subprocess
|
||||
pkg_pwsh_local --> pkg_timeout
|
||||
pkg_fs_local --> pkg_fs
|
||||
pkg_fs_local --> pkg_invariants
|
||||
pkg_fs_policy --> pkg_fs
|
||||
pkg_fs_policy --> pkg_invariants
|
||||
pkg_skill_local --> pkg_fs
|
||||
pkg_skill_local --> pkg_invariants
|
||||
pkg_skill_local --> pkg_paths
|
||||
pkg_skill_local --> pkg_skill
|
||||
pkg_bash --> pkg_invariants
|
||||
pkg_bash --> pkg_sandbox
|
||||
pkg_bash --> pkg_subprocess
|
||||
pkg_fs --> pkg_brand
|
||||
pkg_fs --> pkg_invariants
|
||||
pkg_fs --> pkg_llm
|
||||
pkg_fs --> pkg_sandbox
|
||||
pkg_web_search_deepseek --> pkg_agent
|
||||
pkg_web_search_deepseek --> pkg_credentials
|
||||
pkg_web_search_deepseek --> pkg_environment
|
||||
@@ -543,22 +535,10 @@ flowchart TD
|
||||
pkg_web_search_deepseek --> pkg_web
|
||||
pkg_spill_local --> pkg_invariants
|
||||
pkg_spill_local --> pkg_spill
|
||||
pkg_hook_protocol --> pkg_bash
|
||||
pkg_hook_protocol --> pkg_invariants
|
||||
pkg_hook_protocol --> pkg_session
|
||||
pkg_llm_replay --> pkg_compact
|
||||
pkg_llm_replay --> pkg_invariants
|
||||
pkg_llm_replay --> pkg_llm
|
||||
pkg_llm_replay --> pkg_session
|
||||
pkg_loader_smoke --> pkg_agent
|
||||
pkg_loader_smoke --> pkg_invariants
|
||||
pkg_loader_smoke --> pkg_llm
|
||||
pkg_loader_smoke --> pkg_session
|
||||
pkg_headless --> pkg_agent
|
||||
pkg_headless --> pkg_host_apiproxy
|
||||
pkg_headless --> pkg_host_webserver
|
||||
pkg_headless --> pkg_invariants
|
||||
pkg_headless --> pkg_session
|
||||
pkg_client_ui_layout --> pkg_client_runtime
|
||||
pkg_client_ui_layout --> pkg_client_ui_slots
|
||||
pkg_client_ui_layout --> pkg_client_ui_theme
|
||||
@@ -566,13 +546,8 @@ flowchart TD
|
||||
pkg_time_context --> pkg_agent
|
||||
pkg_time_context --> pkg_invariants
|
||||
pkg_time_context --> pkg_session
|
||||
pkg_tmux_context --> pkg_agent
|
||||
pkg_tmux_context --> pkg_bash
|
||||
pkg_tmux_context --> pkg_invariants
|
||||
pkg_tmux_context --> pkg_session
|
||||
pkg_fs_e2b --> pkg_e2b
|
||||
pkg_fs_e2b --> pkg_fs
|
||||
pkg_fs_e2b --> pkg_invariants
|
||||
pkg_host_apiproxy --> pkg_agent_presets
|
||||
pkg_host_apiproxy --> pkg_invariants
|
||||
pkg_host_directory_picker_browse --> pkg_client_locale
|
||||
pkg_host_directory_picker_browse --> pkg_client_runtime
|
||||
pkg_host_directory_picker_browse --> pkg_client_ui_primitives
|
||||
@@ -598,16 +573,13 @@ flowchart TD
|
||||
pkg_user_interaction --> pkg_agent
|
||||
pkg_user_interaction --> pkg_invariants
|
||||
pkg_user_interaction --> pkg_llm
|
||||
pkg_lsp_local --> pkg_brand
|
||||
pkg_lsp_local --> pkg_fs
|
||||
pkg_lsp_local --> pkg_invariants
|
||||
pkg_lsp_local --> pkg_llm
|
||||
pkg_lsp_local --> pkg_lsp
|
||||
pkg_lsp_local --> pkg_subprocess
|
||||
pkg_lsp_local --> pkg_timeout
|
||||
pkg_pty --> pkg_agent
|
||||
pkg_pty --> pkg_brand
|
||||
pkg_pty --> pkg_invariants
|
||||
pkg_sandbox_local --> pkg_invariants
|
||||
pkg_sandbox_local --> pkg_llm
|
||||
pkg_sandbox_local --> pkg_sandbox
|
||||
pkg_sandbox_local --> pkg_session
|
||||
pkg_sandbox_policy --> pkg_agent
|
||||
pkg_sandbox_policy --> pkg_invariants
|
||||
pkg_sandbox_policy --> pkg_sandbox
|
||||
@@ -665,24 +637,30 @@ flowchart TD
|
||||
pkg_goal_session --> pkg_invariants
|
||||
pkg_goal_session --> pkg_llm
|
||||
pkg_goal_session --> pkg_session
|
||||
pkg_bash_sandbox --> pkg_bash
|
||||
pkg_bash_sandbox --> pkg_bash_local
|
||||
pkg_bash_sandbox --> pkg_invariants
|
||||
pkg_bash_sandbox --> pkg_sandbox
|
||||
pkg_bash_sandbox --> pkg_sandbox_policy
|
||||
pkg_fs_sandbox --> pkg_fs
|
||||
pkg_fs_sandbox --> pkg_fs_local
|
||||
pkg_fs_sandbox --> pkg_invariants
|
||||
pkg_fs_sandbox --> pkg_sandbox
|
||||
pkg_fs_sandbox --> pkg_sandbox_policy
|
||||
pkg_command_compact --> pkg_commands
|
||||
pkg_command_compact --> pkg_compact
|
||||
pkg_command_compact --> pkg_invariants
|
||||
pkg_compact_tool_result_prune --> pkg_compact
|
||||
pkg_compact_tool_result_prune --> pkg_invariants
|
||||
pkg_compact_tool_result_prune --> pkg_llm
|
||||
pkg_compact_tool_result_prune --> pkg_session
|
||||
pkg_compact_tool_result_prune --> pkg_token_meter
|
||||
pkg_bash_local --> pkg_bash
|
||||
pkg_bash_local --> pkg_invariants
|
||||
pkg_bash_local --> pkg_subprocess
|
||||
pkg_bash_local --> pkg_timeout
|
||||
pkg_pwsh_local --> pkg_bash
|
||||
pkg_pwsh_local --> pkg_invariants
|
||||
pkg_pwsh_local --> pkg_subprocess
|
||||
pkg_pwsh_local --> pkg_timeout
|
||||
pkg_fs_local --> pkg_fs
|
||||
pkg_fs_local --> pkg_invariants
|
||||
pkg_fs_policy --> pkg_fs
|
||||
pkg_fs_policy --> pkg_invariants
|
||||
pkg_skill_local --> pkg_fs
|
||||
pkg_skill_local --> pkg_invariants
|
||||
pkg_skill_local --> pkg_paths
|
||||
pkg_skill_local --> pkg_skill
|
||||
pkg_compact --> pkg_brand
|
||||
pkg_compact --> pkg_commands
|
||||
pkg_compact --> pkg_invariants
|
||||
pkg_compact --> pkg_llm
|
||||
pkg_compact --> pkg_session
|
||||
pkg_hook_protocol --> pkg_bash
|
||||
pkg_hook_protocol --> pkg_invariants
|
||||
pkg_hook_protocol --> pkg_session
|
||||
pkg_session_query --> pkg_brand
|
||||
pkg_session_query --> pkg_invariants
|
||||
pkg_session_query --> pkg_llm
|
||||
@@ -699,13 +677,23 @@ flowchart TD
|
||||
pkg_api_remotes --> pkg_session
|
||||
pkg_api_remotes --> pkg_session_persistence
|
||||
pkg_api_remotes --> pkg_typert_registry
|
||||
pkg_client_ui_conversation --> pkg_client_locale
|
||||
pkg_client_ui_conversation --> pkg_client_runtime
|
||||
pkg_client_ui_conversation --> pkg_client_ui_primitives
|
||||
pkg_client_ui_conversation --> pkg_client_ui_slash
|
||||
pkg_client_ui_conversation --> pkg_client_ui_slots
|
||||
pkg_client_ui_conversation --> pkg_invariants
|
||||
pkg_client_ui_conversation --> pkg_token_meter
|
||||
pkg_headless --> pkg_agent
|
||||
pkg_headless --> pkg_agent_default_model
|
||||
pkg_headless --> pkg_invariants
|
||||
pkg_headless --> pkg_llm
|
||||
pkg_headless --> pkg_session
|
||||
pkg_client_test_runtime --> pkg_client_runtime
|
||||
pkg_client_test_runtime --> pkg_client_ui_slots
|
||||
pkg_client_test_runtime --> pkg_client_web_react
|
||||
pkg_client_test_runtime --> pkg_host_apiproxy
|
||||
pkg_client_test_runtime --> pkg_invariants
|
||||
pkg_tmux_context --> pkg_agent
|
||||
pkg_tmux_context --> pkg_bash
|
||||
pkg_tmux_context --> pkg_invariants
|
||||
pkg_tmux_context --> pkg_session
|
||||
pkg_fs_e2b --> pkg_e2b
|
||||
pkg_fs_e2b --> pkg_fs
|
||||
pkg_fs_e2b --> pkg_invariants
|
||||
pkg_command_feedback --> pkg_commands
|
||||
pkg_command_feedback --> pkg_invariants
|
||||
pkg_command_feedback --> pkg_session
|
||||
@@ -722,6 +710,13 @@ flowchart TD
|
||||
pkg_permission --> pkg_session_projection
|
||||
pkg_permission --> pkg_settings
|
||||
pkg_permission --> pkg_user_approval
|
||||
pkg_lsp_local --> pkg_brand
|
||||
pkg_lsp_local --> pkg_fs
|
||||
pkg_lsp_local --> pkg_invariants
|
||||
pkg_lsp_local --> pkg_llm
|
||||
pkg_lsp_local --> pkg_lsp
|
||||
pkg_lsp_local --> pkg_subprocess
|
||||
pkg_lsp_local --> pkg_timeout
|
||||
pkg_pty_local --> pkg_agent
|
||||
pkg_pty_local --> pkg_invariants
|
||||
pkg_pty_local --> pkg_pty
|
||||
@@ -738,6 +733,11 @@ flowchart TD
|
||||
pkg_tasks_local --> pkg_invariants
|
||||
pkg_tasks_local --> pkg_tasks
|
||||
pkg_tasks_local --> pkg_timeout
|
||||
pkg_token_meter --> pkg_compact
|
||||
pkg_token_meter --> pkg_invariants
|
||||
pkg_token_meter --> pkg_llm
|
||||
pkg_token_meter --> pkg_session
|
||||
pkg_token_meter --> pkg_session_projection
|
||||
pkg_agent_loop --> pkg_agent
|
||||
pkg_agent_loop --> pkg_invariants
|
||||
pkg_agent_loop --> pkg_llm
|
||||
@@ -746,6 +746,8 @@ flowchart TD
|
||||
pkg_agent_loop --> pkg_session_persistence
|
||||
pkg_agent_loop --> pkg_system_prompt
|
||||
pkg_agent_loop --> pkg_tools
|
||||
pkg_agent_tool_mode --> pkg_invariants
|
||||
pkg_agent_tool_mode --> pkg_tools
|
||||
pkg_tool_goal --> pkg_agent
|
||||
pkg_tool_goal --> pkg_goal
|
||||
pkg_tool_goal --> pkg_invariants
|
||||
@@ -758,6 +760,21 @@ flowchart TD
|
||||
pkg_bash_env --> pkg_paths
|
||||
pkg_bash_env --> pkg_session_persistence
|
||||
pkg_bash_env --> pkg_tools
|
||||
pkg_bash_sandbox --> pkg_bash
|
||||
pkg_bash_sandbox --> pkg_bash_local
|
||||
pkg_bash_sandbox --> pkg_invariants
|
||||
pkg_bash_sandbox --> pkg_sandbox
|
||||
pkg_bash_sandbox --> pkg_sandbox_policy
|
||||
pkg_pwsh_sandbox --> pkg_bash
|
||||
pkg_pwsh_sandbox --> pkg_invariants
|
||||
pkg_pwsh_sandbox --> pkg_pwsh_local
|
||||
pkg_pwsh_sandbox --> pkg_sandbox
|
||||
pkg_pwsh_sandbox --> pkg_sandbox_policy
|
||||
pkg_fs_sandbox --> pkg_fs
|
||||
pkg_fs_sandbox --> pkg_fs_local
|
||||
pkg_fs_sandbox --> pkg_invariants
|
||||
pkg_fs_sandbox --> pkg_sandbox
|
||||
pkg_fs_sandbox --> pkg_sandbox_policy
|
||||
pkg_tool_fs --> pkg_fs
|
||||
pkg_tool_fs --> pkg_invariants
|
||||
pkg_tool_fs --> pkg_llm
|
||||
@@ -786,13 +803,9 @@ flowchart TD
|
||||
pkg_tool_skill --> pkg_llm
|
||||
pkg_tool_skill --> pkg_skill
|
||||
pkg_tool_skill --> pkg_tools
|
||||
pkg_compact_basic --> pkg_agent
|
||||
pkg_compact_basic --> pkg_compact
|
||||
pkg_compact_basic --> pkg_compact_tool_result_prune
|
||||
pkg_compact_basic --> pkg_invariants
|
||||
pkg_compact_basic --> pkg_llm
|
||||
pkg_compact_basic --> pkg_session
|
||||
pkg_compact_basic --> pkg_token_meter
|
||||
pkg_command_compact --> pkg_commands
|
||||
pkg_command_compact --> pkg_compact
|
||||
pkg_command_compact --> pkg_invariants
|
||||
pkg_subagent --> pkg_agent
|
||||
pkg_subagent --> pkg_brand
|
||||
pkg_subagent --> pkg_invariants
|
||||
@@ -853,39 +866,10 @@ flowchart TD
|
||||
pkg_agent_loop_testkit --> pkg_session
|
||||
pkg_agent_loop_testkit --> pkg_system_prompt
|
||||
pkg_agent_loop_testkit --> pkg_tools
|
||||
pkg_client_ui_command --> pkg_client_connection
|
||||
pkg_client_ui_command --> pkg_client_locale
|
||||
pkg_client_ui_command --> pkg_client_runtime
|
||||
pkg_client_ui_command --> pkg_client_ui_conversation
|
||||
pkg_client_ui_command --> pkg_client_ui_primitives
|
||||
pkg_client_ui_command --> pkg_client_ui_slash
|
||||
pkg_client_ui_command --> pkg_client_ui_slots
|
||||
pkg_client_ui_command --> pkg_invariants
|
||||
pkg_client_ui_deliverables --> pkg_client_locale
|
||||
pkg_client_ui_deliverables --> pkg_client_runtime
|
||||
pkg_client_ui_deliverables --> pkg_client_ui_conversation
|
||||
pkg_client_ui_deliverables --> pkg_client_ui_slots
|
||||
pkg_client_ui_deliverables --> pkg_invariants
|
||||
pkg_client_ui_goal --> pkg_api_remotes
|
||||
pkg_client_ui_goal --> pkg_client_locale
|
||||
pkg_client_ui_goal --> pkg_client_runtime
|
||||
pkg_client_ui_goal --> pkg_client_ui_conversation
|
||||
pkg_client_ui_goal --> pkg_client_ui_primitives
|
||||
pkg_client_ui_goal --> pkg_client_ui_slots
|
||||
pkg_client_ui_goal --> pkg_goal
|
||||
pkg_client_ui_goal --> pkg_invariants
|
||||
pkg_client_ui_task --> pkg_client_locale
|
||||
pkg_client_ui_task --> pkg_client_runtime
|
||||
pkg_client_ui_task --> pkg_client_ui_conversation
|
||||
pkg_client_ui_task --> pkg_client_ui_primitives
|
||||
pkg_client_ui_task --> pkg_client_ui_slots
|
||||
pkg_client_ui_task --> pkg_invariants
|
||||
pkg_client_ui_tool --> pkg_client_locale
|
||||
pkg_client_ui_tool --> pkg_client_runtime
|
||||
pkg_client_ui_tool --> pkg_client_ui_conversation
|
||||
pkg_client_ui_tool --> pkg_client_ui_primitives
|
||||
pkg_client_ui_tool --> pkg_client_ui_slots
|
||||
pkg_client_ui_tool --> pkg_invariants
|
||||
pkg_llm_replay --> pkg_compact
|
||||
pkg_llm_replay --> pkg_invariants
|
||||
pkg_llm_replay --> pkg_llm
|
||||
pkg_llm_replay --> pkg_session
|
||||
pkg_session_reference --> pkg_agent
|
||||
pkg_session_reference --> pkg_compact
|
||||
pkg_session_reference --> pkg_invariants
|
||||
@@ -989,9 +973,17 @@ flowchart TD
|
||||
pkg_tool_pwsh --> pkg_bash_env
|
||||
pkg_tool_pwsh --> pkg_invariants
|
||||
pkg_tool_pwsh --> pkg_llm
|
||||
pkg_tool_pwsh --> pkg_sandbox
|
||||
pkg_tool_pwsh --> pkg_sandbox_policy
|
||||
pkg_tool_pwsh --> pkg_system_prompt
|
||||
pkg_tool_pwsh --> pkg_tasks
|
||||
pkg_tool_pwsh --> pkg_tools
|
||||
pkg_tool_pwsh --> pkg_user_approval
|
||||
pkg_compact_tool_result_prune --> pkg_compact
|
||||
pkg_compact_tool_result_prune --> pkg_invariants
|
||||
pkg_compact_tool_result_prune --> pkg_llm
|
||||
pkg_compact_tool_result_prune --> pkg_session
|
||||
pkg_compact_tool_result_prune --> pkg_token_meter
|
||||
pkg_subagent_acp --> pkg_agent
|
||||
pkg_subagent_acp --> pkg_invariants
|
||||
pkg_subagent_acp --> pkg_llm
|
||||
@@ -1040,50 +1032,18 @@ flowchart TD
|
||||
pkg_web_app --> pkg_bash_env
|
||||
pkg_web_app --> pkg_invariants
|
||||
pkg_web_app --> pkg_system_prompt
|
||||
pkg_client_ui_model --> pkg_client_connection
|
||||
pkg_client_ui_model --> pkg_client_locale
|
||||
pkg_client_ui_model --> pkg_client_runtime
|
||||
pkg_client_ui_model --> pkg_client_ui_command
|
||||
pkg_client_ui_model --> pkg_client_ui_conversation
|
||||
pkg_client_ui_model --> pkg_client_ui_primitives
|
||||
pkg_client_ui_model --> pkg_client_ui_slash
|
||||
pkg_client_ui_model --> pkg_client_ui_slots
|
||||
pkg_client_ui_model --> pkg_invariants
|
||||
pkg_client_ui_permission --> pkg_client_connection
|
||||
pkg_client_ui_permission --> pkg_client_locale
|
||||
pkg_client_ui_permission --> pkg_client_runtime
|
||||
pkg_client_ui_permission --> pkg_client_schema_form
|
||||
pkg_client_ui_permission --> pkg_client_ui_command
|
||||
pkg_client_ui_permission --> pkg_client_ui_primitives
|
||||
pkg_client_ui_permission --> pkg_client_ui_slash
|
||||
pkg_client_ui_permission --> pkg_client_ui_slots
|
||||
pkg_client_ui_permission --> pkg_invariants
|
||||
pkg_client_ui_permission --> pkg_permission
|
||||
pkg_client_ui_plan --> pkg_client_connection
|
||||
pkg_client_ui_plan --> pkg_client_locale
|
||||
pkg_client_ui_plan --> pkg_client_runtime
|
||||
pkg_client_ui_plan --> pkg_client_ui_conversation
|
||||
pkg_client_ui_plan --> pkg_client_ui_primitives
|
||||
pkg_client_ui_plan --> pkg_client_ui_slots
|
||||
pkg_client_ui_plan --> pkg_invariants
|
||||
pkg_client_ui_plan --> pkg_plan_mode
|
||||
pkg_client_ui_skill --> pkg_client_connection
|
||||
pkg_client_ui_skill --> pkg_client_locale
|
||||
pkg_client_ui_skill --> pkg_client_runtime
|
||||
pkg_client_ui_skill --> pkg_client_ui_primitives
|
||||
pkg_client_ui_skill --> pkg_client_ui_slash
|
||||
pkg_client_ui_skill --> pkg_client_ui_slots
|
||||
pkg_client_ui_skill --> pkg_client_ui_tool
|
||||
pkg_client_ui_skill --> pkg_invariants
|
||||
pkg_client_ui_subagent --> pkg_client_locale
|
||||
pkg_client_ui_subagent --> pkg_client_runtime
|
||||
pkg_client_ui_subagent --> pkg_client_ui_conversation
|
||||
pkg_client_ui_subagent --> pkg_client_ui_primitives
|
||||
pkg_client_ui_subagent --> pkg_client_ui_slash
|
||||
pkg_client_ui_subagent --> pkg_client_ui_slots
|
||||
pkg_client_ui_subagent --> pkg_invariants
|
||||
pkg_client_ui_subagent --> pkg_subagent
|
||||
pkg_client_ui_subagent --> pkg_token_meter
|
||||
pkg_client_ui_conversation --> pkg_agent
|
||||
pkg_client_ui_conversation --> pkg_client_locale
|
||||
pkg_client_ui_conversation --> pkg_client_runtime
|
||||
pkg_client_ui_conversation --> pkg_client_ui_primitives
|
||||
pkg_client_ui_conversation --> pkg_client_ui_slash
|
||||
pkg_client_ui_conversation --> pkg_client_ui_slots
|
||||
pkg_client_ui_conversation --> pkg_commands
|
||||
pkg_client_ui_conversation --> pkg_compact
|
||||
pkg_client_ui_conversation --> pkg_invariants
|
||||
pkg_client_ui_conversation --> pkg_llm_retry
|
||||
pkg_client_ui_conversation --> pkg_token_meter
|
||||
pkg_client_ui_conversation --> pkg_tools
|
||||
pkg_sdk_protocol --> pkg_invariants
|
||||
pkg_sdk_protocol --> pkg_llm
|
||||
pkg_sdk_protocol --> pkg_session
|
||||
@@ -1107,6 +1067,14 @@ flowchart TD
|
||||
pkg_workflow_workerthread --> pkg_subagent
|
||||
pkg_workflow_workerthread --> pkg_tools
|
||||
pkg_workflow_workerthread --> pkg_workflow
|
||||
pkg_compact_basic --> pkg_agent
|
||||
pkg_compact_basic --> pkg_commands
|
||||
pkg_compact_basic --> pkg_compact
|
||||
pkg_compact_basic --> pkg_compact_tool_result_prune
|
||||
pkg_compact_basic --> pkg_invariants
|
||||
pkg_compact_basic --> pkg_llm
|
||||
pkg_compact_basic --> pkg_session
|
||||
pkg_compact_basic --> pkg_token_meter
|
||||
pkg_subagent_codex --> pkg_invariants
|
||||
pkg_subagent_codex --> pkg_llm
|
||||
pkg_subagent_codex --> pkg_sdk_protocol
|
||||
@@ -1122,6 +1090,65 @@ flowchart TD
|
||||
pkg_subagent_spawn --> pkg_invariants
|
||||
pkg_subagent_spawn --> pkg_subagent
|
||||
pkg_subagent_spawn --> pkg_subagent_inprocess
|
||||
pkg_client_ui_agent_preset --> pkg_client_connection
|
||||
pkg_client_ui_agent_preset --> pkg_client_locale
|
||||
pkg_client_ui_agent_preset --> pkg_client_runtime
|
||||
pkg_client_ui_agent_preset --> pkg_client_ui_conversation
|
||||
pkg_client_ui_agent_preset --> pkg_client_ui_primitives
|
||||
pkg_client_ui_agent_preset --> pkg_client_ui_settings
|
||||
pkg_client_ui_agent_preset --> pkg_client_ui_slots
|
||||
pkg_client_ui_agent_preset --> pkg_client_web_react
|
||||
pkg_client_ui_agent_preset --> pkg_invariants
|
||||
pkg_client_ui_command --> pkg_client_connection
|
||||
pkg_client_ui_command --> pkg_client_locale
|
||||
pkg_client_ui_command --> pkg_client_runtime
|
||||
pkg_client_ui_command --> pkg_client_ui_conversation
|
||||
pkg_client_ui_command --> pkg_client_ui_primitives
|
||||
pkg_client_ui_command --> pkg_client_ui_slash
|
||||
pkg_client_ui_command --> pkg_client_ui_slots
|
||||
pkg_client_ui_command --> pkg_invariants
|
||||
pkg_client_ui_deliverables --> pkg_client_locale
|
||||
pkg_client_ui_deliverables --> pkg_client_runtime
|
||||
pkg_client_ui_deliverables --> pkg_client_ui_conversation
|
||||
pkg_client_ui_deliverables --> pkg_client_ui_slots
|
||||
pkg_client_ui_deliverables --> pkg_invariants
|
||||
pkg_client_ui_goal --> pkg_api_remotes
|
||||
pkg_client_ui_goal --> pkg_client_locale
|
||||
pkg_client_ui_goal --> pkg_client_runtime
|
||||
pkg_client_ui_goal --> pkg_client_ui_conversation
|
||||
pkg_client_ui_goal --> pkg_client_ui_primitives
|
||||
pkg_client_ui_goal --> pkg_client_ui_slots
|
||||
pkg_client_ui_goal --> pkg_goal
|
||||
pkg_client_ui_goal --> pkg_invariants
|
||||
pkg_client_ui_plan --> pkg_client_connection
|
||||
pkg_client_ui_plan --> pkg_client_locale
|
||||
pkg_client_ui_plan --> pkg_client_runtime
|
||||
pkg_client_ui_plan --> pkg_client_ui_conversation
|
||||
pkg_client_ui_plan --> pkg_client_ui_primitives
|
||||
pkg_client_ui_plan --> pkg_client_ui_slots
|
||||
pkg_client_ui_plan --> pkg_invariants
|
||||
pkg_client_ui_plan --> pkg_plan_mode
|
||||
pkg_client_ui_subagent --> pkg_client_locale
|
||||
pkg_client_ui_subagent --> pkg_client_runtime
|
||||
pkg_client_ui_subagent --> pkg_client_ui_conversation
|
||||
pkg_client_ui_subagent --> pkg_client_ui_primitives
|
||||
pkg_client_ui_subagent --> pkg_client_ui_slash
|
||||
pkg_client_ui_subagent --> pkg_client_ui_slots
|
||||
pkg_client_ui_subagent --> pkg_invariants
|
||||
pkg_client_ui_subagent --> pkg_subagent
|
||||
pkg_client_ui_subagent --> pkg_token_meter
|
||||
pkg_client_ui_task --> pkg_client_locale
|
||||
pkg_client_ui_task --> pkg_client_runtime
|
||||
pkg_client_ui_task --> pkg_client_ui_conversation
|
||||
pkg_client_ui_task --> pkg_client_ui_primitives
|
||||
pkg_client_ui_task --> pkg_client_ui_slots
|
||||
pkg_client_ui_task --> pkg_invariants
|
||||
pkg_client_ui_tool --> pkg_client_locale
|
||||
pkg_client_ui_tool --> pkg_client_runtime
|
||||
pkg_client_ui_tool --> pkg_client_ui_conversation
|
||||
pkg_client_ui_tool --> pkg_client_ui_primitives
|
||||
pkg_client_ui_tool --> pkg_client_ui_slots
|
||||
pkg_client_ui_tool --> pkg_invariants
|
||||
pkg_agent_spine_demo --> pkg_agent
|
||||
pkg_agent_spine_demo --> pkg_agent_loop
|
||||
pkg_agent_spine_demo --> pkg_bash_env
|
||||
@@ -1163,6 +1190,33 @@ flowchart TD
|
||||
pkg_subagent_dsh_sdk --> pkg_session
|
||||
pkg_subagent_dsh_sdk --> pkg_subagent
|
||||
pkg_subagent_dsh_sdk --> pkg_subprocess
|
||||
pkg_client_ui_model --> pkg_client_connection
|
||||
pkg_client_ui_model --> pkg_client_locale
|
||||
pkg_client_ui_model --> pkg_client_runtime
|
||||
pkg_client_ui_model --> pkg_client_ui_command
|
||||
pkg_client_ui_model --> pkg_client_ui_conversation
|
||||
pkg_client_ui_model --> pkg_client_ui_primitives
|
||||
pkg_client_ui_model --> pkg_client_ui_slash
|
||||
pkg_client_ui_model --> pkg_client_ui_slots
|
||||
pkg_client_ui_model --> pkg_invariants
|
||||
pkg_client_ui_permission --> pkg_client_connection
|
||||
pkg_client_ui_permission --> pkg_client_locale
|
||||
pkg_client_ui_permission --> pkg_client_runtime
|
||||
pkg_client_ui_permission --> pkg_client_schema_form
|
||||
pkg_client_ui_permission --> pkg_client_ui_command
|
||||
pkg_client_ui_permission --> pkg_client_ui_primitives
|
||||
pkg_client_ui_permission --> pkg_client_ui_slash
|
||||
pkg_client_ui_permission --> pkg_client_ui_slots
|
||||
pkg_client_ui_permission --> pkg_invariants
|
||||
pkg_client_ui_permission --> pkg_permission
|
||||
pkg_client_ui_skill --> pkg_client_connection
|
||||
pkg_client_ui_skill --> pkg_client_locale
|
||||
pkg_client_ui_skill --> pkg_client_runtime
|
||||
pkg_client_ui_skill --> pkg_client_ui_primitives
|
||||
pkg_client_ui_skill --> pkg_client_ui_slash
|
||||
pkg_client_ui_skill --> pkg_client_ui_slots
|
||||
pkg_client_ui_skill --> pkg_client_ui_tool
|
||||
pkg_client_ui_skill --> pkg_invariants
|
||||
pkg_acp_demo --> pkg_acp
|
||||
pkg_acp_demo --> pkg_agent_spine_demo
|
||||
pkg_acp_demo --> pkg_app_boot
|
||||
@@ -1197,9 +1251,9 @@ flowchart TD
|
||||
| [`code-runtime`](../packages/code-runtime/code-runtime) | `code-runtime` | [`invariants`](../packages/support/invariants) |
|
||||
| [`e2b`](../packages/e2b/e2b) | `e2b` | [`invariants`](../packages/support/invariants) |
|
||||
| [`jsonrpc-demo`](../packages/examples/jsonrpc-demo) | `examples` | [`invariants`](../packages/support/invariants) |
|
||||
| [`host-apiproxy`](../packages/host/apiproxy) | `host` | [`invariants`](../packages/support/invariants) |
|
||||
| [`host-directory-picker`](../packages/host/directory-picker) | `host` | [`invariants`](../packages/support/invariants) |
|
||||
| [`host-webserver`](../packages/host/webserver) | `host` | [`invariants`](../packages/support/invariants) |
|
||||
| [`sandbox-windows-acl`](../packages/sandbox/sandbox-windows-acl) | `sandbox` | [`invariants`](../packages/support/invariants) |
|
||||
| [`storage`](../packages/storage/storage) | `storage` | [`invariants`](../packages/support/invariants) |
|
||||
| [`subprocess`](../packages/subprocess/subprocess) | `subprocess` | [`invariants`](../packages/support/invariants) |
|
||||
| [`type-meta`](../packages/typert/type-meta) | `typert` | [`invariants`](../packages/support/invariants) |
|
||||
@@ -1224,23 +1278,18 @@ flowchart TD
|
||||
| [`llm-pi-ai`](../packages/llm/llm-pi-ai) | `llm` | [`credentials`](../packages/credentials/credentials), [`environment`](../packages/util/environment), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`settings`](../packages/settings/settings), [`timeout`](../packages/util/timeout) |
|
||||
| [`session`](../packages/core/session) | `core` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`type-meta`](../packages/typert/type-meta) |
|
||||
| [`system-prompt`](../packages/core/system-prompt) | `core` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope) |
|
||||
| [`skill`](../packages/skill/skill) | `skill` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm) |
|
||||
| [`skill`](../packages/skill/skill) | `skill` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope) |
|
||||
| [`web`](../packages/web/web) | `web` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm) |
|
||||
| [`api-gateway`](../packages/api/gateway) | `api` | [`client-connection`](../packages/client/connection), [`invariants`](../packages/support/invariants), [`typert-registry`](../packages/typert/registry) |
|
||||
| [`client-locale`](../packages/client/locale) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-test-runtime`](../packages/client/test-runtime) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`client-web-react`](../packages/client/web-react), [`host-apiproxy`](../packages/host/apiproxy), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-models`](../packages/client/ui-models) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-schema-form`](../packages/client/schema-form), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`client-web-react`](../packages/client/web-react), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-settings`](../packages/client/ui-settings) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`invariants`](../packages/support/invariants) |
|
||||
| [`credentials-local`](../packages/credentials/credentials-local) | `credentials` | [`atomic-write`](../packages/util/atomic-write), [`credentials`](../packages/credentials/credentials), [`environment`](../packages/util/environment), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths) |
|
||||
| [`lsp`](../packages/lsp/lsp) | `lsp` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm) |
|
||||
| [`sandbox`](../packages/sandbox/sandbox) | `sandbox` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm) |
|
||||
| [`settings-local`](../packages/settings/settings-local) | `settings` | [`atomic-write`](../packages/util/atomic-write), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths), [`settings`](../packages/settings/settings) |
|
||||
| [`agent`](../packages/core/agent) | `core` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`type-meta`](../packages/typert/type-meta) |
|
||||
| [`bash`](../packages/bash/bash) | `bash` | [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`subprocess`](../packages/subprocess/subprocess) |
|
||||
| [`fs`](../packages/fs/fs) | `fs` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox) |
|
||||
| [`skill-badge`](../packages/skill/skill-badge) | `skill` | [`invariants`](../packages/support/invariants), [`skill`](../packages/skill/skill) |
|
||||
| [`compact`](../packages/compact/compact) | `compact` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
|
||||
| [`web-fetch-local`](../packages/web/web-fetch-local) | `web` | [`invariants`](../packages/support/invariants), [`timeout`](../packages/util/timeout), [`web`](../packages/web/web) |
|
||||
| [`web-search-exa`](../packages/web/web-search-exa) | `web` | [`environment`](../packages/util/environment), [`invariants`](../packages/support/invariants), [`web`](../packages/web/web) |
|
||||
| [`web-search-perplexity`](../packages/web/web-search-perplexity) | `web` | [`environment`](../packages/util/environment), [`invariants`](../packages/support/invariants), [`web`](../packages/web/web) |
|
||||
@@ -1254,34 +1303,29 @@ flowchart TD
|
||||
| [`client-ui-theme`](../packages/client/ui-theme) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-workspace`](../packages/client/ui-workspace) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`code-runtime-worker`](../packages/code-runtime/code-runtime-worker) | `code-runtime` | [`code-runtime`](../packages/code-runtime/code-runtime), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`timeout`](../packages/util/timeout) |
|
||||
| [`sandbox-local`](../packages/sandbox/sandbox-local) | `sandbox` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox) |
|
||||
| [`agent-presets`](../packages/preset/agent-presets) | `preset` | [`atomic-write`](../packages/util/atomic-write), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`settings`](../packages/settings/settings) |
|
||||
| [`persona`](../packages/preset/persona) | `preset` | [`invariants`](../packages/support/invariants), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| [`sandbox`](../packages/sandbox/sandbox) | `sandbox` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
|
||||
| [`session-persistence`](../packages/session/session-persistence) | `session` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`timeout`](../packages/util/timeout) |
|
||||
| [`session-projection`](../packages/session/session-projection) | `session` | [`invariants`](../packages/support/invariants), [`session`](../packages/core/session) |
|
||||
| [`llm-retry`](../packages/llm/llm-retry) | `llm` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`timeout`](../packages/util/timeout) |
|
||||
| [`token-meter`](../packages/llm/token-meter) | `llm` | [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection) |
|
||||
| [`llm-retry`](../packages/llm/llm-retry) | `llm` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`timeout`](../packages/util/timeout) |
|
||||
| [`agent-default-model`](../packages/core/agent-default-model) | `core` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`settings`](../packages/settings/settings) |
|
||||
| [`goal`](../packages/goal/goal) | `goal` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`type-meta`](../packages/typert/type-meta) |
|
||||
| [`bash-local`](../packages/bash/bash-local) | `bash` | [`bash`](../packages/bash/bash), [`invariants`](../packages/support/invariants), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
| [`pwsh-local`](../packages/bash/pwsh-local) | `bash` | [`bash`](../packages/bash/bash), [`invariants`](../packages/support/invariants), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
| [`fs-local`](../packages/fs/fs-local) | `fs` | [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants) |
|
||||
| [`fs-policy`](../packages/fs/fs-policy) | `fs` | [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants) |
|
||||
| [`skill-local`](../packages/skill/skill-local) | `skill` | [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths), [`skill`](../packages/skill/skill) |
|
||||
| [`bash`](../packages/bash/bash) | `bash` | [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`subprocess`](../packages/subprocess/subprocess) |
|
||||
| [`fs`](../packages/fs/fs) | `fs` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox) |
|
||||
| [`web-search-deepseek`](../packages/web/web-search-deepseek) | `web` | [`agent`](../packages/core/agent), [`credentials`](../packages/credentials/credentials), [`environment`](../packages/util/environment), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`web`](../packages/web/web) |
|
||||
| [`spill-local`](../packages/spill/spill-local) | `spill` | [`invariants`](../packages/support/invariants), [`spill`](../packages/spill/spill) |
|
||||
| [`hook-protocol`](../packages/hooks/hook-protocol) | `hooks` | [`bash`](../packages/bash/bash), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session) |
|
||||
| [`llm-replay`](../packages/support/llm-replay) | `support` | [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
|
||||
| [`loader-smoke`](../packages/support/loader-smoke) | `support` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
|
||||
| [`headless`](../packages/bundle/headless) | `bundle` | [`agent`](../packages/core/agent), [`host-apiproxy`](../packages/host/apiproxy), [`host-webserver`](../packages/host/webserver), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session) |
|
||||
| [`client-ui-layout`](../packages/client/ui-layout) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`client-ui-theme`](../packages/client/ui-theme), [`invariants`](../packages/support/invariants) |
|
||||
| [`time-context`](../packages/context/time-context) | `context` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session) |
|
||||
| [`tmux-context`](../packages/context/tmux-context) | `context` | [`agent`](../packages/core/agent), [`bash`](../packages/bash/bash), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session) |
|
||||
| [`fs-e2b`](../packages/e2b/fs-e2b) | `e2b` | [`e2b`](../packages/e2b/e2b), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants) |
|
||||
| [`host-apiproxy`](../packages/host/apiproxy) | `host` | [`agent-presets`](../packages/preset/agent-presets), [`invariants`](../packages/support/invariants) |
|
||||
| [`host-directory-picker-browse`](../packages/host/directory-picker-browse) | `host` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`client-ui-workspace`](../packages/client/ui-workspace), [`invariants`](../packages/support/invariants) |
|
||||
| [`host-directory-picker-native`](../packages/host/directory-picker-native) | `host` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`client-ui-workspace`](../packages/client/ui-workspace), [`invariants`](../packages/support/invariants) |
|
||||
| [`commands`](../packages/interaction/commands) | `interaction` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`scope`](../packages/core/scope), [`session`](../packages/core/session) |
|
||||
| [`user-approval`](../packages/interaction/user-approval) | `interaction` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| [`user-interaction`](../packages/interaction/user-interaction) | `interaction` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm) |
|
||||
| [`lsp-local`](../packages/lsp/lsp-local) | `lsp` | [`brand`](../packages/util/brand), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`lsp`](../packages/lsp/lsp), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
| [`pty`](../packages/pty/pty) | `pty` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants) |
|
||||
| [`sandbox-local`](../packages/sandbox/sandbox-local) | `sandbox` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox), [`session`](../packages/core/session) |
|
||||
| [`sandbox-policy`](../packages/sandbox/sandbox-policy) | `sandbox` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| [`scripts`](../packages/scaffold/scripts) | `scaffold` | [`app-boot`](../packages/boot/app-boot), [`invariants`](../packages/support/invariants) |
|
||||
| [`session-persistence-jsonl`](../packages/session/session-persistence-jsonl) | `session` | [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence) |
|
||||
@@ -1295,28 +1339,40 @@ flowchart TD
|
||||
| [`tools`](../packages/core/tools) | `core` | [`agent`](../packages/core/agent), [`code-runtime`](../packages/code-runtime/code-runtime), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| [`command-goal`](../packages/goal/command-goal) | `goal` | [`commands`](../packages/interaction/commands), [`goal`](../packages/goal/goal), [`invariants`](../packages/support/invariants) |
|
||||
| [`goal-session`](../packages/goal/goal-session) | `goal` | [`agent`](../packages/core/agent), [`goal`](../packages/goal/goal), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
|
||||
| [`bash-sandbox`](../packages/bash/bash-sandbox) | `bash` | [`bash`](../packages/bash/bash), [`bash-local`](../packages/bash/bash-local), [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy) |
|
||||
| [`fs-sandbox`](../packages/fs/fs-sandbox) | `fs` | [`fs`](../packages/fs/fs), [`fs-local`](../packages/fs/fs-local), [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy) |
|
||||
| [`command-compact`](../packages/compact/command-compact) | `compact` | [`commands`](../packages/interaction/commands), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants) |
|
||||
| [`compact-tool-result-prune`](../packages/compact/compact-tool-result-prune) | `compact` | [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`token-meter`](../packages/llm/token-meter) |
|
||||
| [`bash-local`](../packages/bash/bash-local) | `bash` | [`bash`](../packages/bash/bash), [`invariants`](../packages/support/invariants), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
| [`pwsh-local`](../packages/bash/pwsh-local) | `bash` | [`bash`](../packages/bash/bash), [`invariants`](../packages/support/invariants), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
| [`fs-local`](../packages/fs/fs-local) | `fs` | [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants) |
|
||||
| [`fs-policy`](../packages/fs/fs-policy) | `fs` | [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants) |
|
||||
| [`skill-local`](../packages/skill/skill-local) | `skill` | [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths), [`skill`](../packages/skill/skill) |
|
||||
| [`compact`](../packages/compact/compact) | `compact` | [`brand`](../packages/util/brand), [`commands`](../packages/interaction/commands), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
|
||||
| [`hook-protocol`](../packages/hooks/hook-protocol) | `hooks` | [`bash`](../packages/bash/bash), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session) |
|
||||
| [`session-query`](../packages/session-query/session-query) | `session-query` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-title`](../packages/session/session-title) |
|
||||
| [`acp`](../packages/acp/acp) | `acp` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| [`api-remotes`](../packages/api/remotes) | `api` | [`agent`](../packages/core/agent), [`goal`](../packages/goal/goal), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`typert-registry`](../packages/typert/registry) |
|
||||
| [`client-ui-conversation`](../packages/client/ui-conversation) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants), [`token-meter`](../packages/llm/token-meter) |
|
||||
| [`headless`](../packages/bundle/headless) | `bundle` | [`agent`](../packages/core/agent), [`agent-default-model`](../packages/core/agent-default-model), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
|
||||
| [`client-test-runtime`](../packages/client/test-runtime) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`client-web-react`](../packages/client/web-react), [`host-apiproxy`](../packages/host/apiproxy), [`invariants`](../packages/support/invariants) |
|
||||
| [`tmux-context`](../packages/context/tmux-context) | `context` | [`agent`](../packages/core/agent), [`bash`](../packages/bash/bash), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session) |
|
||||
| [`fs-e2b`](../packages/e2b/fs-e2b) | `e2b` | [`e2b`](../packages/e2b/e2b), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants) |
|
||||
| [`command-feedback`](../packages/feedback/command-feedback) | `feedback` | [`commands`](../packages/interaction/commands), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session) |
|
||||
| [`host-directory-picker-auto`](../packages/host/directory-picker-auto) | `host` | [`host-directory-picker-browse`](../packages/host/directory-picker-browse), [`host-directory-picker-native`](../packages/host/directory-picker-native), [`host-webserver`](../packages/host/webserver), [`invariants`](../packages/support/invariants) |
|
||||
| [`permission`](../packages/interaction/permission) | `interaction` | [`bash`](../packages/bash/bash), [`commands`](../packages/interaction/commands), [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`settings`](../packages/settings/settings), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| [`lsp-local`](../packages/lsp/lsp-local) | `lsp` | [`brand`](../packages/util/brand), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`lsp`](../packages/lsp/lsp), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
| [`pty-local`](../packages/pty/pty-local) | `pty` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`pty`](../packages/pty/pty), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`subprocess`](../packages/subprocess/subprocess) |
|
||||
| [`session-title-llm`](../packages/session/session-title-llm) | `session` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-title`](../packages/session/session-title), [`timeout`](../packages/util/timeout) |
|
||||
| [`tasks-local`](../packages/tasks/tasks-local) | `tasks` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tasks`](../packages/tasks/tasks), [`timeout`](../packages/util/timeout) |
|
||||
| [`token-meter`](../packages/llm/token-meter) | `llm` | [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection) |
|
||||
| [`agent-loop`](../packages/core/agent-loop) | `core` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
|
||||
| [`agent-tool-mode`](../packages/core/agent-tool-mode) | `core` | [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) |
|
||||
| [`tool-goal`](../packages/goal/tool-goal) | `goal` | [`agent`](../packages/core/agent), [`goal`](../packages/goal/goal), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
|
||||
| [`bash-env`](../packages/bash/bash-env) | `bash` | [`bash`](../packages/bash/bash), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths), [`session-persistence`](../packages/session/session-persistence), [`tools`](../packages/core/tools) |
|
||||
| [`bash-sandbox`](../packages/bash/bash-sandbox) | `bash` | [`bash`](../packages/bash/bash), [`bash-local`](../packages/bash/bash-local), [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy) |
|
||||
| [`pwsh-sandbox`](../packages/bash/pwsh-sandbox) | `bash` | [`bash`](../packages/bash/bash), [`invariants`](../packages/support/invariants), [`pwsh-local`](../packages/bash/pwsh-local), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy) |
|
||||
| [`fs-sandbox`](../packages/fs/fs-sandbox) | `fs` | [`fs`](../packages/fs/fs), [`fs-local`](../packages/fs/fs-local), [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy) |
|
||||
| [`tool-fs`](../packages/fs/tool-fs) | `fs` | [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| [`tool-fs-search`](../packages/fs/tool-fs-search) | `fs` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`spill`](../packages/spill/spill), [`subprocess`](../packages/subprocess/subprocess), [`system-prompt`](../packages/core/system-prompt), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
|
||||
| [`tool-str-replace-editor`](../packages/fs/tool-str-replace-editor) | `fs` | [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`tools`](../packages/core/tools) |
|
||||
| [`tool-skill`](../packages/skill/tool-skill) | `skill` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`skill`](../packages/skill/skill), [`tools`](../packages/core/tools) |
|
||||
| [`compact-basic`](../packages/compact/compact-basic) | `compact` | [`agent`](../packages/core/agent), [`compact`](../packages/compact/compact), [`compact-tool-result-prune`](../packages/compact/compact-tool-result-prune), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`token-meter`](../packages/llm/token-meter) |
|
||||
| [`command-compact`](../packages/compact/command-compact) | `compact` | [`commands`](../packages/interaction/commands), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants) |
|
||||
| [`subagent`](../packages/subagent/subagent) | `subagent` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
|
||||
| [`tool-web`](../packages/web/tool-web) | `web` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`web`](../packages/web/web) |
|
||||
| [`spill-policy`](../packages/spill/spill-policy) | `spill` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`spill`](../packages/spill/spill), [`tools`](../packages/core/tools) |
|
||||
@@ -1326,11 +1382,7 @@ flowchart TD
|
||||
| [`session-query-sqlite`](../packages/session-query/session-query-sqlite) | `session-query` | [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-query`](../packages/session-query/session-query) |
|
||||
| [`tool-session-query`](../packages/session-query/tool-session-query) | `session-query` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query), [`system-prompt`](../packages/core/system-prompt), [`timeout`](../packages/util/timeout), [`tools`](../packages/core/tools) |
|
||||
| [`agent-loop-testkit`](../packages/support/agent-loop-testkit) | `support` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
|
||||
| [`client-ui-command`](../packages/client/ui-command) | `client` | [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-deliverables`](../packages/client/ui-deliverables) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-goal`](../packages/client/ui-goal) | `client` | [`api-remotes`](../packages/api/remotes), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`goal`](../packages/goal/goal), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-task`](../packages/client/ui-task) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-tool`](../packages/client/ui-tool) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`llm-replay`](../packages/support/llm-replay) | `support` | [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
|
||||
| [`session-reference`](../packages/context/session-reference) | `context` | [`agent`](../packages/core/agent), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query) |
|
||||
| [`workspace-context`](../packages/context/workspace-context) | `context` | [`agent`](../packages/core/agent), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`paths`](../packages/util/paths), [`session`](../packages/core/session), [`tools`](../packages/core/tools) |
|
||||
| [`repeat-tool-guard`](../packages/guard/repeat-tool-guard) | `guard` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) |
|
||||
@@ -1348,7 +1400,8 @@ flowchart TD
|
||||
| [`tool-tasks`](../packages/tasks/tool-tasks) | `tasks` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`system-prompt`](../packages/core/system-prompt), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
|
||||
| [`tool-workflow`](../packages/workflow/tool-workflow) | `workflow` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`workflow`](../packages/workflow/workflow) |
|
||||
| [`tool-bash`](../packages/bash/tool-bash) | `bash` | [`agent`](../packages/core/agent), [`bash`](../packages/bash/bash), [`bash-env`](../packages/bash/bash-env), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`system-prompt`](../packages/core/system-prompt), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| [`tool-pwsh`](../packages/bash/tool-pwsh) | `bash` | [`agent`](../packages/core/agent), [`bash`](../packages/bash/bash), [`bash-env`](../packages/bash/bash-env), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`system-prompt`](../packages/core/system-prompt), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools) |
|
||||
| [`tool-pwsh`](../packages/bash/tool-pwsh) | `bash` | [`agent`](../packages/core/agent), [`bash`](../packages/bash/bash), [`bash-env`](../packages/bash/bash-env), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`system-prompt`](../packages/core/system-prompt), [`tasks`](../packages/tasks/tasks), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
| [`compact-tool-result-prune`](../packages/compact/compact-tool-result-prune) | `compact` | [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`token-meter`](../packages/llm/token-meter) |
|
||||
| [`subagent-acp`](../packages/subagent/subagent-acp) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
| [`subagent-claude-code`](../packages/subagent/subagent-claude-code) | `subagent` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
| [`subagent-inprocess`](../packages/subagent/subagent-inprocess) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
@@ -1357,20 +1410,28 @@ flowchart TD
|
||||
| [`tool-subagent-report`](../packages/subagent/tool-subagent-report) | `subagent` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`subagent`](../packages/subagent/subagent), [`tools`](../packages/core/tools) |
|
||||
| [`hooks-claude`](../packages/hooks/hooks-claude) | `hooks` | [`agent`](../packages/core/agent), [`hook-protocol`](../packages/hooks/hook-protocol), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`subagent`](../packages/subagent/subagent), [`tools`](../packages/core/tools) |
|
||||
| [`web-app`](../packages/bundle/web-app) | `bundle` | [`bash-env`](../packages/bash/bash-env), [`invariants`](../packages/support/invariants), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| [`client-ui-model`](../packages/client/ui-model) | `client` | [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-command`](../packages/client/ui-command), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-permission`](../packages/client/ui-permission) | `client` | [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-schema-form`](../packages/client/schema-form), [`client-ui-command`](../packages/client/ui-command), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants), [`permission`](../packages/interaction/permission) |
|
||||
| [`client-ui-plan`](../packages/client/ui-plan) | `client` | [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants), [`plan-mode`](../packages/plan/plan-mode) |
|
||||
| [`client-ui-skill`](../packages/client/ui-skill) | `client` | [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`client-ui-tool`](../packages/client/ui-tool), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-subagent`](../packages/client/ui-subagent) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants), [`subagent`](../packages/subagent/subagent), [`token-meter`](../packages/llm/token-meter) |
|
||||
| [`client-ui-conversation`](../packages/client/ui-conversation) | `client` | [`agent`](../packages/core/agent), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`commands`](../packages/interaction/commands), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm-retry`](../packages/llm/llm-retry), [`token-meter`](../packages/llm/token-meter), [`tools`](../packages/core/tools) |
|
||||
| [`sdk-protocol`](../packages/scaffold/protocol) | `scaffold` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent) |
|
||||
| [`repository-plugin`](../packages/self-modification/repository-plugin) | `self-modification` | [`invariants`](../packages/support/invariants), [`mcp-client`](../packages/mcp/mcp-client), [`paths`](../packages/util/paths), [`skill-local`](../packages/skill/skill-local) |
|
||||
| [`tool-ralph`](../packages/workflow/tool-ralph) | `workflow` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`workflow`](../packages/workflow/workflow) |
|
||||
| [`workflow-workerthread`](../packages/workflow/workflow-workerthread) | `workflow` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`tools`](../packages/core/tools), [`workflow`](../packages/workflow/workflow) |
|
||||
| [`compact-basic`](../packages/compact/compact-basic) | `compact` | [`agent`](../packages/core/agent), [`commands`](../packages/interaction/commands), [`compact`](../packages/compact/compact), [`compact-tool-result-prune`](../packages/compact/compact-tool-result-prune), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`token-meter`](../packages/llm/token-meter) |
|
||||
| [`subagent-codex`](../packages/subagent/subagent-codex) | `subagent` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sdk-protocol`](../packages/scaffold/protocol), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`subprocess`](../packages/subprocess/subprocess), [`timeout`](../packages/util/timeout) |
|
||||
| [`subagent-fork`](../packages/subagent/subagent-fork) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`subagent-inprocess`](../packages/subagent/subagent-inprocess) |
|
||||
| [`subagent-spawn`](../packages/subagent/subagent-spawn) | `subagent` | [`invariants`](../packages/support/invariants), [`subagent`](../packages/subagent/subagent), [`subagent-inprocess`](../packages/subagent/subagent-inprocess) |
|
||||
| [`client-ui-agent-preset`](../packages/client/ui-agent-preset) | `client` | [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-settings`](../packages/client/ui-settings), [`client-ui-slots`](../packages/client/ui-slots), [`client-web-react`](../packages/client/web-react), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-command`](../packages/client/ui-command) | `client` | [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-deliverables`](../packages/client/ui-deliverables) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-goal`](../packages/client/ui-goal) | `client` | [`api-remotes`](../packages/api/remotes), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`goal`](../packages/goal/goal), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-plan`](../packages/client/ui-plan) | `client` | [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants), [`plan-mode`](../packages/plan/plan-mode) |
|
||||
| [`client-ui-subagent`](../packages/client/ui-subagent) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants), [`subagent`](../packages/subagent/subagent), [`token-meter`](../packages/llm/token-meter) |
|
||||
| [`client-ui-task`](../packages/client/ui-task) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-tool`](../packages/client/ui-tool) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`agent-spine-demo`](../packages/examples/agent-spine-demo) | `examples` | [`agent`](../packages/core/agent), [`agent-loop`](../packages/core/agent-loop), [`bash-env`](../packages/bash/bash-env), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`llm-retry`](../packages/llm/llm-retry), [`paths`](../packages/util/paths), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-title`](../packages/session/session-title), [`skill`](../packages/skill/skill), [`skill-local`](../packages/skill/skill-local), [`system-prompt`](../packages/core/system-prompt), [`tasks-local`](../packages/tasks/tasks-local), [`tool-bash`](../packages/bash/tool-bash), [`tool-goal`](../packages/goal/tool-goal), [`tool-skill`](../packages/skill/tool-skill), [`tool-tasks`](../packages/tasks/tool-tasks), [`tools`](../packages/core/tools), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| [`jsonrpc`](../packages/scaffold/server) | `scaffold` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`llm-deepseek`](../packages/llm/llm-deepseek), [`scope`](../packages/core/scope), [`sdk-protocol`](../packages/scaffold/protocol), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent) |
|
||||
| [`sdk-client`](../packages/scaffold/client) | `scaffold` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sdk-protocol`](../packages/scaffold/protocol), [`session`](../packages/core/session) |
|
||||
| [`subagent-dsh-sdk`](../packages/subagent/subagent-dsh-sdk) | `subagent` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`sdk-client`](../packages/scaffold/client), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent), [`subprocess`](../packages/subprocess/subprocess) |
|
||||
| [`client-ui-model`](../packages/client/ui-model) | `client` | [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-command`](../packages/client/ui-command), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-permission`](../packages/client/ui-permission) | `client` | [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-schema-form`](../packages/client/schema-form), [`client-ui-command`](../packages/client/ui-command), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants), [`permission`](../packages/interaction/permission) |
|
||||
| [`client-ui-skill`](../packages/client/ui-skill) | `client` | [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`client-ui-tool`](../packages/client/ui-tool), [`invariants`](../packages/support/invariants) |
|
||||
| [`acp-demo`](../packages/examples/acp-demo) | `examples` | [`acp`](../packages/acp/acp), [`agent-spine-demo`](../packages/examples/agent-spine-demo), [`app-boot`](../packages/boot/app-boot), [`invariants`](../packages/support/invariants), [`session-checkpoint-policy`](../packages/session/session-checkpoint-policy), [`session-persistence-jsonl`](../packages/session/session-persistence-jsonl), [`session-query`](../packages/session-query/session-query), [`session-query-sqlite`](../packages/session-query/session-query-sqlite), [`tools`](../packages/core/tools), [`workspace-context`](../packages/context/workspace-context) |
|
||||
|
||||
1439
docs/module-graph.zh.md
Normal file
1439
docs/module-graph.zh.md
Normal file
File diff suppressed because it is too large
Load Diff
6
docs/persistence-catalog.i18n.yaml
Normal file
6
docs/persistence-catalog.i18n.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/persistence-catalog.md
|
||||
persistence-catalog.md: 9953214182521ac2c1aac8b4589bad7ad45e3094
|
||||
persistence-catalog.zh.md: 730513ea259dde274c8c63948dd21fdc0b70417f
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
# Session Persistence Event Catalog
|
||||
|
||||
Every event type that can appear in a session's durable event log: the complete persisted `SessionEvent` envelope and each member of the merge-extensible `SessionEventMap` — the owning vocabulary in `@deepseek-ai/dsh-session` plus every plugin declaration merge in this repo — with source JSDoc, full payload declaration, surface badge, and declaration site. It complements [session.md](subsystems/session.md) (surface ordering and the `deriveMessages()` projection), [persistence.md](subsystems/persistence.md) (how the log is made durable), and the generated region of [session.md](subsystems/session.md#cordis-surface) (the live bus wiring — a log event is NOT a cordis event; it reaches listeners via the single `session/event` emit).
|
||||
Every event type that can appear in a session's durable event log: the complete persisted `SessionEvent` envelope and each member of the merge-extensible `SessionEventMap` — the owning vocabulary in `@deepseek-ai/dsh-session` plus every plugin declaration merge into `@deepseek-ai/dsh-session/types` in this repo — with source JSDoc, full payload declaration, surface badge, and declaration site. It complements [session.md](subsystems/session.md) (surface ordering and the `deriveMessages()` projection), [persistence.md](subsystems/persistence.md) (how the log is made durable), and the generated region of [session.md](subsystems/session.md#cordis-surface) (the live bus wiring — a log event is NOT a cordis event; it reaches listeners via the single `session/event` emit).
|
||||
|
||||
This file is GENERATED from source (`scripts/gen-persistence-catalog.ts`) and verified fresh by `pnpm run verify-persistence-catalog` (part of `doc-sync`) — do not edit it by hand. Declaration blocks retain the source declaration and nested property JSDoc, removing only the indentation imposed by a containing interface/module, and use a `ts persistence-catalog` fence (skipped by doc-typecheck because declarations reference types from their owning modules). Type names in a payload link to the page that documents them. See [the persistence-log-catalog Agent Note](../.agents/notes/archived/process/2026-07-04-persistence-log-catalog.md).
|
||||
|
||||
@@ -35,7 +35,8 @@ export type SurfaceEventType =
|
||||
* (inclusive) through `end` (inclusive) with this node. Both must exist as
|
||||
* surface nodes in the current surface. `start === end` replaces a single
|
||||
* node. The node's {@link SessionEvent.sourceEventSeqs} must include every
|
||||
* shadowed surface node. Used by compaction and possible other manipulations.
|
||||
* shadowed surface node. Used by compaction; any surface-replacing producer
|
||||
* may use it.
|
||||
*/
|
||||
export type SurfaceOp =
|
||||
| 'append'
|
||||
@@ -64,11 +65,12 @@ export type SessionEvent<T extends SessionEventType = SessionEventType> = {
|
||||
data: SessionEventMap[K]
|
||||
} & (K extends SurfaceEventType ? {
|
||||
/**
|
||||
* Seq numbers of events that are provenance sources of this event
|
||||
* Seq numbers of earlier events that this event cites as sources
|
||||
* (e.g. the `assistant/chunk` seqs that built an `assistant/message`,
|
||||
* or the surface nodes shadowed by a compaction replace node). An
|
||||
* `assistant/message` may carry a present empty array for a known empty
|
||||
* provider stream; omission means unrecorded provenance.
|
||||
* provider stream; when the field is absent, the event does not record which
|
||||
* earlier events produced the message.
|
||||
*/
|
||||
sourceEventSeqs?: number[]
|
||||
/** How this event entered the surface; absent for non-surface events. */
|
||||
@@ -77,7 +79,7 @@ export type SessionEvent<T extends SessionEventType = SessionEventType> = {
|
||||
}[T]
|
||||
```
|
||||
|
||||
Sources: [`packages/core/session/src/types.ts:308`](../packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:315`](../packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:343`](../packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:375`](../packages/core/session/src/types.ts)
|
||||
Sources: [`packages/core/session/src/types.ts:316`](../packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:323`](../packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:352`](../packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:384`](../packages/core/session/src/types.ts)
|
||||
|
||||
## Events
|
||||
|
||||
@@ -100,7 +102,23 @@ Sources: [`packages/core/session/src/types.ts:308`](../packages/core/session/src
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:300`](../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:19`](../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent-preset/*`
|
||||
|
||||
#### `agent-preset/selected` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* The session's agent preset was chosen after creation, while the session
|
||||
* was still blank. Log-only: it records the composition later turns ran
|
||||
* under, so a resumed or forked session rebuilds the same one instead of
|
||||
* the header's creation-time value.
|
||||
*/
|
||||
'agent-preset/selected': { agentPreset: string }
|
||||
```
|
||||
|
||||
Source: [`packages/preset/agent-presets/src/session.ts:26`](../packages/preset/agent-presets/src/session.ts)
|
||||
|
||||
### `approval/*`
|
||||
|
||||
@@ -174,7 +192,7 @@ Source: [`packages/interaction/user-approval/src/index.ts:67`](../packages/inter
|
||||
|
||||
Types: [StreamChunk](subsystems/llm-streaming.md)
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:238`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:246`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `assistant/message` — surface
|
||||
|
||||
@@ -190,7 +208,7 @@ Source: [`packages/core/session/src/types.ts:238`](../packages/core/session/src/
|
||||
|
||||
Types: [TokenUsage](subsystems/llm-streaming.md)
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:245`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:253`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `command/*`
|
||||
|
||||
@@ -211,7 +229,7 @@ Source: [`packages/core/session/src/types.ts:245`](../packages/core/session/src/
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/interaction/commands/src/index.ts:151`](../packages/interaction/commands/src/index.ts)
|
||||
Source: [`packages/interaction/commands/src/types.ts:41`](../packages/interaction/commands/src/types.ts)
|
||||
|
||||
#### `command/run` — log-only
|
||||
|
||||
@@ -229,7 +247,7 @@ Source: [`packages/interaction/commands/src/index.ts:151`](../packages/interacti
|
||||
'command/run': { commandId: CommandId; name: string; args?: string; source: CommandSource }
|
||||
```
|
||||
|
||||
Source: [`packages/interaction/commands/src/index.ts:144`](../packages/interaction/commands/src/index.ts)
|
||||
Source: [`packages/interaction/commands/src/types.ts:34`](../packages/interaction/commands/src/types.ts)
|
||||
|
||||
### `compact/*`
|
||||
|
||||
@@ -240,10 +258,10 @@ Source: [`packages/interaction/commands/src/index.ts:144`](../packages/interacti
|
||||
* Marks the end of a compaction — log-only, releases the lock. Its owner
|
||||
* matches `compact/start`; `error` records an unsuccessful attempt.
|
||||
*/
|
||||
'compact/end': { turn: number | null; error?: string }
|
||||
'compact/end': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null; error?: string }
|
||||
```
|
||||
|
||||
Source: [`packages/compact/compact/src/types.ts:65`](../packages/compact/compact/src/types.ts)
|
||||
Source: [`packages/compact/compact/src/types.ts:71`](../packages/compact/compact/src/types.ts)
|
||||
|
||||
#### `compact/prune` — log-only
|
||||
|
||||
@@ -267,7 +285,7 @@ Source: [`packages/compact/compact/src/types.ts:65`](../packages/compact/compact
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/compact/compact/src/types.ts:75`](../packages/compact/compact/src/types.ts)
|
||||
Source: [`packages/compact/compact/src/types.ts:81`](../packages/compact/compact/src/types.ts)
|
||||
|
||||
#### `compact/start` — log-only
|
||||
|
||||
@@ -277,16 +295,16 @@ Source: [`packages/compact/compact/src/types.ts:75`](../packages/compact/compact
|
||||
* `compact/end`. A numbered owner is strictly enclosed by that open turn;
|
||||
* `null` identifies a standalone manual transaction between turns.
|
||||
*/
|
||||
'compact/start': { turn: number | null }
|
||||
'compact/start': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null }
|
||||
```
|
||||
|
||||
Source: [`packages/compact/compact/src/types.ts:19`](../packages/compact/compact/src/types.ts)
|
||||
Source: [`packages/compact/compact/src/types.ts:23`](../packages/compact/compact/src/types.ts)
|
||||
|
||||
#### `compact/summary` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Provenance record of a completed summarization — log-only, no surfaceOp.
|
||||
* Completed summary, its inputs, and its model call facts — log-only, no surfaceOp.
|
||||
* The summary content is in `data.summary`; the actual surface replacement
|
||||
* is performed by the immediately following `user/message` event that
|
||||
* shadows the compacted range. That adjacency is contractual — the
|
||||
@@ -295,6 +313,8 @@ Source: [`packages/compact/compact/src/types.ts:19`](../packages/compact/compact
|
||||
* before it (`compact/prune` documents the shared protocol).
|
||||
*/
|
||||
'compact/summary': {
|
||||
compactionId: CompactionId
|
||||
sourceCommandId?: CommandId
|
||||
summary: ContentBlock[]
|
||||
shadowedRange: { start: number; end: number }
|
||||
shadowedSeqs: number[]
|
||||
@@ -330,7 +350,7 @@ Source: [`packages/compact/compact/src/types.ts:19`](../packages/compact/compact
|
||||
|
||||
Types: [ContentBlock](subsystems/core.md) · [TokenUsage](subsystems/llm-streaming.md)
|
||||
|
||||
Source: [`packages/compact/compact/src/types.ts:29`](../packages/compact/compact/src/types.ts)
|
||||
Source: [`packages/compact/compact/src/types.ts:33`](../packages/compact/compact/src/types.ts)
|
||||
|
||||
### `feedback/*`
|
||||
|
||||
@@ -365,7 +385,7 @@ Source: [`packages/goal/goal/src/domain.ts:66`](../packages/goal/goal/src/domain
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* A hook command was invoked at a hook point — log-only provenance (like
|
||||
* A hook command was invoked at a hook point — a log-only record (like
|
||||
* `compact/*`; NOT a {@link SurfaceEventType}, carries no `surfaceOp`).
|
||||
* `dialect` is the bridge that ran it (`claude`/`codex`), `point`
|
||||
* the hook point (`PreToolUse`, `Stop`, …), `matcher` the matcher-group
|
||||
@@ -411,29 +431,19 @@ Source: [`packages/hooks/hook-protocol/src/types.ts:31`](../packages/hooks/hook-
|
||||
|
||||
```ts persistence-catalog
|
||||
/** Durable, non-surface record of one provider-routed retry scheduled after a failed request attempt. */
|
||||
'llm/retry': {
|
||||
turn: number
|
||||
step: number
|
||||
provider: string
|
||||
mode: 'normal'
|
||||
policyKey: string
|
||||
retry: number
|
||||
maxRetries: number
|
||||
delayMs: number
|
||||
failure: LlmFailure
|
||||
} | {
|
||||
turn: number
|
||||
step: number
|
||||
provider: string
|
||||
mode: 'always'
|
||||
policyKey: string
|
||||
retry: number
|
||||
delayMs: number
|
||||
failure: LlmFailure
|
||||
}
|
||||
'llm/retry': LlmRetryEventData
|
||||
```
|
||||
|
||||
Source: [`packages/llm/llm-retry/src/index.ts:17`](../packages/llm/llm-retry/src/index.ts)
|
||||
Source: [`packages/llm/llm-retry/src/types.ts:9`](../packages/llm/llm-retry/src/types.ts)
|
||||
|
||||
#### `llm/retry-started` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/** Durable transition written after a retry wait succeeds and before the next request attempt starts. */
|
||||
'llm/retry-started': LlmRetryStartedEventData
|
||||
```
|
||||
|
||||
Source: [`packages/llm/llm-retry/src/types.ts:11`](../packages/llm/llm-retry/src/types.ts)
|
||||
|
||||
### `permission/*`
|
||||
|
||||
@@ -478,7 +488,7 @@ Source: [`packages/plan/plan-mode/src/index.ts:52`](../packages/plan/plan-mode/s
|
||||
'request/context': RequestContext
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:281`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:289`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `request/header` — log-only
|
||||
|
||||
@@ -490,7 +500,7 @@ Source: [`packages/core/session/src/types.ts:281`](../packages/core/session/src/
|
||||
'request/header': { header: EpochHeader; reason: RequestHeaderReason }
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:276`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:284`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `sandbox/*`
|
||||
|
||||
@@ -543,7 +553,7 @@ Source: [`packages/sandbox/sandbox-policy/src/session-mode.ts:33`](../packages/s
|
||||
'session/end-seed': Record<string, never>
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:304`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:312`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `session/title` — log-only
|
||||
|
||||
@@ -579,7 +589,7 @@ Source: [`packages/session/session-title-llm/src/index.ts:43`](../packages/sessi
|
||||
'step/end': { turn: number; step: number }
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:228`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:236`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `step/start` — log-only
|
||||
|
||||
@@ -588,7 +598,7 @@ Source: [`packages/core/session/src/types.ts:228`](../packages/core/session/src/
|
||||
'step/start': { turn: number; step: number }
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:226`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:234`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `subagent/*`
|
||||
|
||||
@@ -618,7 +628,7 @@ Source: [`packages/subagent/subagent/src/descriptor.ts:37`](../packages/subagent
|
||||
|
||||
Types: [TodoItem](subsystems/session.md)
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:271`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:279`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `tool/*`
|
||||
|
||||
@@ -635,7 +645,7 @@ Source: [`packages/core/session/src/types.ts:271`](../packages/core/session/src/
|
||||
|
||||
Types: [CallId](subsystems/core.md)
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:251`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:259`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `tool/code-dispatch` — log-only
|
||||
|
||||
@@ -655,12 +665,10 @@ Source: [`packages/core/session/src/types.ts:251`](../packages/core/session/src/
|
||||
* before returning), so its execution-enclosure relation holds by
|
||||
* construction.
|
||||
*/
|
||||
'tool/code-dispatch': { parentCallId: CallId; subCallId: CallId; name: string; arguments: unknown; isError: boolean; content: ContentBlock[] }
|
||||
'tool/code-dispatch': CodeDispatchEventData
|
||||
```
|
||||
|
||||
Types: [CallId](subsystems/core.md) · [ContentBlock](subsystems/core.md)
|
||||
|
||||
Source: [`packages/core/tools/src/code-mode.ts:49`](../packages/core/tools/src/code-mode.ts)
|
||||
Source: [`packages/core/tools/src/types.ts:56`](../packages/core/tools/src/types.ts)
|
||||
|
||||
#### `tool/code-dispatch-start` — log-only
|
||||
|
||||
@@ -678,12 +686,10 @@ Source: [`packages/core/tools/src/code-mode.ts:49`](../packages/core/tools/src/c
|
||||
* with `tool/code-dispatch` by `subCallId` (timing = the two events'
|
||||
* `time` fields).
|
||||
*/
|
||||
'tool/code-dispatch-start': { parentCallId: CallId; subCallId: CallId; name: string; arguments: unknown }
|
||||
'tool/code-dispatch-start': CodeDispatchStartEventData
|
||||
```
|
||||
|
||||
Types: [CallId](subsystems/core.md)
|
||||
|
||||
Source: [`packages/core/tools/src/code-mode.ts:33`](../packages/core/tools/src/code-mode.ts)
|
||||
Source: [`packages/core/tools/src/types.ts:40`](../packages/core/tools/src/types.ts)
|
||||
|
||||
#### `tool/result` — surface
|
||||
|
||||
@@ -708,7 +714,7 @@ Source: [`packages/core/tools/src/code-mode.ts:33`](../packages/core/tools/src/c
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:263`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:271`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `turn/*`
|
||||
|
||||
@@ -728,7 +734,7 @@ Source: [`packages/core/session/src/types.ts:263`](../packages/core/session/src/
|
||||
|
||||
Types: [TurnEndReason](subsystems/session.md)
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:224`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:232`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `turn/start` — log-only
|
||||
|
||||
@@ -742,7 +748,7 @@ Source: [`packages/core/session/src/types.ts:224`](../packages/core/session/src/
|
||||
'turn/start': { turn: number }
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:215`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:223`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `user/*`
|
||||
|
||||
@@ -759,7 +765,7 @@ Source: [`packages/core/session/src/types.ts:215`](../packages/core/session/src/
|
||||
'user/message': UserMessage
|
||||
```
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:236`](../packages/core/session/src/types.ts)
|
||||
Source: [`packages/core/session/src/types.ts:244`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `web/*`
|
||||
|
||||
|
||||
781
docs/persistence-catalog.zh.md
Normal file
781
docs/persistence-catalog.zh.md
Normal file
@@ -0,0 +1,781 @@
|
||||
<!-- 英文源文件由 scripts/gen-persistence-catalog.ts 生成;本中文文件是通过双语配对维护的经评审对侧。
|
||||
更新时先运行 `pnpm run gen-persistence-catalog` 更新英文,再更新本文件并运行 `pnpm run verify-translation-pairing --write docs/persistence-catalog.md` 重新记录配对。 -->
|
||||
|
||||
# 会话持久化事件目录
|
||||
|
||||
[English](persistence-catalog.md) | 中文
|
||||
|
||||
会话持久事件日志中可能出现的所有事件类型:完整持久化的 `SessionEvent` 信封,以及可通过合并扩展的 `SessionEventMap` 中的每个成员,包括 `@deepseek-ai/dsh-session` 所属的词汇和本仓库中每个插件对 `@deepseek-ai/dsh-session/types` 的声明合并,并附有源 JSDoc、完整 payload 声明、surface 标记和声明位置。本文档是 [session.md](subsystems/session.md)(surface 排序与 `deriveMessages()` 投影)、[persistence.md](subsystems/persistence.md)(如何让日志持久化)和 [session.md](subsystems/session.md#cordis-surface) 中生成区域(实时总线接线;日志事件**不是** cordis 事件,它通过唯一一次 `session/event` emit 到达监听器)的补充。
|
||||
|
||||
英文源文件根据源码生成(`scripts/gen-persistence-catalog.ts`),并由 `pnpm run verify-persistence-catalog`(`doc-sync`(文档同步门禁)的一部分)验证新鲜度;本中文文件作为经评审对侧通过双语配对维护。声明块保留源码声明和嵌套属性的 JSDoc,只移除其所在接口/模块带来的缩进,并使用 `ts persistence-catalog` 围栏(doc-typecheck 会跳过这些围栏,因为声明引用了其所属模块中的类型)。payload 中的类型名称会链接到记录该类型的页面。参见 [persistence-log-catalog Agent Note](../.agents/notes/archived/process/2026-07-04-persistence-log-catalog.md)。
|
||||
|
||||
以下信封声明组合了每个事件的 `type`、单调递增的 `seq`、以 epoch 毫秒表示的 `time`、`data`,以及条件字段 `surfaceOp`/`sourceEventSeqs`。**surface** 表示 `SurfaceEventType` 成员:它会生成一条 LLM(大语言模型)消息,并声明该事件如何加入 surface 列表。**log-only** 表示其他所有事件:这类记录可持久化、可回放,但不参与派生历史。每个 payload 均可进行 JSON 序列化(在 `Session.append` 处强制执行),整个格式固定为 `SESSION_FORMAT_VERSION = 0`:这是预发布格式,不暗示任何兼容性(参见[版本立场](subsystems/persistence.md))。范围仅限本仓库中的包;下游插件可以继续合并其他事件类型,而这些类型按设计不属于本目录。
|
||||
|
||||
## 事件信封
|
||||
|
||||
```ts persistence-catalog
|
||||
/** The appendable event-type keys of {@link SessionEventMap}, plugin-merged extensions included. */
|
||||
export type SessionEventType = keyof SessionEventMap
|
||||
|
||||
/**
|
||||
* The subset of {@link SessionEventType} values whose events produce LLM
|
||||
* messages and are eligible to appear on the ordered surface. Only these
|
||||
* event types may carry {@link SurfaceOp} and {@link SessionEvent.sourceEventSeqs}.
|
||||
*/
|
||||
export type SurfaceEventType =
|
||||
| 'user/message'
|
||||
| 'assistant/message'
|
||||
| 'tool/result'
|
||||
|
||||
/**
|
||||
* How a session event entered the ordered surface. Only valid on
|
||||
* {@link SurfaceEventType} events.
|
||||
*
|
||||
* - `'append'`: added to the tail — normal path for user/assistant/tool
|
||||
* messages.
|
||||
* - `{ op: 'replace', start, end }`: replaces surface nodes from `start`
|
||||
* (inclusive) through `end` (inclusive) with this node. Both must exist as
|
||||
* surface nodes in the current surface. `start === end` replaces a single
|
||||
* node. The node's {@link SessionEvent.sourceEventSeqs} must include every
|
||||
* shadowed surface node. Used by compaction; any surface-replacing producer
|
||||
* may use it.
|
||||
*/
|
||||
export type SurfaceOp =
|
||||
| 'append'
|
||||
| { op: 'replace'; start: number; end: number }
|
||||
|
||||
/**
|
||||
* One immutable entry in the session log.
|
||||
*
|
||||
* A proper discriminated union over `type` (not independent `type`/`data`
|
||||
* unions), so `switch (event.type)` narrows `event.data` without casts.
|
||||
*
|
||||
* The {@link sourceEventSeqs} and {@link surfaceOp} fields are conditional:
|
||||
* they only exist on {@link SurfaceEventType} variants (`user/message`,
|
||||
* `assistant/message`, `tool/result`).
|
||||
* Non-surface events (boundary markers, chunks, usage, errors) never carry
|
||||
* surface metadata — the compiler enforces this at `Session.append()`
|
||||
* call sites.
|
||||
*/
|
||||
export type SessionEvent<T extends SessionEventType = SessionEventType> = {
|
||||
[K in SessionEventType]: {
|
||||
type: K
|
||||
/** Monotonic sequence number within the session. */
|
||||
seq: number
|
||||
/** Unix epoch milliseconds. */
|
||||
time: number
|
||||
data: SessionEventMap[K]
|
||||
} & (K extends SurfaceEventType ? {
|
||||
/**
|
||||
* Seq numbers of earlier events that this event cites as sources
|
||||
* (e.g. the `assistant/chunk` seqs that built an `assistant/message`,
|
||||
* or the surface nodes shadowed by a compaction replace node). An
|
||||
* `assistant/message` may carry a present empty array for a known empty
|
||||
* provider stream; when the field is absent, the event does not record which
|
||||
* earlier events produced the message.
|
||||
*/
|
||||
sourceEventSeqs?: number[]
|
||||
/** How this event entered the surface; absent for non-surface events. */
|
||||
surfaceOp?: SurfaceOp
|
||||
} : object)
|
||||
}[T]
|
||||
```
|
||||
|
||||
来源:[`packages/core/session/src/types.ts:316`](../packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:323`](../packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:352`](../packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:384`](../packages/core/session/src/types.ts)
|
||||
|
||||
## 事件
|
||||
|
||||
### `agent/*`
|
||||
|
||||
#### `agent/inbox/spliced` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* One normalized mutation of an agent's durable pending-message lists.
|
||||
* Live dispatch precedes projection mutation, so synchronous observers may
|
||||
* read the pre-splice inbox to recover the removed messages.
|
||||
*/
|
||||
'agent/inbox/spliced': {
|
||||
target: InboxTarget
|
||||
start: number
|
||||
removedCount?: number
|
||||
inserted: UserMessage[]
|
||||
outcome?: 'canceled'
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/core/agent/src/types.ts:19`](../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent-preset/*`
|
||||
|
||||
#### `agent-preset/selected` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* The session's agent preset was chosen after creation, while the session
|
||||
* was still blank. Log-only: it records the composition later turns ran
|
||||
* under, so a resumed or forked session rebuilds the same one instead of
|
||||
* the header's creation-time value.
|
||||
*/
|
||||
'agent-preset/selected': { agentPreset: string }
|
||||
```
|
||||
|
||||
来源:[`packages/preset/agent-presets/src/session.ts:26`](../packages/preset/agent-presets/src/session.ts)
|
||||
|
||||
### `approval/*`
|
||||
|
||||
#### `approval/asked` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* An approval question was put to the answerer chain — log-only audit
|
||||
* (like `hook/*`; NOT a surface event, carries no `surfaceOp`). `id` pairs
|
||||
* it with the `approval/decided` that always follows; `toolName` is the
|
||||
* tool the question is about, `callId` the exact tool call when the asker
|
||||
* had one, `reason` the asker's human-readable explanation (e.g. a hook's
|
||||
* permission-decision reason).
|
||||
*/
|
||||
'approval/asked': {
|
||||
id: ApprovalRequestId
|
||||
toolName: string
|
||||
callId?: CallId
|
||||
reason?: string
|
||||
}
|
||||
```
|
||||
|
||||
类型:[CallId](subsystems/core.md)
|
||||
|
||||
来源:[`packages/interaction/user-approval/src/index.ts:44`](../packages/interaction/user-approval/src/index.ts)
|
||||
|
||||
#### `approval/decided` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* The outcome of a prior `approval/asked` (same `id`) — log-only audit.
|
||||
* Exactly one per ask, appended when the outcome is known: a decision, a
|
||||
* cancellation, or the fail-closed `'unavailable'`.
|
||||
*/
|
||||
'approval/decided': {
|
||||
id: ApprovalRequestId
|
||||
outcome: ApprovalOutcome
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/interaction/user-approval/src/index.ts:55`](../packages/interaction/user-approval/src/index.ts)
|
||||
|
||||
#### `approval/policy` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* The session's approval policy was switched — log-only, durable,
|
||||
* replayable, never in the model transcript (the model learns the policy
|
||||
* from the runtime-context snapshot and live switch notices). The LAST
|
||||
* such event is the session's override ({@link effectiveApprovalPolicy}).
|
||||
* `source: 'delegation'` marks an override seeded into a child; an absent
|
||||
* source is a runtime switch.
|
||||
*/
|
||||
'approval/policy': {
|
||||
policy: ApprovalPolicy
|
||||
/** Marks an override seeded into a child at delegation. */
|
||||
source?: 'delegation'
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/interaction/user-approval/src/index.ts:67`](../packages/interaction/user-approval/src/index.ts)
|
||||
|
||||
### `assistant/*`
|
||||
|
||||
#### `assistant/chunk` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/** Raw stream chunk — token-level replay fidelity. */
|
||||
'assistant/chunk': { turn: number; step: number; chunk: StreamChunk }
|
||||
```
|
||||
|
||||
类型:[StreamChunk](subsystems/llm-streaming.md)
|
||||
|
||||
来源:[`packages/core/session/src/types.ts:246`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `assistant/message` — surface
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Assembled assistant message for one step (derived history uses this).
|
||||
* Carries the step's `usage` when the adapter reported token accounting, so
|
||||
* the model output and its accounting travel together (there is no separate
|
||||
* usage record). `usage` is absent when the adapter reported none.
|
||||
*/
|
||||
'assistant/message': { turn: number; step: number; message: AssistantMessage; usage?: TokenUsage }
|
||||
```
|
||||
|
||||
类型:[TokenUsage](subsystems/llm-streaming.md)
|
||||
|
||||
来源:[`packages/core/session/src/types.ts:253`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `command/*`
|
||||
|
||||
#### `command/done` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* The paired command settled. `kind`/`text` carry the handler's verbatim
|
||||
* outcome (a thrown/aborted handler settles as `kind: 'error'` with the
|
||||
* rendered failure). A successful command may identify the earlier
|
||||
* authoritative domain event for a richer client-computed presentation.
|
||||
*/
|
||||
'command/done': {
|
||||
commandId: CommandId
|
||||
kind: 'success' | 'error'
|
||||
text?: string
|
||||
sourceEventSeq?: number
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/interaction/commands/src/types.ts:41`](../packages/interaction/commands/src/types.ts)
|
||||
|
||||
#### `command/run` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* A resolved slash command entered its handler. Log-only (never model
|
||||
* surface); paired with `command/done` by `commandId`, mirroring the
|
||||
* `tool/call`↔`tool/result` pairing. The payload is structured — `name`
|
||||
* and `args` are `parseCommand`'s own split (name and verbatim rawInput,
|
||||
* separator whitespace included), so a consumer (a projection unit
|
||||
* folding its own command records, a rich command card) never re-parses
|
||||
* a line. `args` is absent when the definition sets `recordInput: false`
|
||||
* because an authoritative domain event owns the input payload.
|
||||
*/
|
||||
'command/run': { commandId: CommandId; name: string; args?: string; source: CommandSource }
|
||||
```
|
||||
|
||||
来源:[`packages/interaction/commands/src/types.ts:34`](../packages/interaction/commands/src/types.ts)
|
||||
|
||||
### `compact/*`
|
||||
|
||||
#### `compact/end` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Marks the end of a compaction — log-only, releases the lock. Its owner
|
||||
* matches `compact/start`; `error` records an unsuccessful attempt.
|
||||
*/
|
||||
'compact/end': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null; error?: string }
|
||||
```
|
||||
|
||||
来源:[`packages/compact/compact/src/types.ts:71`](../packages/compact/compact/src/types.ts)
|
||||
|
||||
#### `compact/prune` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Shadow price of one model-free prune replacement — log-only, no
|
||||
* surfaceOp. The shared shadow-price protocol: a surface `replace` event
|
||||
* is priced by the metering event immediately before it (`compact/summary`
|
||||
* for a summarizing compaction, this event for a prune), which states the
|
||||
* heuristic token price of the exact replaced range so a pure consumer
|
||||
* can subtract it without retaining per-node prices. The replacement MUST
|
||||
* be appended synchronously right after this event.
|
||||
*/
|
||||
'compact/prune': {
|
||||
/** The replaced range's first and last surface-node seqs (a surface-position span, like {@link CompactionResult.shadowedRange}). */
|
||||
shadowedRange: { start: number; end: number }
|
||||
/** The seqs of all shadowed surface nodes, in surface order. */
|
||||
shadowedSeqs: number[]
|
||||
/** Heuristic price of the shadowed content under the token-meter's fixed estimator. */
|
||||
shadowedTokenCount: number
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/compact/compact/src/types.ts:81`](../packages/compact/compact/src/types.ts)
|
||||
|
||||
#### `compact/start` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Marks the start of a compaction — log-only, holds the lock until
|
||||
* `compact/end`. A numbered owner is strictly enclosed by that open turn;
|
||||
* `null` identifies a standalone manual transaction between turns.
|
||||
*/
|
||||
'compact/start': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null }
|
||||
```
|
||||
|
||||
来源:[`packages/compact/compact/src/types.ts:23`](../packages/compact/compact/src/types.ts)
|
||||
|
||||
#### `compact/summary` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Completed summary, its inputs, and its model call facts — log-only, no surfaceOp.
|
||||
* The summary content is in `data.summary`; the actual surface replacement
|
||||
* is performed by the immediately following `user/message` event that
|
||||
* shadows the compacted range. That adjacency is contractual — the
|
||||
* shadowed pricing fields are the replacement's shadow price, so a
|
||||
* consumer may pair a replacement with the metering event directly
|
||||
* before it (`compact/prune` documents the shared protocol).
|
||||
*/
|
||||
'compact/summary': {
|
||||
compactionId: CompactionId
|
||||
sourceCommandId?: CommandId
|
||||
summary: ContentBlock[]
|
||||
shadowedRange: { start: number; end: number }
|
||||
shadowedSeqs: number[]
|
||||
shadowedTokenCount: number
|
||||
/** The provider route that wrote the summary. */
|
||||
provider: string
|
||||
/**
|
||||
* The model that wrote the summary — the summarize call's envelope,
|
||||
* reported by the backend that made the call, logged so the one-shot
|
||||
* request is reconstructable from log + code and "which model wrote
|
||||
* this summary" has a durable answer (the reconstructability Agent Note).
|
||||
*/
|
||||
model: string
|
||||
/** The generation cap the summarize call sent, when one applied. */
|
||||
maxTokens?: number
|
||||
/** Provider-reported token usage for the summarization request, when emitted. */
|
||||
usage?: TokenUsage
|
||||
} & (
|
||||
| {
|
||||
/** Complete provider output before the backend's safe summary projection. */
|
||||
rawOutput: ContentBlock[]
|
||||
/** Identifies exactly one call through this context's `ctx.llm.stream()`. */
|
||||
llmStreamCall: true
|
||||
}
|
||||
| {
|
||||
/** Optional complete output from an unmarked template, remote, or other summarizer. */
|
||||
rawOutput?: ContentBlock[]
|
||||
/** An unmarked summary does not identify a call through this context's LLM seam. */
|
||||
llmStreamCall?: never
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
类型:[ContentBlock](subsystems/core.md) · [TokenUsage](subsystems/llm-streaming.md)
|
||||
|
||||
来源:[`packages/compact/compact/src/types.ts:33`](../packages/compact/compact/src/types.ts)
|
||||
|
||||
### `feedback/*`
|
||||
|
||||
#### `feedback/record` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* One recorded human remark about this session. Log-only and independent
|
||||
* of its trigger; it never enters the model surface or derived history.
|
||||
*/
|
||||
'feedback/record': { text: string }
|
||||
```
|
||||
|
||||
来源:[`packages/feedback/command-feedback/src/index.ts:24`](../packages/feedback/command-feedback/src/index.ts)
|
||||
|
||||
### `goal/*`
|
||||
|
||||
#### `goal/change` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Complete post-mutation goal state or clear tombstone.
|
||||
*/
|
||||
'goal/change': GoalChangeMeta
|
||||
```
|
||||
|
||||
来源:[`packages/goal/goal/src/domain.ts:66`](../packages/goal/goal/src/domain.ts)
|
||||
|
||||
### `hook/*`
|
||||
|
||||
#### `hook/invoked` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* A hook command was invoked at a hook point — a log-only record (like
|
||||
* `compact/*`; NOT a {@link SurfaceEventType}, carries no `surfaceOp`).
|
||||
* `dialect` is the bridge that ran it (`claude`/`codex`), `point`
|
||||
* the hook point (`PreToolUse`, `Stop`, …), `matcher` the matcher-group
|
||||
* pattern that selected it (absent for match-all), `handlerId` a stable id
|
||||
* for the command (so an invoked/result pair correlates). `turn` is the open
|
||||
* turn the invocation lives inside.
|
||||
*/
|
||||
'hook/invoked': {
|
||||
turn: number
|
||||
point: string
|
||||
dialect: HookDialect
|
||||
matcher?: string
|
||||
handlerId: string
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/hooks/hook-protocol/src/types.ts:19`](../packages/hooks/hook-protocol/src/types.ts)
|
||||
|
||||
#### `hook/result` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Log-only outcome paired to `hook/invoked` by `handlerId`. Decision is the
|
||||
* parsed permission result, `stop` for `continue:false`, or `pass`; exit code
|
||||
* may be absent, stderr is bounded, and duration is wall-clock runtime.
|
||||
*/
|
||||
'hook/result': {
|
||||
turn: number
|
||||
point: string
|
||||
handlerId: string
|
||||
decision: string
|
||||
exitCode?: number
|
||||
stderrSummary?: string
|
||||
durationMs: number
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/hooks/hook-protocol/src/types.ts:31`](../packages/hooks/hook-protocol/src/types.ts)
|
||||
|
||||
### `llm/*`
|
||||
|
||||
#### `llm/retry` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/** Durable, non-surface record of one provider-routed retry scheduled after a failed request attempt. */
|
||||
'llm/retry': LlmRetryEventData
|
||||
```
|
||||
|
||||
来源:[`packages/llm/llm-retry/src/types.ts:9`](../packages/llm/llm-retry/src/types.ts)
|
||||
|
||||
#### `llm/retry-started` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/** Durable transition written after a retry wait succeeds and before the next request attempt starts. */
|
||||
'llm/retry-started': LlmRetryStartedEventData
|
||||
```
|
||||
|
||||
来源:[`packages/llm/llm-retry/src/types.ts:11`](../packages/llm/llm-retry/src/types.ts)
|
||||
|
||||
### `permission/*`
|
||||
|
||||
#### `permission/preset` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Records the selected preset as durable, log-only user intent. The knob
|
||||
* events follow in the same turn and control execution; this event stays
|
||||
* out of the model transcript and lets {@link effectivePermissionPreset}
|
||||
* preserve a selection when bundles match.
|
||||
*/
|
||||
'permission/preset': { preset: string }
|
||||
```
|
||||
|
||||
来源:[`packages/interaction/permission/src/index.ts:50`](../packages/interaction/permission/src/index.ts)
|
||||
|
||||
### `plan/*`
|
||||
|
||||
#### `plan/mode` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Whether plan mode is in force from this point on: log-only, non-surface,
|
||||
* whole-value replace. The last `plan/mode` wins; a log with none folds to
|
||||
* inactive through {@link foldPlanMode}.
|
||||
*/
|
||||
'plan/mode': { active: boolean }
|
||||
```
|
||||
|
||||
来源:[`packages/plan/plan-mode/src/index.ts:52`](../packages/plan/plan-mode/src/index.ts)
|
||||
|
||||
### `request/*`
|
||||
|
||||
#### `request/context` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Route metadata for the next request, logged only when the route or capacity
|
||||
* changes. It does not participate in request reconstruction or header equality.
|
||||
*/
|
||||
'request/context': RequestContext
|
||||
```
|
||||
|
||||
来源:[`packages/core/session/src/types.ts:289`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `request/header` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Full header for the next request, appended inside its step before dispatch.
|
||||
* It is log-only; the latest snapshot reconstructs the request header.
|
||||
*/
|
||||
'request/header': { header: EpochHeader; reason: RequestHeaderReason }
|
||||
```
|
||||
|
||||
来源:[`packages/core/session/src/types.ts:284`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `sandbox/*`
|
||||
|
||||
#### `sandbox/mode` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* The session's sandbox mode was switched — log-only (like `approval/*`;
|
||||
* NOT a surface event, carries no `surfaceOp`): durable and replayable,
|
||||
* never in the model transcript. The LAST such event is the session's
|
||||
* override ({@link effectiveSandboxMode}). `source: 'delegation'` marks
|
||||
* an override seeded into a child; an absent source is a runtime switch.
|
||||
*/
|
||||
'sandbox/mode': {
|
||||
mode: SandboxMode
|
||||
/** Marks an override seeded into a child at delegation. */
|
||||
source?: 'delegation'
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/sandbox/sandbox-policy/src/session-mode.ts:33`](../packages/sandbox/sandbox-policy/src/session-mode.ts)
|
||||
|
||||
### `session/*`
|
||||
|
||||
#### `session/end-seed` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Marks the end of a constructor seed. Events before it have smaller seq
|
||||
* values and came from the seed (resume, fork, or replay); this lifecycle
|
||||
* produced none of them. This log-only event is the durable projection of
|
||||
* {@link Session.firstLiveSeq}. Its payload is empty — position and `time`
|
||||
* carry the meaning.
|
||||
*
|
||||
* Locate the LAST one in stored history. A seed already ending in one is not
|
||||
* re-marked, so reopening an untouched session does not grow its log per
|
||||
* pickup and the event need not be at the current `firstLiveSeq`.
|
||||
*
|
||||
* `Session`'s constructor is the only legitimate writer. The invariant
|
||||
* companion deliberately constrains nothing here, so a plugin appending one
|
||||
* would silently classify every live bracket before it as seed history.
|
||||
*
|
||||
* An owner of a standalone open/close bracket (`compact/start` …
|
||||
* `compact/end`) reads it because seed history and live work are otherwise
|
||||
* byte-identical: an unmatched opening marker before this event belongs to
|
||||
* an ended lifecycle, whatever ended it. NOT a liveness signal about other
|
||||
* writers — a concurrently live session holds its own boundary elsewhere,
|
||||
* so tolerating concurrent writers needs a signal beyond the log.
|
||||
*/
|
||||
'session/end-seed': Record<string, never>
|
||||
```
|
||||
|
||||
来源:[`packages/core/session/src/types.ts:312`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `session/title` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Latest-wins session title snapshot. Log-only: it never enters the model
|
||||
* surface or derived history.
|
||||
*/
|
||||
'session/title': SessionTitleEventData
|
||||
```
|
||||
|
||||
类型:[SessionTitleEventData](subsystems/session-title.md)
|
||||
|
||||
来源:[`packages/session/session-title/src/index.ts:100`](../packages/session/session-title/src/index.ts)
|
||||
|
||||
#### `session/title-llm-request` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/** Log-only pre-dispatch record of one session-title model request. */
|
||||
'session/title-llm-request': SessionTitleLlmRequestEventData
|
||||
```
|
||||
|
||||
类型:[SessionTitleLlmRequestEventData](subsystems/session-title.md)
|
||||
|
||||
来源:[`packages/session/session-title-llm/src/index.ts:43`](../packages/session/session-title-llm/src/index.ts)
|
||||
|
||||
### `step/*`
|
||||
|
||||
#### `step/end` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/** Closes step `step` of turn `turn`. */
|
||||
'step/end': { turn: number; step: number }
|
||||
```
|
||||
|
||||
来源:[`packages/core/session/src/types.ts:236`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `step/start` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/** Opens step `step` of turn `turn` — one model call plus the tool executions it requested. */
|
||||
'step/start': { turn: number; step: number }
|
||||
```
|
||||
|
||||
来源:[`packages/core/session/src/types.ts:234`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `subagent/*`
|
||||
|
||||
#### `subagent/descriptor` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Durable identity and lifecycle mode of a session-backed subagent child,
|
||||
* appended once by the establishing provider inside the child's initial
|
||||
* turn, before its first request. Continuable records also carry their
|
||||
* resumable composition. Log-only: it carries no `surfaceOp`, never enters
|
||||
* model history, and survives compaction.
|
||||
*/
|
||||
'subagent/descriptor': SubagentDescriptorData
|
||||
```
|
||||
|
||||
来源:[`packages/subagent/subagent/src/descriptor.ts:37`](../packages/subagent/subagent/src/descriptor.ts)
|
||||
|
||||
### `todo/*`
|
||||
|
||||
#### `todo/write` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/** Whole-list snapshot; latest write wins on replay. Log-only UI state; never derived history. */
|
||||
'todo/write': { todos: TodoItem[] }
|
||||
```
|
||||
|
||||
类型:[TodoItem](subsystems/session.md)
|
||||
|
||||
来源:[`packages/core/session/src/types.ts:279`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `tool/*`
|
||||
|
||||
#### `tool/call` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* The model requested one tool invocation: `name` with the raw `arguments`
|
||||
* JSON string exactly as the model produced it (unparsed). `callId` pairs the
|
||||
* call with its `tool/result`.
|
||||
*/
|
||||
'tool/call': { turn: number; step: number; callId: CallId; name: string; arguments: string }
|
||||
```
|
||||
|
||||
类型:[CallId](subsystems/core.md)
|
||||
|
||||
来源:[`packages/core/session/src/types.ts:259`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `tool/code-dispatch` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* One bridged sub-dispatch SETTLING: the pairing ids (matching the
|
||||
* `tool/code-dispatch-start` with the same `subCallId`), the tool `name`
|
||||
* with the same JSON-normalized `arguments`, and the sub-call's complete
|
||||
* model-facing outcome in `tool/result`'s own vocabulary
|
||||
* (`content` + `isError`), so UIs render a sub-call through the exact
|
||||
* code path that renders a native call. Every started sub-call settles
|
||||
* with exactly one of these (abort included: the aborted pipeline result
|
||||
* is an `isError` outcome).
|
||||
* Log-only: `deriveMessages()` ignores it, so sub-calls never re-enter
|
||||
* model context; persistence and UIs get every call. Appended inside the
|
||||
* parent `run_code`'s execution (the bridge drains in-flight dispatches
|
||||
* before returning), so its execution-enclosure relation holds by
|
||||
* construction.
|
||||
*/
|
||||
'tool/code-dispatch': CodeDispatchEventData
|
||||
```
|
||||
|
||||
来源:[`packages/core/tools/src/types.ts:56`](../packages/core/tools/src/types.ts)
|
||||
|
||||
#### `tool/code-dispatch-start` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* One sub-dispatch STARTING inside a `run_code` program: the parent
|
||||
* `run_code` call id, the deterministic sub-call id (`<parent>:code:<n>`,
|
||||
* numbered in submission order), and the tool `name` with its
|
||||
* JSON-normalized `arguments` — the exact value dispatched, normalized
|
||||
* BEFORE dispatch, so this append can never fail on payload shape.
|
||||
* Appended when the scheduler actually starts the call (not at
|
||||
* submission), so a start means the tool body pipeline was entered; a
|
||||
* call abandoned in the queue logs nothing. Log-only: `deriveMessages()`
|
||||
* ignores it; UIs use it for live per-sub-call running state and pair it
|
||||
* with `tool/code-dispatch` by `subCallId` (timing = the two events'
|
||||
* `time` fields).
|
||||
*/
|
||||
'tool/code-dispatch-start': CodeDispatchStartEventData
|
||||
```
|
||||
|
||||
来源:[`packages/core/tools/src/types.ts:40`](../packages/core/tools/src/types.ts)
|
||||
|
||||
#### `tool/result` — surface
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* A completed tool call's model-facing result, optional internal failure
|
||||
* identity, and optional tool-private `meta` presentation payload. `meta` is
|
||||
* opaque to the core (the producing tool owns its shape and reads it back in
|
||||
* `presentResult`) but MUST be JSON-serializable: `Session.append`
|
||||
* runtime-validates all event data with `isJsonValue`, so a non-serializable
|
||||
* `meta` is rejected at the source, and the durable log reproduces the
|
||||
* identical card on replay. Absent
|
||||
* unless the tool attaches one (e.g. `dsh-tool-fs` carries its result-time
|
||||
* contextual diff here).
|
||||
*/
|
||||
'tool/result': {
|
||||
turn: number
|
||||
step: number
|
||||
message: ToolResultMessage
|
||||
error?: { name: string; code: string }
|
||||
meta?: JsonValue
|
||||
}
|
||||
```
|
||||
|
||||
来源:[`packages/core/session/src/types.ts:271`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `turn/*`
|
||||
|
||||
#### `turn/end` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Closes turn `turn` with the {@link TurnEndReason} that ended it. A turn
|
||||
* with no entered step has no `step/start` or `step/end`. The loop does not await a
|
||||
* flush at turn boundaries: `dsh-session-checkpoint-policy` owns the
|
||||
* per-request durability checkpoint, and consumers that read storage after
|
||||
* `whenIdle()` flush themselves. Success commits the turn; rejection is
|
||||
* reported live and does not prevent later work.
|
||||
*/
|
||||
'turn/end': { turn: number; reason: TurnEndReason }
|
||||
```
|
||||
|
||||
类型:[TurnEndReason](subsystems/session.md)
|
||||
|
||||
来源:[`packages/core/session/src/types.ts:232`](../packages/core/session/src/types.ts)
|
||||
|
||||
#### `turn/start` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Opens turn `turn` before the loop claims queued input or runs pre-step.
|
||||
* Rejection, empty input, cancellation, or failure may close it with no
|
||||
* step; otherwise the following identified `user/message` event or batch
|
||||
* records the messages entering the step.
|
||||
*/
|
||||
'turn/start': { turn: number }
|
||||
```
|
||||
|
||||
来源:[`packages/core/session/src/types.ts:223`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `user/*`
|
||||
|
||||
#### `user/message` — surface
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* A user-role message on the model-visible surface: a direct human prompt
|
||||
* (the queued message claimed for this turn), a synthetic `agent.inject()`
|
||||
* context (file-change notices, subdir AGENTS.md, skill content, cron
|
||||
* notifications, …), or an entered goal continuation round. All three
|
||||
* project their `content` verbatim; `source` tells them apart.
|
||||
*/
|
||||
'user/message': UserMessage
|
||||
```
|
||||
|
||||
来源:[`packages/core/session/src/types.ts:244`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `web/*`
|
||||
|
||||
#### `web/deepseek-search-llm-request` — log-only
|
||||
|
||||
```ts persistence-catalog
|
||||
/** Secret-free auxiliary DeepSeek search request recorded before dispatch. */
|
||||
'web/deepseek-search-llm-request': DeepSeekSearchLlmRequest
|
||||
```
|
||||
|
||||
来源:[`packages/web/web-search-deepseek/src/provider.ts:83`](../packages/web/web-search-deepseek/src/provider.ts)
|
||||
@@ -3,4 +3,4 @@
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/postmortem/0003-web-agent-gui-feedback-loop.md
|
||||
0003-web-agent-gui-feedback-loop.md: 13d13a607babfe7f5ddfdb6773c94f973bbef0db
|
||||
0003-web-agent-gui-feedback-loop.zh.md: 84c9043ce2e286512483c99c2e23ebdc99cb49b2
|
||||
0003-web-agent-gui-feedback-loop.zh.md: 44d4febc30344135932aad2394b3054587feca1d
|
||||
|
||||
@@ -18,16 +18,16 @@ Web agent 修改了 GUI 源码,却不知道由哪个 URL 和进程承载当前
|
||||
|
||||
## 影响
|
||||
|
||||
用户不得不连续指出三个错误:agent 把验收交还给用户;建议预览的页面一片空白;报告成功的 URL 并不是用户正在使用的页面。一个不受管理的替代服务器还持续运行到下一轮,直到用户提出质疑。
|
||||
用户不得不连续指出三个错误:agent 把验收交还给用户;建议预览的页面一片空白;报告成功的 URL 并不是用户正在使用的页面。一个不受管理的替代服务器还持续运行到下一个轮次,直到用户提出质疑。
|
||||
|
||||
本次调查没有重启或修改只读的 3081 和 3082 试验服务。
|
||||
|
||||
## 时间线
|
||||
|
||||
- 在第 2 轮中,agent 修改主题后,在序列 30939 的消息中让用户运行 `pnpm run demo:tui` 或打开一个未明确指定的 Web 应用。它没有对组装后的 Web 应用执行任何验收。
|
||||
- 在第 3 轮中,agent 读取 `apps/web/package.json`,在序列 31865 于端口 5173 上启动裸 Vite,观察到 HTTP 200 后便宣布成功。浏览器却抛出 `client-modules: window.__DSH_BOOT__ is missing or not an object`,并显示白屏。
|
||||
- 在第 4 轮中,agent 找到了完整的 `dsh web` 启动路径,重新构建 shell,在序列 34309 于端口 3334 上启动一个不受管理的进程,并且只在序列 34441 检查了这个替代服务是否返回 200 和启动 manifest。它从未探测端口 3081。
|
||||
- 在第 5 轮中,用户在序列 34556 报告 3081 已经显示新主题。直到序列 34681,agent 才检查既有进程并移除冗余服务器。
|
||||
- 在第 2 个轮次中,agent 修改主题后,在序列 30939 的消息中让用户运行 `pnpm run demo:tui` 或打开一个未明确指定的 Web 应用。它没有对组装后的 Web 应用执行任何验收。
|
||||
- 在第 3 个轮次中,agent 读取 `apps/web/package.json`,在序列 31865 于端口 5173 上启动裸 Vite,观察到 HTTP 200 后便宣布成功。浏览器却抛出 `client-modules: window.__DSH_BOOT__ is missing or not an object`,并显示白屏。
|
||||
- 在第 4 个轮次中,agent 找到了完整的 `dsh web` 启动路径,重新构建 shell,在序列 34309 于端口 3334 上启动一个不受管理的进程,并且只在序列 34441 检查了这个替代服务是否返回 200 和启动 manifest。它从未探测端口 3081。
|
||||
- 在第 5 个轮次中,用户在序列 34556 报告 3081 已经显示新主题。直到序列 34681,agent 才检查既有进程并移除冗余服务器。
|
||||
|
||||
## 根因
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/README.md
|
||||
README.md: 1c3d14aeb4fd11cbc45eaadd83f0b84de0dfda52
|
||||
README.zh.md: 04e07cc9c8b8b16c69bb09344e8533729525fe5c
|
||||
README.md: 096fd7de4d2644dac664fac940b6487052115258
|
||||
README.zh.md: 6b6758db8f7118a09f6b0998231d3944f44f5052
|
||||
|
||||
@@ -7,18 +7,18 @@ One page per subsystem of the DeepSeek Harness: what it is, the data structures
|
||||
| Page | Owns |
|
||||
|---|---|
|
||||
| [core.md](core.md) | the `packages/core` control spine: the package-by-package loop map, agent creation and ownership (`AgentHandle`), the `Agent` handle with its delivery/cancellation/interception contracts, and the repo-wide type patterns (`…Map → derived-union`, branded ids) |
|
||||
| [llm-streaming.md](llm-streaming.md) | the `packages/llm` conversation vocabulary — `Message`/`ContentBlock`, the assembled model request, the `StreamChunk` wire protocol + adapter contract, `BlockAssembler`, the `LlmAdapter` seam |
|
||||
| [llm-streaming.md](llm-streaming.md) | the `packages/llm` conversation vocabulary — `Message`/`ContentBlock`, the assembled model request, the `StreamChunk` wire protocol + adapter contract, `BlockAssembler`, the `LlmAdapter` provider contract |
|
||||
| [token-meter.md](token-meter.md) | immutable scalar and positional replay measurements with consumed-log revisions |
|
||||
| [scope.md](scope.md) | scoped registration identity, dispatch carriers, and the owned `Scope` context |
|
||||
| [typert.md](typert.md) | Remote invocation descriptors, lookup/Context declarations, TypeRT registries, and the Host Gateway/Client API seams |
|
||||
| [typert.md](typert.md) | Remote invocation descriptors, lookup/Context declarations, TypeRT registries, and the Host Gateway/Client API boundaries |
|
||||
| [goal.md](goal.md) | persisted goal identity, lifecycle snapshots, activation, change records, and round attribution |
|
||||
| [commands.md](commands.md) | the human-command seam: definitions, adapter discovery, direct invocation, results, and parsing views |
|
||||
| [commands.md](commands.md) | the human-command registry service: definitions, adapter discovery, direct invocation, results, and parsing views |
|
||||
| [session.md](session.md) | the full `SessionEventMap` variant catalog, `TurnTrigger`/`TurnEndReason`, `deriveMessages()`, execution enclosure, and standalone events |
|
||||
| [persistence.md](persistence.md) | the durability seam: `SessionPersistence`, JSONL + SQLite backends, `session/flush`, crash recovery, `SessionHeader` |
|
||||
| [settings.md](settings.md) | the user-settings seam: `SettingsNamespace` registration, layered resolution (defaults → composition `base` → user document), owner scopes, hot commits |
|
||||
| [credentials.md](credentials.md) | the credential seam: `CredentialRef` references (never values) in configuration, per-operation resolution, UI-safe `CredentialInfo`, provider source layers |
|
||||
| [session-query.md](session-query.md) | logical records, bounded exact-event reads, relationship traces, semantic filters/documents, and full-text result pages |
|
||||
| [session-title.md](session-title.md) | durable title snapshots, source provenance, and the asynchronous provider contract |
|
||||
| [session-title.md](session-title.md) | durable title snapshots, cited source-message seqs, and the asynchronous provider contract |
|
||||
| [session-reference.md](session-reference.md) | structured cross-session references: `SessionReferenceInput`/`Candidate`, prepared message contexts, the stable error taxonomy |
|
||||
| [system-prompt.md](system-prompt.md) | per-assembly context, tool-provider results, prompt sections, and cooperative assembly |
|
||||
| [tools.md](tools.md) | `ToolDefinition` full fields, the schema DSL, `ToolExecution`/`ToolResult`, tool-presentation UI types, and the guarded execution pipeline |
|
||||
@@ -42,10 +42,10 @@ One page per subsystem of the DeepSeek Harness: what it is, the data structures
|
||||
| [plan.md](plan.md) | plan mode: the log-only `plan/mode` state, pending-selection flush, `PlanModeConfig`, the `exit_plan_mode` review arc |
|
||||
| [invariants.md](invariants.md) | the runtime-invariant registry: selection `Config`, `InvariantInstaller`/`InvariantFailure`, the empty-companion contract |
|
||||
| [http-server.md](http-server.md) | the HTTP carrier: `WebRouteKind`/`WebRoute`, match order, the claimable fallback seat, index taps |
|
||||
| [storage.md](storage.md) | the storage subsystem: the backend seam (`StorageBackend`), `StorageForms`, `DomainSpec`/`Domain`, `domain/changed` |
|
||||
| [storage.md](storage.md) | the storage subsystem: the backend contract (`StorageBackend`), `StorageForms`, `DomainSpec`/`Domain`, `domain/changed` |
|
||||
| [workspace.md](workspace.md) | the workspace registry: `Workspace`/`WorkspaceId`, registration and resolution, the session `cwd` relationship |
|
||||
| [client-modules.md](client-modules.md) | the web plugin table: `dshClient` declarations, `WebBootGraph` wire composition, the bundle route and index tap |
|
||||
| [session-projection.md](session-projection.md) | the projection seam: `SessionProjectionMap`, the pure `ProjectionDefinition` unit, `ProjectionSnapshot`'s consistent cut, the change feed |
|
||||
| [telemetry.md](telemetry.md) | the outbound reporting seam: `TelemetryRecord`/`TelemetrySeverity`, the `TelemetryBackend` contract, the `telemetry/record` redact waterfall |
|
||||
| [telemetry.md](telemetry.md) | the session-telemetry capability seam: `TelemetryRecord`/`TelemetrySeverity`, the `TelemetryBackend` contract, the `telemetry/record` redact waterfall |
|
||||
|
||||
> Type declarations and their JSDoc on these pages are source-equivalent and drift-checked by `pnpm run verify-type-equiv` (see [development.md](../development.md#documenting-types-verbatim-ts-type-equiv)). Ordinary blocks preserve complete declarations; `public-api` blocks preserve body-stripped public class declarations. Cordis services and events use each page's generated **Cordis surface** section.
|
||||
|
||||
@@ -7,18 +7,18 @@
|
||||
| 页面 | 负责内容 |
|
||||
|---|---|
|
||||
| [core.md](core.md) | `packages/core` 控制主干:逐包循环地图、agent 创建与所有权(`AgentHandle`)、`Agent` 句柄及其投递/取消/拦截约定,以及全仓通用类型模式(`…Map → 派生联合`、品牌化 id) |
|
||||
| [llm-streaming.md](llm-streaming.md) | `packages/llm` 的对话词汇——`Message`/`ContentBlock`、组装完成的模型请求、`StreamChunk` 协议格式(wire format)+ 适配器约定(adapter contract)、`BlockAssembler`、`LlmAdapter` seam |
|
||||
| [llm-streaming.md](llm-streaming.md) | `packages/llm` 的对话词汇——`Message`/`ContentBlock`、组装完成的模型请求、`StreamChunk` 协议格式(wire format)+ 适配器约定(adapter contract)、`BlockAssembler`、`LlmAdapter` 提供方约定 |
|
||||
| [token-meter.md](token-meter.md) | 不可变的标量与位置回放度量,附带已消费日志修订号 |
|
||||
| [scope.md](scope.md) | 作用域注册标识、dispatch 载体,以及拥有的 `Scope` 上下文 |
|
||||
| [typert.md](typert.md) | 远程调用描述符、lookup/Context 声明、TypeRT 注册表,以及 Host Gateway/Client API seam |
|
||||
| [typert.md](typert.md) | 远程调用描述符、lookup/Context 声明、TypeRT 注册表,以及 Host Gateway/Client API 边界 |
|
||||
| [goal.md](goal.md) | 持久 goal 标识、生命周期快照、激活、变更记录与 Round 归属 |
|
||||
| [commands.md](commands.md) | 人类命令 seam:定义、适配器发现、直接调用、结果与解析视图 |
|
||||
| [commands.md](commands.md) | 人类命令注册表服务:定义、适配器发现、直接调用、结果与解析视图 |
|
||||
| [session.md](session.md) | 完整的 `SessionEventMap` 变体目录、`TurnTrigger`/`TurnEndReason`、`deriveMessages()`、执行封闭与独立事件 |
|
||||
| [persistence.md](persistence.md) | 持久性 seam:`SessionPersistence`、JSONL + SQLite 后端、`session/flush`、崩溃恢复、`SessionHeader` |
|
||||
| [settings.md](settings.md) | 用户设置 seam:`SettingsNamespace` 注册、分层解析(默认值 → 组合 `base` → 用户文档)、owner scope、热提交 |
|
||||
| [credentials.md](credentials.md) | 凭据 seam:配置中的 `CredentialRef` 引用(绝不含值)、按操作解析、对 UI 安全的 `CredentialInfo`、provider 来源层 |
|
||||
| [session-query.md](session-query.md) | 逻辑记录、有界精确事件读取、关系追踪、语义筛选器/文档与全文检索结果页 |
|
||||
| [session-title.md](session-title.md) | 持久标题快照、来源 provenance 与异步提供方约定 |
|
||||
| [session-title.md](session-title.md) | 持久标题快照、被引用的来源消息 seq 与异步提供方约定 |
|
||||
| [session-reference.md](session-reference.md) | 结构化跨会话引用:`SessionReferenceInput`/`Candidate`、prepared 消息上下文、稳定错误分类 |
|
||||
| [system-prompt.md](system-prompt.md) | 逐次组装的上下文、工具提供方结果、提示词段落与协作式组装 |
|
||||
| [tools.md](tools.md) | `ToolDefinition` 完整字段、schema DSL、`ToolExecution`/`ToolResult`、工具展示 UI 类型,以及受保护的执行流水线 |
|
||||
@@ -42,10 +42,10 @@
|
||||
| [plan.md](plan.md) | 计划模式:仅记日志的 `plan/mode` 状态、待定选择的冲刷、`PlanModeConfig`、`exit_plan_mode` 审阅流程 |
|
||||
| [invariants.md](invariants.md) | 运行时不变式注册表:选择配置 `Config`、`InvariantInstaller`/`InvariantFailure`、空配套插件约定 |
|
||||
| [http-server.md](http-server.md) | HTTP 载体:`WebRouteKind`/`WebRoute`、匹配顺序、可认领的回退席位、index 转换 |
|
||||
| [storage.md](storage.md) | 存储子系统:后端 seam(`StorageBackend`)、`StorageForms`、`DomainSpec`/`Domain`、`domain/changed` |
|
||||
| [storage.md](storage.md) | 存储子系统:后端约定(`StorageBackend`)、`StorageForms`、`DomainSpec`/`Domain`、`domain/changed` |
|
||||
| [workspace.md](workspace.md) | 工作区注册表:`Workspace`/`WorkspaceId`、注册与解析、与会话 `cwd` 的关系 |
|
||||
| [client-modules.md](client-modules.md) | Web 插件表:`dshClient` 声明、`WebBootGraph` 线上组合、bundle 路由与 index 转换 |
|
||||
| [session-projection.md](session-projection.md) | 投影 seam:`SessionProjectionMap`、纯函数 `ProjectionDefinition` 单元、`ProjectionSnapshot` 的一致切面、变更馈送 |
|
||||
| [telemetry.md](telemetry.md) | 对外上报 seam:`TelemetryRecord`/`TelemetrySeverity`、`TelemetryBackend` 约定、`telemetry/record` 脱敏 waterfall |
|
||||
| [telemetry.md](telemetry.md) | 会话遥测能力 seam:`TelemetryRecord`/`TelemetrySeverity`、`TelemetryBackend` 约定、`telemetry/record` 脱敏 waterfall |
|
||||
|
||||
> 这些页面上的类型声明及其 JSDoc 与源码等价,并由 `pnpm run verify-type-equiv` 检查漂移(见 [development.md](../development.md#documenting-types-verbatim-ts-type-equiv))。普通块保留完整声明;`public-api` 块保留去除实现体的公开 class 声明。Cordis 服务与事件使用每页生成的 **Cordis surface** 小节。
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/approval.md
|
||||
approval.md: 2045f2073b72fa265728cbf77b673053a2eaf371
|
||||
approval.zh.md: c021db14c4925acaeef5d984d9dfa88ad55bd8dd
|
||||
approval.md: 660ced6d75886bbea41985fd1f357bf92e8a7838
|
||||
approval.zh.md: 56975914098978af99580694ca19f20a02ed4022
|
||||
|
||||
@@ -38,8 +38,7 @@ type ApprovalOutcome = 'allowed-once' | 'rejected' | 'cancelled' | 'unavailable'
|
||||
* ask BEFORE any interactive answerer sees it:
|
||||
*
|
||||
* - `'ask'` (the default) — delegate to the composed answerers; with none
|
||||
* composed the chain falls through to the fail-closed `'unavailable'`
|
||||
* (exactly today's behavior).
|
||||
* composed the chain falls through to the fail-closed `'unavailable'`.
|
||||
* - `'never'` — never prompt anyone: every ask resolves `'rejected'`
|
||||
* deterministically. The strict headless stance (CI, unattended runs) and
|
||||
* the policy whose outcome is knowable without asking.
|
||||
@@ -142,7 +141,7 @@ overrideOf(session: Session): ApprovalPolicy | undefined
|
||||
|
||||
Types: [Agent](core.md) · [Session](session.md)
|
||||
|
||||
Source: [`packages/interaction/user-approval/src/index.ts:193`](../../packages/interaction/user-approval/src/index.ts)
|
||||
Source: [`packages/interaction/user-approval/src/index.ts:192`](../../packages/interaction/user-approval/src/index.ts)
|
||||
|
||||
<a id="approval-events"></a>
|
||||
|
||||
|
||||
@@ -38,8 +38,7 @@ type ApprovalOutcome = 'allowed-once' | 'rejected' | 'cancelled' | 'unavailable'
|
||||
* ask BEFORE any interactive answerer sees it:
|
||||
*
|
||||
* - `'ask'` (the default) — delegate to the composed answerers; with none
|
||||
* composed the chain falls through to the fail-closed `'unavailable'`
|
||||
* (exactly today's behavior).
|
||||
* composed the chain falls through to the fail-closed `'unavailable'`.
|
||||
* - `'never'` — never prompt anyone: every ask resolves `'rejected'`
|
||||
* deterministically. The strict headless stance (CI, unattended runs) and
|
||||
* the policy whose outcome is knowable without asking.
|
||||
@@ -142,7 +141,7 @@ overrideOf(session: Session): ApprovalPolicy | undefined
|
||||
|
||||
Types: [Agent](core.md) · [Session](session.md)
|
||||
|
||||
Source: [`packages/interaction/user-approval/src/index.ts:193`](../../packages/interaction/user-approval/src/index.ts)
|
||||
Source: [`packages/interaction/user-approval/src/index.ts:192`](../../packages/interaction/user-approval/src/index.ts)
|
||||
|
||||
<a id="approval-events"></a>
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/bash.md
|
||||
bash.md: dd7649ce46bea5642270fa553eb3d82f2dc33e9b
|
||||
bash.zh.md: e3c607cb1599da97cb69369a34135abc310387ed
|
||||
bash.md: d2797c1e3ff73fe8ecb5a053ed4a1d13b13298dd
|
||||
bash.zh.md: b38a4f332978e94d2945f5fa49b38e8d7df8c9ca
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
English | [中文](bash.zh.md)
|
||||
|
||||
The bash execution seam is split across interface ([dsh-bash](../../packages/bash/bash), `ctx.bash`), implementations ([dsh-bash-local](../../packages/bash/bash-local) and [dsh-bash-sandbox](../../packages/bash/bash-sandbox)), and consumer ([dsh-tool-bash](../../packages/bash/tool-bash), the `bash` schema). Generic background-task ids, ownership, and controls live in [tasks.md](tasks.md); this seam returns a task-free process handle. Raw process-group mechanics live behind the [subprocess seam](subprocess.md).
|
||||
The bash execution seam is split across a Service Definition ([dsh-bash](../../packages/bash/bash), `ctx.bash`), Service providers ([dsh-bash-local](../../packages/bash/bash-local) and [dsh-bash-sandbox](../../packages/bash/bash-sandbox)), and Consumer ([dsh-tool-bash](../../packages/bash/tool-bash), the `bash` schema). Generic background-task ids, ownership, and controls live in [tasks.md](tasks.md); this seam returns a task-free process handle. Raw process-group mechanics live behind the [subprocess seam](subprocess.md).
|
||||
|
||||
Source: [`packages/bash/bash/src/types.ts`](../../packages/bash/bash/src/types.ts)
|
||||
|
||||
@@ -12,7 +12,7 @@ Source: [`packages/bash/bash/src/types.ts`](../../packages/bash/bash/src/types.t
|
||||
|
||||
## Request vs. spec: the `resolve()` split
|
||||
|
||||
The seam separates the **model-/plugin-facing request** (optional `workdir`/`timeoutMs`/`stdoutMaxBytes`, filled from config or request policy) from the **fully-resolved spec** the executor acts on (those fields required). The tool layer calls `ctx.bash.resolve(request)` between them — this is the repo's "explicit > implicit at package seams" rule made concrete: the reader of a `BashExecSpec` never wonders where the working directory or output budget came from.
|
||||
The seam separates the **model-/plugin-facing request** (optional `workdir`/`timeoutMs`/`stdoutMaxBytes`, filled from config or request policy) from the **fully-resolved spec** the executor acts on (those fields required). The tool layer calls `ctx.bash.resolve(request)` between them (the repo's "explicit > implicit at package boundaries" rule); a `BashExecSpec` carries resolved values.
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
@@ -162,7 +162,7 @@ interface BashSandboxInfo {
|
||||
}
|
||||
```
|
||||
|
||||
One more piece completes the vocabulary: the `SANDBOX_UNAVAILABLE` error code (owned by the [sandbox seam](sandbox.md)) is what the `ctx.sandbox` provider throws — and the executor propagates — when a confined mode has no usable backend. A selected runner refusing its profile reaches the same fail-closed foreground error; a settled background task records `runnerFailed`. The model receives denial/runner facts in results, learns the effective mode only when a denial marker names it, and can request a one-shot strictly wider retry through `sandbox_permissions` plus `justification`; `ctx.approval` must grant that exact call before anything executes. The complete policy and switching design is the [sandbox Agent Note](../../.agents/notes/implemented/feature/2026-07-06-sandbox.md).
|
||||
The `SANDBOX_UNAVAILABLE` error code (owned by the [sandbox seam](sandbox.md)) is what the `ctx.sandbox` provider throws — and the executor propagates — when a confined mode has no usable backend. A selected runner refusing its profile reaches the same fail-closed foreground error; a settled background task records `runnerFailed`. The model receives denial/runner facts in results, learns the effective mode only when a denial marker names it, and can request a one-shot strictly wider retry through `sandbox_permissions` plus `justification`; `ctx.approval` must grant that exact call before anything executes. The complete policy and switching design is the [sandbox Agent Note](../../.agents/notes/implemented/feature/2026-07-06-sandbox.md).
|
||||
|
||||
## Background processes: `BashProcess`
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](bash.md) | 中文
|
||||
|
||||
bash 执行 seam 分为接口([dsh-bash](../../packages/bash/bash),`ctx.bash`)、实现([dsh-bash-local](../../packages/bash/bash-local) 与 [dsh-bash-sandbox](../../packages/bash/bash-sandbox))和消费方([dsh-tool-bash](../../packages/bash/tool-bash),即 `bash` schema)。通用后台任务的 task id、所有权与控制位于 [tasks.md](tasks.md);本 seam 返回一个不含任务概念的进程句柄。原始进程组机制位于[进程管理器 seam](subprocess.md)之后。
|
||||
bash 执行 seam 分为 Service Definition([dsh-bash](../../packages/bash/bash),`ctx.bash`)、Service provider([dsh-bash-local](../../packages/bash/bash-local) 与 [dsh-bash-sandbox](../../packages/bash/bash-sandbox))和 Consumer([dsh-tool-bash](../../packages/bash/tool-bash),即 `bash` schema)。通用后台任务的 task id、所有权与控制位于 [tasks.md](tasks.md);本 seam 返回一个不含任务概念的进程句柄。原始进程组机制位于[进程管理器 seam](subprocess.md)之后。
|
||||
|
||||
源码:[`packages/bash/bash/src/types.ts`](../../packages/bash/bash/src/types.ts)
|
||||
|
||||
@@ -12,7 +12,7 @@ bash 执行 seam 分为接口([dsh-bash](../../packages/bash/bash),`ctx.bash
|
||||
|
||||
## 请求与规格:`resolve()` 拆分
|
||||
|
||||
该 seam 将**面向模型/插件的请求**(`workdir`/`timeoutMs`/`stdoutMaxBytes` 可选,由配置或请求策略补全)与执行器实际使用的**完全解析后的 spec**(这些字段均为必填)分开。工具层在二者之间调用 `ctx.bash.resolve(request)`——这具体落实了仓库的「包 seam 上显式优于隐式」规则:`BashExecSpec` 的读者不必猜测工作目录或输出预算来自何处。
|
||||
该 seam 将**面向模型/插件的请求**(`workdir`/`timeoutMs`/`stdoutMaxBytes` 可选,由配置或请求策略补全)与执行器实际使用的**完全解析后的 spec**(这些字段均为必填)分开。工具层在二者之间调用 `ctx.bash.resolve(request)`(仓库的「包边界处显式优于隐式」规则);`BashExecSpec` 携带的是已解析的值。
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
@@ -162,7 +162,7 @@ interface BashSandboxInfo {
|
||||
}
|
||||
```
|
||||
|
||||
最后一项补全了这套词汇:当受限模式没有可用后端时,`ctx.sandbox` 提供方会抛出、执行器会传播由[沙箱 seam](sandbox.md)所有的 `SANDBOX_UNAVAILABLE` 错误码。选定的 runner 拒绝其 profile 时会触达同一个故障关闭的前台错误;已结束的后台任务则记录 `runnerFailed`。模型会在结果中收到拒绝/runner 事实,仅当拒绝标记指出生效模式时才得知该模式,并可通过 `sandbox_permissions` 加 `justification` 请求一次性、严格更宽松的重试;执行任何操作前,`ctx.approval` 必须批准该次确切调用。完整的策略与切换设计见[沙箱 Agent Note](../../.agents/notes/implemented/feature/2026-07-06-sandbox.md)。
|
||||
当受限模式没有可用后端时,`ctx.sandbox` 提供方会抛出、执行器会传播由[沙箱 seam](sandbox.md)所有的 `SANDBOX_UNAVAILABLE` 错误码。选定的 runner 拒绝其 profile 时会触达同一个故障关闭的前台错误;已结束的后台任务则记录 `runnerFailed`。模型会在结果中收到拒绝/runner 事实,仅当拒绝标记指出生效模式时才得知该模式,并可通过 `sandbox_permissions` 加 `justification` 请求一次性、严格更宽松的重试;执行任何操作前,`ctx.approval` 必须批准该次确切调用。完整的策略与切换设计见[沙箱 Agent Note](../../.agents/notes/implemented/feature/2026-07-06-sandbox.md)。
|
||||
|
||||
## 后台进程:`BashProcess`
|
||||
|
||||
|
||||
@@ -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: 19bcc6304e9d917c3950fd9857e7b2c2b3c16e73
|
||||
client-modules.zh.md: b0ad293cad2f67de1982ef271308b2a7f06ebaf4
|
||||
client-modules.md: 808fa62b2e5a4351b1dc98bbe4f3d2af63c9dd2b
|
||||
client-modules.zh.md: dcab60bea7c54770cc5e6032afb39d6dd189d037
|
||||
|
||||
@@ -12,7 +12,7 @@ The graph is the wire single source between the Node and browser halves: the hos
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
* One composed client entry pushed by the host (web2 §0 graph row). Wire
|
||||
* One composed client entry pushed by the host (a graph row). Wire
|
||||
* single source: the host node half (package root) produces this same shape.
|
||||
* `immediately` marks stage-one prefetch; `inject` is informational graph
|
||||
* metadata (the authoritative edges live in each package's dshClient
|
||||
|
||||
@@ -12,7 +12,7 @@ Web 插件表:[dsh-client-modules](../../packages/client/modules) 中 client
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
* One composed client entry pushed by the host (web2 §0 graph row). Wire
|
||||
* One composed client entry pushed by the host (a graph row). Wire
|
||||
* single source: the host node half (package root) produces this same shape.
|
||||
* `immediately` marks stage-one prefetch; `inject` is informational graph
|
||||
* metadata (the authoritative edges live in each package's dshClient
|
||||
|
||||
@@ -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/code-runtime.md
|
||||
code-runtime.md: 12779f1aafc8930410ae0d695e3f617caafcf607
|
||||
code-runtime.zh.md: 0bb18aaafff5a9b390685ee4c93a67f3f15502d5
|
||||
code-runtime.md: 6d3fa7fa72891897155cb9c611c7aa472629de4f
|
||||
code-runtime.zh.md: 47516c7d21c24399498a05410ab9a46b61736fb4
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
English | [中文](code-runtime.zh.md)
|
||||
|
||||
The code-execution seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md) whose interface ([dsh-code-runtime](../../packages/code-runtime/code-runtime), `ctx.codeRuntime`) runs one model-written program against host-provided async bindings and reports what it printed and returned. Code execution is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). Backends differ by execution substrate and source language, both readonly descriptors on the service; the worker-thread backend and tool-registry consumer are specified by the [Code Mode foundation](../../.agents/notes/implemented/feature/2026-06-15-code-mode.md) and [typed-return contract](../../.agents/notes/implemented/feature/2026-07-20-code-mode-typed-tool-returns.md).
|
||||
The code-execution seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md) whose Service Definition ([dsh-code-runtime](../../packages/code-runtime/code-runtime), `ctx.codeRuntime`) runs one model-written program against host-provided async bindings and reports what it printed and returned. Code execution is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). Backends differ by execution substrate and source language, both readonly descriptors on the service; the worker-thread Service provider and tool-registry Consumer are specified by the [Code Mode foundation](../../.agents/notes/implemented/feature/2026-06-15-code-mode.md) and [typed-return contract](../../.agents/notes/implemented/feature/2026-07-20-code-mode-typed-tool-returns.md).
|
||||
|
||||
Source: [`packages/code-runtime/code-runtime/src/types.ts`](../../packages/code-runtime/code-runtime/src/types.ts)
|
||||
|
||||
## The run: request in, result out
|
||||
|
||||
A `CodeRunRequest` carries **everything the runtime acts on** — per the "explicit > implicit at package seams" rule, defaulting (time budgets, output caps) is the implementation's validated config, never a hidden `??` inside `run()`:
|
||||
A `CodeRunRequest` carries **everything the runtime acts on** — per the "explicit > implicit at package boundaries" rule, defaulting (time budgets, output caps) is the implementation's validated config, never a hidden `??` inside `run()`:
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
@@ -112,7 +112,7 @@ interface CodeBindingNamespace {
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
/** A lossless JSON value transferable across the dependency-light code-runtime seam. */
|
||||
/** A lossless JSON value transferable through the dependency-light Service Definition. */
|
||||
type CodeJsonValue = null | boolean | number | string | CodeJsonValue[] | { [key: string]: CodeJsonValue }
|
||||
```
|
||||
|
||||
@@ -172,13 +172,13 @@ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnp
|
||||
|
||||
### `ctx.codeRuntime` — `CodeRuntime` (abstract seam)
|
||||
|
||||
Registers one `ctx.codeRuntime` implementation. Program, budget, abort, and substrate failures resolve in CodeRunResult; only seam misuse rejects. Implementations bridge structured-cloneable bindings, materialize each declared namespace rejection class, treat programs as hostile peers, isolate runs from one another, and terminate and await in-flight runs during disposal.
|
||||
Registers one `ctx.codeRuntime` implementation. Program, budget, abort, and substrate failures resolve in CodeRunResult; only Service Definition contract misuse rejects. Implementations bridge structured-cloneable bindings, materialize each declared namespace rejection class, treat programs as hostile peers, isolate runs from one another, and terminate and await in-flight runs during disposal.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Execute one program against the request's bindings and capture what it
|
||||
* emitted. See the class doc for the resolution contract (error is a result
|
||||
* field; rejection means seam misuse only).
|
||||
* field; rejection means Service Definition contract misuse only).
|
||||
* @param request - the program, its bindings, and the abort signal; the
|
||||
* request carries everything the runtime acts on, with no hidden defaults.
|
||||
* @returns the run's outcome: completion value (when transferable), the
|
||||
@@ -187,5 +187,5 @@ Registers one `ctx.codeRuntime` implementation. Program, budget, abort, and subs
|
||||
abstract run(request: CodeRunRequest): Promise<CodeRunResult>
|
||||
```
|
||||
|
||||
Source: [`packages/code-runtime/code-runtime/src/index.ts:104`](../../packages/code-runtime/code-runtime/src/index.ts)
|
||||
Source: [`packages/code-runtime/code-runtime/src/index.ts:102`](../../packages/code-runtime/code-runtime/src/index.ts)
|
||||
<!-- END GENERATED cordis-surface -->
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](code-runtime.md) | 中文
|
||||
|
||||
代码执行 seam 是一个[能力 seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md):其接口([dsh-code-runtime](../../packages/code-runtime/code-runtime),`ctx.codeRuntime`)使用宿主提供的异步绑定运行一段模型编写的程序,并报告其打印内容与返回值。代码执行是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇定义在此而非 [core.md](core.md) 中。各后端的执行基底与源语言不同,这两项均为服务上的只读描述符;worker-thread 后端与工具注册表消费方的约定见 [Code Mode 基础设计](../../.agents/notes/implemented/feature/2026-06-15-code-mode.md) 和[类型化返回约定](../../.agents/notes/implemented/feature/2026-07-20-code-mode-typed-tool-returns.md)。
|
||||
代码执行 seam 是一个[能力 seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md):其 Service Definition([dsh-code-runtime](../../packages/code-runtime/code-runtime),`ctx.codeRuntime`)使用宿主提供的异步绑定运行一段模型编写的程序,并报告其打印内容与返回值。代码执行是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇定义在此而非 [core.md](core.md) 中。各后端的执行基底与源语言不同,这两项均为服务上的只读描述符;worker-thread Service provider 与工具注册表 Consumer 的约定见 [Code Mode 基础设计](../../.agents/notes/implemented/feature/2026-06-15-code-mode.md) 和[类型化返回约定](../../.agents/notes/implemented/feature/2026-07-20-code-mode-typed-tool-returns.md)。
|
||||
|
||||
源码:[`packages/code-runtime/code-runtime/src/types.ts`](../../packages/code-runtime/code-runtime/src/types.ts)
|
||||
|
||||
@@ -112,7 +112,7 @@ interface CodeBindingNamespace {
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
/** A lossless JSON value transferable across the dependency-light code-runtime seam. */
|
||||
/** A lossless JSON value transferable through the dependency-light Service Definition. */
|
||||
type CodeJsonValue = null | boolean | number | string | CodeJsonValue[] | { [key: string]: CodeJsonValue }
|
||||
```
|
||||
|
||||
@@ -172,13 +172,13 @@ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnp
|
||||
|
||||
### `ctx.codeRuntime` — `CodeRuntime` (abstract seam)
|
||||
|
||||
Registers one `ctx.codeRuntime` implementation. Program, budget, abort, and substrate failures resolve in CodeRunResult; only seam misuse rejects. Implementations bridge structured-cloneable bindings, materialize each declared namespace rejection class, treat programs as hostile peers, isolate runs from one another, and terminate and await in-flight runs during disposal.
|
||||
Registers one `ctx.codeRuntime` implementation. Program, budget, abort, and substrate failures resolve in CodeRunResult; only Service Definition contract misuse rejects. Implementations bridge structured-cloneable bindings, materialize each declared namespace rejection class, treat programs as hostile peers, isolate runs from one another, and terminate and await in-flight runs during disposal.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Execute one program against the request's bindings and capture what it
|
||||
* emitted. See the class doc for the resolution contract (error is a result
|
||||
* field; rejection means seam misuse only).
|
||||
* field; rejection means Service Definition contract misuse only).
|
||||
* @param request - the program, its bindings, and the abort signal; the
|
||||
* request carries everything the runtime acts on, with no hidden defaults.
|
||||
* @returns the run's outcome: completion value (when transferable), the
|
||||
@@ -187,5 +187,5 @@ Registers one `ctx.codeRuntime` implementation. Program, budget, abort, and subs
|
||||
abstract run(request: CodeRunRequest): Promise<CodeRunResult>
|
||||
```
|
||||
|
||||
Source: [`packages/code-runtime/code-runtime/src/index.ts:104`](../../packages/code-runtime/code-runtime/src/index.ts)
|
||||
Source: [`packages/code-runtime/code-runtime/src/index.ts:102`](../../packages/code-runtime/code-runtime/src/index.ts)
|
||||
<!-- END GENERATED cordis-surface -->
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/commands.md
|
||||
commands.md: c1ab6d9782f515321104d0cf4d9e037c6a68a18d
|
||||
commands.zh.md: 3b3d8def042b107c5098e76c511424f023975e77
|
||||
commands.md: 5e280d659c2a74b3d8ba20f362922e9eb4e0b84c
|
||||
commands.zh.md: 24f099d1926f7dba45122bdc53c23a4274e3f507
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
English | [中文](commands.zh.md)
|
||||
|
||||
The human-command seam of [`dsh-commands`](../../packages/interaction/commands). Interactive adapters use it to discover and directly execute plugin-owned commands for an exact agent without creating a model message. The [command Agent Note](../../.agents/notes/implemented/feature/2026-07-19-plugin-command-registration.md) owns dispatch and lifecycle rationale; the [package README](../../packages/interaction/commands/README.md) owns composition and limitations.
|
||||
The human-command registry service from [`dsh-commands`](../../packages/interaction/commands). Interactive adapters use it to discover and directly execute plugin-owned commands for an exact agent without creating a model message. The [command Agent Note](../../.agents/notes/implemented/feature/2026-07-19-plugin-command-registration.md) owns dispatch and lifecycle rationale; the [package README](../../packages/interaction/commands/README.md) owns composition and limitations.
|
||||
|
||||
Source: [`packages/interaction/commands/src/index.ts`](../../packages/interaction/commands/src/index.ts)
|
||||
|
||||
## Input metadata
|
||||
|
||||
The seam exposes one optional unstructured-input hint. Command availability follows plugin composition: every adapter consuming the registry sees every effective definition.
|
||||
The service exposes one optional unstructured-input hint. Command availability follows plugin composition: every adapter consuming the registry sees every effective definition.
|
||||
|
||||
```ts type-equiv
|
||||
/** Immutable metadata for a command's optional unstructured input. */
|
||||
@@ -49,6 +49,8 @@ The adapter owns cancellation and passes the exact target agent. `rawInput` begi
|
||||
```ts type-equiv
|
||||
/** Invocation passed to one registered command handler. */
|
||||
interface CommandInvocation {
|
||||
/** Pairing id already written to this invocation's `command/run` event. */
|
||||
readonly commandId: CommandId
|
||||
/** Exact agent whose human-facing surface received the command. */
|
||||
readonly agent: Agent
|
||||
/** Exact text following the registered command name, including separator whitespace. */
|
||||
@@ -159,7 +161,7 @@ async execute( agent: Agent, line: string, signal: AbortSignal, ): Promise<Comma
|
||||
|
||||
Types: [Agent](core.md)
|
||||
|
||||
Source: [`packages/interaction/commands/src/index.ts:305`](../../packages/interaction/commands/src/index.ts)
|
||||
Source: [`packages/interaction/commands/src/index.ts:267`](../../packages/interaction/commands/src/index.ts)
|
||||
|
||||
<a id="commands-events"></a>
|
||||
|
||||
@@ -181,5 +183,5 @@ A command was registered or unregistered. This is an unfiltered registry notific
|
||||
'commands/change'(): void
|
||||
```
|
||||
|
||||
Source: [`packages/interaction/commands/src/index.ts:172`](../../packages/interaction/commands/src/index.ts)
|
||||
Source: [`packages/interaction/commands/src/index.ts:134`](../../packages/interaction/commands/src/index.ts)
|
||||
<!-- END GENERATED cordis-surface -->
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
[English](commands.md) | 中文
|
||||
|
||||
[`dsh-commands`](../../packages/interaction/commands) 的用户命令 seam。交互式适配器用它发现插件拥有的命令,并针对确切的 agent(智能体)直接执行这些命令,而不创建模型消息。[命令 Agent Note](../../.agents/notes/implemented/feature/2026-07-19-plugin-command-registration.md) 负责分发与生命周期的决策依据;[包 README](../../packages/interaction/commands/README.md) 负责组合方式与限制。
|
||||
[`dsh-commands`](../../packages/interaction/commands) 提供的用户命令注册表服务。交互式适配器用它发现插件拥有的命令,并针对确切的 agent(智能体)直接执行这些命令,而不创建模型消息。[命令 Agent Note](../../.agents/notes/implemented/feature/2026-07-19-plugin-command-registration.md) 负责分发与生命周期的决策依据;[包 README](../../packages/interaction/commands/README.md) 负责组合方式与限制。
|
||||
|
||||
来源:[`packages/interaction/commands/src/index.ts`](../../packages/interaction/commands/src/index.ts)
|
||||
|
||||
## 输入元数据
|
||||
|
||||
该 seam 公开一个可选的非结构化输入提示。命令的可用性由插件组合决定:每个消费注册表的适配器都会看到全部生效定义。
|
||||
该服务公开一个可选的非结构化输入提示。命令的可用性由插件组合决定:每个消费注册表的适配器都会看到全部生效定义。
|
||||
|
||||
```ts type-equiv
|
||||
/** Immutable metadata for a command's optional unstructured input. */
|
||||
@@ -49,6 +49,8 @@ interface CommandDefinition {
|
||||
```ts type-equiv
|
||||
/** Invocation passed to one registered command handler. */
|
||||
interface CommandInvocation {
|
||||
/** Pairing id already written to this invocation's `command/run` event. */
|
||||
readonly commandId: CommandId
|
||||
/** Exact agent whose human-facing surface received the command. */
|
||||
readonly agent: Agent
|
||||
/** Exact text following the registered command name, including separator whitespace. */
|
||||
@@ -159,7 +161,7 @@ async execute( agent: Agent, line: string, signal: AbortSignal, ): Promise<Comma
|
||||
|
||||
Types: [Agent](core.md)
|
||||
|
||||
Source: [`packages/interaction/commands/src/index.ts:305`](../../packages/interaction/commands/src/index.ts)
|
||||
Source: [`packages/interaction/commands/src/index.ts:267`](../../packages/interaction/commands/src/index.ts)
|
||||
|
||||
<a id="commands-events"></a>
|
||||
|
||||
@@ -181,5 +183,5 @@ A command was registered or unregistered. This is an unfiltered registry notific
|
||||
'commands/change'(): void
|
||||
```
|
||||
|
||||
Source: [`packages/interaction/commands/src/index.ts:172`](../../packages/interaction/commands/src/index.ts)
|
||||
Source: [`packages/interaction/commands/src/index.ts:134`](../../packages/interaction/commands/src/index.ts)
|
||||
<!-- END GENERATED cordis-surface -->
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/compaction.md
|
||||
compaction.md: 5aef839192ea6f67bb409622187fe65fed795e73
|
||||
compaction.zh.md: 20b4b2381f6e638e1d1b4db13ba98d53379b38db
|
||||
compaction.md: fdff28ac2ec83966a03050ba8d54fe0ee26c4fc6
|
||||
compaction.zh.md: e4227320d9829cac695dc4ba0c5779086f77194b
|
||||
|
||||
@@ -2,25 +2,25 @@
|
||||
|
||||
English | [中文](compaction.zh.md)
|
||||
|
||||
The compaction seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md) split like bash: interface ([dsh-compact](../../packages/compact/compact), `ctx.compact`), implementation (a backend such as [dsh-compact-basic](../../packages/compact/compact-basic)), and human consumer ([dsh-command-compact](../../packages/compact/command-compact)). Compaction is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). A tokenizer- or template-based backend is a sibling package implementing the same interface. Unlike bash, the interface necessarily depends on `dsh-session` and `dsh-llm`: its verbs act on an agent-owned `Session`, and its durable summary event uses the `ContentBlock` vocabulary (see the [compaction capability-seam Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md)).
|
||||
The compaction seam — a [capability seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md) split like bash: Service Definition ([dsh-compact](../../packages/compact/compact), `ctx.compact`), Service provider (a backend such as [dsh-compact-basic](../../packages/compact/compact-basic)), and human Consumer ([dsh-command-compact](../../packages/compact/command-compact)). Compaction is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](core.md). A tokenizer- or template-based backend is a sibling package implementing the same interface. Unlike bash, the interface necessarily depends on `dsh-session` and `dsh-llm`: its verbs act on an agent-owned `Session`, and its durable summary event uses the `ContentBlock` vocabulary (see the [compaction capability-seam Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md)).
|
||||
|
||||
Source: [`packages/compact/compact/src/types.ts`](../../packages/compact/compact/src/types.ts)
|
||||
|
||||
## The `compact/*` session events
|
||||
|
||||
Compaction extends [`SessionEventMap`](session.md) with three event types via declaration merging. All three are **log-only** — they record the compaction lock and its provenance, and never join the surface. `SurfaceEventType` is deliberately NOT extended (only message-producing events reach the model), so the summary itself rides on a separate `user/message` with `surfaceOp: { op: 'replace', start, end }` — the only surface mutation performed by summary compaction. See the Agent Note for why reusing `user/message` is honest rather than a workaround.
|
||||
Compaction extends [`SessionEventMap`](session.md) with three event types via declaration merging. All three are **log-only** — they record the lock, summary, selected range, shadowed event seqs, token count, and model call without joining the surface. `SurfaceEventType` is deliberately NOT extended (only message-producing events reach the model), so the summary itself rides on a separate `user/message` with `surfaceOp: { op: 'replace', start, end }` — the only surface mutation performed by summary compaction. The [Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md) owns the rationale for reusing `user/message`.
|
||||
|
||||
| Event | Payload | Role |
|
||||
|---|---|---|
|
||||
| `compact/start` | `{ turn }` | acquires the log-recorded lock; a number identifies the open automatic turn, while `null` identifies a standalone manual attempt |
|
||||
| `compact/summary` | `{ summary, rawOutput?, llmStreamCall?, shadowedRange, shadowedSeqs, shadowedTokenCount, provider, model, maxTokens?, usage? }` | provenance: the safe summary projection, optional complete provider output and usage, an `llmStreamCall: true` marker when producing the result consumed exactly one call through this context's `ctx.llm.stream()` (which requires complete `rawOutput`), the shadowed surface-boundary pair (`start`/`end` seqs — a position span, not a numeric interval), the shadowed seqs in surface order, the estimated token count, and the summarize call's envelope (`provider`, `model`, plus its generation cap when one applied) — logged so the one-shot request is reconstructable from log + code (the reconstructability Agent Note); unmarked `rawOutput` does not identify the call path |
|
||||
| `compact/summary` | `{ summary, rawOutput?, llmStreamCall?, shadowedRange, shadowedSeqs, shadowedTokenCount, provider, model, maxTokens?, usage? }` | the safe summary projection, optional complete provider output and usage, an `llmStreamCall: true` marker when producing the result consumed exactly one call through this context's `ctx.llm.stream()` (which requires complete `rawOutput`), the shadowed surface-boundary pair (`start`/`end` seqs — a position span, not a numeric interval), the shadowed seqs in surface order, the estimated token count, and the summarize call's envelope (`provider`, `model`, plus its generation cap when one applied) — logged so the one-shot request is reconstructable from log + code (the reconstructability Agent Note); unmarked `rawOutput` does not identify the call path |
|
||||
| `compact/end` | `{ turn, error? }` | releases the lock with the same numeric-or-null owner (`error` records an unsuccessful attempt) |
|
||||
|
||||
The lock brackets the **whole** operation: `compact/start` is appended first, then summarization, the `compact/summary` provenance record, and the `user/message` replacement all land, and only then `compact/end`. Releasing the lock last turns a crash mid-operation into a detectable orphaned lock (a `compact/start` with no matching `compact/end`) rather than a `compact/end` that falsely claims compaction finished.
|
||||
The lock brackets the **whole** operation: `compact/start` is appended first, then summarization, the `compact/summary` record, and the `user/message` replacement all land, and only then `compact/end`. Releasing the lock last turns a crash mid-operation into a detectable orphaned lock (a `compact/start` with no matching `compact/end`) rather than a `compact/end` that falsely claims compaction finished.
|
||||
|
||||
The markers are lock time points, not an exclusive container. An unrelated idle injection can appear between a standalone manual start and end while summarization is pending. The manual path revalidates only its selected positional span, so that injected context survives after the replacement checkpoint. A live unmatched start blocks every entry point; an unmatched start before a newer `session/end-seed` is stale evidence from a prior lifecycle and is ignored.
|
||||
|
||||
These variants are merged inside a `declare module '@deepseek-ai/dsh-session'` block, so — unlike the top-level types on the other subsystem pages — they are not pasted as a drift-checked ` ```ts type-equiv ` block (the `verify-type-equiv` extractor matches only top-level declarations by name). The payload table above is the catalog entry; follow the source link for the authoritative shapes.
|
||||
These variants are merged inside a `declare module '@deepseek-ai/dsh-session/types'` block, so — unlike the top-level types on the other subsystem pages — they are not pasted as a drift-checked ` ```ts type-equiv ` block (the `verify-type-equiv` extractor matches only top-level declarations by name). The payload table above is the catalog entry; follow the source link for the authoritative shapes.
|
||||
|
||||
## `CompactionResult`
|
||||
|
||||
@@ -29,6 +29,10 @@ What a successful compaction returns to its caller: the bookkeeping-event seqs,
|
||||
```ts type-equiv
|
||||
/** Result of a successful compaction operation. */
|
||||
interface CompactionResult {
|
||||
/** Stable identity shared by this compaction's complete durable lifecycle. */
|
||||
compactionId: CompactionId
|
||||
/** Human command that initiated this compaction, when it was manual. */
|
||||
sourceCommandId?: CommandId
|
||||
/** The seq of the appended `compact/start` event. */
|
||||
startSeq: number
|
||||
/** The seq of the appended `compact/summary` event. */
|
||||
@@ -62,7 +66,7 @@ Automatic callers state why policy is running; implementations may treat confirm
|
||||
type CompactionTrigger = 'pressure' | 'context-overflow'
|
||||
```
|
||||
|
||||
`CompactService` exposes `compactIfNeeded(agent, trigger, signal)` for automatic `pressure` or `context-overflow` policy, `compactNow(agent, signal)` for one useful idle-session reduction even below pressure, and `compactRegion(...)` for an explicit inclusive surface range. `compactNow()` runs as agent maintenance between turns, returns `null` without writing when no useful range exists, records a standalone `turn: null` bracket before summarization, and flushes a closed attempt before later queued prompts may derive from the new surface. Every backend marks its replacement `user/message` with `COMPACT_CHECKPOINT_SOURCE`; client and wire consumers import that value and `isCompactCheckpointSource()` from the cordis-free `@deepseek-ai/dsh-compact/checkpoint` subpath, while the package root re-exports both for host consumers. The predicate keeps checkpoint recognition independent of any one backend. Implementations must forward the supplied signal to summarization. The seam owns no pricing API: the singleton [`ctx.tokenMeter`](token-meter.md) directly owns estimation and replay, while `dsh-compact-basic` owns retention, event sequencing, routed summarization calls, and their configuration.
|
||||
`CompactService` exposes `compactIfNeeded(agent, trigger, signal)` for automatic `pressure` or `context-overflow` policy, `compactNow(agent, signal)` for one useful idle-session reduction even below pressure, and `compactRegion(...)` for an explicit inclusive surface range. `compactNow()` runs as agent maintenance between turns, returns `null` without writing when no useful range exists, records a standalone `turn: null` bracket before summarization, and flushes a closed attempt before later queued prompts may derive from the new surface. Every backend creates its replacement `user/message` source with `compactCheckpointSource(compactionId, sourceCommandId?)`; client and wire consumers import that constructor, `CompactCheckpointSource`, and `isCompactCheckpointSource()` from the cordis-free `@deepseek-ai/dsh-compact/checkpoint` subpath, while the package root re-exports them for host consumers. The required transaction identity correlates the replacement checkpoint, while the predicate keeps recognition independent of any one backend. Implementations must forward the supplied signal to summarization. The seam owns no pricing API: the singleton [`ctx.tokenMeter`](token-meter.md) directly owns estimation and replay, while `dsh-compact-basic` owns retention, event sequencing, routed summarization calls, and their configuration.
|
||||
|
||||
Expected manual failures use `ManualCompactionErrorCode`:
|
||||
|
||||
@@ -81,14 +85,14 @@ type ManualCompactionErrorCode =
|
||||
|
||||
Pressure compaction runs at serial `agent/pre-step` before request derivation. Once pressure or canonical overflow qualifies, compact-basic invokes optional [`ctx.toolResultPrune`](../../packages/compact/compact-tool-result-prune/README.md) before range selection, remeasures through `ctx.tokenMeter`, and can advance the surface without a summary. Failed-request recovery runs through `agent/request-error` after the failed step closes and returns a retry action only when the surface replacement generation advances, even if later summary work throws after pruning; cancellation still wins. Region boundaries preserve tool-call/result pairing but not whole turns, allowing early closed steps of one oversized turn to compact. `dsh-compact-basic` owns thresholds, retained-tail policy, overflow caps, and failure handling.
|
||||
|
||||
The seam exports `toolPairingBalancedBefore(session, seq)` and `toolPairingBalancedAfter(session, seq)` for those edge checks. Both validate current surface membership and reject missing seqs and orphan results; the [package contract](../../packages/compact/compact/README.md#tool-pairing-boundaries) owns their cache semantics.
|
||||
The Service Definition exports `toolPairingBalancedBefore(session, seq)` and `toolPairingBalancedAfter(session, seq)` for those edge checks. Both validate current surface membership and reject missing seqs and orphan results; the [package contract](../../packages/compact/compact/README.md#tool-pairing-boundaries) owns their cache semantics.
|
||||
|
||||
## Tool-result pruning outcomes
|
||||
|
||||
The optional tool-result pruning service reports each durable content replacement and the aggregate Unicode-code-point reduction. Its public result types live in [`compact-tool-result-prune/src/types.ts`](../../packages/compact/compact-tool-result-prune/src/types.ts).
|
||||
|
||||
```ts type-equiv
|
||||
/** Provenance and size accounting for one landed surface replacement. */
|
||||
/** Cited source event and size accounting for one landed surface replacement. */
|
||||
interface PrunedEntry {
|
||||
/** Full-fidelity tool-result event shadowed by the replacement. */
|
||||
readonly originalSeq: number
|
||||
@@ -125,7 +129,7 @@ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnp
|
||||
|
||||
### `ctx.compact` — `CompactService` (abstract seam)
|
||||
|
||||
Abstract compaction service. Implementations own trigger policy, retention, and summarization, and may consume a separate measurement service. A successful run replaces the selected surface span with one summary node and prevents concurrent compaction of the same session. The replacement user message uses COMPACT_CHECKPOINT_SOURCE so consumers recognize it independently of the backend. Load one implementation per context as `ctx.compact`.
|
||||
Abstract compaction service. Implementations own trigger policy, retention, and summarization, and may consume a separate measurement service. A successful run replaces the selected surface span with one summary node and prevents concurrent compaction of the same session. The replacement user message uses compactCheckpointSource with the transaction identity so consumers recognize and correlate it independently of the backend. Load one implementation per context as `ctx.compact`.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
@@ -155,13 +159,14 @@ abstract compactIfNeeded( agent: CompactAgentContext, trigger: CompactionTrigger
|
||||
*
|
||||
* @param agent - idle agent whose durable history should be compacted.
|
||||
* @param signal - cancellation scoped to this compaction request.
|
||||
* @param sourceCommandId - initiating command identity for a manual compaction.
|
||||
* @returns the compaction result, or `null` when no safe useful range exists.
|
||||
* @throws {@link ManualCompactionError} for expected busy, agent-cancellation,
|
||||
* changed-span, summarization/shrink, commit-stage, or persistence failures;
|
||||
* an aborted request preserves its exact abort reason. Failed attempts remain
|
||||
* visible in the log.
|
||||
*/
|
||||
abstract compactNow( agent: ManualCompactAgentContext, signal: AbortSignal, ): Promise<CompactionResult | null>
|
||||
abstract compactNow( agent: ManualCompactAgentContext, signal: AbortSignal, sourceCommandId?: CommandId, ): Promise<CompactionResult | null>
|
||||
|
||||
/**
|
||||
* Forcibly compact a range of surface nodes into a single summary node.
|
||||
@@ -170,7 +175,8 @@ abstract compactNow( agent: ManualCompactAgentContext, signal: AbortSignal, ): P
|
||||
* balanced so assistant tool calls remain paired with their results. A model-
|
||||
* backed implementation forwards cancellation and rejects active, missing,
|
||||
* reversed, or unbalanced ranges. The target session is `agent.session`.
|
||||
* Its replacement user message must use {@link COMPACT_CHECKPOINT_SOURCE}.
|
||||
* Its replacement user message must use {@link compactCheckpointSource} with
|
||||
* the transaction's `CompactionId`.
|
||||
* Use {@link toolPairingBalancedBefore} and {@link toolPairingBalancedAfter}
|
||||
* for the edge checks.
|
||||
*
|
||||
@@ -184,7 +190,9 @@ abstract compactNow( agent: ManualCompactAgentContext, signal: AbortSignal, ): P
|
||||
abstract compactRegion( start: number, end: number, agent: CompactAgentContext, signal?: AbortSignal, ): Promise<CompactionResult>
|
||||
```
|
||||
|
||||
Source: [`packages/compact/compact/src/index.ts:93`](../../packages/compact/compact/src/index.ts)
|
||||
Types: [CommandId](commands.md)
|
||||
|
||||
Source: [`packages/compact/compact/src/index.ts:96`](../../packages/compact/compact/src/index.ts)
|
||||
|
||||
<a id="ctxtoolresultprune--toolresultpruneservice"></a>
|
||||
|
||||
@@ -212,7 +220,7 @@ pruneContent(blocks: readonly ContentBlock[]): ContentBlock[] | null
|
||||
/**
|
||||
* Prune every over-budget tool result from one stable current-surface snapshot.
|
||||
* Each replacement preserves the complete event data except for `content`,
|
||||
* points at the shadowed node for durable provenance and replay, and is
|
||||
* cites the shadowed node so replay can recover the replacement input, and is
|
||||
* immediately preceded by a `compact/prune` shadow-price event pricing the
|
||||
* shadowed node through the injected token meter, so pure consumers can
|
||||
* subtract it without per-node state.
|
||||
|
||||
@@ -2,25 +2,25 @@
|
||||
|
||||
[English](compaction.md) | 中文
|
||||
|
||||
压缩 seam 是一个[能力 seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md),与 bash 一样分为接口([dsh-compact](../../packages/compact/compact),`ctx.compact`)、实现(例如 [dsh-compact-basic](../../packages/compact/compact-basic) 后端)和面向用户的消费方([dsh-command-compact](../../packages/compact/command-compact))。压缩是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇定义在此而非 [core.md](core.md) 中。基于 tokenizer 或模板的后端是实现同一接口的兄弟包。与 bash 不同,该接口必然依赖 `dsh-session` 和 `dsh-llm`:其动词作用于 agent 所有的 `Session`,而其持久摘要事件使用 `ContentBlock` 词汇(见[压缩能力 seam Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md))。
|
||||
压缩 seam 是一个[能力 seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md),与 bash 一样分为 Service Definition([dsh-compact](../../packages/compact/compact),`ctx.compact`)、Service provider(例如 [dsh-compact-basic](../../packages/compact/compact-basic) 后端)和面向用户的 Consumer([dsh-command-compact](../../packages/compact/command-compact))。压缩是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇定义在此而非 [core.md](core.md) 中。基于 tokenizer 或模板的后端是实现同一接口的兄弟包。与 bash 不同,该接口必然依赖 `dsh-session` 和 `dsh-llm`:其动词作用于 agent 所有的 `Session`,而其持久摘要事件使用 `ContentBlock` 词汇(见[压缩能力 seam Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md))。
|
||||
|
||||
源码:[`packages/compact/compact/src/types.ts`](../../packages/compact/compact/src/types.ts)
|
||||
|
||||
## `compact/*` 会话事件
|
||||
|
||||
压缩通过声明合并为 [`SessionEventMap`](session.md) 扩展三种事件类型。三者都**仅写入日志**——记录压缩锁及其 provenance,绝不进入 surface。这里有意不扩展 `SurfaceEventType`(只有产生消息的事件才到达模型),因此摘要本身承载在另一条带有 `surfaceOp: { op: 'replace', start, end }` 的 `user/message` 上——这是摘要压缩执行的唯一 surface 变更。关于复用 `user/message` 为何是如实建模而非权宜之计,见对应 Agent Note。
|
||||
压缩通过声明合并为 [`SessionEventMap`](session.md) 扩展三种事件类型。三者都**仅写入日志**——它们记录锁、摘要、选中范围、被遮蔽事件 seq、token 数以及模型调用,绝不进入 surface。这里有意不扩展 `SurfaceEventType`(只有产生消息的事件才到达模型),因此摘要本身承载在另一条带有 `surfaceOp: { op: 'replace', start, end }` 的 `user/message` 上——这是摘要压缩执行的唯一 surface 变更。[Agent Note](../../.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md) 负责复用 `user/message` 的决策依据。
|
||||
|
||||
| 事件 | 载荷 | 作用 |
|
||||
|---|---|---|
|
||||
| `compact/start` | `{ turn }` | 获取日志记录的锁;数字标识打开的自动轮次,`null` 标识独立手动尝试 |
|
||||
| `compact/summary` | `{ summary, rawOutput?, llmStreamCall?, shadowedRange, shadowedSeqs, shadowedTokenCount, provider, model, maxTokens?, usage? }` | provenance:安全摘要投影、可选的完整 provider 输出与 usage、生成结果时恰好通过此上下文的 `ctx.llm.stream()` 发起一次调用所带的 `llmStreamCall: true` 标记(此时必须提供完整的 `rawOutput`)、被遮蔽的 surface 边界对(`start`/`end` seq——位置跨度,而非数值区间)、按 surface 顺序排列的被遮蔽 seq、估算 token 数,以及摘要调用的 envelope(`provider`、`model`,若有生成上限则还包括该上限)——写入日志后,该一次性请求可由日志 + 代码重建(见可重建性 Agent Note);未带标记的 `rawOutput` 并不能判定调用路径 |
|
||||
| `compact/summary` | `{ summary, rawOutput?, llmStreamCall?, shadowedRange, shadowedSeqs, shadowedTokenCount, provider, model, maxTokens?, usage? }` | 安全摘要投影、可选的完整 provider 输出与 usage、生成结果时恰好通过此上下文的 `ctx.llm.stream()` 发起一次调用所带的 `llmStreamCall: true` 标记(此时必须提供完整的 `rawOutput`)、被遮蔽的 surface 边界对(`start`/`end` seq——位置跨度,而非数值区间)、按 surface 顺序排列的被遮蔽 seq、估算 token 数,以及摘要调用的 envelope(`provider`、`model`,若有生成上限则还包括该上限)——写入日志后,该一次性请求可由日志 + 代码重建(见可重建性 Agent Note);未带标记的 `rawOutput` 并不能判定调用路径 |
|
||||
| `compact/end` | `{ turn, error? }` | 使用相同的数字或 `null` 归属值释放锁(`error` 记录失败尝试) |
|
||||
|
||||
锁括住**整个**操作:先追加 `compact/start`,然后执行摘要生成、写入 `compact/summary` 来源记录与 `user/message` 替换,最后才追加 `compact/end`。最后释放锁意味着操作中途崩溃会表现为可检测的遗留锁(有 `compact/start` 而无匹配的 `compact/end`),而非一个虚假声称压缩已完成的 `compact/end`。
|
||||
锁括住**整个**操作:先追加 `compact/start`,然后执行摘要生成、写入 `compact/summary` 记录与 `user/message` 替换,最后才追加 `compact/end`。最后释放锁意味着操作中途崩溃会表现为可检测的遗留锁(有 `compact/start` 而无匹配的 `compact/end`),而非一个虚假声称压缩已完成的 `compact/end`。
|
||||
|
||||
这些标记表示锁的时间点,而不是排他的容器。摘要等待期间,不相关的空闲注入可以出现在独立的手动 start 与 end 之间。手动路径只重新验证所选位置 span,因此替换检查点之后仍保留该注入上下文。活动的未匹配 start 会阻塞所有入口点;较新 `session/end-seed` 之前的未匹配 start 是先前生命周期留下的陈旧证据,会被忽略。
|
||||
|
||||
这些变体在 `declare module '@deepseek-ai/dsh-session'` 块内合并,因此——与其他子系统页面上的顶层类型不同——它们不以漂移检查的 ` ```ts type-equiv ` 块粘贴(`verify-type-equiv` 提取器只按名称匹配顶层声明)。上方的载荷表即为目录条目;权威形状请循源码链接查看。
|
||||
这些变体在 `declare module '@deepseek-ai/dsh-session/types'` 块内合并,因此——与其他子系统页面上的顶层类型不同——它们不以漂移检查的 ` ```ts type-equiv ` 块粘贴(`verify-type-equiv` 提取器只按名称匹配顶层声明)。上方的载荷表即为目录条目;权威形状请循源码链接查看。
|
||||
|
||||
## `CompactionResult`
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
```ts type-equiv
|
||||
/** Result of a successful compaction operation. */
|
||||
interface CompactionResult {
|
||||
/** Stable identity shared by this compaction's complete durable lifecycle. */
|
||||
compactionId: CompactionId
|
||||
/** Human command that initiated this compaction, when it was manual. */
|
||||
sourceCommandId?: CommandId
|
||||
/** The seq of the appended `compact/start` event. */
|
||||
startSeq: number
|
||||
/** The seq of the appended `compact/summary` event. */
|
||||
@@ -62,7 +66,7 @@ interface CompactionResult {
|
||||
type CompactionTrigger = 'pressure' | 'context-overflow'
|
||||
```
|
||||
|
||||
`CompactService` 暴露 `compactIfNeeded(agent, trigger, signal)` 以执行自动 `pressure` 或 `context-overflow` 策略,暴露 `compactNow(agent, signal)` 以便即使未达到压力也对空闲会话进行一次有效缩减,还针对显式、两端均包含的 surface 范围暴露 `compactRegion(...)`。`compactNow()` 作为轮次之间的 agent maintenance 运行;没有有效范围时返回 `null` 且不写入;在摘要前记录独立的 `turn: null` 标记对,并在后续排队提示词能够从新表层派生前 flush 已闭合尝试。每个后端都使用 `COMPACT_CHECKPOINT_SOURCE` 标记其替换用的 `user/message`;client 与 wire 消费方从无 cordis 的 `@deepseek-ai/dsh-compact/checkpoint` 子路径导入该值和 `isCompactCheckpointSource()`,包根则为 host 消费方重新导出两者。该判定函数使检查点识别不依赖任一特定后端。实现必须把传入的 signal 转发给摘要流程。该 seam 不拥有计价 API:单例 [`ctx.tokenMeter`](token-meter.md) 直接拥有估算与回放,而 `dsh-compact-basic` 拥有保留策略、事件排序、按路由执行的摘要调用及其配置。
|
||||
`CompactService` 暴露 `compactIfNeeded(agent, trigger, signal)` 以执行自动 `pressure` 或 `context-overflow` 策略,暴露 `compactNow(agent, signal)` 以便即使未达到压力也对空闲会话进行一次有效缩减,还针对显式、两端均包含的 surface 范围暴露 `compactRegion(...)`。`compactNow()` 作为轮次之间的 agent maintenance 运行;没有有效范围时返回 `null` 且不写入;在摘要前记录独立的 `turn: null` 标记对,并在后续排队提示词能够从新表层派生前 flush 已闭合尝试。每个后端都使用 `compactCheckpointSource(compactionId, sourceCommandId?)` 创建替换用 `user/message` 的源;client 与 wire 消费方从无 cordis 的 `@deepseek-ai/dsh-compact/checkpoint` 子路径导入该构造函数、`CompactCheckpointSource` 和 `isCompactCheckpointSource()`,包根则为 host 消费方重新导出它们。必填的事务身份会关联替换检查点,而该判定函数使检查点识别不依赖任一特定后端。实现必须把传入的 signal 转发给摘要流程。该 seam 不拥有计价 API:单例 [`ctx.tokenMeter`](token-meter.md) 直接拥有估算与回放,而 `dsh-compact-basic` 拥有保留策略、事件排序、按路由执行的摘要调用及其配置。
|
||||
|
||||
预期的手动失败使用 `ManualCompactionErrorCode`:
|
||||
|
||||
@@ -81,14 +85,14 @@ type ManualCompactionErrorCode =
|
||||
|
||||
压力压缩在串行 `agent/pre-step` 中运行,先于请求推导。一旦压力或规范化溢出满足条件,compact-basic 会在选择范围前调用可选的 [`ctx.toolResultPrune`](../../packages/compact/compact-tool-result-prune/README.md),再通过 `ctx.tokenMeter` 重新测量,并且可以在不生成摘要的情况下推进 surface。失败请求的恢复在失败的步骤关闭后通过 `agent/request-error` 运行;仅当 surface replacement generation 前进时才返回重试动作,即便后续摘要工作在剪枝后抛异常亦如此;取消仍然优先。区域边界保持工具调用/结果配对,但不保持整个轮次,因此一个过大轮次中较早关闭的步骤可以被压缩。`dsh-compact-basic` 拥有阈值、保留尾部策略、溢出上限与失败处理。
|
||||
|
||||
该 seam 导出 `toolPairingBalancedBefore(session, seq)` 与 `toolPairingBalancedAfter(session, seq)`,用于这些边缘检查。两者都会验证当前 surface 成员关系,并拒绝缺失的 seq 与遗留结果;其缓存语义由[包约定](../../packages/compact/compact/README.md#tool-pairing-boundaries)规定。
|
||||
该 Service Definition 导出 `toolPairingBalancedBefore(session, seq)` 与 `toolPairingBalancedAfter(session, seq)`,用于这些边缘检查。两者都会验证当前 surface 成员关系,并拒绝缺失的 seq 与遗留结果;其缓存语义由[包约定](../../packages/compact/compact/README.md#tool-pairing-boundaries)规定。
|
||||
|
||||
## 工具结果剪枝产出
|
||||
|
||||
可选的工具结果剪枝服务会报告每次持久内容替换以及 Unicode code point 的总减少量。其公开结果类型位于 [`compact-tool-result-prune/src/types.ts`](../../packages/compact/compact-tool-result-prune/src/types.ts)。
|
||||
|
||||
```ts type-equiv
|
||||
/** Provenance and size accounting for one landed surface replacement. */
|
||||
/** Cited source event and size accounting for one landed surface replacement. */
|
||||
interface PrunedEntry {
|
||||
/** Full-fidelity tool-result event shadowed by the replacement. */
|
||||
readonly originalSeq: number
|
||||
@@ -125,7 +129,7 @@ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnp
|
||||
|
||||
### `ctx.compact` — `CompactService` (abstract seam)
|
||||
|
||||
Abstract compaction service. Implementations own trigger policy, retention, and summarization, and may consume a separate measurement service. A successful run replaces the selected surface span with one summary node and prevents concurrent compaction of the same session. The replacement user message uses COMPACT_CHECKPOINT_SOURCE so consumers recognize it independently of the backend. Load one implementation per context as `ctx.compact`.
|
||||
Abstract compaction service. Implementations own trigger policy, retention, and summarization, and may consume a separate measurement service. A successful run replaces the selected surface span with one summary node and prevents concurrent compaction of the same session. The replacement user message uses compactCheckpointSource with the transaction identity so consumers recognize and correlate it independently of the backend. Load one implementation per context as `ctx.compact`.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
@@ -155,13 +159,14 @@ abstract compactIfNeeded( agent: CompactAgentContext, trigger: CompactionTrigger
|
||||
*
|
||||
* @param agent - idle agent whose durable history should be compacted.
|
||||
* @param signal - cancellation scoped to this compaction request.
|
||||
* @param sourceCommandId - initiating command identity for a manual compaction.
|
||||
* @returns the compaction result, or `null` when no safe useful range exists.
|
||||
* @throws {@link ManualCompactionError} for expected busy, agent-cancellation,
|
||||
* changed-span, summarization/shrink, commit-stage, or persistence failures;
|
||||
* an aborted request preserves its exact abort reason. Failed attempts remain
|
||||
* visible in the log.
|
||||
*/
|
||||
abstract compactNow( agent: ManualCompactAgentContext, signal: AbortSignal, ): Promise<CompactionResult | null>
|
||||
abstract compactNow( agent: ManualCompactAgentContext, signal: AbortSignal, sourceCommandId?: CommandId, ): Promise<CompactionResult | null>
|
||||
|
||||
/**
|
||||
* Forcibly compact a range of surface nodes into a single summary node.
|
||||
@@ -170,7 +175,8 @@ abstract compactNow( agent: ManualCompactAgentContext, signal: AbortSignal, ): P
|
||||
* balanced so assistant tool calls remain paired with their results. A model-
|
||||
* backed implementation forwards cancellation and rejects active, missing,
|
||||
* reversed, or unbalanced ranges. The target session is `agent.session`.
|
||||
* Its replacement user message must use {@link COMPACT_CHECKPOINT_SOURCE}.
|
||||
* Its replacement user message must use {@link compactCheckpointSource} with
|
||||
* the transaction's `CompactionId`.
|
||||
* Use {@link toolPairingBalancedBefore} and {@link toolPairingBalancedAfter}
|
||||
* for the edge checks.
|
||||
*
|
||||
@@ -184,7 +190,9 @@ abstract compactNow( agent: ManualCompactAgentContext, signal: AbortSignal, ): P
|
||||
abstract compactRegion( start: number, end: number, agent: CompactAgentContext, signal?: AbortSignal, ): Promise<CompactionResult>
|
||||
```
|
||||
|
||||
Source: [`packages/compact/compact/src/index.ts:93`](../../packages/compact/compact/src/index.ts)
|
||||
Types: [CommandId](commands.md)
|
||||
|
||||
Source: [`packages/compact/compact/src/index.ts:96`](../../packages/compact/compact/src/index.ts)
|
||||
|
||||
<a id="ctxtoolresultprune--toolresultpruneservice"></a>
|
||||
|
||||
@@ -212,7 +220,7 @@ pruneContent(blocks: readonly ContentBlock[]): ContentBlock[] | null
|
||||
/**
|
||||
* Prune every over-budget tool result from one stable current-surface snapshot.
|
||||
* Each replacement preserves the complete event data except for `content`,
|
||||
* points at the shadowed node for durable provenance and replay, and is
|
||||
* cites the shadowed node so replay can recover the replacement input, and is
|
||||
* immediately preceded by a `compact/prune` shadow-price event pricing the
|
||||
* shadowed node through the injected token meter, so pure consumers can
|
||||
* subtract it without per-node state.
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/core.md
|
||||
core.md: cc9cc30677b0b657492d8a5118489e8b801f3fd3
|
||||
core.zh.md: 96854801d684509d4d77b6408a4bb45b93438cdb
|
||||
core.md: 9a1fa827a7e0168e662bc4595a3c0fc486be8d49
|
||||
core.zh.md: e51f8b61fb6ed0c7a6e2de377f8f93877f972831
|
||||
|
||||
@@ -17,7 +17,7 @@ A turn flows through the six packages in one loop: the driver in [`agent-loop`](
|
||||
| `agent-loop/` | The concrete driver implementing the public `Agent` contract (`ctx.agentLoop`) | this page |
|
||||
| `scope/` | The scoped-registration primitive the registries and loop build per-agent scoping on | [scope.md](scope.md) |
|
||||
|
||||
`scope/` is the one non-service package: a dependency-free library (`createScope`/`scopeOf`/`scopeTarget`) that sits below `session/` and `system-prompt/` in the module graph precisely so they can consume it without a cycle. `agent-loop` is the one concrete implementation of the `agent` seam and lives here because it is the harness's default product loop; it runs each driver inside `ctx.agents.withInitiator()`. Extension plugins depend on `agent` — including when they need the initiating Agent — and never on `agent-loop` directly, so the loop stays swappable. The default composition that wires this spine into a runnable agent is [`examples/agent-spine-demo`](../../packages/examples/agent-spine-demo/README.md).
|
||||
`scope/` is the one non-service package: a dependency-free library (`createScope`/`scopeOf`/`scopeTarget`) that sits below `session/` and `system-prompt/` in the module graph precisely so they can consume it without a cycle. `agent-loop` is the one concrete implementation of the public `Agent` contract and lives here because it is the harness's default product loop; it runs each driver inside `ctx.agents.withInitiator()`. Extension plugins depend on `agent` — including when they need the initiating Agent — and never on `agent-loop` directly, so the loop stays swappable. The default composition that wires this spine into a runnable agent is [`examples/agent-spine-demo`](../../packages/examples/agent-spine-demo/README.md).
|
||||
|
||||
## Creation and ownership
|
||||
|
||||
@@ -48,7 +48,7 @@ interface AgentHandle {
|
||||
|
||||
`CreateAgentOptions` carries the shared identity and everything a fresh agent needs before publication: session metadata (`meta` — validated `cwd`, fork lineage, seed boundary, origin classification, delegation depth), an optional `seed` replay prefix for forks, per-agent `AgentOptions`, a creation-only cancellation `signal`, and `setup`. `ResumeAgentOptions` is the persisted-identity counterpart: `resumeSessionId`, `agentOptions`, `signal`, and `setup`. The `setup` callback (`AgentSetup`) composes the agent's scoped world while both ids are still unpublished — everything registered through `agentCtx` exists before `agent/created` and the first prompt assembly — and may return a synchronous commit invoked immediately before publication; a setup rejection, commit throw, or owner disposal rolls the transaction back without publishing either id.
|
||||
|
||||
`AgentFactory` is the creation seam behind the registry: the loop registers its factory via `ctx.agents.setFactory()`, so consumers program against `ctx.agents` without depending on the concrete loop package. The exact `create`/`resume` signatures and their rollback contracts are in the [generated section](#ctxagents--agentregistry) below.
|
||||
`AgentFactory` is the creation contract behind the registry: the loop registers its factory via `ctx.agents.setFactory()`, so consumers program against `ctx.agents` without depending on the concrete loop package. The exact `create`/`resume` signatures and their rollback contracts are in the [generated section](#ctxagents--agentregistry) below.
|
||||
|
||||
## The agent handle
|
||||
|
||||
@@ -107,7 +107,7 @@ interface Agent {
|
||||
* cancel leaves it parked. A wake submitted while already idle always opens
|
||||
* its turn boundary, even when its message is cleared before the driver
|
||||
* claims ([cancel-convergence wake latch](../../../../.agents/notes/implemented/bug-fix/2026-08-07-cancel-convergence-wake-latch.md)).
|
||||
* @param message - identified content and its producer provenance.
|
||||
* @param message - identified content and the source that supplied it.
|
||||
* @param target - the preferred next-turn or next-step inbox boundary.
|
||||
* @param wakeup - whether delivery may wake the driver.
|
||||
*/
|
||||
@@ -116,7 +116,7 @@ interface Agent {
|
||||
/**
|
||||
* Queue an ordinary follow-up turn and wake the driver. The item becomes the
|
||||
* sole ordinary message of its own turn.
|
||||
* @param message - identified prompt content and its producer provenance.
|
||||
* @param message - identified prompt content and the source that supplied it.
|
||||
*/
|
||||
followup(message: UserMessage): void
|
||||
|
||||
@@ -125,7 +125,7 @@ interface Agent {
|
||||
* a running driver consumes it at its next step boundary.
|
||||
* A rejected step leaves steering parked in the inbox until the next
|
||||
* wake; cancellation or disposal may discard pending steering.
|
||||
* @param message - identified steering content and its producer provenance.
|
||||
* @param message - identified steering content and the source that supplied it.
|
||||
*/
|
||||
steer(message: UserMessage): void
|
||||
|
||||
@@ -135,7 +135,7 @@ interface Agent {
|
||||
* idle drivers leave it pending until follow-up or steering
|
||||
* wakes them. It may miss a request whose pre-step already claimed its
|
||||
* batch. Cancellation or disposal may discard pending context.
|
||||
* @param message - identified injected context and its producer provenance.
|
||||
* @param message - identified injected context and the source that supplied it.
|
||||
*/
|
||||
inject(message: UserMessage): void
|
||||
}
|
||||
@@ -200,7 +200,7 @@ type AgentCancelCause =
|
||||
| { readonly kind: 'disposed' }
|
||||
```
|
||||
|
||||
The cause is a TypeScript-enforced same-process input. An active cancellation holder copies it into the runtime-only `AbortSignal.reason`; a signal grants cooperating listeners no classification authority. Durable `turn/end` retains the coarse `{ kind: 'aborted' }` outcome; request provenance would require a separate durable event rather than overloading the terminal result.
|
||||
The cause is a TypeScript-enforced same-process input. An active cancellation holder copies it into the runtime-only `AbortSignal.reason`; a signal grants cooperating listeners no classification authority. Durable `turn/end` retains the coarse `{ kind: 'aborted' }` outcome; recording who requested cancellation would require a separate durable event rather than overloading the terminal result.
|
||||
|
||||
The [event taxonomy](../architecture.md#event) owns the `agent/*` lifecycle, checkpoint, and waterfall contracts. Turn and step boundaries are durable session events rather than agent emits.
|
||||
|
||||
@@ -210,7 +210,7 @@ The process-local initiator carried by `ctx.agents` is the exact `Agent` above,
|
||||
|
||||
## Interception decisions
|
||||
|
||||
Pre-step decisions use the same identified `UserMessage` shape as durable user-role input. The entered batch is authoritative and preserves every message's identity and provenance. Hook bridges map their native decision fields onto this typed result.
|
||||
Pre-step decisions use the same identified `UserMessage` shape as durable user-role input. The entered batch is authoritative and preserves every message's id and source. Hook bridges map their native decision fields onto this typed result.
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
@@ -243,7 +243,7 @@ type SessionStartSource = 'startup' | 'resume' | 'clear' | 'compact'
|
||||
|
||||
## Sessions
|
||||
|
||||
A `Session` is an **append-only log** of typed `SessionEvent`s — the single source of truth. The LLM message history is *derived* from the log (`deriveMessages()`), not stored separately. Every entry carries a monotonic `seq`, a `time`, and a `type`-discriminated `data` payload; surface variants additionally carry `sourceEventSeqs` provenance and a `surfaceOp`.
|
||||
A `Session` is an **append-only log** of typed `SessionEvent`s — the single source of truth. The LLM message history is *derived* from the log (`deriveMessages()`), not stored separately. Every entry carries a monotonic `seq`, a `time`, and a `type`-discriminated `data` payload; surface variants may also list cited earlier events in `sourceEventSeqs` and carry a `surfaceOp`.
|
||||
|
||||
The `SessionEvent` envelope's exact conditional shape, the twelve event variants (`turn/start`, `turn/end`, `step/start`, `step/end`, `user/message`, `assistant/chunk`, `assistant/message`, `tool/call`, `tool/result`, `steering/message`, `todo/write`, `request/header`), the `deriveMessages()` projection rules, the `TurnTrigger`/`TurnEndReason` reasons, and the execution-enclosure and standalone-event rules are on **[session.md](session.md)**. How the log is made durable — the `SessionPersistence` seam, JSONL/SQLite backends, the `session/flush` checkpoint, crash recovery, and `SessionHeader` — is on **[persistence.md](persistence.md)**.
|
||||
|
||||
@@ -314,6 +314,30 @@ The two core IDs are `CallId` (correlates a tool call with its result; dsh-llm)
|
||||
|
||||
Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — this section is byte-identical in both language sides of the page. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` surface lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
|
||||
|
||||
<a id="ctxagentdefaultmodel--agentdefaultmodelservice"></a>
|
||||
|
||||
### `ctx.agentDefaultModel` — `AgentDefaultModelService`
|
||||
|
||||
Owns the default model selection independently of any Host or transport. The composition entry remains usable without a settings provider; when one is mounted, its user layer is read live.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Read the current default model selection.
|
||||
* @returns a detached provider, model, and optional reasoning selection.
|
||||
*/
|
||||
currentSelection(): ModelSelection
|
||||
|
||||
/**
|
||||
* Save the complete default model selection. A deployment without a settings
|
||||
* provider keeps its composition entry.
|
||||
* @param next - resolved selection accepted by a front door.
|
||||
* @returns fulfillment after the optional settings write settles.
|
||||
*/
|
||||
async saveSelection(next: ModelSelection): Promise<void>
|
||||
```
|
||||
|
||||
Source: [`packages/core/agent-default-model/src/index.ts:64`](../../packages/core/agent-default-model/src/index.ts)
|
||||
|
||||
<a id="ctxagentloop--agentloop"></a>
|
||||
|
||||
### `ctx.agentLoop` — `AgentLoop`
|
||||
@@ -353,6 +377,138 @@ Types: [SessionHeader](persistence.md)
|
||||
|
||||
Source: [`packages/core/agent-loop/src/index.ts:277`](../../packages/core/agent-loop/src/index.ts)
|
||||
|
||||
<a id="ctxagentpresets--agentpresets"></a>
|
||||
|
||||
### `ctx.agentPresets` — `AgentPresets`
|
||||
|
||||
Registry over the deployment's agent presets.
|
||||
|
||||
Discovery is unmemoized: `list()` and `resolve()` re-read the roots on every call so a preset authored while the process runs is visible immediately, and a preset deleted underneath a picker disappears from the next read.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Every preset the configured roots currently supply.
|
||||
* @returns the presets, first-root-wins per id.
|
||||
*/
|
||||
async list(): Promise<AgentPreset[]>
|
||||
|
||||
/**
|
||||
* Resolve one preset by id.
|
||||
*
|
||||
* A broken preset resolves — deleting one, reading one, and reporting one
|
||||
* all need the row — and the mounting paths refuse it AFTER resolution
|
||||
* through {@link resolveMountable}.
|
||||
* @param id - the preset id, or `undefined` for {@link defaultId}.
|
||||
* @returns the resolved preset.
|
||||
* @throws when no configured root supplies that id.
|
||||
*/
|
||||
async resolve(id?: string): Promise<AgentPreset>
|
||||
|
||||
/**
|
||||
* Compose one agent from a preset: ensure the preset's standing mount, then
|
||||
* parent the agent's scope key to it so the mount's registrations and
|
||||
* listeners cover this agent.
|
||||
*
|
||||
* Call from the agent factory's `setup(agentCtx)`; a rejection there rolls
|
||||
* the agent creation back, so a broken preset never yields a half-composed
|
||||
* session.
|
||||
* @param agentCtx - the agent's scope context.
|
||||
* @param id - the preset id, or `undefined` for {@link defaultId}.
|
||||
* @returns the preset that was composed, for the caller to record.
|
||||
* @throws when the preset is unknown or its composition is unusable.
|
||||
*/
|
||||
async mount(agentCtx: Context, id?: string): Promise<AgentPreset>
|
||||
|
||||
/**
|
||||
* Read one preset's composition text.
|
||||
* @param id - the preset id.
|
||||
* @returns the composition exactly as stored.
|
||||
* @throws when no configured root supplies that id.
|
||||
*/
|
||||
async read(id: string): Promise<string>
|
||||
|
||||
/**
|
||||
* Create a locally authored preset by copying an existing one whole.
|
||||
*
|
||||
* Copy is the only authoring write. Composition text never crosses this
|
||||
* seam: the source is named by id and its directory is copied as it stands,
|
||||
* so the copy is exactly as loadable as its source and authoring grants no
|
||||
* capability the roster did not already carry. The copy is NOT mounted to
|
||||
* validate — a source that mounts today yields a copy that mounts today.
|
||||
* @param from - the preset the copy starts from; shipped presets are the
|
||||
* primary source, so any trust is accepted.
|
||||
* @param id - the new preset's id, which becomes its directory name.
|
||||
* @param name - display name for the copy; absent falls back to the id.
|
||||
* @throws when the source is unknown, the id is unusable or already taken,
|
||||
* or the deployment configures no writable root.
|
||||
*/
|
||||
async copy(from: string, id: string, name?: string): Promise<void>
|
||||
|
||||
/**
|
||||
* Delete a locally authored preset.
|
||||
* @param id - the preset id.
|
||||
* @throws when the preset is unknown or ships with the deployment.
|
||||
*/
|
||||
async remove(id: string): Promise<void>
|
||||
|
||||
/**
|
||||
* One agent's instance of a service its preset mounted.
|
||||
*
|
||||
* A preset publishes services behind `isolate` realms, which are invisible
|
||||
* outside the group that declares them — including to the host. This is how a
|
||||
* caller holding the agent reads one anyway: a request that is ABOUT a
|
||||
* session but arrives from outside it, which is every browser RPC.
|
||||
*
|
||||
* Read addressing only. A host row that `inject`s a service cannot use this,
|
||||
* because injection resolves before any session exists and has no agent to
|
||||
* key by; such a service belongs on the host plane instead.
|
||||
* @param agent - the agent whose composition to look inside.
|
||||
* @param name - the service name as the preset's rows resolve it.
|
||||
* @returns the agent's instance, or undefined when its preset mounts none.
|
||||
*/
|
||||
serviceFor<K extends string & keyof Context>(agent: { ctx: Context }, name: K): Context[K] | undefined
|
||||
|
||||
/**
|
||||
* Re-link one agent to a different preset's standing composition.
|
||||
*
|
||||
* Only valid while the agent has produced nothing: swapping tools mid
|
||||
* conversation would leave logged tool calls the new composition cannot
|
||||
* make. The CALLER owns that check — this method does not read session
|
||||
* history.
|
||||
*
|
||||
* The swap is a parent re-link, not an unmount: standing mounts are shared
|
||||
* and permanent, so the old composition stays for its other agents and the
|
||||
* new one is ensured BEFORE the link moves. An unknown or unusable preset
|
||||
* therefore throws with the agent exactly as it was — there is no torn-down
|
||||
* state to restore. The re-link runs through the binding this roster kept
|
||||
* from the agent's mount — dsh-scope's only re-link authority. An agent
|
||||
* that never composed one has nothing to re-link: the switch is then the
|
||||
* agent's first bind, exactly a mount.
|
||||
* @param agentCtx - the agent's scope context.
|
||||
* @param id - the preset to compose the agent from instead.
|
||||
* @returns the preset now installed.
|
||||
* @throws when the preset is unknown or its composition is unusable.
|
||||
*/
|
||||
async recompose(agentCtx: Context, id: string): Promise<AgentPreset>
|
||||
|
||||
/**
|
||||
* The standing scope key of one preset, for a host reader with no agent.
|
||||
*
|
||||
* A cold transcript read resolves tool presenters against the composition
|
||||
* the session recorded, and the standing mount makes that possible without
|
||||
* resuming anything: ensuring the mount composes plugins but starts no
|
||||
* agent, no session, and no turn.
|
||||
* @param id - the preset id, or `undefined` for {@link defaultId}.
|
||||
* @returns the standing scope key readers pass as a registry view scope.
|
||||
* @throws when the preset is unknown or its composition is unusable.
|
||||
*/
|
||||
async standingKeyFor(id?: string): Promise<ScopeKey>
|
||||
```
|
||||
|
||||
Types: [ScopeKey](scope.md)
|
||||
|
||||
Source: [`packages/preset/agent-presets/src/index.ts:78`](../../packages/preset/agent-presets/src/index.ts)
|
||||
|
||||
<a id="ctxagents--agentregistry"></a>
|
||||
|
||||
### `ctx.agents` — `AgentRegistry`
|
||||
@@ -377,7 +533,7 @@ currentInitiator(): Agent | undefined
|
||||
* Read the initiating Agent and fail when no initiator boundary is active.
|
||||
* Use this for private helpers contractually below a driver, or for a
|
||||
* deployment-owned outbound request whose contract forbids agentless calls.
|
||||
* Generic or direct-call seams use optional lookup or explicit request fields.
|
||||
* Generic or direct-call paths use optional lookup or explicit request fields.
|
||||
* @returns the inherited Agent.
|
||||
* @throws when no initiator is active or this service instance has been disposed.
|
||||
*/
|
||||
@@ -523,7 +679,7 @@ list(): Agent[]
|
||||
roots(): Agent[]
|
||||
```
|
||||
|
||||
Source: [`packages/core/agent/src/index.ts:253`](../../packages/core/agent/src/index.ts)
|
||||
Source: [`packages/core/agent/src/index.ts:255`](../../packages/core/agent/src/index.ts)
|
||||
|
||||
<a id="agent-events"></a>
|
||||
|
||||
@@ -533,12 +689,12 @@ Source: [`packages/core/agent/src/index.ts:253`](../../packages/core/agent/src/i
|
||||
|
||||
#### `agent/created` — emit
|
||||
|
||||
A fully configured agent and live session were published. Setup is composition-only; `agent/session-start` is the first startup-driving seam. Synchronous listener failure vetoes publication, while returned-promise rejection is reported. Detach requested during dispatch waits until every creation listener has observed the stable entry.
|
||||
A fully configured agent and live session were published. Setup is composition-only; `agent/session-start` is the first startup-driving extension point. Synchronous listener failure vetoes publication, while returned-promise rejection is reported. Detach requested during dispatch waits until every creation listener has observed the stable entry.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* A fully configured agent and live session were published. Setup is
|
||||
* composition-only; `agent/session-start` is the first startup-driving seam.
|
||||
* composition-only; `agent/session-start` is the first startup-driving extension point.
|
||||
* Synchronous listener failure vetoes publication, while returned-promise
|
||||
* rejection is reported. Detach requested during dispatch waits until every
|
||||
* creation listener has observed the stable entry.
|
||||
@@ -551,7 +707,7 @@ A fully configured agent and live session were published. Setup is composition-o
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:158`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:159`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentdisposed--emit"></a>
|
||||
|
||||
@@ -573,7 +729,7 @@ An agent left the registry; AgentLoop emits this after driver quiescence and sco
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:167`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:168`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agenterror--emit"></a>
|
||||
|
||||
@@ -597,7 +753,7 @@ A step or turn errored. The machine reports a failure here even when the error h
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:289`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:290`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentinboxclaimed--emit"></a>
|
||||
|
||||
@@ -621,7 +777,7 @@ One message left the inbox inside its open turn. If the proposed step is rejecte
|
||||
|
||||
Types: [Scoped](scope.md) · [UserMessage](session.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:196`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:197`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentinboxdiscarded--emit"></a>
|
||||
|
||||
@@ -642,7 +798,7 @@ One message was discarded from the live inbox.
|
||||
|
||||
Types: [Scoped](scope.md) · [UserMessage](session.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:204`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:205`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentinboxinserted--emit"></a>
|
||||
|
||||
@@ -663,7 +819,7 @@ One message entered the live inbox.
|
||||
|
||||
Types: [Scoped](scope.md) · [UserMessage](session.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:185`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:186`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentpre-step--waterfall"></a>
|
||||
|
||||
@@ -688,20 +844,20 @@ Reject a proposed step or replace the messages that enter it. Calling `next()` p
|
||||
|
||||
Types: [Scoped](scope.md) · [UserMessage](session.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:230`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:231`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentrequest--waterfall"></a>
|
||||
|
||||
#### `agent/request` — waterfall
|
||||
|
||||
Replace the frozen call configuration. `await next()` yields the config the machine would use (agent options on the first request, the logged header afterwards); return a replacement to switch. Model-visible content must use logged channels; this seam cannot mutate messages.
|
||||
Replace the frozen call configuration. `await next()` yields the config the machine would use (agent options on the first request, the logged header afterwards); return a replacement to switch. Model-visible content must use logged channels; this waterfall cannot mutate messages.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Replace the frozen call configuration. `await next()` yields the config
|
||||
* the machine would use (agent options on the first request, the logged
|
||||
* header afterwards); return a replacement to switch. Model-visible
|
||||
* content must use logged channels; this seam cannot mutate messages.
|
||||
* content must use logged channels; this waterfall cannot mutate messages.
|
||||
* @param payload.agent - the agent making the model call.
|
||||
* @param payload.turn - the open turn number.
|
||||
* @param payload.step - the step whose request this is.
|
||||
@@ -714,7 +870,7 @@ Replace the frozen call configuration. `await next()` yields the config the mach
|
||||
|
||||
Types: [LlmCallConfig](llm-streaming.md) · [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:243`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:244`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentrequest-error--waterfall"></a>
|
||||
|
||||
@@ -743,7 +899,7 @@ Handle one failed model-request attempt before the loop retries or closes its st
|
||||
|
||||
Types: [LlmFailure](llm-streaming.md) · [ResolvedRetryPolicy](llm-streaming.md) · [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:259`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:260`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentsession-start--emit"></a>
|
||||
|
||||
@@ -767,7 +923,7 @@ The session lifecycle began, once before the first turn. Use `agent.inject()` to
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:216`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:217`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentstatus--emit"></a>
|
||||
|
||||
@@ -790,7 +946,7 @@ Agent status changed (`idle` ⇄ `running`). A waking delivery enters `running`
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:177`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:178`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentturn-stopping--serial"></a>
|
||||
|
||||
@@ -821,7 +977,7 @@ The turn is about to close: the model owes no response (no live tool calls, no f
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:277`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:278`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agent-loop-events"></a>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
| `agent-loop/` | 实现公开 `Agent` 约定的具体 driver(`ctx.agentLoop`) | 本页 |
|
||||
| `scope/` | 注册表与循环用于构建按 agent 作用域的注册原语 | [scope.md](scope.md) |
|
||||
|
||||
`scope/` 是这里唯一的非服务包:一个零依赖库(`createScope`/`scopeOf`/`scopeTarget`),在模块图中位于 `session/` 与 `system-prompt/` 之下,正是为了让它们消费它而不形成环。`agent-loop` 是 `agent` seam 的唯一具体实现,放在这里因为它是 harness 的默认产品循环;它在 `ctx.agents.withInitiator()` 内运行每个 driver。扩展插件依赖 `agent`——包括需要发起 Agent 时——而绝不直接依赖 `agent-loop`,因此循环保持可替换。把这条主干接成可运行 agent 的默认组合是 [`examples/agent-spine-demo`](../../packages/examples/agent-spine-demo/README.md)。
|
||||
`scope/` 是这里唯一的非服务包:一个零依赖库(`createScope`/`scopeOf`/`scopeTarget`),在模块图中位于 `session/` 与 `system-prompt/` 之下,正是为了让它们消费它而不形成环。`agent-loop` 是公开 `Agent` 约定的唯一具体实现,放在这里因为它是 harness 的默认产品循环;它在 `ctx.agents.withInitiator()` 内运行每个 driver。扩展插件依赖 `agent`——包括需要发起 Agent 时——而绝不直接依赖 `agent-loop`,因此循环保持可替换。把这条主干接成可运行 agent 的默认组合是 [`examples/agent-spine-demo`](../../packages/examples/agent-spine-demo/README.md)。
|
||||
|
||||
<a id="creation-and-ownership"></a>
|
||||
|
||||
@@ -50,7 +50,7 @@ interface AgentHandle {
|
||||
|
||||
`CreateAgentOptions` 携带共享标识以及新 agent 发布前所需的一切:会话元数据(`meta`——已校验的 `cwd`、fork 谱系、seed 边界、来源分类、委派深度)、fork 用的可选 `seed` 回放前缀、按 agent 的 `AgentOptions`、仅创建期有效的取消 `signal`,以及 `setup`。`ResumeAgentOptions` 是持久标识的对应物:`resumeSessionId`、`agentOptions`、`signal` 与 `setup`。`setup` 回调(`AgentSetup`)在两个 id 都尚未发布时组装 agent 的作用域世界——凡经 `agentCtx` 注册的内容都先于 `agent/created` 与第一次提示词组装存在——并可返回一个在发布前一刻调用的同步 commit;setup 拒绝、commit 抛出或所有者 dispose 都会回滚事务,两个 id 均不发布。
|
||||
|
||||
`AgentFactory` 是注册表背后的创建 seam:循环经 `ctx.agents.setFactory()` 注册其工厂,因此消费方面向 `ctx.agents` 编程,无需依赖具体循环包。确切的 `create`/`resume` 签名及其回滚约定见下方[生成区块](#ctxagents--agentregistry)。
|
||||
`AgentFactory` 是注册表背后的创建约定:循环经 `ctx.agents.setFactory()` 注册其工厂,因此消费方面向 `ctx.agents` 编程,无需依赖具体循环包。确切的 `create`/`resume` 签名及其回滚约定见下方[生成区块](#ctxagents--agentregistry)。
|
||||
|
||||
<a id="the-agent-handle"></a>
|
||||
|
||||
@@ -111,7 +111,7 @@ interface Agent {
|
||||
* cancel leaves it parked. A wake submitted while already idle always opens
|
||||
* its turn boundary, even when its message is cleared before the driver
|
||||
* claims ([cancel-convergence wake latch](../../../../.agents/notes/implemented/bug-fix/2026-08-07-cancel-convergence-wake-latch.md)).
|
||||
* @param message - identified content and its producer provenance.
|
||||
* @param message - identified content and the source that supplied it.
|
||||
* @param target - the preferred next-turn or next-step inbox boundary.
|
||||
* @param wakeup - whether delivery may wake the driver.
|
||||
*/
|
||||
@@ -120,7 +120,7 @@ interface Agent {
|
||||
/**
|
||||
* Queue an ordinary follow-up turn and wake the driver. The item becomes the
|
||||
* sole ordinary message of its own turn.
|
||||
* @param message - identified prompt content and its producer provenance.
|
||||
* @param message - identified prompt content and the source that supplied it.
|
||||
*/
|
||||
followup(message: UserMessage): void
|
||||
|
||||
@@ -129,7 +129,7 @@ interface Agent {
|
||||
* a running driver consumes it at its next step boundary.
|
||||
* A rejected step leaves steering parked in the inbox until the next
|
||||
* wake; cancellation or disposal may discard pending steering.
|
||||
* @param message - identified steering content and its producer provenance.
|
||||
* @param message - identified steering content and the source that supplied it.
|
||||
*/
|
||||
steer(message: UserMessage): void
|
||||
|
||||
@@ -139,7 +139,7 @@ interface Agent {
|
||||
* idle drivers leave it pending until follow-up or steering
|
||||
* wakes them. It may miss a request whose pre-step already claimed its
|
||||
* batch. Cancellation or disposal may discard pending context.
|
||||
* @param message - identified injected context and its producer provenance.
|
||||
* @param message - identified injected context and the source that supplied it.
|
||||
*/
|
||||
inject(message: UserMessage): void
|
||||
}
|
||||
@@ -204,7 +204,7 @@ type AgentCancelCause =
|
||||
| { readonly kind: 'disposed' }
|
||||
```
|
||||
|
||||
cause 是由 TypeScript 强制约束的同进程输入。活跃的取消持有者会将它复制到仅运行时的 `AbortSignal.reason`;signal 不授予协作监听器任何分类权限。持久 `turn/end` 保留粗粒度 `{ kind: 'aborted' }` 结果;若需记录请求 provenance,应使用单独的持久事件,而不是让终态结果承担额外含义。
|
||||
cause 是由 TypeScript 强制约束的同进程输入。活跃的取消持有者会将它复制到仅运行时的 `AbortSignal.reason`;signal 不授予协作监听器任何分类权限。持久 `turn/end` 保留粗粒度 `{ kind: 'aborted' }` 结果;若需记录谁请求了取消,应使用单独的持久事件,而不是让终态结果承担额外含义。
|
||||
|
||||
[事件分类](../architecture.md#event)拥有 `agent/*` 生命周期、检查点与 waterfall(瀑布式事件)约定。轮次和步骤边界是持久会话事件,而不是 agent emit。
|
||||
|
||||
@@ -216,7 +216,7 @@ cause 是由 TypeScript 强制约束的同进程输入。活跃的取消持有
|
||||
|
||||
## 拦截决策
|
||||
|
||||
pre-step 决策使用与持久 user-role 输入相同、带标识的 `UserMessage` 形状。进入步骤的批次具有权威性,并保留每条消息的标识与 provenance。钩子桥接层把其原生决策字段映射到这一类型化结果上。
|
||||
pre-step 决策使用与持久 user-role 输入相同、带标识的 `UserMessage` 形状。进入步骤的批次具有权威性,并保留每条消息的 id 和 source。钩子桥接层把其原生决策字段映射到这一类型化结果上。
|
||||
|
||||
源码:[`packages/core/agent/src/types.ts`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
@@ -249,7 +249,7 @@ type SessionStartSource = 'startup' | 'resume' | 'clear' | 'compact'
|
||||
|
||||
## 会话
|
||||
|
||||
`Session` 是一份类型化 `SessionEvent` 的**仅追加日志**——唯一的真源。LLM(大语言模型)消息历史从日志*派生*(`deriveMessages()`),而非单独存储。每个条目携带单调的 `seq`、`time` 与按 `type` 判别的 `data` payload;surface 变体还额外携带 `sourceEventSeqs` provenance 与 `surfaceOp`。
|
||||
`Session` 是一份类型化 `SessionEvent` 的**仅追加日志**——唯一的真源。LLM(大语言模型)消息历史从日志*派生*(`deriveMessages()`),而非单独存储。每个条目携带单调的 `seq`、`time` 与按 `type` 判别的 `data` payload;surface 变体还可以在 `sourceEventSeqs` 中列出被引用的较早事件,并携带 `surfaceOp`。
|
||||
|
||||
`SessionEvent` 信封的确切条件形状、十二种事件变体(`turn/start`、`turn/end`、`step/start`、`step/end`、`user/message`、`assistant/chunk`、`assistant/message`、`tool/call`、`tool/result`、`steering/message`、`todo/write`、`request/header`)、`deriveMessages()` 投影规则、`TurnTrigger`/`TurnEndReason` 原因以及执行封闭和独立事件规则都在 **[session.md](session.md)** 中。日志如何持久化——`SessionPersistence` seam、JSONL/SQLite 后端、`session/flush` 检查点、崩溃恢复与 `SessionHeader`——则在 **[persistence.md](persistence.md)** 中。
|
||||
|
||||
@@ -265,7 +265,7 @@ type SessionStartSource = 'startup' | 'resume' | 'clear' | 'compact'
|
||||
|
||||
### `…Map → derived-union` 模式
|
||||
|
||||
harness 中几乎所有可扩展的和类型都遵循同一形状:一个以判别标签为键的接口(`…Map`),联合类型由 `keyof` 派生。插件通过**声明合并**添加变体——无需修改拥有该类型的包(package)。
|
||||
harness 中几乎所有可扩展的和类型都遵循同一形状:一个以判别标签为键的接口(`…Map`),联合类型由 `keyof` 派生。插件通过**声明合并**添加变体——无需修改拥有该类型的包。
|
||||
|
||||
```ts ignore-check
|
||||
// The pattern, schematically:
|
||||
@@ -322,6 +322,30 @@ type Branded<B extends string> = string & { readonly [BRAND]: B }
|
||||
|
||||
Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — this section is byte-identical in both language sides of the page. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` surface lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
|
||||
|
||||
<a id="ctxagentdefaultmodel--agentdefaultmodelservice"></a>
|
||||
|
||||
### `ctx.agentDefaultModel` — `AgentDefaultModelService`
|
||||
|
||||
Owns the default model selection independently of any Host or transport. The composition entry remains usable without a settings provider; when one is mounted, its user layer is read live.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Read the current default model selection.
|
||||
* @returns a detached provider, model, and optional reasoning selection.
|
||||
*/
|
||||
currentSelection(): ModelSelection
|
||||
|
||||
/**
|
||||
* Save the complete default model selection. A deployment without a settings
|
||||
* provider keeps its composition entry.
|
||||
* @param next - resolved selection accepted by a front door.
|
||||
* @returns fulfillment after the optional settings write settles.
|
||||
*/
|
||||
async saveSelection(next: ModelSelection): Promise<void>
|
||||
```
|
||||
|
||||
Source: [`packages/core/agent-default-model/src/index.ts:64`](../../packages/core/agent-default-model/src/index.ts)
|
||||
|
||||
<a id="ctxagentloop--agentloop"></a>
|
||||
|
||||
### `ctx.agentLoop` — `AgentLoop`
|
||||
@@ -361,6 +385,138 @@ Types: [SessionHeader](persistence.md)
|
||||
|
||||
Source: [`packages/core/agent-loop/src/index.ts:277`](../../packages/core/agent-loop/src/index.ts)
|
||||
|
||||
<a id="ctxagentpresets--agentpresets"></a>
|
||||
|
||||
### `ctx.agentPresets` — `AgentPresets`
|
||||
|
||||
Registry over the deployment's agent presets.
|
||||
|
||||
Discovery is unmemoized: `list()` and `resolve()` re-read the roots on every call so a preset authored while the process runs is visible immediately, and a preset deleted underneath a picker disappears from the next read.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Every preset the configured roots currently supply.
|
||||
* @returns the presets, first-root-wins per id.
|
||||
*/
|
||||
async list(): Promise<AgentPreset[]>
|
||||
|
||||
/**
|
||||
* Resolve one preset by id.
|
||||
*
|
||||
* A broken preset resolves — deleting one, reading one, and reporting one
|
||||
* all need the row — and the mounting paths refuse it AFTER resolution
|
||||
* through {@link resolveMountable}.
|
||||
* @param id - the preset id, or `undefined` for {@link defaultId}.
|
||||
* @returns the resolved preset.
|
||||
* @throws when no configured root supplies that id.
|
||||
*/
|
||||
async resolve(id?: string): Promise<AgentPreset>
|
||||
|
||||
/**
|
||||
* Compose one agent from a preset: ensure the preset's standing mount, then
|
||||
* parent the agent's scope key to it so the mount's registrations and
|
||||
* listeners cover this agent.
|
||||
*
|
||||
* Call from the agent factory's `setup(agentCtx)`; a rejection there rolls
|
||||
* the agent creation back, so a broken preset never yields a half-composed
|
||||
* session.
|
||||
* @param agentCtx - the agent's scope context.
|
||||
* @param id - the preset id, or `undefined` for {@link defaultId}.
|
||||
* @returns the preset that was composed, for the caller to record.
|
||||
* @throws when the preset is unknown or its composition is unusable.
|
||||
*/
|
||||
async mount(agentCtx: Context, id?: string): Promise<AgentPreset>
|
||||
|
||||
/**
|
||||
* Read one preset's composition text.
|
||||
* @param id - the preset id.
|
||||
* @returns the composition exactly as stored.
|
||||
* @throws when no configured root supplies that id.
|
||||
*/
|
||||
async read(id: string): Promise<string>
|
||||
|
||||
/**
|
||||
* Create a locally authored preset by copying an existing one whole.
|
||||
*
|
||||
* Copy is the only authoring write. Composition text never crosses this
|
||||
* seam: the source is named by id and its directory is copied as it stands,
|
||||
* so the copy is exactly as loadable as its source and authoring grants no
|
||||
* capability the roster did not already carry. The copy is NOT mounted to
|
||||
* validate — a source that mounts today yields a copy that mounts today.
|
||||
* @param from - the preset the copy starts from; shipped presets are the
|
||||
* primary source, so any trust is accepted.
|
||||
* @param id - the new preset's id, which becomes its directory name.
|
||||
* @param name - display name for the copy; absent falls back to the id.
|
||||
* @throws when the source is unknown, the id is unusable or already taken,
|
||||
* or the deployment configures no writable root.
|
||||
*/
|
||||
async copy(from: string, id: string, name?: string): Promise<void>
|
||||
|
||||
/**
|
||||
* Delete a locally authored preset.
|
||||
* @param id - the preset id.
|
||||
* @throws when the preset is unknown or ships with the deployment.
|
||||
*/
|
||||
async remove(id: string): Promise<void>
|
||||
|
||||
/**
|
||||
* One agent's instance of a service its preset mounted.
|
||||
*
|
||||
* A preset publishes services behind `isolate` realms, which are invisible
|
||||
* outside the group that declares them — including to the host. This is how a
|
||||
* caller holding the agent reads one anyway: a request that is ABOUT a
|
||||
* session but arrives from outside it, which is every browser RPC.
|
||||
*
|
||||
* Read addressing only. A host row that `inject`s a service cannot use this,
|
||||
* because injection resolves before any session exists and has no agent to
|
||||
* key by; such a service belongs on the host plane instead.
|
||||
* @param agent - the agent whose composition to look inside.
|
||||
* @param name - the service name as the preset's rows resolve it.
|
||||
* @returns the agent's instance, or undefined when its preset mounts none.
|
||||
*/
|
||||
serviceFor<K extends string & keyof Context>(agent: { ctx: Context }, name: K): Context[K] | undefined
|
||||
|
||||
/**
|
||||
* Re-link one agent to a different preset's standing composition.
|
||||
*
|
||||
* Only valid while the agent has produced nothing: swapping tools mid
|
||||
* conversation would leave logged tool calls the new composition cannot
|
||||
* make. The CALLER owns that check — this method does not read session
|
||||
* history.
|
||||
*
|
||||
* The swap is a parent re-link, not an unmount: standing mounts are shared
|
||||
* and permanent, so the old composition stays for its other agents and the
|
||||
* new one is ensured BEFORE the link moves. An unknown or unusable preset
|
||||
* therefore throws with the agent exactly as it was — there is no torn-down
|
||||
* state to restore. The re-link runs through the binding this roster kept
|
||||
* from the agent's mount — dsh-scope's only re-link authority. An agent
|
||||
* that never composed one has nothing to re-link: the switch is then the
|
||||
* agent's first bind, exactly a mount.
|
||||
* @param agentCtx - the agent's scope context.
|
||||
* @param id - the preset to compose the agent from instead.
|
||||
* @returns the preset now installed.
|
||||
* @throws when the preset is unknown or its composition is unusable.
|
||||
*/
|
||||
async recompose(agentCtx: Context, id: string): Promise<AgentPreset>
|
||||
|
||||
/**
|
||||
* The standing scope key of one preset, for a host reader with no agent.
|
||||
*
|
||||
* A cold transcript read resolves tool presenters against the composition
|
||||
* the session recorded, and the standing mount makes that possible without
|
||||
* resuming anything: ensuring the mount composes plugins but starts no
|
||||
* agent, no session, and no turn.
|
||||
* @param id - the preset id, or `undefined` for {@link defaultId}.
|
||||
* @returns the standing scope key readers pass as a registry view scope.
|
||||
* @throws when the preset is unknown or its composition is unusable.
|
||||
*/
|
||||
async standingKeyFor(id?: string): Promise<ScopeKey>
|
||||
```
|
||||
|
||||
Types: [ScopeKey](scope.md)
|
||||
|
||||
Source: [`packages/preset/agent-presets/src/index.ts:78`](../../packages/preset/agent-presets/src/index.ts)
|
||||
|
||||
<a id="ctxagents--agentregistry"></a>
|
||||
|
||||
### `ctx.agents` — `AgentRegistry`
|
||||
@@ -385,7 +541,7 @@ currentInitiator(): Agent | undefined
|
||||
* Read the initiating Agent and fail when no initiator boundary is active.
|
||||
* Use this for private helpers contractually below a driver, or for a
|
||||
* deployment-owned outbound request whose contract forbids agentless calls.
|
||||
* Generic or direct-call seams use optional lookup or explicit request fields.
|
||||
* Generic or direct-call paths use optional lookup or explicit request fields.
|
||||
* @returns the inherited Agent.
|
||||
* @throws when no initiator is active or this service instance has been disposed.
|
||||
*/
|
||||
@@ -531,7 +687,7 @@ list(): Agent[]
|
||||
roots(): Agent[]
|
||||
```
|
||||
|
||||
Source: [`packages/core/agent/src/index.ts:253`](../../packages/core/agent/src/index.ts)
|
||||
Source: [`packages/core/agent/src/index.ts:255`](../../packages/core/agent/src/index.ts)
|
||||
|
||||
<a id="agent-events"></a>
|
||||
|
||||
@@ -541,12 +697,12 @@ Source: [`packages/core/agent/src/index.ts:253`](../../packages/core/agent/src/i
|
||||
|
||||
#### `agent/created` — emit
|
||||
|
||||
A fully configured agent and live session were published. Setup is composition-only; `agent/session-start` is the first startup-driving seam. Synchronous listener failure vetoes publication, while returned-promise rejection is reported. Detach requested during dispatch waits until every creation listener has observed the stable entry.
|
||||
A fully configured agent and live session were published. Setup is composition-only; `agent/session-start` is the first startup-driving extension point. Synchronous listener failure vetoes publication, while returned-promise rejection is reported. Detach requested during dispatch waits until every creation listener has observed the stable entry.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* A fully configured agent and live session were published. Setup is
|
||||
* composition-only; `agent/session-start` is the first startup-driving seam.
|
||||
* composition-only; `agent/session-start` is the first startup-driving extension point.
|
||||
* Synchronous listener failure vetoes publication, while returned-promise
|
||||
* rejection is reported. Detach requested during dispatch waits until every
|
||||
* creation listener has observed the stable entry.
|
||||
@@ -559,7 +715,7 @@ A fully configured agent and live session were published. Setup is composition-o
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:158`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:159`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentdisposed--emit"></a>
|
||||
|
||||
@@ -581,7 +737,7 @@ An agent left the registry; AgentLoop emits this after driver quiescence and sco
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:167`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:168`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agenterror--emit"></a>
|
||||
|
||||
@@ -605,7 +761,7 @@ A step or turn errored. The machine reports a failure here even when the error h
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:289`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:290`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentinboxclaimed--emit"></a>
|
||||
|
||||
@@ -629,7 +785,7 @@ One message left the inbox inside its open turn. If the proposed step is rejecte
|
||||
|
||||
Types: [Scoped](scope.md) · [UserMessage](session.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:196`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:197`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentinboxdiscarded--emit"></a>
|
||||
|
||||
@@ -650,7 +806,7 @@ One message was discarded from the live inbox.
|
||||
|
||||
Types: [Scoped](scope.md) · [UserMessage](session.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:204`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:205`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentinboxinserted--emit"></a>
|
||||
|
||||
@@ -671,7 +827,7 @@ One message entered the live inbox.
|
||||
|
||||
Types: [Scoped](scope.md) · [UserMessage](session.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:185`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:186`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentpre-step--waterfall"></a>
|
||||
|
||||
@@ -696,20 +852,20 @@ Reject a proposed step or replace the messages that enter it. Calling `next()` p
|
||||
|
||||
Types: [Scoped](scope.md) · [UserMessage](session.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:230`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:231`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentrequest--waterfall"></a>
|
||||
|
||||
#### `agent/request` — waterfall
|
||||
|
||||
Replace the frozen call configuration. `await next()` yields the config the machine would use (agent options on the first request, the logged header afterwards); return a replacement to switch. Model-visible content must use logged channels; this seam cannot mutate messages.
|
||||
Replace the frozen call configuration. `await next()` yields the config the machine would use (agent options on the first request, the logged header afterwards); return a replacement to switch. Model-visible content must use logged channels; this waterfall cannot mutate messages.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Replace the frozen call configuration. `await next()` yields the config
|
||||
* the machine would use (agent options on the first request, the logged
|
||||
* header afterwards); return a replacement to switch. Model-visible
|
||||
* content must use logged channels; this seam cannot mutate messages.
|
||||
* content must use logged channels; this waterfall cannot mutate messages.
|
||||
* @param payload.agent - the agent making the model call.
|
||||
* @param payload.turn - the open turn number.
|
||||
* @param payload.step - the step whose request this is.
|
||||
@@ -722,7 +878,7 @@ Replace the frozen call configuration. `await next()` yields the config the mach
|
||||
|
||||
Types: [LlmCallConfig](llm-streaming.md) · [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:243`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:244`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentrequest-error--waterfall"></a>
|
||||
|
||||
@@ -751,7 +907,7 @@ Handle one failed model-request attempt before the loop retries or closes its st
|
||||
|
||||
Types: [LlmFailure](llm-streaming.md) · [ResolvedRetryPolicy](llm-streaming.md) · [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:259`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:260`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentsession-start--emit"></a>
|
||||
|
||||
@@ -775,7 +931,7 @@ The session lifecycle began, once before the first turn. Use `agent.inject()` to
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:216`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:217`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentstatus--emit"></a>
|
||||
|
||||
@@ -798,7 +954,7 @@ Agent status changed (`idle` ⇄ `running`). A waking delivery enters `running`
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:177`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:178`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agentturn-stopping--serial"></a>
|
||||
|
||||
@@ -829,7 +985,7 @@ The turn is about to close: the model owes no response (no live tool calls, no f
|
||||
|
||||
Types: [Scoped](scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:277`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/runtime-types.ts:278`](../../packages/core/agent/src/runtime-types.ts)
|
||||
|
||||
<a id="agent-loop-events"></a>
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user