mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
Merge remote-tracking branch 'origin/master' into web-e2e-lane
# Conflicts: # vitest.web.config.ts
This commit is contained in:
@@ -40,8 +40,10 @@ flowchart LR
|
||||
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"]
|
||||
pkg_apiproxy["apiproxy"]
|
||||
svc_sessionQuery["ctx.sessionQuery<br/>Session reads, traces, filters, and search"]
|
||||
pkg_session_reference["session-reference"]
|
||||
svc_sessionReferences["ctx.sessionReferences<br/>Cross-session snapshot preparation"]
|
||||
@@ -180,6 +182,7 @@ flowchart LR
|
||||
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
|
||||
@@ -253,7 +256,7 @@ flowchart LR
|
||||
svc_skills --> pkg_tool_skill
|
||||
svc_spillStore --> pkg_spill_policy
|
||||
svc_storage --> pkg_storage_domain
|
||||
svc_storage --> pkg_workspace
|
||||
svc_storageDomain --> pkg_workspace
|
||||
svc_subagents --> pkg_tool_ralph
|
||||
svc_subagents --> pkg_tool_subagent
|
||||
svc_systemPrompt --> pkg_agent_loop
|
||||
@@ -282,6 +285,7 @@ flowchart LR
|
||||
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
|
||||
```
|
||||
|
||||
@@ -293,8 +297,9 @@ flowchart LR
|
||||
| `ctx.sessions` | `core` | [`session`](../packages/core/session) | - | [`agent-loop`](../packages/core/agent-loop), [`agent`](../packages/core/agent), [`cli-demo`](../packages/examples/cli-demo), [`session-persistence`](../packages/session-persistence/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) | - | Owns append-only Session instances and emits the durable session event feed. |
|
||||
| `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) | - | Companion subpaths register owner-local checks; the service owns selection, uniqueness, child fibers, and package-attributed failures. |
|
||||
| `ctx.sessionPersistence` | `seam` | [`session-persistence`](../packages/session-persistence/session-persistence) | [`session-persistence-jsonl`](../packages/session-persistence/session-persistence-jsonl), [`session-persistence-sqlite`](../packages/session-persistence/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) | - | Backends persist the same SessionEvent vocabulary; apps choose a backend at composition time. |
|
||||
| `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), [`workspace`](../packages/workspace/workspace) | - | Backends register side by side under names; data forms (domain first) mount on the hub and translate typed operations into opaque KV-unit primitives. |
|
||||
| `ctx.workspace` | `core` | [`workspace`](../packages/workspace/workspace) | - | - | - | Owns WorkspaceId-branded records over the domain form; sessionIds is the single source of ownership truth. RPC and GUI consumers arrive next phase. |
|
||||
| `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) | - | Backends register side by side under names; data forms (domain first) mount on the hub and translate typed operations into opaque KV-unit primitives. |
|
||||
| `ctx.storageDomain` | `core` | [`storage-domain`](../packages/storage/storage-domain) | - | [`workspace`](../packages/workspace/workspace) | - | Waits for every configured backend, then publishes the domain form as one lifecycle-bound service for typed durable state. |
|
||||
| `ctx.workspace` | `core` | [`workspace`](../packages/workspace/workspace) | - | `apiproxy` | - | Owns WorkspaceId-branded records over the domain facility; stable sessionIds accounts drive Host RPC and GUI projections. |
|
||||
| `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) | - | The interface supplies exact reads, filters, and traces; its concrete backend adds full-text reconciliation, ranking, snippets, and cursor generations on the same service. |
|
||||
| `ctx.sessionReferences` | `core` | [`session-reference`](../packages/context/session-reference) | - | [`tui`](../packages/ui/tui) | - | Projects bounded current-surface conversation snapshots into durable untrusted message context; host adapters own mention syntax. |
|
||||
| `ctx.sessionTitle` | `seam` | [`session-title`](../packages/session-title/session-title) | [`session-title-first-message-llm`](../packages/session-title/session-title-first-message-llm), [`session-title-all-messages-llm`](../packages/session-title/session-title-all-messages-llm) | - | - | Owns the deterministic fallback, latest-title fold, and sole optional asynchronous provider registration. |
|
||||
|
||||
@@ -487,19 +487,21 @@ Source: [`packages/hooks/hooks-codex/src/index.ts:42`](../packages/hooks/hooks-c
|
||||
|
||||
## `@deepseek-ai/dsh-host-apiproxy`
|
||||
|
||||
Requires: `agents` · `sessions` · `tools` · `userInteraction`
|
||||
Requires: `agents` · `sessions` · `tools` · `userInteraction` · `workspace`
|
||||
|
||||
```ts config-catalog
|
||||
/** Gateway plugin config: the host-level default agent routing. */
|
||||
/** Gateway plugin config: host-level agent routing and Workspace creation root. */
|
||||
export interface Config {
|
||||
/** Default provider route for created/resumed agents. */
|
||||
provider: string
|
||||
/** Default model id. */
|
||||
model: string
|
||||
/** Parent directory for name-created Workspaces; defaults to the Host cwd. */
|
||||
workspaceRoot?: string
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/host/apiproxy/src/index.ts:32`](../packages/host/apiproxy/src/index.ts)
|
||||
Source: [`packages/host/apiproxy/src/index.ts:33`](../packages/host/apiproxy/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-host-webserver`
|
||||
|
||||
@@ -755,12 +757,12 @@ Source: [`packages/lsp/lsp-local/src/index.ts:85`](../packages/lsp/lsp-local/src
|
||||
Requires: `tools`
|
||||
|
||||
```ts config-catalog
|
||||
/** Discriminated union of all supported MCP transport configurations. */
|
||||
/** Configuration for one stdio or Streamable HTTP MCP server. */
|
||||
export type Config = StdioConfig | StreamableHttpConfig
|
||||
|
||||
/** Config for connecting to an MCP server via a spawned child process over stdio. */
|
||||
export interface StdioConfig {
|
||||
/** Transport type: spawn a child process and communicate over stdio. */
|
||||
/** Selects child-process stdio transport. */
|
||||
transport: 'stdio'
|
||||
/**
|
||||
* Stable local namespace for this server's model-facing tool names
|
||||
@@ -768,21 +770,21 @@ export interface StdioConfig {
|
||||
* unique across live mcp-client instances.
|
||||
*/
|
||||
serverName: string
|
||||
/** Executable to spawn. */
|
||||
/** Executable used to start the server. */
|
||||
command: string
|
||||
/** Arguments passed to the command. */
|
||||
/** Arguments passed directly, without shell interpolation. */
|
||||
args: string[]
|
||||
/** Extra env vars merged on top of scrubbed ambient env. */
|
||||
env: Record<string, string>
|
||||
/** Working directory for the child process. */
|
||||
cwd: string
|
||||
/** Timeout per callTool invocation (ms). */
|
||||
/** Per-tool-call timeout in milliseconds. */
|
||||
toolCallTimeoutMs: number
|
||||
}
|
||||
|
||||
/** Config for connecting to an MCP server over Streamable HTTP (SSE). */
|
||||
export interface StreamableHttpConfig {
|
||||
/** Transport type: connect to an MCP server over Streamable HTTP (SSE). */
|
||||
/** Selects Streamable HTTP transport. */
|
||||
transport: 'streamable-http'
|
||||
/**
|
||||
* Stable local namespace for this server's model-facing tool names
|
||||
@@ -790,11 +792,11 @@ export interface StreamableHttpConfig {
|
||||
* unique across live mcp-client instances.
|
||||
*/
|
||||
serverName: string
|
||||
/** MCP server URL. */
|
||||
/** MCP endpoint URL. */
|
||||
url: string
|
||||
/** Extra headers (e.g. auth tokens). */
|
||||
/** Additional headers attached to MCP requests. */
|
||||
headers: Record<string, string>
|
||||
/** Timeout per callTool invocation (ms). */
|
||||
/** Per-tool-call timeout in milliseconds. */
|
||||
toolCallTimeoutMs: number
|
||||
}
|
||||
```
|
||||
@@ -980,9 +982,9 @@ export interface Config {
|
||||
/**
|
||||
* Root directory for all session files. Required (no default): a default of
|
||||
* `process.cwd()` would scatter session files as the process's cwd changes
|
||||
* (bash calls, subprocesses). Sessions group under per-cwd subdirectories. An
|
||||
* existing root must be a readable directory; an absent root is created on
|
||||
* first materialization.
|
||||
* (bash calls, subprocesses). Sessions group under human-readable project
|
||||
* directories, then per-session directories. An existing root must be a
|
||||
* readable directory; an absent root is created on first materialization.
|
||||
*/
|
||||
root: string
|
||||
/**
|
||||
@@ -1219,7 +1221,7 @@ export interface Config {
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/storage/storage-domain/src/index.ts:45`](../packages/storage/storage-domain/src/index.ts)
|
||||
Source: [`packages/storage/storage-domain/src/index.ts:52`](../packages/storage/storage-domain/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-storage-json`
|
||||
|
||||
@@ -2026,6 +2028,7 @@ These load from a `cordis.yml` entry with no `config:` block; they declare no co
|
||||
- `@deepseek-ai/dsh-client-ui-sidebar` ([`packages/client/ui-sidebar/src/index.ts`](../packages/client/ui-sidebar/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-theme` ([`packages/client/ui-theme/src/index.ts`](../packages/client/ui-theme/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-trajectory` ([`packages/client/ui-trajectory/src/index.ts`](../packages/client/ui-trajectory/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-workspace` ([`packages/client/ui-workspace/src/index.ts`](../packages/client/ui-workspace/src/index.ts))
|
||||
- `@deepseek-ai/dsh-command-goal` — requires `commands` · `goals` ([`packages/goal/command-goal/src/index.ts`](../packages/goal/command-goal/src/index.ts))
|
||||
- `@deepseek-ai/dsh-commands` ([`packages/ui/commands/src/index.ts`](../packages/ui/commands/src/index.ts))
|
||||
- `@deepseek-ai/dsh-fs-policy` ([`packages/fs/fs-policy/src/index.ts`](../packages/fs/fs-policy/src/index.ts))
|
||||
@@ -2042,7 +2045,7 @@ These load from a `cordis.yml` entry with no `config:` block; they declare no co
|
||||
- `@deepseek-ai/dsh-tool-ask-user` — requires `tools` · `userInteraction` ([`packages/ui/tool-ask-user/src/index.ts`](../packages/ui/tool-ask-user/src/index.ts))
|
||||
- `@deepseek-ai/dsh-tool-todo` — requires `tools` ([`packages/todo/tool-todo/src/index.ts`](../packages/todo/tool-todo/src/index.ts))
|
||||
- `@deepseek-ai/dsh-user-interaction` ([`packages/ui/user-interaction/src/index.ts`](../packages/ui/user-interaction/src/index.ts))
|
||||
- `@deepseek-ai/dsh-workspace` — requires `storage` ([`packages/workspace/workspace/src/index.ts`](../packages/workspace/workspace/src/index.ts))
|
||||
- `@deepseek-ai/dsh-workspace` — requires `storageDomain` · `sessionPersistence` ([`packages/workspace/workspace/src/index.ts`](../packages/workspace/workspace/src/index.ts))
|
||||
|
||||
## Seam packages (not directly loadable)
|
||||
|
||||
@@ -2073,7 +2076,6 @@ Imported as libraries by other packages; a `cordis.yml` cannot load them.
|
||||
- `@deepseek-ai/dsh-client-web-react` ([`packages/client/web-react/src/index.ts`](../packages/client/web-react/src/index.ts))
|
||||
- `@deepseek-ai/dsh-helper` ([`packages/sdk/helper/src/index.ts`](../packages/sdk/helper/src/index.ts))
|
||||
- `@deepseek-ai/dsh-hook-protocol` ([`packages/hooks/hook-protocol/src/index.ts`](../packages/hooks/hook-protocol/src/index.ts))
|
||||
- `@deepseek-ai/dsh-host-runtime` ([`packages/host/runtime/src/index.ts`](../packages/host/runtime/src/index.ts))
|
||||
- `@deepseek-ai/dsh-jsonrpc-demo` ([`packages/examples/jsonrpc-demo/src/index.ts`](../packages/examples/jsonrpc-demo/src/index.ts))
|
||||
- `@deepseek-ai/dsh-loader-smoke` ([`packages/support/loader-smoke/src/index.ts`](../packages/support/loader-smoke/src/index.ts))
|
||||
- `@deepseek-ai/dsh-paths` ([`packages/util/paths/src/index.ts`](../packages/util/paths/src/index.ts))
|
||||
|
||||
@@ -1443,7 +1443,50 @@ mount<K extends keyof StorageForms>(form: K, facility: StorageForms[K]): () => v
|
||||
form<K extends keyof StorageForms>(form: K): StorageForms[K]
|
||||
```
|
||||
|
||||
Source: [`packages/storage/storage/src/index.ts:35`](../../packages/storage/storage/src/index.ts)
|
||||
Source: [`packages/storage/storage/src/index.ts:47`](../../packages/storage/storage/src/index.ts)
|
||||
|
||||
## `ctx.storageDomain` — `DomainFacility`
|
||||
|
||||
The mounted domain facility. Opens declared domains over routed backends; one facility instance owns the open-domain table and enforces single-open per domain name.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Open one declared domain. Steps, each failing the whole call: reject a
|
||||
* name that is already open (`already-open`); resolve the backend route
|
||||
* (`backend-not-found` passes through from the hub); require its `kv` facet
|
||||
* (`facet-unsupported`); open the unit projected from the spec (backend
|
||||
* `version-mismatch`/`malformed-medium` pass through); load and validate
|
||||
* every stored record against the spec's zod schemas (`invalid-record`
|
||||
* with the offending table and key); construct the domain.
|
||||
*
|
||||
* Lifecycle: the CALLER owns the returned handle and closes it via
|
||||
* `Domain.close()` (typically as its own `ctx.effect` disposer) — the
|
||||
* facility does not tie the domain to any consumer fiber. Domains still
|
||||
* open when the facility unmounts are closed by the plugin disposer.
|
||||
* @param spec - The domain declaration, typically from `defineDomain`.
|
||||
* @returns the opened domain handle, typed by the spec.
|
||||
*/
|
||||
async open<S extends DomainSpec>(spec: S): Promise<Domain<S>>
|
||||
|
||||
/**
|
||||
* Look up an open domain by name, untyped. Diagnostic surface (the package
|
||||
* invariant cross-checks change events against live domain state); typed
|
||||
* consumers hold the handle returned by {@link open}.
|
||||
* @param name - Domain name.
|
||||
* @returns the open domain runtime, or `undefined` when not open.
|
||||
*/
|
||||
get(name: string): DomainImpl | undefined
|
||||
|
||||
/**
|
||||
* Close every domain still open on this facility. The unmount path for
|
||||
* consumers that never called `Domain.close()` themselves; closing is
|
||||
* idempotent, so double-closing an already-closed domain is harmless.
|
||||
* @returns resolution after every unit is released.
|
||||
*/
|
||||
async closeAll(): Promise<void>
|
||||
```
|
||||
|
||||
Source: [`packages/storage/storage-domain/src/index.ts:69`](../../packages/storage/storage-domain/src/index.ts)
|
||||
|
||||
## `ctx.subagents` — `SubagentService`
|
||||
|
||||
@@ -1907,49 +1950,59 @@ Source: [`packages/workflow/workflow/src/index.ts:159`](../../packages/workflow/
|
||||
|
||||
## `ctx.workspace` — `WorkspaceRegistry`
|
||||
|
||||
The workspace registry service. Opens the `workspace` domain at startup, rebuilds one entity per stored record, and serves entities from an in-memory cache keyed by id. Session persistence is an OPTIONAL peer (resolved via `ctx.get`, never injected): while it is absent, session attachment rejects (what cannot be validated is not recorded) and `sessionIds` projections serve the account unfiltered.
|
||||
|
||||
There is deliberately no delete entry point in this phase: workspace deletion ships as one complete semantic together with the session-cascade primitives (future work in the owning Agent Note).
|
||||
Durable workspace registry. Startup waits for `sessionPersistence`, builds one canonical-cwd header index, and completes the one-time history bootstrap before the service becomes active. The persistence dependency is mandatory so an unavailable peer can never be mistaken for an empty history and commit the initialized marker.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Create a workspace over an existing directory. The path is canonicalized
|
||||
* through `fs.realpath` first — a nonexistent path rejects with the
|
||||
* original `ENOENT`, a path resolving to anything but a directory rejects,
|
||||
* and a canonical path already owned by another workspace (including a
|
||||
* symlink resolving to it) rejects.
|
||||
* @param path - Directory the workspace points at; canonicalized before storing.
|
||||
* @param title - Display title; defaults to `basename` of the canonical path.
|
||||
* @returns the created workspace after durability.
|
||||
* Create or reuse a workspace for an existing directory. The path is
|
||||
* canonicalized through `fs.realpath`; a nonexistent path rejects with the
|
||||
* original error and a non-directory rejects. Repeated calls for the same
|
||||
* canonical path return the existing entity without changing its title.
|
||||
* A newly created workspace is prepended to the durable registry order.
|
||||
* A different canonical path cannot create a duplicate display title.
|
||||
* @param path - Existing directory to own, in any path spelling.
|
||||
* @param title - Display title used only when a new record is created.
|
||||
* @returns the existing or newly durable workspace.
|
||||
*/
|
||||
async create(path: string, title?: string): Promise<Workspace>
|
||||
|
||||
/**
|
||||
* Look up a workspace by id.
|
||||
* @param id - The workspace id.
|
||||
* @param id - Workspace id.
|
||||
* @returns the workspace, or `undefined` when unknown.
|
||||
*/
|
||||
get(id: WorkspaceId): Workspace | undefined
|
||||
|
||||
/**
|
||||
* Snapshot of all workspaces, in load-then-creation order.
|
||||
* @returns a fresh array of the cached entities.
|
||||
* Synchronous workspace projection in durable registry order. Every
|
||||
* entity's `sessionIds` getter is already filtered by the startup/live
|
||||
* canonical-cwd header index; this method performs no persistence reads.
|
||||
* @returns a fresh ordered array of workspace entities.
|
||||
*/
|
||||
list(): Workspace[]
|
||||
|
||||
/**
|
||||
* Resolve a workspace by directory path, through the same `fs.realpath`
|
||||
* canon as {@link create} (hence async). A path that does not exist rejects
|
||||
* with the original error — a missing directory has no canonical form to
|
||||
* compare (a workspace whose recorded directory vanished is only reachable
|
||||
* by id; see `Workspace.status`).
|
||||
* @param path - Directory path in any spelling (symlinks, `..`, trailing slash).
|
||||
* @returns the owning workspace, or `undefined` when none matches.
|
||||
* Move one accounted, cwd-validated session to the front of its workspace.
|
||||
* Ungrouped sessions and candidates filtered by the header check are
|
||||
* no-ops. The owning workspace's relative position never changes.
|
||||
* @param sessionId - Session whose activity was observed.
|
||||
* @returns resolution after the possible record write.
|
||||
*/
|
||||
async touchSession(sessionId: SessionId): Promise<void>
|
||||
|
||||
/**
|
||||
* Resolve by canonical directory path without creating or mutating a
|
||||
* workspace. A missing path rejects during `realpath`; an existing unowned
|
||||
* directory returns `undefined`.
|
||||
* @param path - Existing directory path in any spelling.
|
||||
* @returns the workspace owning the canonical path, when one exists.
|
||||
*/
|
||||
async resolveByPath(path: string): Promise<Workspace | undefined>
|
||||
```
|
||||
|
||||
Source: [`packages/workspace/workspace/src/index.ts:60`](../../packages/workspace/workspace/src/index.ts)
|
||||
Types: [SessionId](../core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/workspace/workspace/src/index.ts:75`](../../packages/workspace/workspace/src/index.ts)
|
||||
|
||||
## Inherited `ctx` members (cordis core + loader/hmr/timer)
|
||||
|
||||
|
||||
@@ -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
|
||||
llm-streaming.md: cb99c935aea2dc9cc769e3056fdb98a2e5c9eacb
|
||||
llm-streaming.zh.md: 740fa1f796088e63d0195cfbecf975adb236381c
|
||||
llm-streaming.md: fb97e74a9ec01e62ba940295112fb157cc73bd1d
|
||||
llm-streaming.zh.md: fda59a64aeef1c037372d69dbc15ee0de48de222
|
||||
|
||||
@@ -63,6 +63,7 @@ Every adapter MUST obey these, and every consumer may rely on them:
|
||||
- **One adapter call is one provider attempt.** Adapters disable library retries. Agent-level recovery opens another durable numbered step; direct `ctx.llm.stream()` callers remain single-attempt.
|
||||
- **Provider stalls are bounded at the transport.** Both shipping remote adapters expose positive finite `streamIdleTimeoutMs` with a five-minute default. The watchdog arms only while iterator `next()` is outstanding, uses one stable signal for the whole request, maps its own expiry to `TIMEOUT`, and keeps an earlier caller abort as `ABORTED`.
|
||||
- **Context overflow has one canonical code.** Both DeepSeek adapters classify explicit provider detail through `isContextWindowExceededError()` and surface `CONTEXT_WINDOW_EXCEEDED`, whether the failure arrives as a thrown HTTP `LlmError` or an in-band finish error. Consumers route on the code, never provider text.
|
||||
- **An empty completion is a retryable error, not a silent success.** Both adapters map a terminal `stop` finish that carried no content blocks to `finish {kind:'error'}` with the canonical `EMPTY_RESPONSE` code, and `dsh-llm-retry` retries it by default; see [empty model responses are retryable](../../.agents/notes/implemented/bug-fix/2026-07-24-empty-model-response-is-retryable.md).
|
||||
- **Every provider HTTP request carries the app-attribution header.** Adapters send `attributionHeaders()` (below) - the `User-Agent` baseline - and prove it with a wire-level test (mock server asserting the received header, or the library's header hook for a library-backed adapter).
|
||||
- **Replay state is adapter-owned.** A successful `finish` may carry lossless-JSON state needed to reconstruct a native provider response. The loop stores it with the assembled assistant message unless an `agent/step-result` listener rewrote the content. On a later request, `LlmService` passes the state only when the historical provider and target provider are currently registered to the exact same adapter instance. That adapter validates the state and owns any cross-model or cross-provider conversion; other adapters receive the provider-neutral content and provenance without the private state.
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ interface LlmFailure {
|
||||
- **一次适配器调用就是一次提供方尝试。** 适配器禁用库重试。agent 层恢复会打开另一个持久、带编号的步骤;直接调用 `ctx.llm.stream()` 的调用方仍然只尝试一次。
|
||||
- **提供方停顿在传输层受到时限约束。** 两个已交付的远程适配器都暴露正数且有限的 `streamIdleTimeoutMs`,默认五分钟。watchdog 只在 iterator `next()` 尚未完成时启动,整个请求使用同一个稳定 signal,把自身到期映射为 `TIMEOUT`,并把更早发生的调用方中止保留为 `ABORTED`。
|
||||
- **上下文溢出只有一个规范 code。** 两个 DeepSeek 适配器都通过 `isContextWindowExceededError()` 对提供方的显式细节分类并暴露 `CONTEXT_WINDOW_EXCEEDED`,无论失败以抛出的 HTTP `LlmError` 还是带内 finish error 到达。消费方按 code 路由,绝不依赖提供方文本。
|
||||
- **空 completion 是可重试错误,而不是静默的成功结果。** 两个适配器都把没有携带任何内容块的终止性 `stop` 结束映射为携带规范 `EMPTY_RESPONSE` code 的 `finish {kind:'error'}`,`dsh-llm-retry` 默认会重试它;详见[空模型响应可重试](../../.agents/notes/implemented/bug-fix/2026-07-24-empty-model-response-is-retryable.md)。
|
||||
- **每个提供方 HTTP 请求都携带应用归属头。** 适配器发送 `attributionHeaders()`(见下文)作为 `User-Agent` 基线,并通过协议级测试加以证明(mock 服务器断言收到的 header,或对基于库的适配器使用库的 header 钩子)。
|
||||
- **回放状态归适配器所有。** 成功的 `finish` 可以携带重建提供方原生响应所需的无损 JSON 状态。除非 `agent/step-result` listener 改写了内容,否则循环会将其与组装后的 assistant 消息一起存储。后续请求中,仅当历史提供方与目标提供方当前注册到完全相同的适配器实例时,`LlmService` 才会传递该状态。该适配器负责校验状态并拥有所有跨模型或跨提供方转换;其他适配器只会收到提供方无关的内容与 provenance,不会收到私有状态。
|
||||
|
||||
|
||||
@@ -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
|
||||
persistence.md: dc497fd85f44660c0a981579351b5cfbe0040a4d
|
||||
persistence.zh.md: 5236f4fe2ba8ad1be7e74bffafebfea19014d7aa
|
||||
persistence.md: b03cc07d2e514b3900d4035ea386f31c761470a7
|
||||
persistence.zh.md: 3030ff2fe949cb02385331800d826df227e3d6cd
|
||||
|
||||
@@ -20,7 +20,7 @@ Repair applies only to cold sessions. For a live id, `SessionPersistence.load(id
|
||||
|
||||
## `SessionLocation` — optional per-session artifact target
|
||||
|
||||
`SessionPersistence.locate(meta)` synchronously resolves a backend-owned independent artifact without reading, creating, or flushing it. JSONL returns its absolute target path; SQLite returns `undefined` because sessions share one database. A returned path can therefore name a file that does not yet exist or lacks the current unflushed turn; it is a location hint, not authorization or a freshness guarantee.
|
||||
`SessionPersistence.locate(meta)` synchronously resolves a backend-owned independent artifact without reading, creating, or flushing it. JSONL returns the absolute transcript path inside its project/session directory; SQLite returns `undefined` because sessions share one database. A returned path can therefore name a file that does not yet exist or lacks the current unflushed turn; it is a location hint, not authorization or a freshness guarantee.
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
## `SessionLocation`——可选的逐会话产物目标
|
||||
|
||||
`SessionPersistence.locate(meta)` 会同步解析一个归后端所有的独立产物,而不会读取、创建或 flush 它。JSONL 返回其绝对目标路径;SQLite 因各会话共享一个数据库而返回 `undefined`。因此,返回的路径可能指向尚不存在、或还不包含当前尚未 flush 的轮次;它是位置提示,不是授权或新鲜度保证。
|
||||
`SessionPersistence.locate(meta)` 会同步解析一个归后端所有的独立产物,而不会读取、创建或 flush 它。JSONL 返回其项目/会话目录内 transcript(文本记录)的绝对路径;SQLite 因各会话共享一个数据库而返回 `undefined`。因此,返回的路径可能指向尚不存在、或还不包含当前尚未 flush 的轮次;它是位置提示,不是授权或新鲜度保证。
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
subagent.md: 0335a3f0780ae17b57ae730f5a49a269261c8073
|
||||
subagent.zh.md: dac48b624f6e0cfc28737e3e1a2774ba2d97e85b
|
||||
subagent.md: 2497dbab9cfc8304eb7aaeba7109404ac614bbff
|
||||
subagent.zh.md: 2d96e9bc635951746e72ed58a7c3638dc2598cc2
|
||||
|
||||
@@ -19,16 +19,13 @@ A provider advertises its **start-time** features on a static descriptor the ser
|
||||
* is rejected with a typed error rather than accepted-then-ignored (the "fail loud, no silent
|
||||
* degradation" rule). These static flags cover features needed before a run exists; runtime
|
||||
* capabilities such as steering and resume are optional {@link SubagentRun} methods whose presence
|
||||
* is the capability.
|
||||
* is the capability. Each flag corresponds one-to-one to a {@link SubagentStartRequest} option:
|
||||
* `depthLimit` to `maxDepth`; the other names match.
|
||||
*/
|
||||
interface SubagentCapabilities {
|
||||
/** Honor {@link SubagentStartRequest.outputSchema} (structured final output). */
|
||||
readonly outputSchema: boolean
|
||||
/** Enforce {@link SubagentStartRequest.maxDepth} (recursion cap). */
|
||||
readonly depthLimit: boolean
|
||||
/** Enforce {@link SubagentStartRequest.toolFilter} (child tool scoping). */
|
||||
readonly toolFilter: boolean
|
||||
/** Honor {@link SubagentStartRequest.persona} (a per-child persona). */
|
||||
readonly persona: boolean
|
||||
}
|
||||
```
|
||||
@@ -45,16 +42,12 @@ The tool layer builds this request from the model input and its own config; the
|
||||
* passes it to {@link SubagentProvider.start}.
|
||||
*/
|
||||
interface SubagentStartRequest {
|
||||
/** The task/prompt for the child agent (a user message in the child session). */
|
||||
/** Content delivered as the child's user message. */
|
||||
readonly prompt: ContentBlock[]
|
||||
/**
|
||||
* The spawning ("parent") agent — the one whose tool call started this
|
||||
* subagent. REQUIRED: in-process backends read `parent.session.header` for
|
||||
* the working directory, the `parentSession` lineage to stamp on the child,
|
||||
* and the parent's delegation depth. The out-of-process backend (ACP) reads
|
||||
* exactly one field — the session header's cwd, the child's workspace when
|
||||
* no deployment `cwd` override is configured; nothing else crosses the
|
||||
* process boundary.
|
||||
* The spawning agent. In-process providers derive workspace, lineage, and
|
||||
* delegation depth from its durable session state. ACP reads only its cwd,
|
||||
* and only when no deployment `cwd` override is configured.
|
||||
*/
|
||||
readonly parent: Agent
|
||||
/**
|
||||
@@ -65,7 +58,6 @@ interface SubagentStartRequest {
|
||||
* afterward.
|
||||
*/
|
||||
readonly signal: AbortSignal
|
||||
/** Per-child agent options (model and plugin-defined extension fields). */
|
||||
readonly agentOptions?: AgentOptions
|
||||
/**
|
||||
* Object-rooted JSON Schema within `assertObjectJsonSchema`'s enforced subset. Start rejects
|
||||
@@ -137,9 +129,9 @@ interface SubagentResult {
|
||||
interface SubagentStopReasonMap {
|
||||
/** The child finished its turn normally. */
|
||||
completed: 'completed'
|
||||
/** The run was cancelled by its request signal or by disposal. */
|
||||
/** Cancelled through the request signal or disposal. */
|
||||
aborted: 'aborted'
|
||||
/** The child failed (model error, transport error). */
|
||||
/** Model or transport failure. */
|
||||
error: 'error'
|
||||
/** The child hit its token ceiling before finishing. */
|
||||
'max-tokens': 'max-tokens'
|
||||
@@ -180,9 +172,8 @@ interface SubagentRun {
|
||||
*/
|
||||
readonly result: Promise<SubagentResult>
|
||||
/**
|
||||
* Cancel remaining work, reach child quiescence, and release the run's
|
||||
* resources (in-process: dispose the owned agent and remove its session;
|
||||
* ACP: kill and reap the subprocess). Idempotent.
|
||||
* Cancel remaining work, reach child quiescence, and release resources.
|
||||
* Idempotent.
|
||||
*/
|
||||
dispose(): Promise<void>
|
||||
/**
|
||||
@@ -206,12 +197,9 @@ Each provider is a named child-agent transport, and multiple providers may coexi
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
* A subagent backend: one transport for running a child agent (in-process
|
||||
* spawn/fork, ACP to another process, …). Implementations register under a
|
||||
* unique name via {@link SubagentService.registerProvider}; multiple providers
|
||||
* coexist in one context (unlike the single-implementation bash seam). The
|
||||
* Providers are trusted same-process implementations; callers treat their
|
||||
* descriptors and returned values as borrowed immutable data.
|
||||
* One registered transport for running child agents. Providers are trusted
|
||||
* same-process implementations; callers treat descriptors and returned values
|
||||
* as borrowed immutable data.
|
||||
*/
|
||||
interface SubagentProvider {
|
||||
/** Unique registry name (e.g. `spawn`, `fork`, `acp`). */
|
||||
|
||||
@@ -19,16 +19,13 @@ subagent seam:一个 agent(智能体)将工作委派给子 agent。与 [ba
|
||||
* is rejected with a typed error rather than accepted-then-ignored (the "fail loud, no silent
|
||||
* degradation" rule). These static flags cover features needed before a run exists; runtime
|
||||
* capabilities such as steering and resume are optional {@link SubagentRun} methods whose presence
|
||||
* is the capability.
|
||||
* is the capability. Each flag corresponds one-to-one to a {@link SubagentStartRequest} option:
|
||||
* `depthLimit` to `maxDepth`; the other names match.
|
||||
*/
|
||||
interface SubagentCapabilities {
|
||||
/** Honor {@link SubagentStartRequest.outputSchema} (structured final output). */
|
||||
readonly outputSchema: boolean
|
||||
/** Enforce {@link SubagentStartRequest.maxDepth} (recursion cap). */
|
||||
readonly depthLimit: boolean
|
||||
/** Enforce {@link SubagentStartRequest.toolFilter} (child tool scoping). */
|
||||
readonly toolFilter: boolean
|
||||
/** Honor {@link SubagentStartRequest.persona} (a per-child persona). */
|
||||
readonly persona: boolean
|
||||
}
|
||||
```
|
||||
@@ -45,16 +42,12 @@ interface SubagentCapabilities {
|
||||
* passes it to {@link SubagentProvider.start}.
|
||||
*/
|
||||
interface SubagentStartRequest {
|
||||
/** The task/prompt for the child agent (a user message in the child session). */
|
||||
/** Content delivered as the child's user message. */
|
||||
readonly prompt: ContentBlock[]
|
||||
/**
|
||||
* The spawning ("parent") agent — the one whose tool call started this
|
||||
* subagent. REQUIRED: in-process backends read `parent.session.header` for
|
||||
* the working directory, the `parentSession` lineage to stamp on the child,
|
||||
* and the parent's delegation depth. The out-of-process backend (ACP) reads
|
||||
* exactly one field — the session header's cwd, the child's workspace when
|
||||
* no deployment `cwd` override is configured; nothing else crosses the
|
||||
* process boundary.
|
||||
* The spawning agent. In-process providers derive workspace, lineage, and
|
||||
* delegation depth from its durable session state. ACP reads only its cwd,
|
||||
* and only when no deployment `cwd` override is configured.
|
||||
*/
|
||||
readonly parent: Agent
|
||||
/**
|
||||
@@ -65,7 +58,6 @@ interface SubagentStartRequest {
|
||||
* afterward.
|
||||
*/
|
||||
readonly signal: AbortSignal
|
||||
/** Per-child agent options (model and plugin-defined extension fields). */
|
||||
readonly agentOptions?: AgentOptions
|
||||
/**
|
||||
* Object-rooted JSON Schema within `assertObjectJsonSchema`'s enforced subset. Start rejects
|
||||
@@ -137,9 +129,9 @@ interface SubagentResult {
|
||||
interface SubagentStopReasonMap {
|
||||
/** The child finished its turn normally. */
|
||||
completed: 'completed'
|
||||
/** The run was cancelled by its request signal or by disposal. */
|
||||
/** Cancelled through the request signal or disposal. */
|
||||
aborted: 'aborted'
|
||||
/** The child failed (model error, transport error). */
|
||||
/** Model or transport failure. */
|
||||
error: 'error'
|
||||
/** The child hit its token ceiling before finishing. */
|
||||
'max-tokens': 'max-tokens'
|
||||
@@ -182,9 +174,8 @@ interface SubagentRun {
|
||||
*/
|
||||
readonly result: Promise<SubagentResult>
|
||||
/**
|
||||
* Cancel remaining work, reach child quiescence, and release the run's
|
||||
* resources (in-process: dispose the owned agent and remove its session;
|
||||
* ACP: kill and reap the subprocess). Idempotent.
|
||||
* Cancel remaining work, reach child quiescence, and release resources.
|
||||
* Idempotent.
|
||||
*/
|
||||
dispose(): Promise<void>
|
||||
/**
|
||||
@@ -208,12 +199,9 @@ interface SubagentRun {
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
* A subagent backend: one transport for running a child agent (in-process
|
||||
* spawn/fork, ACP to another process, …). Implementations register under a
|
||||
* unique name via {@link SubagentService.registerProvider}; multiple providers
|
||||
* coexist in one context (unlike the single-implementation bash seam). The
|
||||
* Providers are trusted same-process implementations; callers treat their
|
||||
* descriptors and returned values as borrowed immutable data.
|
||||
* One registered transport for running child agents. Providers are trusted
|
||||
* same-process implementations; callers treat descriptors and returned values
|
||||
* as borrowed immutable data.
|
||||
*/
|
||||
interface SubagentProvider {
|
||||
/** Unique registry name (e.g. `spawn`, `fork`, `acp`). */
|
||||
|
||||
@@ -28,7 +28,7 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `agent/turn-stop` | `serial` | [`packages/core/agent/src/types.ts:485`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`subagent-inprocess`](../packages/subagent/subagent-inprocess), [`tool-goal`](../packages/goal/tool-goal) |
|
||||
| `approval/request` | `waterfall` | [`packages/ui/user-approval/src/index.ts:30`](../packages/ui/user-approval/src/index.ts) | [`user-approval`](../packages/ui/user-approval) (`waterfall`) | [`acp`](../packages/acp/acp) |
|
||||
| `commands/change` | `emit` | [`packages/ui/commands/src/index.ts:103`](../packages/ui/commands/src/index.ts) | [`commands`](../packages/ui/commands) (`events.dispatch`) | [`tui`](../packages/ui/tui) |
|
||||
| `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`) | [`storage-domain`](../packages/storage/storage-domain), [`workspace`](../packages/workspace/workspace) |
|
||||
| `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:62`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`) | [`fs-policy`](../packages/fs/fs-policy) |
|
||||
| `fs/observed` | `emit` | [`packages/fs/fs/src/index.ts:71`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`emit`) | [`fs-policy`](../packages/fs/fs-policy) |
|
||||
| `fs/write-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:54`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`) | [`fs-policy`](../packages/fs/fs-policy) |
|
||||
@@ -36,7 +36,7 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `llm/stream` | `waterfall` | [`packages/llm/llm/src/index.ts:52`](../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-persistence/session-checkpoint-policy), [`session-title`](../packages/session-title/session-title) |
|
||||
| `session/created` | `emit` | [`packages/core/session/src/index.ts:79`](../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), [`jsonrpc`](../packages/ui/jsonrpc), [`llm-retry`](../packages/llm/llm-retry), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`user-approval`](../packages/ui/user-approval) |
|
||||
| `session/disposed` | `emit` | [`packages/core/session/src/index.ts:89`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), `apiproxy`, [`session-persistence`](../packages/session-persistence/session-persistence), [`session-title`](../packages/session-title/session-title) |
|
||||
| `session/event` | `emit` | [`packages/core/session/src/index.ts:101`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`acp`](../packages/acp/acp), `apiproxy`, [`cli-demo`](../packages/examples/cli-demo), [`compact`](../packages/compact/compact), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`jsonrpc`](../packages/ui/jsonrpc), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-title`](../packages/session-title/session-title), [`token-meter`](../packages/llm/token-meter), [`tui`](../packages/ui/tui), [`user-approval`](../packages/ui/user-approval), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `session/event` | `emit` | [`packages/core/session/src/index.ts:101`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`acp`](../packages/acp/acp), `apiproxy`, [`cli-demo`](../packages/examples/cli-demo), [`compact`](../packages/compact/compact), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`jsonrpc`](../packages/ui/jsonrpc), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-title`](../packages/session-title/session-title), [`token-meter`](../packages/llm/token-meter), [`tui`](../packages/ui/tui), [`user-approval`](../packages/ui/user-approval), [`workspace`](../packages/workspace/workspace), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `session/flush` | `parallel` | [`packages/core/session/src/index.ts:111`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`session-persistence`](../packages/session-persistence/session-persistence) |
|
||||
| `subagent/end` | `emit` | [`packages/subagent/subagent/src/index.ts:139`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`jsonrpc`](../packages/ui/jsonrpc), [`subagent`](../packages/subagent/subagent) |
|
||||
| `subagent/provider-added` | `emit` | [`packages/subagent/subagent/src/index.ts:113`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`emit`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
|
||||
@@ -147,6 +147,7 @@ flowchart TD
|
||||
pkg_client_ui_slots["client-ui-slots"]
|
||||
pkg_client_ui_theme["client-ui-theme"]
|
||||
pkg_client_ui_trajectory["client-ui-trajectory"]
|
||||
pkg_client_ui_workspace["client-ui-workspace"]
|
||||
pkg_client_web["client-web"]
|
||||
pkg_client_web_react["client-web-react"]
|
||||
end
|
||||
@@ -171,7 +172,6 @@ flowchart TD
|
||||
end
|
||||
subgraph group_host["packages/host"]
|
||||
pkg_host_apiproxy["host-apiproxy"]
|
||||
pkg_host_runtime["host-runtime"]
|
||||
pkg_host_webserver["host-webserver"]
|
||||
end
|
||||
subgraph group_lsp["packages/lsp"]
|
||||
@@ -238,7 +238,6 @@ flowchart TD
|
||||
pkg_code_runtime --> pkg_invariants
|
||||
pkg_jsonrpc_demo --> pkg_invariants
|
||||
pkg_host_apiproxy --> pkg_invariants
|
||||
pkg_host_runtime --> pkg_invariants
|
||||
pkg_host_webserver --> pkg_invariants
|
||||
pkg_storage --> pkg_invariants
|
||||
pkg_llm --> pkg_brand
|
||||
@@ -259,6 +258,10 @@ flowchart TD
|
||||
pkg_client_ui_sidebar --> pkg_client_ui_primitives
|
||||
pkg_client_ui_sidebar --> pkg_client_ui_slots
|
||||
pkg_client_ui_sidebar --> pkg_invariants
|
||||
pkg_client_ui_workspace --> pkg_client_runtime
|
||||
pkg_client_ui_workspace --> pkg_client_ui_primitives
|
||||
pkg_client_ui_workspace --> pkg_client_ui_slots
|
||||
pkg_client_ui_workspace --> pkg_invariants
|
||||
pkg_helper --> pkg_brand
|
||||
pkg_helper --> pkg_invariants
|
||||
pkg_telemetry --> pkg_brand
|
||||
@@ -808,7 +811,6 @@ flowchart TD
|
||||
| [`code-runtime`](../packages/code-runtime/code-runtime) | `code-runtime` | [`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-runtime`](../packages/host/runtime) | `host` | [`invariants`](../packages/support/invariants) |
|
||||
| [`host-webserver`](../packages/host/webserver) | `host` | [`invariants`](../packages/support/invariants) |
|
||||
| [`storage`](../packages/storage/storage) | `storage` | [`invariants`](../packages/support/invariants) |
|
||||
| [`llm`](../packages/llm/llm) | `llm` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants) |
|
||||
@@ -817,6 +819,7 @@ flowchart TD
|
||||
| [`client-ui-conversation`](../packages/client/ui-conversation) | `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-layout`](../packages/client/ui-layout) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-sidebar`](../packages/client/ui-sidebar) | `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-workspace`](../packages/client/ui-workspace) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`helper`](../packages/sdk/helper) | `sdk` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants) |
|
||||
| [`telemetry`](../packages/sdk/telemetry) | `sdk` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths) |
|
||||
| [`storage-domain`](../packages/storage/storage-domain) | `storage` | [`invariants`](../packages/support/invariants), [`storage`](../packages/storage/storage) |
|
||||
|
||||
Reference in New Issue
Block a user