Merge remote-tracking branch 'upstream/master' into feat/gui-full-access-confirmation
# Conflicts: # packages/client/ui-primitives/src/Modal.tsx # packages/client/ui-primitives/tests/atoms.spec.tsx
This commit is contained in:
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/architecture.md
|
||||
architecture.md: 1fd9bd128d1bcc0dd91d46131981ea4fc331bd74
|
||||
architecture.zh.md: 8521f09c6e415f9f8d1c0a44f7534b59c876decc
|
||||
architecture.md: bfea67b9f83958e16b58e63b99e326349f6eff15
|
||||
architecture.zh.md: c2fd6cdd84ad2f6435faebffa0c4c1a6da0ade96
|
||||
|
||||
@@ -46,6 +46,8 @@ Harnesses are [Cordis](cordis-primer.md) contexts; packages contribute services,
|
||||
| `ctx.sessionPersistence` | [`session-persistence/`](../packages/session-persistence/README.md) | durable session-log storage |
|
||||
| `ctx.sessionQuery` | [`session-query/`](../packages/session-query/README.md) | live-preferred exact/filter/trace queries over SQLite FTS, workspace-authorized model tools |
|
||||
| `ctx.sessionTitle` | [`session-title/`](../packages/session-title/README.md) | log-backed fallbacks, one optional asynchronous provider |
|
||||
| `ctx.settings` | [`settings/`](../packages/settings/README.md) | per-plugin user-settings namespaces layered over composition entries |
|
||||
| `ctx.credentials` | [`credentials/`](../packages/credentials/README.md) | named secret references resolved per operation, never inlined in configuration |
|
||||
| `ctx.directoryPicker` | [`host/directory-picker`](../packages/host/directory-picker/README.md) | GUI-host directory picking (`native`/`browse` interactions) |
|
||||
| `ctx.typert` | [`typert/registry`](../packages/typert/registry/README.md) | runtime registry for generated package reflection and live Zod schemas |
|
||||
| `ctx.invariants` | [`support/invariants`](../packages/support/invariants/README.md) | package-name-selected registry of package-owned runtime checks |
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
| `ctx.sessionPersistence` | [`session-persistence/`](../packages/session-persistence/README.md) | 会话日志的持久化存储 |
|
||||
| `ctx.sessionQuery` | [`session-query/`](../packages/session-query/README.md) | 基于 SQLite 全文搜索的实时优先精确检索/过滤/追踪、经工作区授权的模型工具 |
|
||||
| `ctx.sessionTitle` | [`session-title/`](../packages/session-title/README.md) | 基于日志的回退标题和单个可选异步提供方 |
|
||||
| `ctx.settings` | [`settings/`](../packages/settings/README.md) | 按插件划分的用户设置命名空间,分层叠加在装配条目之上 |
|
||||
| `ctx.credentials` | [`credentials/`](../packages/credentials/README.md) | 具名密钥引用,按操作解析,绝不内联进配置 |
|
||||
| `ctx.directoryPicker` | [`host/directory-picker`](../packages/host/directory-picker/README.md) | GUI 宿主目录选取(`native`/`browse` 交互) |
|
||||
| `ctx.typert` | [`typert/registry`](../packages/typert/registry/README.md) | 生成的包反射和实时 Zod schema 的运行时注册表 |
|
||||
| `ctx.invariants` | [`support/invariants`](../packages/support/invariants/README.md) | 按包名筛选包自有运行时检查的注册表 |
|
||||
|
||||
@@ -41,6 +41,10 @@ flowchart LR
|
||||
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"]
|
||||
@@ -52,7 +56,6 @@ flowchart LR
|
||||
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"]
|
||||
pkg_tool_session_query["tool-session-query"]
|
||||
@@ -174,6 +177,8 @@ flowchart LR
|
||||
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
|
||||
@@ -258,6 +263,9 @@ flowchart LR
|
||||
svc_codeRuntime --> pkg_tools
|
||||
svc_commands --> pkg_tui
|
||||
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_fs --> pkg_tool_fs
|
||||
svc_httpServer --> pkg_connection
|
||||
@@ -296,6 +304,9 @@ flowchart LR
|
||||
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
|
||||
@@ -346,7 +357,8 @@ flowchart LR
|
||||
| `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.typert` | `core` | [`typert-registry`](../packages/typert/registry) | - | [`typert-loader`](../packages/typert/loader) | - | Plugins register live zod contributions directly or through dsh-typert-loader; runtime consumers query schemas and reflection metadata at their own edges. |
|
||||
| `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.settings` | `seam` | [`settings`](../packages/settings/settings) | [`settings-local`](../packages/settings/settings-local) | - | - | Plugins register namespace schemas and resolve layered values; providers store the raw document. No production consumer is migrated yet. |
|
||||
| `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` | - | Plugins register namespace schemas and resolve layered values; providers store the raw document. The LLM adapters register their entry config as the composition base under the user section; the web gateway serves redacted layered descriptors and writes the user layer. |
|
||||
| `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` | - | Configuration carries references to secrets; providers own the values. Consumers resolve per operation, so a rotated credential reaches the very next request; the web gateway exposes value-free views and write-only storage. |
|
||||
| `ctx.telemetry` | `seam` | [`session-telemetry`](../packages/telemetry/session-telemetry) | [`session-telemetry-otel`](../packages/telemetry/session-telemetry-otel) | - | - | The seam captures, redacts, and hands session records to one backend; nothing else consumes the service — its output leaves the process. |
|
||||
| `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. |
|
||||
|
||||
@@ -407,6 +407,24 @@ export interface ToolResultPruneConfig {
|
||||
|
||||
Source: [`packages/compact/compact-tool-result-prune/src/types.ts:4`](../packages/compact/compact-tool-result-prune/src/types.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-credentials-local`
|
||||
|
||||
```ts config-catalog
|
||||
/** Plugin config: file location and hot-reload behavior. */
|
||||
export interface Config {
|
||||
/** Credentials document path; defaults to `.env` under the harness home. */
|
||||
path?: string
|
||||
/** Harness home used when `path` is omitted; defaults to `$DSH_HOME` or `~/.dsh`. */
|
||||
dshHome?: string
|
||||
/** Watch the document and hot-publish external edits; defaults to true. */
|
||||
watch?: boolean
|
||||
/** Watcher write-settle window in milliseconds; defaults to 100. */
|
||||
debounceMs?: number
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/credentials/credentials-local/src/index.ts:26`](../packages/credentials/credentials-local/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-fs-local`
|
||||
|
||||
```ts config-catalog
|
||||
@@ -602,15 +620,18 @@ Requires: `llm`
|
||||
|
||||
```ts config-catalog
|
||||
/**
|
||||
* Plugin config, validated by the same-named schemastery schema. Every field
|
||||
* is optional in yml: credentials/endpoint fall back to the environment (a
|
||||
* missing API key fails plugin load, not the first call), omitted thinking
|
||||
* mode uses the provider default, and omitted reasoning effort resolves to
|
||||
* `high`.
|
||||
* Plugin config, validated by the same-named schemastery schema and doubling
|
||||
* as the `llm-deepseek` settings-section shape. Every field is optional in
|
||||
* yml: a missing API key resolves through {@link Config.apiKeyEnv} at each
|
||||
* request (a request without any key fails with `MISSING_CREDENTIAL`, not at
|
||||
* plugin load), omitted thinking mode uses the provider default, and omitted
|
||||
* reasoning effort resolves to `high`.
|
||||
*/
|
||||
export interface Config {
|
||||
/** API key; falls back to $DEEPSEEK_API_KEY. Required one way or the other. */
|
||||
/** Literal API key; prefer {@link apiKeyEnv} so no secret enters configuration files. */
|
||||
apiKey?: string
|
||||
/** Credential reference (environment-variable name) resolved per request; defaults to `DEEPSEEK_API_KEY`. */
|
||||
apiKeyEnv?: string
|
||||
/** Endpoint base; falls back to $DEEPSEEK_BASE_URL, then the public API. */
|
||||
baseURL?: string
|
||||
/** Deployment thinking policy; `disabled` limits every conversation request to `off`. */
|
||||
@@ -642,25 +663,29 @@ export interface DeepSeekCatalogModel {
|
||||
|
||||
Depends on: [`RetryPolicyConfig`](../packages/llm/llm/src/index.ts)
|
||||
|
||||
Source: [`packages/llm/llm-deepseek/src/index.ts:36`](../packages/llm/llm-deepseek/src/index.ts)
|
||||
Source: [`packages/llm/llm-deepseek/src/index.ts:50`](../packages/llm/llm-deepseek/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-llm-pi-ai`
|
||||
|
||||
Requires: `llm`
|
||||
|
||||
```ts config-catalog
|
||||
/** Plugin configuration: the non-empty provider profiles this instance owns. */
|
||||
/** Plugin configuration: the provider routes this instance owns. */
|
||||
export interface Config {
|
||||
/** Non-empty set of pi-ai provider routes this adapter instance owns. */
|
||||
providers: PiAiProviderProfile[]
|
||||
/**
|
||||
* pi-ai provider routes, keyed by provider. An empty (or omitted) dict is
|
||||
* the dormant settings-driven posture: the adapter mounts with no routes
|
||||
* and registers them the moment a settings section supplies profiles.
|
||||
*/
|
||||
providers?: Record<string, PiAiProviderProfile>
|
||||
}
|
||||
|
||||
/** Configuration for one pi-ai provider route. */
|
||||
/** Configuration for one pi-ai provider route; the `providers` dict key IS the route. */
|
||||
export interface PiAiProviderProfile {
|
||||
/** pi-ai provider catalog name and Harness route key. */
|
||||
provider: string
|
||||
/** Provider credential; when absent pi-ai uses its provider-native ambient discovery. */
|
||||
/** Literal provider credential; prefer {@link apiKeyEnv}. With both absent pi-ai uses its provider-native ambient discovery. */
|
||||
apiKey?: string
|
||||
/** Credential reference (environment-variable name) resolved per request through `ctx.credentials`. */
|
||||
apiKeyEnv?: string
|
||||
/** Override the selected catalog model's endpoint without changing its protocol metadata. */
|
||||
baseURL?: string
|
||||
/** Provider request headers; Harness attribution wins reserved names. */
|
||||
@@ -686,7 +711,7 @@ export interface PiAiProviderProfile {
|
||||
|
||||
Depends on: `CacheRetention` (`@earendil-works/pi-ai`) · `ModelThinkingLevel` (`@earendil-works/pi-ai`) · [`RetryPolicyConfig`](../packages/llm/llm/src/index.ts) · `ThinkingBudgets` (`@earendil-works/pi-ai`) · `Transport` (`@earendil-works/pi-ai`)
|
||||
|
||||
Source: [`packages/llm/llm-pi-ai/src/config.ts:54`](../packages/llm/llm-pi-ai/src/config.ts)
|
||||
Source: [`packages/llm/llm-pi-ai/src/config.ts:62`](../packages/llm/llm-pi-ai/src/config.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-llm-replay`
|
||||
|
||||
@@ -1484,7 +1509,7 @@ export interface Config {
|
||||
* fails.
|
||||
*/
|
||||
cwd?: string
|
||||
/** Provider route the child runtime initializes with (default `deepseek`). */
|
||||
/** Provider route the child runtime initializes with (default `deepseek-official`). */
|
||||
provider: string
|
||||
/** Model the child runtime initializes with (default `deepseek-v4-flash`). */
|
||||
model: string
|
||||
@@ -2298,6 +2323,7 @@ Abstract service classes — a deployment loads a concrete implementation packag
|
||||
- `@deepseek-ai/dsh-bash` — abstract `BashExecutor` ([`packages/bash/bash/src/index.ts`](../packages/bash/bash/src/index.ts))
|
||||
- `@deepseek-ai/dsh-code-runtime` — abstract `CodeRuntime` ([`packages/code-runtime/code-runtime/src/index.ts`](../packages/code-runtime/code-runtime/src/index.ts))
|
||||
- `@deepseek-ai/dsh-compact` — abstract `CompactService` ([`packages/compact/compact/src/index.ts`](../packages/compact/compact/src/index.ts))
|
||||
- `@deepseek-ai/dsh-credentials` — abstract `Credentials` ([`packages/credentials/credentials/src/index.ts`](../packages/credentials/credentials/src/index.ts))
|
||||
- `@deepseek-ai/dsh-fs` — abstract `FileSystem` ([`packages/fs/fs/src/index.ts`](../packages/fs/fs/src/index.ts))
|
||||
- `@deepseek-ai/dsh-host-directory-picker` — abstract `DirectoryPicker` ([`packages/host/directory-picker/src/index.ts`](../packages/host/directory-picker/src/index.ts))
|
||||
- `@deepseek-ai/dsh-sandbox` — abstract `SandboxProvider` ([`packages/sandbox/sandbox/src/index.ts`](../packages/sandbox/sandbox/src/index.ts))
|
||||
@@ -2317,7 +2343,9 @@ Imported as libraries by other packages; a `cordis.yml` cannot load them.
|
||||
- `@deepseek-ai/dsh-acp-snapshot` ([`packages/support/acp-snapshot/src/index.ts`](../packages/support/acp-snapshot/src/index.ts))
|
||||
- `@deepseek-ai/dsh-agent-loop-testkit` ([`packages/support/agent-loop-testkit/src/index.ts`](../packages/support/agent-loop-testkit/src/index.ts))
|
||||
- `@deepseek-ai/dsh-app-boot` ([`packages/ui/app-boot/src/index.ts`](../packages/ui/app-boot/src/index.ts))
|
||||
- `@deepseek-ai/dsh-atomic-write` ([`packages/util/atomic-write/src/index.ts`](../packages/util/atomic-write/src/index.ts))
|
||||
- `@deepseek-ai/dsh-brand` ([`packages/util/brand/src/index.ts`](../packages/util/brand/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-schema-form` ([`packages/client/schema-form/src/index.ts`](../packages/client/schema-form/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-test-runtime` ([`packages/client/test-runtime/src/index.ts`](../packages/client/test-runtime/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-primitives` ([`packages/client/ui-primitives/src/index.ts`](../packages/client/ui-primitives/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-ui-slots` ([`packages/client/ui-slots/src/index.ts`](../packages/client/ui-slots/src/index.ts))
|
||||
|
||||
@@ -439,6 +439,32 @@ A command was registered or unregistered. This is an unfiltered registry notific
|
||||
|
||||
Source: [`packages/ui/commands/src/index.ts:154`](../../packages/ui/commands/src/index.ts)
|
||||
|
||||
## `credentials/*`
|
||||
|
||||
### `credentials/updated` — emit
|
||||
|
||||
Committed change to a provider-managed credential source: a `set`, an `unset`, or an external edit observed in storage. Ambient process-environment changes are not observable and never emit. Listener failures are contained and logged — a sync throw and an async rejection alike — without changing the committed operation's outcome, except `INVARIANT`-coded failures, which rethrow after every listener ran; that rethrow reaches the emitter only from synchronous listeners, so invariant checks on this event must not be async functions.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Committed change to a provider-managed credential source: a `set`, an
|
||||
* `unset`, or an external edit observed in storage. Ambient
|
||||
* process-environment changes are not observable and never emit. Listener
|
||||
* failures are contained and logged — a sync throw and an async rejection
|
||||
* alike — without changing the committed operation's outcome, except
|
||||
* `INVARIANT`-coded failures, which rethrow after every listener ran;
|
||||
* that rethrow reaches the emitter only from synchronous listeners, so
|
||||
* invariant checks on this event must not be async functions.
|
||||
* @param ref - the reference whose stored value changed.
|
||||
* @mode emit
|
||||
*/
|
||||
'credentials/updated'(ref: CredentialRef): void
|
||||
```
|
||||
|
||||
Types: [CredentialRef](../core-data-structures/credentials.md)
|
||||
|
||||
Source: [`packages/credentials/credentials/src/index.ts:67`](../../packages/credentials/credentials/src/index.ts)
|
||||
|
||||
## `domain/*`
|
||||
|
||||
### `domain/changed` — emit
|
||||
@@ -545,6 +571,25 @@ Source: [`packages/goal/goal/src/domain.ts:135`](../../packages/goal/goal/src/do
|
||||
|
||||
## `llm/*`
|
||||
|
||||
### `llm/adapters-updated` — emit
|
||||
|
||||
The provider topology changed: an adapter registered or unregistered routes, or the configurable-provider directory gained or lost entries. This is a payload-free registry notification fired at each commit point (including registration disposal); consumers re-read `listProviders()`, `listModels()`, or `listConfigurableProviders()` for the new state. Observer failures are contained and cannot veto the registry mutation.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* The provider topology changed: an adapter registered or unregistered
|
||||
* routes, or the configurable-provider directory gained or lost entries.
|
||||
* This is a payload-free registry notification fired at each commit point
|
||||
* (including registration disposal); consumers re-read `listProviders()`,
|
||||
* `listModels()`, or `listConfigurableProviders()` for the new state.
|
||||
* Observer failures are contained and cannot veto the registry mutation.
|
||||
* @mode emit
|
||||
*/
|
||||
'llm/adapters-updated'(): void
|
||||
```
|
||||
|
||||
Source: [`packages/llm/llm/src/index.ts:70`](../../packages/llm/llm/src/index.ts)
|
||||
|
||||
### `llm/stream` — waterfall
|
||||
|
||||
Waterfall around every streaming model call (retry, replay, routing). Bound to the LlmService; call `next()` to reach the resolved adapter's stream, or yield your own chunks to short-circuit.
|
||||
@@ -567,7 +612,7 @@ Waterfall around every streaming model call (retry, replay, routing). Bound to t
|
||||
|
||||
Types: [GenerateOptions](../core-data-structures/core.md) · [LlmService](../core-data-structures/llm-streaming.md) · [StreamChunk](../core-data-structures/llm-streaming.md)
|
||||
|
||||
Source: [`packages/llm/llm/src/index.ts:58`](../../packages/llm/llm/src/index.ts)
|
||||
Source: [`packages/llm/llm/src/index.ts:59`](../../packages/llm/llm/src/index.ts)
|
||||
|
||||
## `session/*`
|
||||
|
||||
@@ -661,6 +706,29 @@ Source: [`packages/core/session/src/index.ts:103`](../../packages/core/session/s
|
||||
|
||||
## `settings/*`
|
||||
|
||||
### `settings/document-updated` — emit
|
||||
|
||||
One registered namespace's RAW user section changed, whether or not the resolved value did. `settings/updated` is the consumer-facing event and stays deep-equal-gated; this one exists for configuration surfaces, which must learn that a field went from inherited to overridden (same resolved value, different meaning) and that their held revision is stale. Listener containment matches `settings/updated`.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* One registered namespace's RAW user section changed, whether or not the
|
||||
* resolved value did. `settings/updated` is the consumer-facing event and
|
||||
* stays deep-equal-gated; this one exists for configuration surfaces,
|
||||
* which must learn that a field went from inherited to overridden (same
|
||||
* resolved value, different meaning) and that their held revision is
|
||||
* stale. Listener containment matches `settings/updated`.
|
||||
* @param ns - the namespace whose stored section changed.
|
||||
* @param revision - the namespace's new revision.
|
||||
* @mode emit
|
||||
*/
|
||||
'settings/document-updated'(ns: SettingsNamespace, revision: number): void
|
||||
```
|
||||
|
||||
Types: [SettingsNamespace](../core-data-structures/settings.md)
|
||||
|
||||
Source: [`packages/settings/settings/src/index.ts:150`](../../packages/settings/settings/src/index.ts)
|
||||
|
||||
### `settings/updated` — emit
|
||||
|
||||
Committed change to one registered namespace's resolved value. Emitted after the provider persisted (for `update`) or published (`provider`) the change; never emitted when the resolved value is deep-equal. Listener failures are contained and logged — a sync throw and an async rejection alike — except `INVARIANT`-coded failures, which rethrow after every listener ran; that rethrow reaches the emitter only from synchronous listeners, so invariant checks on this event must not be async functions.
|
||||
@@ -686,7 +754,7 @@ Committed change to one registered namespace's resolved value. Emitted after the
|
||||
|
||||
Types: [SettingsNamespace](../core-data-structures/settings.md) · [SettingsUpdateSource](../core-data-structures/settings.md)
|
||||
|
||||
Source: [`packages/settings/settings/src/index.ts:108`](../../packages/settings/settings/src/index.ts)
|
||||
Source: [`packages/settings/settings/src/index.ts:137`](../../packages/settings/settings/src/index.ts)
|
||||
|
||||
## `skills/*`
|
||||
|
||||
|
||||
@@ -488,6 +488,52 @@ Types: [CompactionResult](../core-data-structures/compaction.md) · [CompactionT
|
||||
|
||||
Source: [`packages/compact/compact/src/index.ts:54`](../../packages/compact/compact/src/index.ts)
|
||||
|
||||
## `ctx.credentials` — `Credentials` (abstract seam)
|
||||
|
||||
Abstract credential service. Providers implement the four operations over their source layers; one seam-wide rule binds them all: an empty stored value is absent everywhere — `resolve` skips it, `describe` reports it unconfigured — so a blank never masquerades as a configured secret.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Resolve one reference to its current value. Resolution is per call:
|
||||
* consumers re-resolve at each operation and must not cache across
|
||||
* operations — that per-operation read is what makes a changed credential
|
||||
* reach the next operation without a restart.
|
||||
* @param ref - the reference to resolve.
|
||||
* @returns the value and its source, or `undefined` while unconfigured.
|
||||
*/
|
||||
abstract resolve(ref: CredentialRef): Promise<ResolvedCredential | undefined>
|
||||
|
||||
/**
|
||||
* Describe one reference for configuration surfaces without exposing the
|
||||
* value.
|
||||
* @param ref - the reference to describe.
|
||||
* @returns configured state, supplying source, and writability.
|
||||
*/
|
||||
abstract describe(ref: CredentialRef): Promise<CredentialInfo>
|
||||
|
||||
/**
|
||||
* Durably store one value in the provider-managed writable source. Rejects
|
||||
* while a read-only source shadows the reference — the write would appear
|
||||
* to succeed while resolution keeps returning the shadowing value — and
|
||||
* rejects an empty value (use {@link unset}).
|
||||
* @param ref - the reference to store.
|
||||
* @param value - the non-empty secret value.
|
||||
*/
|
||||
abstract set(ref: CredentialRef, value: string): Promise<void>
|
||||
|
||||
/**
|
||||
* Remove one reference from the provider-managed writable source; removing
|
||||
* an absent reference is a no-op. Rejects while a read-only source shadows
|
||||
* the reference, like {@link set}.
|
||||
* @param ref - the reference to remove.
|
||||
*/
|
||||
abstract unset(ref: CredentialRef): Promise<void>
|
||||
```
|
||||
|
||||
Types: [CredentialInfo](../core-data-structures/credentials.md) · [CredentialRef](../core-data-structures/credentials.md) · [ResolvedCredential](../core-data-structures/credentials.md)
|
||||
|
||||
Source: [`packages/credentials/credentials/src/index.ts:77`](../../packages/credentials/credentials/src/index.ts)
|
||||
|
||||
## `ctx.directoryPicker` — `DirectoryPicker` (abstract seam)
|
||||
|
||||
Abstract directory-picking service. Subclass, implement `capability()`, and load the subclass as a plugin — it registers as `ctx.directoryPicker` (one implementation per context; loading a second throws, cordis' standard duplicate-service behavior). The capability object must be stable for the service lifetime: consumers may capture it across calls.
|
||||
@@ -744,9 +790,9 @@ The abstract `llm` service: an adapter registry plus a streaming model-call surf
|
||||
* Disposed with the fiber.
|
||||
* @param providers - every provider route this adapter should serve.
|
||||
* @param adapter - the adapter that streams calls for those providers.
|
||||
* @returns the disposer that unregisters all of them.
|
||||
* @returns the disposer, carrying {@link AdapterRegistrationHandle.replace}.
|
||||
*/
|
||||
registerAdapter(providers: string[], adapter: LlmAdapter): () => void
|
||||
registerAdapter(providers: string[], adapter: LlmAdapter): AdapterRegistrationHandle
|
||||
|
||||
/**
|
||||
* Describe provider routes with a registered adapter.
|
||||
@@ -754,6 +800,22 @@ registerAdapter(providers: string[], adapter: LlmAdapter): () => void
|
||||
*/
|
||||
listProviders(): LlmProviderInfo[]
|
||||
|
||||
/**
|
||||
* Declare provider routes an adapter plugin can activate through
|
||||
* configuration. Registration is all-or-nothing: an empty list, invalid
|
||||
* entry, or a provider already declared by any registration throws
|
||||
* `LlmError` without registering the rest. Disposed with the fiber.
|
||||
* @param entries - every configurable provider this plugin owns.
|
||||
* @returns the disposer that withdraws all of them.
|
||||
*/
|
||||
registerConfigurableProviders(entries: readonly LlmConfigurableProvider[]): () => void
|
||||
|
||||
/**
|
||||
* List every declared configurable provider, registered or dormant.
|
||||
* @returns detached directory entries in declaration order.
|
||||
*/
|
||||
listConfigurableProviders(): LlmConfigurableProvider[]
|
||||
|
||||
/**
|
||||
* Resolve the retry policy captured when one provider route was registered.
|
||||
* @param provider - registered provider route to inspect.
|
||||
@@ -818,9 +880,9 @@ async prepareCall(config: LlmCallConfig, signal?: AbortSignal): Promise<Prepared
|
||||
stream(options: GenerateOptions): AsyncIterable<StreamChunk>
|
||||
```
|
||||
|
||||
Types: [GenerateOptions](../core-data-structures/core.md) · [LlmAdapter](../core-data-structures/llm-streaming.md) · [LlmCallConfig](../core-data-structures/core.md) · [LlmModelInfo](../core-data-structures/core.md) · [LlmProviderInfo](../core-data-structures/core.md) · [LlmResolvedModelInfo](../core-data-structures/core.md) · [PreparedLlmCall](../core-data-structures/llm-streaming.md) · [ResolvedRetryPolicy](../core-data-structures/llm-streaming.md) · [StreamChunk](../core-data-structures/llm-streaming.md)
|
||||
Types: [AdapterRegistrationHandle](../core-data-structures/core.md) · [GenerateOptions](../core-data-structures/core.md) · [LlmAdapter](../core-data-structures/llm-streaming.md) · [LlmCallConfig](../core-data-structures/core.md) · [LlmConfigurableProvider](../core-data-structures/core.md) · [LlmModelInfo](../core-data-structures/core.md) · [LlmProviderInfo](../core-data-structures/core.md) · [LlmResolvedModelInfo](../core-data-structures/core.md) · [PreparedLlmCall](../core-data-structures/llm-streaming.md) · [ResolvedRetryPolicy](../core-data-structures/llm-streaming.md) · [StreamChunk](../core-data-structures/llm-streaming.md)
|
||||
|
||||
Source: [`packages/llm/llm/src/index.ts:191`](../../packages/llm/llm/src/index.ts)
|
||||
Source: [`packages/llm/llm/src/index.ts:227`](../../packages/llm/llm/src/index.ts)
|
||||
|
||||
## `ctx.permission` — `PermissionService`
|
||||
|
||||
@@ -1657,10 +1719,13 @@ Abstract settings service. Providers implement raw-document storage (`load`/`per
|
||||
register<T>(ns: SettingsNamespace, schema: z<T>, options?: SettingsRegisterOptions<T>): SettingsScope<T>
|
||||
|
||||
/**
|
||||
* Describe every registered namespace for configuration surfaces.
|
||||
* Describe every registered namespace for configuration surfaces, including
|
||||
* the composition `base` and raw user layers so a form can mark which fields
|
||||
* the user overrode (presence in `user`) and what a reset returns to.
|
||||
* @param options - redaction switch; wire surfaces must redact.
|
||||
* @returns one descriptor per registered namespace, in registration order.
|
||||
*/
|
||||
describe(): SettingsDescriptor[]
|
||||
describe(options?: SettingsDescribeOptions): SettingsDescriptor[]
|
||||
|
||||
/**
|
||||
* Read one registered namespace's resolved value.
|
||||
@@ -1677,8 +1742,10 @@ get(ns: SettingsNamespace): unknown
|
||||
* merging over the previous write's committed section.
|
||||
* @param ns - the registered namespace to update.
|
||||
* @param patch - plain-object patch over the user section.
|
||||
* @param expectedRevision - the descriptor `revision` the caller read; a
|
||||
* namespace that moved past it rejects with {@link SettingsConflictError}.
|
||||
*/
|
||||
async update(ns: SettingsNamespace, patch: object): Promise<void>
|
||||
async update(ns: SettingsNamespace, patch: object, expectedRevision?: number): Promise<void>
|
||||
|
||||
/**
|
||||
* Replace one registered namespace's user section wholesale, validate,
|
||||
@@ -1687,13 +1754,29 @@ async update(ns: SettingsNamespace, patch: object): Promise<void>
|
||||
* merge-only patch cannot express (`replace({})` re-inherits everything).
|
||||
* @param ns - the registered namespace to replace.
|
||||
* @param section - the complete next user section.
|
||||
* @param expectedRevision - the descriptor `revision` the caller read; a
|
||||
* namespace that moved past it rejects with {@link SettingsConflictError}.
|
||||
*/
|
||||
async replace(ns: SettingsNamespace, section: object): Promise<void>
|
||||
async replace(ns: SettingsNamespace, section: object, expectedRevision?: number): Promise<void>
|
||||
|
||||
/**
|
||||
* Apply path-addressed edits to one registered namespace's user section,
|
||||
* validate, persist, then commit and emit. The ops are applied to the
|
||||
* section as it stands when the write reaches the front of the queue, so a
|
||||
* caller never has to restate fields it did not touch — and, crucially,
|
||||
* cannot delete fields it never saw. This is the write path for any caller
|
||||
* holding a redacted view; `replace` remains the wholesale reset.
|
||||
* @param ns - the registered namespace to edit.
|
||||
* @param ops - ordered path edits; later ops observe earlier ones.
|
||||
* @param expectedRevision - the descriptor `revision` the caller read; a
|
||||
* namespace that moved past it rejects with {@link SettingsConflictError}.
|
||||
*/
|
||||
async mutate(ns: SettingsNamespace, ops: readonly SettingsPathOp[], expectedRevision?: number): Promise<void>
|
||||
```
|
||||
|
||||
Types: [SettingsDescriptor](../core-data-structures/settings.md) · [SettingsNamespace](../core-data-structures/settings.md) · [SettingsRegisterOptions](../core-data-structures/settings.md) · [SettingsScope](../core-data-structures/settings.md)
|
||||
Types: [SettingsDescribeOptions](../core-data-structures/settings.md) · [SettingsDescriptor](../core-data-structures/settings.md) · [SettingsNamespace](../core-data-structures/settings.md) · [SettingsPathOp](../core-data-structures/settings.md) · [SettingsRegisterOptions](../core-data-structures/settings.md) · [SettingsScope](../core-data-structures/settings.md)
|
||||
|
||||
Source: [`packages/settings/settings/src/index.ts:250`](../../packages/settings/settings/src/index.ts)
|
||||
Source: [`packages/settings/settings/src/index.ts:365`](../../packages/settings/settings/src/index.ts)
|
||||
|
||||
## `ctx.skills` — `SkillService`
|
||||
|
||||
|
||||
@@ -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/core-data-structures/core.md
|
||||
core.md: a12e96b4156b4ccd8f6f0c453224ed57d6040966
|
||||
core.zh.md: ac10c801bde8898ebd3393b05a94cc63627e1b89
|
||||
core.md: 7176a6949211566c5f162bc3289189d047c6fc85
|
||||
core.zh.md: de06529d602fc0871688d0b8e038c8d1c3ac2ef7
|
||||
|
||||
@@ -25,6 +25,7 @@ Everything else is documented on a **sub-page**, not here. The rule that draws t
|
||||
| [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 |
|
||||
| [system-prompt.md](system-prompt.md) | per-assembly context, tool-provider results, prompt sections, and cooperative assembly |
|
||||
@@ -182,6 +183,34 @@ Source: [`packages/llm/llm/src/types.ts`](../../packages/llm/llm/src/types.ts)
|
||||
|
||||
Provider and model discovery uses small provider-neutral descriptors. A model catalog is advisory: routing still keys on a registered provider, and an adapter may accept unlisted model ids.
|
||||
|
||||
Registering an adapter returns a handle: the disposer, plus the atomic route replacement a plugin whose route set is user-configurable needs.
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
* What {@link LlmService.registerAdapter} returns: the disposer, plus an
|
||||
* atomic route replacement for the same adapter instance.
|
||||
*/
|
||||
interface AdapterRegistrationHandle {
|
||||
/** Release every route this registration currently holds. */
|
||||
(): void
|
||||
/**
|
||||
* Replace this registration's routes with `providers`, keeping the same
|
||||
* adapter instance. The candidate set is validated in full first — a
|
||||
* conflict with another adapter, an invalid name, or bad provider metadata
|
||||
* throws and leaves the current routes untouched — and the swap itself is
|
||||
* one synchronous section, so no request can observe a gap. An empty array
|
||||
* is legal here (a settings section that emptied holds zero routes while
|
||||
* staying registered), unlike an empty initial registration.
|
||||
*
|
||||
* Throws `LlmError` with code `REGISTRATION_DISPOSED` once the registration
|
||||
* has been released: its routes are gone and its disposer has already run,
|
||||
* so anything registered afterwards would have no owner left to release it.
|
||||
* @param providers - the complete next route set for this registration.
|
||||
*/
|
||||
replace(providers: string[]): void
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
/** Display metadata for one registered provider route. */
|
||||
interface LlmProviderInfo {
|
||||
@@ -192,6 +221,30 @@ interface LlmProviderInfo {
|
||||
}
|
||||
```
|
||||
|
||||
Adapter plugins additionally declare which routes *could* run through `registerConfigurableProviders()`, addressing each one's user-settings section, so configuration surfaces can offer dormant providers before any route registers.
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
* One provider route an adapter plugin can activate through configuration,
|
||||
* whether or not the route is currently registered. Configuration surfaces
|
||||
* merge this directory with `listProviders()` to offer every configurable
|
||||
* provider alongside its live/dormant state.
|
||||
*/
|
||||
interface LlmConfigurableProvider {
|
||||
/** Provider route key this entry activates when configured. */
|
||||
provider: string
|
||||
/** Human-readable provider name for configuration surfaces. */
|
||||
displayName: string
|
||||
/** User-settings namespace whose section configures this provider. */
|
||||
settingsNs: string
|
||||
/**
|
||||
* Path from that namespace's section root to this provider's profile
|
||||
* object; empty when the whole section is the profile.
|
||||
*/
|
||||
settingsPath: readonly string[]
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
/** One adapter-discovered model; catalog membership is advisory, not request validation. */
|
||||
interface LlmModelInfo {
|
||||
|
||||
@@ -25,6 +25,7 @@ harness 是一个微内核:一个极小的核心加上众多插件。大多数
|
||||
| [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 与异步提供方契约 |
|
||||
| [system-prompt.md](system-prompt.md) | 逐次组装的上下文、工具提供方结果、提示词段落与协作式组装 |
|
||||
@@ -188,6 +189,34 @@ interface MessageSourceMap {
|
||||
|
||||
提供方与模型发现使用小型、提供方无关的描述符。模型目录仅供参考:路由仍以已注册提供方为键,适配器也可以接受未列出的模型 id。
|
||||
|
||||
注册适配器会返回一个句柄:既是释放器,也带有原子的路由替换——路由集合由用户配置决定的插件正需要它。
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
* What {@link LlmService.registerAdapter} returns: the disposer, plus an
|
||||
* atomic route replacement for the same adapter instance.
|
||||
*/
|
||||
interface AdapterRegistrationHandle {
|
||||
/** Release every route this registration currently holds. */
|
||||
(): void
|
||||
/**
|
||||
* Replace this registration's routes with `providers`, keeping the same
|
||||
* adapter instance. The candidate set is validated in full first — a
|
||||
* conflict with another adapter, an invalid name, or bad provider metadata
|
||||
* throws and leaves the current routes untouched — and the swap itself is
|
||||
* one synchronous section, so no request can observe a gap. An empty array
|
||||
* is legal here (a settings section that emptied holds zero routes while
|
||||
* staying registered), unlike an empty initial registration.
|
||||
*
|
||||
* Throws `LlmError` with code `REGISTRATION_DISPOSED` once the registration
|
||||
* has been released: its routes are gone and its disposer has already run,
|
||||
* so anything registered afterwards would have no owner left to release it.
|
||||
* @param providers - the complete next route set for this registration.
|
||||
*/
|
||||
replace(providers: string[]): void
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
/** Display metadata for one registered provider route. */
|
||||
interface LlmProviderInfo {
|
||||
@@ -198,6 +227,30 @@ interface LlmProviderInfo {
|
||||
}
|
||||
```
|
||||
|
||||
适配器插件还会通过 `registerConfigurableProviders()` 声明哪些路由*可以*运行,并指明每条路由的用户设置分节,使配置界面能在任何路由注册之前就呈现休眠的提供方。
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
* One provider route an adapter plugin can activate through configuration,
|
||||
* whether or not the route is currently registered. Configuration surfaces
|
||||
* merge this directory with `listProviders()` to offer every configurable
|
||||
* provider alongside its live/dormant state.
|
||||
*/
|
||||
interface LlmConfigurableProvider {
|
||||
/** Provider route key this entry activates when configured. */
|
||||
provider: string
|
||||
/** Human-readable provider name for configuration surfaces. */
|
||||
displayName: string
|
||||
/** User-settings namespace whose section configures this provider. */
|
||||
settingsNs: string
|
||||
/**
|
||||
* Path from that namespace's section root to this provider's profile
|
||||
* object; empty when the whole section is the profile.
|
||||
*/
|
||||
settingsPath: readonly string[]
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
/** One adapter-discovered model; catalog membership is advisory, not request validation. */
|
||||
interface LlmModelInfo {
|
||||
|
||||
6
docs/core-data-structures/credentials.i18n.yaml
Normal file
6
docs/core-data-structures/credentials.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/core-data-structures/credentials.md
|
||||
credentials.md: 3f6fcd127d01e2c49e17c70c002bebe9f363e951
|
||||
credentials.zh.md: b5d2d9e164a85ce090790635c438b768cae4c9ca
|
||||
50
docs/core-data-structures/credentials.md
Normal file
50
docs/core-data-structures/credentials.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# User Credentials
|
||||
|
||||
English | [中文](credentials.zh.md)
|
||||
|
||||
The credential seam of [dsh-credentials](../../packages/credentials/credentials) keeps secrets out of configuration: settings sections and `cordis.yml` entries carry *references* (environment-variable names), providers such as [dsh-credentials-local](../../packages/credentials/credentials-local) own the values, and consumers resolve a reference once per operation — the LLM adapters resolve once per model request, so a rotated credential reaches the very next request without any restart. One seam-wide rule binds every provider: an empty stored value is absent everywhere.
|
||||
|
||||
Source: [`packages/credentials/credentials/src/index.ts`](../../packages/credentials/credentials/src/index.ts)
|
||||
|
||||
## Identity
|
||||
|
||||
A reference names one credential as a POSIX-style environment-variable name. The brand keeps references from mixing with other cross-boundary strings; construction validates the shell-identifier shape.
|
||||
|
||||
```ts type-equiv
|
||||
/** Nominal reference to one credential: a POSIX-style environment-variable name. */
|
||||
type CredentialRef = Branded<'CredentialRef'>
|
||||
```
|
||||
|
||||
## Resolution
|
||||
|
||||
`resolve(ref)` returns the value with the provider-defined source layer that supplied it, or `undefined` while unconfigured. Consumers re-resolve at each operation and never cache across operations — that per-operation read is the hot-update mechanism.
|
||||
|
||||
```ts type-equiv
|
||||
/** One resolved credential value and the source layer that supplied it. */
|
||||
interface ResolvedCredential {
|
||||
/** The non-empty secret value. */
|
||||
value: string
|
||||
/** Provider-defined source layer id (the local provider uses `env` and `file`). */
|
||||
source: string
|
||||
}
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
`describe(ref)` answers configuration surfaces without ever exposing a value: whether the reference resolves, from which layer, and whether `set` would currently succeed. The local provider reports a reference supplied by the live process environment as `writable: false` — a write would appear to succeed while resolution kept returning the shadowing value, so the seam rejects it and the UI can render the reference read-only up front.
|
||||
|
||||
```ts type-equiv
|
||||
/** Source and writability facts for one reference, safe for configuration UIs — never the value. */
|
||||
interface CredentialInfo {
|
||||
/** Whether {@link Credentials.resolve} would currently return a value. */
|
||||
configured: boolean
|
||||
/** Source layer currently supplying the value; absent while unconfigured. */
|
||||
source?: string
|
||||
/** Whether {@link Credentials.set} would currently succeed for this reference. */
|
||||
writable: boolean
|
||||
}
|
||||
```
|
||||
|
||||
## Change commits
|
||||
|
||||
`credentials/updated (ref)` fires after a committed change to a provider-managed source — a `set`, an `unset`, or an external edit observed in storage. Ambient process-environment changes are not observable and never emit. Consumers do not need the event (they re-resolve per operation); it exists for configuration surfaces refreshing a "configured" badge.
|
||||
50
docs/core-data-structures/credentials.zh.md
Normal file
50
docs/core-data-structures/credentials.zh.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# 用户凭据
|
||||
|
||||
[English](credentials.md) | 中文
|
||||
|
||||
[dsh-credentials](../../packages/credentials/credentials) 的凭据 seam 把机密挡在配置之外:settings 分节与 `cordis.yml` 条目携带的是*引用*(环境变量名),值归 [dsh-credentials-local](../../packages/credentials/credentials-local) 这类 provider 所有,消费方每个操作解析一次引用——LLM 适配器每次模型请求解析一次,因此轮换后的凭据无需任何重启即可作用于紧随其后的下一次请求。一条 seam 级规则约束每个 provider:空的存储值在任何地方都视为不存在。
|
||||
|
||||
Source: [`packages/credentials/credentials/src/index.ts`](../../packages/credentials/credentials/src/index.ts)
|
||||
|
||||
## 标识
|
||||
|
||||
引用以 POSIX 风格环境变量名命名一条凭据。brand 使引用不与其他跨边界字符串混用;构造时校验 shell 标识符形态。
|
||||
|
||||
```ts type-equiv
|
||||
/** Nominal reference to one credential: a POSIX-style environment-variable name. */
|
||||
type CredentialRef = Branded<'CredentialRef'>
|
||||
```
|
||||
|
||||
## 解析
|
||||
|
||||
`resolve(ref)` 返回值,连同供出该值、由 provider 定义的来源层;未配置期间返回 `undefined`。消费方在每个操作中重新解析,绝不跨操作缓存——这次按操作进行的读取正是热更新机制。
|
||||
|
||||
```ts type-equiv
|
||||
/** One resolved credential value and the source layer that supplied it. */
|
||||
interface ResolvedCredential {
|
||||
/** The non-empty secret value. */
|
||||
value: string
|
||||
/** Provider-defined source layer id (the local provider uses `env` and `file`). */
|
||||
source: string
|
||||
}
|
||||
```
|
||||
|
||||
## 描述
|
||||
|
||||
`describe(ref)` 在绝不暴露值的前提下回应配置界面:引用当前是否可解析、来自哪一层、`set` 当前能否成功。本地 provider 把由活跃进程环境供值的引用报告为 `writable: false`——那样的写入会表面成功而解析持续返回遮蔽值,因此 seam 直接拒绝,界面也得以提前把该引用渲染为只读。
|
||||
|
||||
```ts type-equiv
|
||||
/** Source and writability facts for one reference, safe for configuration UIs — never the value. */
|
||||
interface CredentialInfo {
|
||||
/** Whether {@link Credentials.resolve} would currently return a value. */
|
||||
configured: boolean
|
||||
/** Source layer currently supplying the value; absent while unconfigured. */
|
||||
source?: string
|
||||
/** Whether {@link Credentials.set} would currently succeed for this reference. */
|
||||
writable: boolean
|
||||
}
|
||||
```
|
||||
|
||||
## 变更提交
|
||||
|
||||
`credentials/updated (ref)` 在 provider 管理的来源发生已提交变更后触发——`set`、`unset` 或在存储中观察到的外部编辑。进程环境自身的变化不可观测,永不发出事件。消费方不需要该事件(它们按操作重新解析);它服务于配置界面刷新「已配置」徽标。
|
||||
@@ -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/core-data-structures/settings.md
|
||||
settings.md: 381b36b3ff2f45a2090a2a2eac0f700bd00270c4
|
||||
settings.zh.md: bc6547db3b05c5a78f112462ae205d848f93da60
|
||||
settings.md: 1cabfae5d8dc72a9cd79341d250ee79820693872
|
||||
settings.zh.md: d63a1384646fa38199e7d65e9f0504f0440597be
|
||||
|
||||
@@ -73,7 +73,7 @@ interface SettingsScope<T> {
|
||||
|
||||
## Descriptors
|
||||
|
||||
`describe()` serializes every registered namespace for configuration surfaces: the schemastery `toJSON()` envelope drives schema-rendered forms, and the resolved value fills them.
|
||||
`describe()` serializes every registered namespace for configuration surfaces: the schemastery `toJSON()` envelope drives schema-rendered forms, the resolved value fills them, and the detached `base`/`user` layers let a form mark user-overridden fields by presence. `describe({ redactSecrets: true })` — mandatory on every wire surface — strips `role('secret')` fields from all three layers and enumerates their `{path, set}` slots so a page can render write-only inputs without ever receiving a secret.
|
||||
|
||||
```ts type-equiv
|
||||
/** One registered namespace as surfaced to configuration UIs. */
|
||||
@@ -84,8 +84,49 @@ interface SettingsDescriptor {
|
||||
schema: unknown
|
||||
/** Current resolved value. */
|
||||
value: unknown
|
||||
/**
|
||||
* Monotonic revision of the raw user section this descriptor was read at.
|
||||
* Send it back as `expectedRevision` on a write to refuse a stale one.
|
||||
*/
|
||||
revision: number
|
||||
/** Registrant's composition `base` layer (detached), when one was declared. */
|
||||
base?: unknown
|
||||
/**
|
||||
* Raw user section from the stored document (detached), when one exists and
|
||||
* is well-formed; a field's presence here is what marks it user-overridden.
|
||||
*/
|
||||
user?: unknown
|
||||
/** Owner's declared effect timing. */
|
||||
applies: SettingsApplies
|
||||
/** Schema-declared secret positions; present only under `redactSecrets`. */
|
||||
secrets?: RedactedSecret[]
|
||||
}
|
||||
```
|
||||
|
||||
A caller that holds only the redacted descriptor cannot safely rebuild a section, so removals travel as path ops instead. Each descriptor also carries a `revision` over the raw section; a write may send it back as `expectedRevision`, and one that no longer matches is refused rather than applied over the writer that landed first.
|
||||
```ts type-equiv
|
||||
/**
|
||||
* One path-addressed edit to a namespace's user section. Path mutation exists
|
||||
* for a caller holding an INCOMPLETE view of the section — a configuration UI
|
||||
* reads the redacted descriptor, which by construction never received the
|
||||
* `role('secret')` fields. Such a caller can name the field it means without
|
||||
* restating the section: a wholesale `replace` rebuilt from a redacted
|
||||
* document silently deletes every secret the wire never returned.
|
||||
*/
|
||||
type SettingsPathOp =
|
||||
| { op: 'set'; path: readonly string[]; value: unknown }
|
||||
| { op: 'unset'; path: readonly string[] }
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
/** Options for {@link Settings.describe}. */
|
||||
interface SettingsDescribeOptions {
|
||||
/**
|
||||
* Strip `role('secret')` fields from `value`/`base`/`user` and enumerate
|
||||
* them in each descriptor's `secrets`. Every wire surface MUST pass this;
|
||||
* the verbatim default exists for same-process configuration UIs only.
|
||||
*/
|
||||
redactSecrets?: boolean
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ interface SettingsScope<T> {
|
||||
|
||||
## 描述符
|
||||
|
||||
`describe()` 为配置界面序列化每个已注册 namespace:schemastery 的 `toJSON()` 信封驱动 schema 渲染的表单,解析值填充表单。
|
||||
`describe()` 为配置界面序列化每个已注册 namespace:schemastery 的 `toJSON()` 信封驱动 schema 渲染的表单,解析值填充表单,分离出的 `base`/`user` 层让表单按字段是否出现在 user 层标注「用户已覆盖」。`describe({ redactSecrets: true })`——每个 wire 面都必须传入——从三层剥离 `role('secret')` 字段并枚举其 `{path, set}` 槽位,页面因此能渲染只写输入框而永远收不到机密值。
|
||||
|
||||
```ts type-equiv
|
||||
/** One registered namespace as surfaced to configuration UIs. */
|
||||
@@ -84,8 +84,49 @@ interface SettingsDescriptor {
|
||||
schema: unknown
|
||||
/** Current resolved value. */
|
||||
value: unknown
|
||||
/**
|
||||
* Monotonic revision of the raw user section this descriptor was read at.
|
||||
* Send it back as `expectedRevision` on a write to refuse a stale one.
|
||||
*/
|
||||
revision: number
|
||||
/** Registrant's composition `base` layer (detached), when one was declared. */
|
||||
base?: unknown
|
||||
/**
|
||||
* Raw user section from the stored document (detached), when one exists and
|
||||
* is well-formed; a field's presence here is what marks it user-overridden.
|
||||
*/
|
||||
user?: unknown
|
||||
/** Owner's declared effect timing. */
|
||||
applies: SettingsApplies
|
||||
/** Schema-declared secret positions; present only under `redactSecrets`. */
|
||||
secrets?: RedactedSecret[]
|
||||
}
|
||||
```
|
||||
|
||||
只持有脱敏 descriptor 的调用方无法安全地重建分节,因此删除改以路径 op 传递。每个 descriptor 还携带针对原始分节的 `revision`;写入可以把它作为 `expectedRevision` 送回,不再匹配的写入会被拒绝,而不是覆盖在先落地的那个写方之上。
|
||||
```ts type-equiv
|
||||
/**
|
||||
* One path-addressed edit to a namespace's user section. Path mutation exists
|
||||
* for a caller holding an INCOMPLETE view of the section — a configuration UI
|
||||
* reads the redacted descriptor, which by construction never received the
|
||||
* `role('secret')` fields. Such a caller can name the field it means without
|
||||
* restating the section: a wholesale `replace` rebuilt from a redacted
|
||||
* document silently deletes every secret the wire never returned.
|
||||
*/
|
||||
type SettingsPathOp =
|
||||
| { op: 'set'; path: readonly string[]; value: unknown }
|
||||
| { op: 'unset'; path: readonly string[] }
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
/** Options for {@link Settings.describe}. */
|
||||
interface SettingsDescribeOptions {
|
||||
/**
|
||||
* Strip `role('secret')` fields from `value`/`base`/`user` and enumerate
|
||||
* them in each descriptor's `secrets`. Every wire surface MUST pass this;
|
||||
* the verbatim default exists for same-process configuration UIs only.
|
||||
*/
|
||||
redactSecrets?: boolean
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -26,17 +26,20 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `agent/turn-stopping` | `serial` | [`packages/core/agent/src/types.ts:406`](../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) |
|
||||
| `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), `apiproxy` |
|
||||
| `commands/change` | `emit` | [`packages/ui/commands/src/index.ts:154`](../packages/ui/commands/src/index.ts) | [`commands`](../packages/ui/commands) (`events.dispatch`) | `apiproxy`, [`tui`](../packages/ui/tui) |
|
||||
| `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:62`](../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:71`](../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:54`](../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:135`](../packages/goal/goal/src/domain.ts) | [`goal`](../packages/goal/goal) (`emit`) | [`goal-session`](../packages/goal/goal-session) |
|
||||
| `llm/stream` | `waterfall` | [`packages/llm/llm/src/index.ts:58`](../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) |
|
||||
| `llm/adapters-updated` | `emit` | [`packages/llm/llm/src/index.ts:70`](../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:59`](../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:71`](../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), [`plan-mode`](../packages/plan/plan-mode), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-telemetry`](../packages/telemetry/session-telemetry), [`tools`](../packages/core/tools), [`user-approval`](../packages/ui/user-approval) |
|
||||
| `session/disposed` | `emit` | [`packages/core/session/src/index.ts:81`](../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-projection-cache`](../packages/session-projection/session-projection-cache), [`session-telemetry`](../packages/telemetry/session-telemetry), [`session-title`](../packages/session-title/session-title) |
|
||||
| `session/event` | `emit` | [`packages/core/session/src/index.ts:93`](../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), [`compact-basic`](../packages/compact/compact-basic), [`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-projection`](../packages/session-projection/session-projection), [`session-projection-cache`](../packages/session-projection/session-projection-cache), [`session-telemetry`](../packages/telemetry/session-telemetry), [`session-title`](../packages/session-title/session-title), [`token-meter`](../packages/llm/token-meter), [`tools`](../packages/core/tools), [`tui`](../packages/ui/tui), [`user-approval`](../packages/ui/user-approval), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `session/flush` | `parallel` | [`packages/core/session/src/index.ts:103`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`session-persistence`](../packages/session-persistence/session-persistence), [`session-telemetry`](../packages/telemetry/session-telemetry) |
|
||||
| `settings/updated` | `emit` | [`packages/settings/settings/src/index.ts:108`](../packages/settings/settings/src/index.ts) | [`settings`](../packages/settings/settings) (`events.dispatch`) | [`settings`](../packages/settings/settings) |
|
||||
| `settings/document-updated` | `emit` | [`packages/settings/settings/src/index.ts:150`](../packages/settings/settings/src/index.ts) | [`settings`](../packages/settings/settings) (`events.dispatch`) | `apiproxy` |
|
||||
| `settings/updated` | `emit` | [`packages/settings/settings/src/index.ts:137`](../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:188`](../packages/skill/skill/src/index.ts) | [`skill`](../packages/skill/skill) (`events.dispatch`) | [`tui`](../packages/ui/tui) |
|
||||
| `subagent/end` | `emit` | [`packages/subagent/subagent/src/index.ts:140`](../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:114`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`emit`) | [`subagent`](../packages/subagent/subagent), [`tool-subagent`](../packages/subagent/tool-subagent) |
|
||||
@@ -63,11 +66,14 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| Event string | Dispatchers | Listeners |
|
||||
| --- | --- | --- |
|
||||
| `commands/changed` | `runtime` (`emit`) | `ui-command` |
|
||||
| `connection/reset` | `runtime` (`emit`) | `ui-command` |
|
||||
| `connection/reset` | `runtime` (`emit`) | `ui-command`, `ui-models` |
|
||||
| `credentials/changed` | `runtime` (`emit`) | `ui-models` |
|
||||
| `internal/dispatch` | - | [`commands`](../packages/ui/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/ui/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-title/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/ui/user-approval), [`workflow`](../packages/workflow/workflow) |
|
||||
| `internal/plugin` | - | `hmr`, `loader`, `modules`, `webserver` |
|
||||
| `internal/status` | - | [`agent`](../packages/core/agent) |
|
||||
| `locale/change` | `locale` (`emit`) | `locale`, `ui-models`, `ui-settings-general` |
|
||||
| `models/changed` | `runtime` (`emit`) | `ui-models` |
|
||||
| `settings/changed` | `runtime` (`emit`) | `ui-models` |
|
||||
| `slash/input-begin-command` | - | `ui-conversation` |
|
||||
| `slash/input-consume-token` | - | `ui-conversation` |
|
||||
| `slash/input-insert-reference` | - | `ui-conversation` |
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
| Cookbook | 实操手册 | | | 文档标题用语 |
|
||||
| context | 上下文 | | | |
|
||||
| counterpart | 对侧文件 | | 对应物、配对物 | 双语配对语境;泛指"另一侧"时可写「另一侧」 |
|
||||
| configurable-provider directory | 可配置提供方目录 | | | llm seam 中 `registerConfigurableProviders()` 维护的目录;沿用 Service Catalog →「服务目录」先例 |
|
||||
| context compaction | 上下文压缩 | 上下文压缩(context compaction) | | |
|
||||
| contract | 契约 | | | 如:`pairing contract` →`配对契约` |
|
||||
| Cordis config entry | Cordis 配置项 | | | 指 `cordis.yml` 插件列表中的一项;插件实现本身写`Cordis 插件` |
|
||||
@@ -103,6 +104,7 @@
|
||||
| coverage | 覆盖率 | | | |
|
||||
| crash recovery | 崩溃恢复 | | | |
|
||||
| deploy root | 部署根目录 | | | |
|
||||
| dormant | 休眠 | | 睡眠、蛰伏 | 指已声明可配置但当前未注册路由的提供方 |
|
||||
| durability | 持久性 | | | |
|
||||
| feature requirement | 功能依赖 | | | 功能或功能选项通过 `requires` 声明的关系 |
|
||||
| ergonomics | 易用性 / 开发体验 | | 人体工学 | API 或面向模型的接口用「易用性」;工具链或开发者工作流用「开发体验」 |
|
||||
@@ -119,6 +121,7 @@
|
||||
| fenced code block | 围栏代码块 | | | 沿用 MDN 中文翻译 |
|
||||
| fingerprint | 指纹 | | | 通用内容指纹;双语配对机制使用 sidecar record 记录两侧 blob hash |
|
||||
| finish reason | 结束原因 | | | |
|
||||
| fold | 折叠区 | | | 配置界面语境:默认收起的字段分区(collapsed →「收起」)|
|
||||
| foreground run | 前台运行 | | | |
|
||||
| freshness | 新鲜度 | | | 沿用 MDN 中文翻译;在本项目中指译文相对源文的同步状态 |
|
||||
| hook | 钩子 | | | |
|
||||
@@ -166,6 +169,7 @@
|
||||
| serving surface | 对外服务接口 | | | |
|
||||
| session | 会话 | | | |
|
||||
| session event | 会话事件 | | | |
|
||||
| setup card | 设置卡片 | | | 首次运行时代替行卡直接展开的配置卡 |
|
||||
| sidecar record | 伴随记录 | | 旁挂记录 | 指与文档同目录的伴随记录文件 |
|
||||
| smoke test | 冒烟测试 | | | |
|
||||
| snapshot | 快照 | | | |
|
||||
|
||||
@@ -8,6 +8,7 @@ Inter-package dependencies among the `@deepseek-ai/dsh-*` harness packages, deri
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph group_util["packages/util"]
|
||||
pkg_atomic_write["atomic-write"]
|
||||
pkg_brand["brand"]
|
||||
pkg_native_command["native-command"]
|
||||
pkg_paths["paths"]
|
||||
@@ -143,6 +144,7 @@ flowchart TD
|
||||
pkg_client_locale["client-locale"]
|
||||
pkg_client_modules["client-modules"]
|
||||
pkg_client_runtime["client-runtime"]
|
||||
pkg_client_schema_form["client-schema-form"]
|
||||
pkg_client_test_runtime["client-test-runtime"]
|
||||
pkg_client_ui_command["client-ui-command"]
|
||||
pkg_client_ui_conversation["client-ui-conversation"]
|
||||
@@ -177,6 +179,10 @@ flowchart TD
|
||||
pkg_tmux_context["tmux-context"]
|
||||
pkg_workspace_context["workspace-context"]
|
||||
end
|
||||
subgraph group_credentials["packages/credentials"]
|
||||
pkg_credentials["credentials"]
|
||||
pkg_credentials_local["credentials-local"]
|
||||
end
|
||||
subgraph group_examples["packages/examples"]
|
||||
pkg_acp_demo["acp-demo"]
|
||||
pkg_agent_spine_demo["agent-spine-demo"]
|
||||
@@ -261,6 +267,7 @@ flowchart TD
|
||||
subgraph group_workspace["packages/workspace"]
|
||||
pkg_workspace["workspace"]
|
||||
end
|
||||
pkg_atomic_write --> pkg_invariants
|
||||
pkg_brand --> pkg_invariants
|
||||
pkg_native_command --> pkg_invariants
|
||||
pkg_paths --> pkg_invariants
|
||||
@@ -273,6 +280,7 @@ flowchart TD
|
||||
pkg_loader_smoke --> pkg_invariants
|
||||
pkg_client_modules --> pkg_invariants
|
||||
pkg_client_runtime --> pkg_invariants
|
||||
pkg_client_schema_form --> pkg_invariants
|
||||
pkg_client_ui_primitives --> pkg_invariants
|
||||
pkg_client_ui_slots --> pkg_invariants
|
||||
pkg_client_web --> pkg_invariants
|
||||
@@ -302,9 +310,6 @@ flowchart TD
|
||||
pkg_client_test_runtime --> pkg_client_ui_slots
|
||||
pkg_client_test_runtime --> pkg_client_web_react
|
||||
pkg_client_test_runtime --> pkg_invariants
|
||||
pkg_client_ui_models --> pkg_client_runtime
|
||||
pkg_client_ui_models --> pkg_client_ui_slots
|
||||
pkg_client_ui_models --> pkg_invariants
|
||||
pkg_client_ui_settings --> pkg_client_runtime
|
||||
pkg_client_ui_settings --> pkg_client_ui_primitives
|
||||
pkg_client_ui_settings --> pkg_client_ui_slots
|
||||
@@ -315,6 +320,8 @@ flowchart TD
|
||||
pkg_client_ui_workspace --> pkg_client_ui_primitives
|
||||
pkg_client_ui_workspace --> pkg_client_ui_slots
|
||||
pkg_client_ui_workspace --> pkg_invariants
|
||||
pkg_credentials --> pkg_brand
|
||||
pkg_credentials --> pkg_invariants
|
||||
pkg_helper --> pkg_brand
|
||||
pkg_helper --> pkg_invariants
|
||||
pkg_helper --> pkg_subprocess
|
||||
@@ -333,11 +340,15 @@ flowchart TD
|
||||
pkg_subprocess_local --> pkg_subprocess
|
||||
pkg_typert_loader --> pkg_invariants
|
||||
pkg_typert_loader --> pkg_typert_registry
|
||||
pkg_llm_deepseek --> pkg_credentials
|
||||
pkg_llm_deepseek --> pkg_invariants
|
||||
pkg_llm_deepseek --> pkg_llm
|
||||
pkg_llm_deepseek --> pkg_settings
|
||||
pkg_llm_deepseek --> pkg_timeout
|
||||
pkg_llm_pi_ai --> pkg_credentials
|
||||
pkg_llm_pi_ai --> pkg_invariants
|
||||
pkg_llm_pi_ai --> pkg_llm
|
||||
pkg_llm_pi_ai --> pkg_settings
|
||||
pkg_llm_pi_ai --> pkg_timeout
|
||||
pkg_session --> pkg_brand
|
||||
pkg_session --> pkg_invariants
|
||||
@@ -348,6 +359,13 @@ flowchart TD
|
||||
pkg_system_prompt --> pkg_scope
|
||||
pkg_web --> pkg_invariants
|
||||
pkg_web --> pkg_llm
|
||||
pkg_client_ui_models --> pkg_client_connection
|
||||
pkg_client_ui_models --> pkg_client_runtime
|
||||
pkg_client_ui_models --> pkg_client_schema_form
|
||||
pkg_client_ui_models --> pkg_client_ui_primitives
|
||||
pkg_client_ui_models --> pkg_client_ui_slots
|
||||
pkg_client_ui_models --> pkg_client_web_react
|
||||
pkg_client_ui_models --> pkg_invariants
|
||||
pkg_client_ui_question --> pkg_client_locale
|
||||
pkg_client_ui_question --> pkg_invariants
|
||||
pkg_client_ui_settings_general --> pkg_client_locale
|
||||
@@ -371,6 +389,10 @@ flowchart TD
|
||||
pkg_client_ui_theme --> pkg_client_ui_primitives
|
||||
pkg_client_ui_theme --> pkg_client_ui_slots
|
||||
pkg_client_ui_theme --> pkg_invariants
|
||||
pkg_credentials_local --> pkg_atomic_write
|
||||
pkg_credentials_local --> pkg_credentials
|
||||
pkg_credentials_local --> pkg_invariants
|
||||
pkg_credentials_local --> pkg_paths
|
||||
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
|
||||
@@ -386,6 +408,7 @@ flowchart TD
|
||||
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
|
||||
pkg_settings_local --> pkg_settings
|
||||
@@ -1000,6 +1023,7 @@ flowchart TD
|
||||
| Package | Group | Depends on |
|
||||
| --- | --- | --- |
|
||||
| [`invariants`](../packages/support/invariants) | `support` | — |
|
||||
| [`atomic-write`](../packages/util/atomic-write) | `util` | [`invariants`](../packages/support/invariants) |
|
||||
| [`brand`](../packages/util/brand) | `util` | [`invariants`](../packages/support/invariants) |
|
||||
| [`native-command`](../packages/util/native-command) | `util` | [`invariants`](../packages/support/invariants) |
|
||||
| [`paths`](../packages/util/paths) | `util` | [`invariants`](../packages/support/invariants) |
|
||||
@@ -1012,6 +1036,7 @@ flowchart TD
|
||||
| [`loader-smoke`](../packages/support/loader-smoke) | `support` | [`invariants`](../packages/support/invariants) |
|
||||
| [`client-modules`](../packages/client/modules) | `client` | [`invariants`](../packages/support/invariants) |
|
||||
| [`client-runtime`](../packages/client/runtime) | `client` | [`invariants`](../packages/support/invariants) |
|
||||
| [`client-schema-form`](../packages/client/schema-form) | `client` | [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-primitives`](../packages/client/ui-primitives) | `client` | [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-slots`](../packages/client/ui-slots) | `client` | [`invariants`](../packages/support/invariants) |
|
||||
| [`client-web`](../packages/client/web) | `client` | [`invariants`](../packages/support/invariants) |
|
||||
@@ -1030,10 +1055,10 @@ flowchart TD
|
||||
| [`client-hmr`](../packages/client/hmr) | `client` | [`client-modules`](../packages/client/modules), [`host-webserver`](../packages/host/webserver), [`invariants`](../packages/support/invariants) |
|
||||
| [`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), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-models`](../packages/client/ui-models) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`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-ui-primitives`](../packages/client/ui-primitives), [`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) |
|
||||
| [`credentials`](../packages/credentials/credentials) | `credentials` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants) |
|
||||
| [`helper`](../packages/sdk/helper) | `sdk` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`subprocess`](../packages/subprocess/subprocess) |
|
||||
| [`telemetry`](../packages/sdk/telemetry) | `sdk` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths) |
|
||||
| [`settings`](../packages/settings/settings) | `settings` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants) |
|
||||
@@ -1042,21 +1067,23 @@ flowchart TD
|
||||
| [`storage-sqlite`](../packages/storage/storage-sqlite) | `storage` | [`invariants`](../packages/support/invariants), [`storage`](../packages/storage/storage) |
|
||||
| [`subprocess-local`](../packages/subprocess/subprocess-local) | `subprocess` | [`invariants`](../packages/support/invariants), [`subprocess`](../packages/subprocess/subprocess) |
|
||||
| [`typert-loader`](../packages/typert/loader) | `typert` | [`invariants`](../packages/support/invariants), [`typert-registry`](../packages/typert/registry) |
|
||||
| [`llm-deepseek`](../packages/llm/llm-deepseek) | `llm` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`timeout`](../packages/util/timeout) |
|
||||
| [`llm-pi-ai`](../packages/llm/llm-pi-ai) | `llm` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`timeout`](../packages/util/timeout) |
|
||||
| [`llm-deepseek`](../packages/llm/llm-deepseek) | `llm` | [`credentials`](../packages/credentials/credentials), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`settings`](../packages/settings/settings), [`timeout`](../packages/util/timeout) |
|
||||
| [`llm-pi-ai`](../packages/llm/llm-pi-ai) | `llm` | [`credentials`](../packages/credentials/credentials), [`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) |
|
||||
| [`system-prompt`](../packages/core/system-prompt) | `core` | [`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) |
|
||||
| [`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-question`](../packages/client/ui-question) | `client` | [`client-locale`](../packages/client/locale), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-settings-general`](../packages/client/ui-settings-general) | `client` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-settings`](../packages/client/ui-settings), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||
| [`client-ui-sidebar`](../packages/client/ui-sidebar) | `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-slash`](../packages/client/ui-slash) | `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-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) |
|
||||
| [`credentials-local`](../packages/credentials/credentials-local) | `credentials` | [`atomic-write`](../packages/util/atomic-write), [`credentials`](../packages/credentials/credentials), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths) |
|
||||
| [`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) |
|
||||
| [`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` | [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths), [`settings`](../packages/settings/settings) |
|
||||
| [`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) |
|
||||
| [`token-meter`](../packages/llm/token-meter) | `llm` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
|
||||
| [`agent`](../packages/core/agent) | `core` | [`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) |
|
||||
| [`bash`](../packages/bash/bash) | `bash` | [`invariants`](../packages/support/invariants), [`sandbox`](../packages/sandbox/sandbox), [`subprocess`](../packages/subprocess/subprocess) |
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/user/guide/config.md
|
||||
config.md: 00d103be990f3e5af315ab7667771b01be96ba5d
|
||||
config.zh.md: a296619c3f3d68726efc4fc13703a510719fc008
|
||||
config.md: 0e2e0e7e7077adcacfaada1d038a0b1e63fcc0cd
|
||||
config.zh.md: 850a841286fe77db9169738b0b155f008205a1a8
|
||||
|
||||
@@ -30,7 +30,7 @@ A minimal configuration is a list of plugin entries:
|
||||
config:
|
||||
agents:
|
||||
- id: main
|
||||
provider: deepseek
|
||||
provider: deepseek-official
|
||||
model: deepseek-v4-flash
|
||||
```
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ Harness 使用 `cordis.yml` 描述 Agent 加载哪些插件以及每个插件的
|
||||
config:
|
||||
agents:
|
||||
- id: main
|
||||
provider: deepseek
|
||||
provider: deepseek-official
|
||||
model: deepseek-v4-flash
|
||||
```
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/user/guide/index.md
|
||||
index.md: 72d822f6377089f56abda4383f393eed30a6709a
|
||||
index.zh.md: 442cda48072c3f6bf9579e880c0ab381b799966f
|
||||
index.md: cefb978019c21a24e9fb57f96ab8e0fee82dc812
|
||||
index.zh.md: 2f1298b5bf5ce44f7d653154b263cb533a3b3ba4
|
||||
|
||||
@@ -20,7 +20,7 @@ Harness implements every capability an AI agent needs—including LLM calls, too
|
||||
config:
|
||||
agents:
|
||||
- id: main
|
||||
provider: deepseek
|
||||
provider: deepseek-official
|
||||
model: deepseek-v4-flash
|
||||
|
||||
# Select the interactive front door
|
||||
|
||||
@@ -20,7 +20,7 @@ Harness 将一个 AI Agent(智能体) 所需要的所有能力——LLM 调
|
||||
config:
|
||||
agents:
|
||||
- id: main
|
||||
provider: deepseek
|
||||
provider: deepseek-official
|
||||
model: deepseek-v4-flash
|
||||
|
||||
# Select the interactive front door
|
||||
|
||||
Reference in New Issue
Block a user