Merge remote-tracking branch 'origin/master' into worktree/windows-acl-hardening-followup
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/config-catalog.md
|
||||
config-catalog.md: 67327e6e3ccad0222514b2b9be4539934ae09e5a
|
||||
config-catalog.zh.md: 587ca858018779854bc17e76f5903d311e4767d4
|
||||
config-catalog.md: 1958a9258118ef3e54b61cc8a6aa7a667520c610
|
||||
config-catalog.zh.md: d22773fe99a62000f727f955050a0def8d315d8d
|
||||
|
||||
@@ -572,7 +572,7 @@ Source: [`packages/goal/goal/src/index.ts:116`](../packages/goal/goal/src/index.
|
||||
Requires: `agentDefaultModel` · `agents` · `sessions`
|
||||
|
||||
```ts config-catalog
|
||||
/** Plugin config: the task, patched in by the launcher. */
|
||||
/** Plugin config: the task resolved from this app's injected provider service. */
|
||||
export interface Config {
|
||||
/** The prompt text for the single run. */
|
||||
task: string
|
||||
@@ -2520,33 +2520,28 @@ Source: [`packages/web/web/src/index.ts:55`](../packages/web/web/src/index.ts)
|
||||
Requires: `httpServer`
|
||||
|
||||
```ts config-catalog
|
||||
/** Plugin config: the surface facts the launcher patches over this bundle's defaults. */
|
||||
/** Plugin config: composed deployment settings plus per-invocation command-line values. */
|
||||
export interface Config {
|
||||
/** Whether this process mounted the client-plugin HMR receiver (`dsh web --dev`). */
|
||||
mode: WebMode
|
||||
/** Print the URL line on activation; a headless layer over this bundle turns it off. */
|
||||
/** Print the URL line on activation; a non-interactive layer can turn it off. */
|
||||
printUrl: boolean
|
||||
/**
|
||||
* Register the model-visible surface context (the `app:web-surface` prompt
|
||||
* section and the `DSH_WEB_URL`/`DSH_WEB_MODE` bash variables). A one-shot
|
||||
* layer turns it off: its user is not interacting through the GUI, so the
|
||||
* non-interactive layer can turn it off when its user is not in the GUI, so the
|
||||
* orientation text would be false.
|
||||
*/
|
||||
surfaceContext: boolean
|
||||
/**
|
||||
* LAN IPv4 addresses sampled once by the launcher when the effective bind
|
||||
* is all-interfaces — the exact snapshot the /api trust fence was
|
||||
* configured with, so the printed LAN URL can never name an address the
|
||||
* fence rejects. Empty on a loopback bind.
|
||||
*/
|
||||
lanAddresses: string[]
|
||||
/** Explicit `--trusted-host` authorities from this invocation. */
|
||||
trustedHosts: string[]
|
||||
}
|
||||
|
||||
/** Web runtime mode: production, or development when the client-plugin HMR receiver is active. */
|
||||
export type WebMode = 'production' | 'development'
|
||||
```
|
||||
|
||||
Source: [`packages/bundle/web-app/src/index.ts:32`](../packages/bundle/web-app/src/index.ts)
|
||||
Source: [`packages/bundle/web-app/src/index.ts:43`](../packages/bundle/web-app/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-web-fetch-local`
|
||||
|
||||
@@ -2792,6 +2787,7 @@ Imported as libraries by other packages; a `cordis.yml` cannot load them.
|
||||
- `@deepseek-ai/dsh-client-ui-slots` ([`packages/client/ui-slots/src/index.ts`](../packages/client/ui-slots/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-web` ([`packages/client/web/src/index.ts`](../packages/client/web/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-web-react` ([`packages/client/web-react/src/index.ts`](../packages/client/web-react/src/index.ts))
|
||||
- `@deepseek-ai/dsh-cmdline` ([`packages/boot/cmdline/src/index.ts`](../packages/boot/cmdline/src/index.ts))
|
||||
- `@deepseek-ai/dsh-environment` ([`packages/util/environment/src/index.ts`](../packages/util/environment/src/index.ts))
|
||||
- `@deepseek-ai/dsh-helper` ([`packages/scaffold/helper/src/index.ts`](../packages/scaffold/helper/src/index.ts))
|
||||
- `@deepseek-ai/dsh-hook-protocol` ([`packages/hooks/hook-protocol/src/index.ts`](../packages/hooks/hook-protocol/src/index.ts))
|
||||
|
||||
@@ -574,7 +574,7 @@ export interface Config {
|
||||
需要:`agentDefaultModel` · `agents` · `sessions`
|
||||
|
||||
```ts config-catalog
|
||||
/** Plugin config: the task, patched in by the launcher. */
|
||||
/** Plugin config: the task resolved from this app's injected provider service. */
|
||||
export interface Config {
|
||||
/** The prompt text for the single run. */
|
||||
task: string
|
||||
@@ -2521,33 +2521,28 @@ export interface WebServiceConfig {
|
||||
需要:`httpServer`
|
||||
|
||||
```ts config-catalog
|
||||
/** Plugin config: the surface facts the launcher patches over this bundle's defaults. */
|
||||
/** Plugin config: composed deployment settings plus per-invocation command-line values. */
|
||||
export interface Config {
|
||||
/** Whether this process mounted the client-plugin HMR receiver (`dsh web --dev`). */
|
||||
mode: WebMode
|
||||
/** Print the URL line on activation; a headless layer over this bundle turns it off. */
|
||||
/** Print the URL line on activation; a non-interactive layer can turn it off. */
|
||||
printUrl: boolean
|
||||
/**
|
||||
* Register the model-visible surface context (the `app:web-surface` prompt
|
||||
* section and the `DSH_WEB_URL`/`DSH_WEB_MODE` bash variables). A one-shot
|
||||
* layer turns it off: its user is not interacting through the GUI, so the
|
||||
* non-interactive layer can turn it off when its user is not in the GUI, so the
|
||||
* orientation text would be false.
|
||||
*/
|
||||
surfaceContext: boolean
|
||||
/**
|
||||
* LAN IPv4 addresses sampled once by the launcher when the effective bind
|
||||
* is all-interfaces — the exact snapshot the /api trust fence was
|
||||
* configured with, so the printed LAN URL can never name an address the
|
||||
* fence rejects. Empty on a loopback bind.
|
||||
*/
|
||||
lanAddresses: string[]
|
||||
/** Explicit `--trusted-host` authorities from this invocation. */
|
||||
trustedHosts: string[]
|
||||
}
|
||||
|
||||
/** Web runtime mode: production, or development when the client-plugin HMR receiver is active. */
|
||||
export type WebMode = 'production' | 'development'
|
||||
```
|
||||
|
||||
来源:[`packages/bundle/web-app/src/index.ts:32`](../packages/bundle/web-app/src/index.ts)
|
||||
来源:[`packages/bundle/web-app/src/index.ts:43`](../packages/bundle/web-app/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-web-fetch-local`
|
||||
|
||||
@@ -2792,6 +2787,7 @@ export interface Config {
|
||||
- `@deepseek-ai/dsh-client-ui-slots`([`packages/client/ui-slots/src/index.ts`](../packages/client/ui-slots/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-web`([`packages/client/web/src/index.ts`](../packages/client/web/src/index.ts))
|
||||
- `@deepseek-ai/dsh-client-web-react`([`packages/client/web-react/src/index.ts`](../packages/client/web-react/src/index.ts))
|
||||
- `@deepseek-ai/dsh-cmdline`([`packages/boot/cmdline/src/index.ts`](../packages/boot/cmdline/src/index.ts))
|
||||
- `@deepseek-ai/dsh-environment`([`packages/util/environment/src/index.ts`](../packages/util/environment/src/index.ts))
|
||||
- `@deepseek-ai/dsh-helper`([`packages/scaffold/helper/src/index.ts`](../packages/scaffold/helper/src/index.ts))
|
||||
- `@deepseek-ai/dsh-hook-protocol`([`packages/hooks/hook-protocol/src/index.ts`](../packages/hooks/hook-protocol/src/index.ts))
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-api/fiber.md
|
||||
fiber.md: 36d2861ac6a53e8186a92d86c65ba228d4b59ee5
|
||||
fiber.zh.md: fafa559ca911677c43893862190009d82c39c56b
|
||||
fiber.md: 182b77390b29b8a90504437d0ccc2dfeba23921a
|
||||
fiber.zh.md: 9ed3e52618586dc3815b9d913439d11a227fb64b
|
||||
|
||||
@@ -34,7 +34,7 @@ Register a cleanup-aware effect on this fiber.
|
||||
|
||||
**Returns** a disposer that tears the effect down and settles once done.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L420)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L415)
|
||||
|
||||
### ctx.fiber
|
||||
|
||||
@@ -97,7 +97,7 @@ public state
|
||||
|
||||
Current lifecycle state; transitions emit `internal/status`.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L192)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L194)
|
||||
|
||||
### fiber.dispose
|
||||
|
||||
@@ -108,7 +108,7 @@ public readonly dispose: () => Promise<void>
|
||||
|
||||
Dispose this fiber: unload the plugin, then settle once cleanup finished.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L194)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L196)
|
||||
|
||||
### fiber.store
|
||||
|
||||
@@ -119,7 +119,7 @@ public store: Dict<Impl> | undefined
|
||||
|
||||
Snapshot of required service implementations while loaded; `undefined` otherwise.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L196)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L198)
|
||||
|
||||
### fiber.inertia
|
||||
|
||||
@@ -130,7 +130,7 @@ public inertia: Promise<void> | undefined
|
||||
|
||||
The in-flight load/unload transition, if one is currently running.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L198)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L200)
|
||||
|
||||
### fiber.name
|
||||
|
||||
@@ -141,7 +141,7 @@ get name()
|
||||
|
||||
The plugin's display name, inherited from the nearest named ancestor, else `'root'`.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L341)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L336)
|
||||
|
||||
### fiber.assertActive()
|
||||
|
||||
@@ -159,7 +159,7 @@ Throw if the fiber has already been disposed.
|
||||
|
||||
**Returns** nothing when the fiber is still active.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L356)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L351)
|
||||
|
||||
### fiber.effect(execute, label?)
|
||||
|
||||
@@ -190,7 +190,7 @@ Register a cleanup-aware effect on this fiber.
|
||||
|
||||
**Returns** a disposer that tears the effect down and settles once done.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L420)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L415)
|
||||
|
||||
### fiber.getEffects()
|
||||
|
||||
@@ -207,7 +207,7 @@ Return metadata for currently registered effects.
|
||||
|
||||
**Returns** one `EffectMeta` tree per labeled live effect.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L573)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L568)
|
||||
|
||||
### fiber.await()
|
||||
|
||||
@@ -225,7 +225,7 @@ Wait for current lifecycle work and rethrow startup errors.
|
||||
|
||||
**Returns** this fiber, once it has settled into a stable state.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L702)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L704)
|
||||
|
||||
### fiber.restart()
|
||||
|
||||
@@ -243,7 +243,7 @@ Dispose and immediately reload this plugin with its current config.
|
||||
|
||||
**Returns** a promise resolving once the reload settled.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L716)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L718)
|
||||
|
||||
### fiber.update(config, noSave?)
|
||||
|
||||
@@ -271,7 +271,7 @@ Runs the `internal/update` waterfall first, so update hooks (and HMR) can veto o
|
||||
|
||||
**Returns** the update waterfall result; the default restart returns a promise.
|
||||
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L734)
|
||||
[Source](../../vendor/cordis/src/fiber.ts#L736)
|
||||
|
||||
## Effect
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ effect(execute: () => Effect, label?: string): AsyncDisposable<Promise<void>>
|
||||
|
||||
**返回**一个用于撤销该作用的清理函数,并在清理完成后结算。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L420)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L415)
|
||||
|
||||
### ctx.fiber
|
||||
|
||||
@@ -99,7 +99,7 @@ public state
|
||||
|
||||
当前生命周期状态;状态转换会发出 `internal/status`。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L192)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L194)
|
||||
|
||||
### fiber.dispose
|
||||
|
||||
@@ -110,7 +110,7 @@ public readonly dispose: () => Promise<void>
|
||||
|
||||
dispose 此 fiber:卸载插件,并在清理完成后结算。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L194)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L196)
|
||||
|
||||
### fiber.store
|
||||
|
||||
@@ -121,7 +121,7 @@ public store: Dict<Impl> | undefined
|
||||
|
||||
加载期间所需服务实现的快照;其他情况下为 `undefined`。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L196)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L198)
|
||||
|
||||
### fiber.inertia
|
||||
|
||||
@@ -132,7 +132,7 @@ public inertia: Promise<void> | undefined
|
||||
|
||||
当前正在进行的加载或卸载转换;如果没有此类转换,则为 undefined。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L198)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L200)
|
||||
|
||||
### fiber.name
|
||||
|
||||
@@ -143,7 +143,7 @@ get name()
|
||||
|
||||
插件的显示名称,继承自最近的具名祖先;如果不存在,则为 `'root'`。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L341)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L336)
|
||||
|
||||
### fiber.assertActive()
|
||||
|
||||
@@ -161,7 +161,7 @@ assertActive()
|
||||
|
||||
**返回**:fiber 仍处于活动状态时不返回任何内容。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L356)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L351)
|
||||
|
||||
### fiber.effect(execute, label?)
|
||||
|
||||
@@ -192,7 +192,7 @@ effect(execute: () => Effect, label?: string): AsyncDisposable<Promise<void>>
|
||||
|
||||
**返回**一个用于撤销该作用的清理函数,并在清理完成后结算。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L420)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L415)
|
||||
|
||||
### fiber.getEffects()
|
||||
|
||||
@@ -209,7 +209,7 @@ getEffects()
|
||||
|
||||
**返回**:每个带标签的活动作用对应一棵 `EffectMeta` 树。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L573)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L568)
|
||||
|
||||
### fiber.await()
|
||||
|
||||
@@ -227,7 +227,7 @@ async await()
|
||||
|
||||
**返回**:进入稳定状态后的此 fiber。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L702)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L704)
|
||||
|
||||
### fiber.restart()
|
||||
|
||||
@@ -245,7 +245,7 @@ dispose 此插件,并立即使用其当前配置重新加载。
|
||||
|
||||
**返回**一个在重新加载完成后兑现的 promise。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L716)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L718)
|
||||
|
||||
### fiber.update(config, noSave?)
|
||||
|
||||
@@ -273,7 +273,7 @@ update(config: any, noSave = false)
|
||||
|
||||
**返回**更新 waterfall 的结果;默认的重新启动操作返回一个 promise。
|
||||
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L734)
|
||||
[源码](../../vendor/cordis/src/fiber.ts#L736)
|
||||
|
||||
## Effect
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/cordis-primer.md
|
||||
cordis-primer.md: 93725949a9490f757edebcf3e8391db9e73321b1
|
||||
cordis-primer.zh.md: fd2a327b526b210986bc1574013fca2c0cec5dda
|
||||
cordis-primer.md: d1e7c5fd8eaaa89fe448d238359389d945cd6346
|
||||
cordis-primer.zh.md: d6ce0f2024f65b006c9505daffaa06a08bb56875
|
||||
|
||||
@@ -35,7 +35,7 @@ For single-decision events, short-circuiting is the design. A policy listener ca
|
||||
|
||||
## Loader Configuration
|
||||
|
||||
`@deepseek-ai/cordis-plugin-include` parses `!!js` into expression nodes, but the Loader interpolates only an entry's `config` before mounting the plugin. Entry metadata (`id`, `name`, `group`, `disabled`, `inject`, `intercept`, and `isolate`) remains literal; `disabled: !!js ...` is therefore a truthy object that always disables the entry. Use explicit config overlays when environment selection changes which plugins are mounted.
|
||||
`@deepseek-ai/cordis-plugin-include` parses `!!js` into expression nodes. Loader interpolates only an entry's `config`, after declared injections activate, against that plugin context (`ctx.serviceName`); Include preserves nested row expressions until target activation. Entry metadata (`id`, `name`, `group`, `disabled`, `inject`, `intercept`, `isolate`) stays literal, so `disabled: !!js ...` always disables the entry. Use overlays when the environment selects plugins.
|
||||
|
||||
## Practical Rules
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ Cordis 是 DeepSeek Harness SDK 底层以 vendor 方式引入的插件框架。
|
||||
|
||||
## Loader 配置
|
||||
|
||||
`@deepseek-ai/cordis-plugin-include` 将 `!!js` 解析为表达式节点,但 Loader 仅在挂载插件前对条目的 `config` 做插值。条目元数据(`id`、`name`、`group`、`disabled`、`inject`、`intercept` 和 `isolate`)保持字面值;因此 `disabled: !!js ...` 是一个 truthy 对象,会始终禁用该条目。需要根据环境选择挂载哪些插件时,请使用显式的配置覆盖层。
|
||||
`@deepseek-ai/cordis-plugin-include` 将 `!!js` 解析为表达式节点。Loader 只在声明的注入激活后,基于该插件上下文(`ctx.serviceName`)插值条目的 `config`;Include 会保留嵌套行表达式,直到目标行激活。条目元数据(`id`、`name`、`group`、`disabled`、`inject`、`intercept`、`isolate`)保持字面值,因此 `disabled: !!js ...` 始终禁用该条目。由环境选择插件时,请使用 overlay。
|
||||
|
||||
## 实践规则
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/module-graph.md
|
||||
module-graph.md: 2b1f8dd9d41ab5ad34a4787ffa54c6b7d13144af
|
||||
module-graph.zh.md: 192943312b672c1ae10d32182e9ccd7456eac90b
|
||||
module-graph.md: 3efb73d075f3d5d7a8bae990fc2f524dc710bcb7
|
||||
module-graph.zh.md: df3b9b38497893471b2613c0c95da409dda0262b
|
||||
|
||||
@@ -133,6 +133,7 @@ flowchart TD
|
||||
end
|
||||
subgraph group_boot["packages/boot"]
|
||||
pkg_app_boot["app-boot"]
|
||||
pkg_cmdline["cmdline"]
|
||||
end
|
||||
subgraph group_bundle["packages/bundle"]
|
||||
pkg_base["base"]
|
||||
@@ -313,6 +314,7 @@ flowchart TD
|
||||
pkg_timeout --> pkg_invariants
|
||||
pkg_scope --> pkg_invariants
|
||||
pkg_llm_mock_server --> pkg_invariants
|
||||
pkg_cmdline --> pkg_invariants
|
||||
pkg_base --> pkg_invariants
|
||||
pkg_client_modules --> pkg_invariants
|
||||
pkg_client_schema_form --> pkg_invariants
|
||||
@@ -1252,6 +1254,7 @@ flowchart TD
|
||||
| [`timeout`](../packages/util/timeout) | `util` | [`invariants`](../packages/support/invariants) |
|
||||
| [`scope`](../packages/core/scope) | `core` | [`invariants`](../packages/support/invariants) |
|
||||
| [`llm-mock-server`](../packages/support/llm-mock-server) | `support` | [`invariants`](../packages/support/invariants) |
|
||||
| [`cmdline`](../packages/boot/cmdline) | `boot` | [`invariants`](../packages/support/invariants) |
|
||||
| [`base`](../packages/bundle/base) | `bundle` | [`invariants`](../packages/support/invariants) |
|
||||
| [`client-modules`](../packages/client/modules) | `client` | [`invariants`](../packages/support/invariants) |
|
||||
| [`client-schema-form`](../packages/client/schema-form) | `client` | [`invariants`](../packages/support/invariants) |
|
||||
|
||||
@@ -135,6 +135,7 @@ flowchart TD
|
||||
end
|
||||
subgraph group_boot["packages/boot"]
|
||||
pkg_app_boot["app-boot"]
|
||||
pkg_cmdline["cmdline"]
|
||||
end
|
||||
subgraph group_bundle["packages/bundle"]
|
||||
pkg_base["base"]
|
||||
@@ -315,6 +316,7 @@ flowchart TD
|
||||
pkg_timeout --> pkg_invariants
|
||||
pkg_scope --> pkg_invariants
|
||||
pkg_llm_mock_server --> pkg_invariants
|
||||
pkg_cmdline --> pkg_invariants
|
||||
pkg_base --> pkg_invariants
|
||||
pkg_client_modules --> pkg_invariants
|
||||
pkg_client_schema_form --> pkg_invariants
|
||||
@@ -1254,6 +1256,7 @@ flowchart TD
|
||||
| [`timeout`](../packages/util/timeout) | `util` | [`invariants`](../packages/support/invariants) |
|
||||
| [`scope`](../packages/core/scope) | `core` | [`invariants`](../packages/support/invariants) |
|
||||
| [`llm-mock-server`](../packages/support/llm-mock-server) | `support` | [`invariants`](../packages/support/invariants) |
|
||||
| [`cmdline`](../packages/boot/cmdline) | `boot` | [`invariants`](../packages/support/invariants) |
|
||||
| [`base`](../packages/bundle/base) | `bundle` | [`invariants`](../packages/support/invariants) |
|
||||
| [`client-modules`](../packages/client/modules) | `client` | [`invariants`](../packages/support/invariants) |
|
||||
| [`client-schema-form`](../packages/client/schema-form) | `client` | [`invariants`](../packages/support/invariants) |
|
||||
|
||||
@@ -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/testing.md
|
||||
testing.md: f5e8a478ec86c29c52f4127c51682c1c44fd23a7
|
||||
testing.zh.md: bd1fa7d23263d7c6e3bed65ef4ed09576ca47cc1
|
||||
testing.md: f330bb1e02f3613c63f3989a8f9128f737bf5c52
|
||||
testing.zh.md: db6facb4fa4bf07eda0a6ee7e558c8c60d4c331e
|
||||
|
||||
@@ -9,7 +9,7 @@ How this repo tests, tier by tier, and the rules that keep a green suite meaning
|
||||
- **Unit** (`pnpm run test`): vitest over package and example specs under their `tests/**` directories plus repository script specs under `scripts/**/*.spec.ts`; tests stay with the code area they exercise. Every registry gets an HMR-safety test (dispose the contributing fiber, assert cleanup). Prefer edge cases, error paths, event ordering, concurrency races, and permanent tests for contract regressions (see `packages/core/agent-loop/tests/contract-regressions.spec.ts`).
|
||||
- **Coverage gate** (`pnpm run test:coverage`): the gating run, per-file 100% on `packages/*/*/src`. An uncovered line is often dead code the gate is correctly flagging for deletion, not a missing test to bolt on. Line coverage is necessary, never sufficient — it proves lines ran, not that the feature works as shipped. Per-file 100% on `packages/bash/pwsh-local/src` needs a real `pwsh`: without one its executor suites self-skip and `vitest.config.ts` exempts the file so pwsh-less hosts stay green, while CI runners ship pwsh and enforce the full bar.
|
||||
- **Real-API e2e** (`pnpm run test:e2e`): with-key tests against live provider APIs — the DeepSeek model plus provider-specific smokes that gate on their own keys (`EXA_API_KEY`, `PERPLEXITY_API_KEY`, …); each suite self-skips without its key so keyless CI stays green ([real-API e2e Agent Note](../.agents/notes/implemented/testing/2026-06-19-real-api-e2e-ci.md)).
|
||||
- **Snapshot** (`pnpm run test:snapshot`): keyless expected outputs cover external behavior — transport contracts and presentation, while persisted logs pin assembled backend behavior. ACP boots the real automation-server example, replays a recorded session, and diffs normalized JSON-RPC plus the re-persisted log ([ACP snapshot Agent Note](../.agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.md)); headless backend scenarios boot their explicit example composition through an unexported JSONL test driver, while `apps/cli` separately owns product `dsh run` acceptance. Use `pnpm run test:snapshot:record` when a model transcript changes and `pnpm run test:snapshot:refresh` when replay input remains valid; review every JSONL and expected-output diff. One ACP scenario (`text-turn`) pins full system-prompt/tool-schema content; other fixtures tokenize it so an edit churns one line ([pinned-header Agent Note](../.agents/notes/archived/testing/2026-07-06-pin-request-header-content-in-one-scenario.md)).
|
||||
- **Snapshot** (`pnpm run test:snapshot`): keyless expected outputs cover external behavior — transport contracts and presentation, while persisted logs pin assembled backend behavior. ACP boots the real automation-server example, replays a recorded session, and diffs normalized JSON-RPC plus the re-persisted log ([ACP snapshot Agent Note](../.agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.md)); headless backend scenarios boot their explicit example composition through an unexported JSONL test driver, while `apps/cli` separately owns product `dsh --profile headless` acceptance. Use `pnpm run test:snapshot:record` when a model transcript changes and `pnpm run test:snapshot:refresh` when replay input remains valid; review every JSONL and expected-output diff. One ACP scenario (`text-turn`) pins full system-prompt/tool-schema content; other fixtures tokenize it so an edit churns one line ([pinned-header Agent Note](../.agents/notes/archived/testing/2026-07-06-pin-request-header-content-in-one-scenario.md)).
|
||||
- **Web browser snapshot** (`pnpm run test:web`; required Linux PR gate): Chromium compares replayed browser output with `apps/web/tests/snapshots/`. CI forces read-only `DSH_SNAPSHOT=replay`, never writing expected outputs; record/refresh stay local and every diff is reviewed ([web e2e lane](../.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.md), [CI gate decision](../.agents/notes/implemented/testing/2026-07-30-web-browser-snapshot-ci-gate.md)). `test:web` [builds first](../.agents/notes/implemented/bug-fix/2026-07-28-themed-scrollbars-and-reserved-gutter.md) for plugin CSS.
|
||||
|
||||
Committed session-format JSONL uses the canonical packed-row layout, and the keyless snapshot gate discovers every such fixture by its `session` header; the [temporary migrator](../scripts/migrate-packed-session-fixtures.ts) rewrites older fixture layouts.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
- **单元测试**(`pnpm run test`):vitest 运行包(package)和示例各自的 `tests/**` 目录下的测试,以及匹配 `scripts/**/*.spec.ts` 的仓库脚本测试;测试文件与其所覆盖的代码区域放在一起。每个注册表都有一个 HMR(热模块替换)安全测试(dispose(资源释放)贡献的 fiber,断言清理完成)。优先覆盖边界情况、错误路径、事件顺序、并发竞态,以及针对约定回归的永久测试(见 `packages/core/agent-loop/tests/contract-regressions.spec.ts`)。
|
||||
- **覆盖率门禁**(`pnpm run test:coverage`):门禁级运行,对 `packages/*/*/src` 按文件 100% 覆盖。未覆盖的行往往是门禁正确标记出的死代码(应删除),而非需要补写的测试。行覆盖率是必要条件,但永远不是充分条件:它证明行被执行过,不证明功能按交付预期工作。`packages/bash/pwsh-local/src` 的按文件 100% 覆盖需要真实的 `pwsh`:缺少它时其 executor 套件会自动跳过,`vitest.config.ts` 会豁免该文件以使无 pwsh 的主机保持绿色,而 CI runner 自带 pwsh,仍按完整标准执行门禁。
|
||||
- **真实 API e2e**(`pnpm run test:e2e`):带密钥测试调用真实提供方 API,包括 DeepSeek 模型以及各提供方特有的冒烟测试;这些测试各自由自己的密钥控制(`EXA_API_KEY`、`PERPLEXITY_API_KEY` 等),缺少密钥时套件会自动跳过,使 keyless CI 保持绿色([真实 API e2e Agent Note](../.agents/notes/implemented/testing/2026-06-19-real-api-e2e-ci.md))。
|
||||
- **快照**(`pnpm run test:snapshot`):无密钥预期输出覆盖对外行为(传输约定与呈现),持久化日志则固定组装后的后端行为。ACP 启动真实的自动化服务器示例、回放录制会话,并对归一化 JSON-RPC 与重新持久化的日志执行 diff([ACP 快照 Agent Note](../.agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.md));headless 后端场景通过未导出的 JSONL 测试 driver 启动各自显式的示例组装,而 `apps/cli` 则单独负责产品 CLI(命令行界面)`dsh run` 的验收。当模型 transcript(文本记录)发生变化时使用 `pnpm run test:snapshot:record`,回放输入仍然有效时使用 `pnpm run test:snapshot:refresh`;请审查每一处 JSONL 与预期输出差异。一个 ACP 场景(`text-turn`)固定完整的系统提示词与工具 schema 内容;其他 fixture(测试前置数据)将其 token 化,因此修改只会扰动一行([pinned-header Agent Note](../.agents/notes/archived/testing/2026-07-06-pin-request-header-content-in-one-scenario.md))。
|
||||
- **快照**(`pnpm run test:snapshot`):无密钥预期输出覆盖对外行为(传输约定与呈现),持久化日志则固定组装后的后端行为。ACP 启动真实的自动化服务器示例、回放录制会话,并对归一化 JSON-RPC 与重新持久化的日志执行 diff([ACP 快照 Agent Note](../.agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.md));headless 后端场景通过未导出的 JSONL 测试 driver 启动各自显式的示例组装,而 `apps/cli` 则单独负责产品 CLI(命令行界面)`dsh --profile headless` 的验收。当模型 transcript(文本记录)发生变化时使用 `pnpm run test:snapshot:record`,回放输入仍然有效时使用 `pnpm run test:snapshot:refresh`;请审查每一处 JSONL 与预期输出差异。一个 ACP 场景(`text-turn`)固定完整的系统提示词与工具 schema 内容;其他 fixture(测试前置数据)将其 token 化,因此修改只会扰动一行([pinned-header Agent Note](../.agents/notes/archived/testing/2026-07-06-pin-request-header-content-in-one-scenario.md))。
|
||||
- **Web 浏览器快照**(`pnpm run test:web`;必需的 Linux PR(Pull Request)门禁):Chromium 将回放后的浏览器输出与 `apps/web/tests/snapshots/` 比较。CI 强制只读的 `DSH_SNAPSHOT=replay`,绝不写入预期输出;record/refresh 留在本地,每处 diff 都须评审([web e2e 车道](../.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.md)、[CI 门禁决策](../.agents/notes/implemented/testing/2026-07-30-web-browser-snapshot-ci-gate.md))。`test:web` 会[先构建](../.agents/notes/implemented/bug-fix/2026-07-28-themed-scrollbars-and-reserved-gutter.md)以交付插件 CSS。
|
||||
|
||||
签入仓库的会话格式 JSONL 使用规范打包行布局,无密钥快照门禁会通过 `session` header 发现每一份此类 fixture;[临时迁移器](../scripts/migrate-packed-session-fixtures.ts)会改写旧版 fixture 布局。
|
||||
|
||||
@@ -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/develop/basic/publish.md
|
||||
publish.md: 7657654b1467c14b22e0eb6372c2bc4e77db2f38
|
||||
publish.zh.md: 7af2ae3a06cc74597d5cbd6fddd46fbab069e287
|
||||
publish.md: 8437c7ea5c4cb966f9f3d68977949c78986ec9a5
|
||||
publish.zh.md: 4409dbfda060a84b316029d87ec985209cfa286a
|
||||
|
||||
@@ -98,7 +98,8 @@ The effective configuration composes over an empty root by applying, in order:
|
||||
2. The profile's own `cordis.patch.yml`.
|
||||
3. The home-level `$DSH_HOME/cordis.patch.yml` — machine-local preferences shared by every profile.
|
||||
4. Each `--patch <path>` overlay, in argv order.
|
||||
5. Launcher flag patches (for example `dsh web --port`).
|
||||
|
||||
App arguments are not another patch layer. A surface bundle can resolve them through an ordinary app-owned service, described below.
|
||||
|
||||
Later layers win per row, and a patch replaces a row's entire `config` value rather than deep-merging keys. Two consequences for bundle authors:
|
||||
|
||||
@@ -107,6 +108,29 @@ Later layers win per row, and a patch replaces a row's entire `config` value rat
|
||||
|
||||
In-box bundle names always resolve from the dsh installation itself; pnpm manages only out-of-tree packages, so your bundle can rely on `@deepseek-ai/dsh-base` being present and current.
|
||||
|
||||
## Give a surface bundle its own command line
|
||||
|
||||
A bundle that defines a runnable app mounts an ordinary provider plugin:
|
||||
|
||||
```yaml
|
||||
- id: hello-startup
|
||||
name: 'dsh-hello-plugin/startup'
|
||||
```
|
||||
|
||||
The plugin exports `inject = ['cmdlineArgs']`, calls `parseCmdline` from [`@deepseek-ai/dsh-cmdline`](../../../../packages/boot/cmdline/README.md) with its own commander program, and provides the returned value as its app-owned service. The launcher hands every plugin the same immutable arguments after launcher flags, so app-specific flags need no launcher change and multiple plugins may parse the snapshot. The Loader row needs no launcher marker or special kind.
|
||||
|
||||
Rows configured by those arguments inject the provider's service and read it from their own `!!js` options, with the deployment value beside it as the fallback:
|
||||
|
||||
```yaml
|
||||
- id: my-app
|
||||
name: '@example/my-app'
|
||||
inject: [myAppStartup]
|
||||
config:
|
||||
port: !!js ctx.myAppStartup.port ?? 8080
|
||||
```
|
||||
|
||||
On `--help`, the provider publishes no service, so those rows never activate. Loader mounts the composition once, waits for each row's ordinary injections, and only then evaluates that row's `!!js` config against its injected context.
|
||||
|
||||
## Installing from GitHub: the build-script catch
|
||||
|
||||
Publishing to a registry is not required — users can install straight from a git host:
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
[English](publish.md) | 中文
|
||||
|
||||
前几篇教程通过 `--patch` overlay 加载本地插件。本教程把它打包成可安装的**组合包**,用 `dsh plugin add` 安装进一个 **profile**,并解释决定组合后配置的层顺序。请先完成[插件配置](./config.md)。
|
||||
前几篇教程通过 `--patch` overlay 加载本地插件。本教程把它打包成可安装的**组合包**(bundle),用 `dsh plugin add` 安装进一个 **profile**,并解释决定组合后配置的层顺序。请先完成[插件配置](./config.md)。
|
||||
|
||||
## 两个概念,两种 manifest(元数据清单)
|
||||
## 两个概念,两种 manifest
|
||||
|
||||
安装机制建立在两个概念之上。二者都由一份 `package.json` 描述,但它们在 `dsh` 键下携带的 manifest 种类不同,回答的问题也不同:
|
||||
安装机制建立在两个概念之上。二者都由一份 `package.json` 描述,但它们在 `dsh` 键下携带的 manifest(元数据清单)种类不同,回答的问题也不同:
|
||||
|
||||
- **组合包**是附带一个配置层的 npm 包。它的 manifest 声明 `dsh.bundle`,回答的是「这个包贡献什么?」:一个插入或覆盖插件行的 patch 文件。
|
||||
- **profile** 是位于 `$DSH_HOME/profiles/<name>` 下、描述一份可启动组合的目录。它的 manifest 声明 `dsh.profile`,回答的是「这套配置由哪些组合包按什么顺序组成?」。
|
||||
- **组合包**是附带一个配置层的 npm 包。它的 manifest 声明 `dsh.bundle`,回答的是"这个包贡献什么?":一个插入或覆盖插件行的 patch 文件。
|
||||
- **profile** 是位于 `$DSH_HOME/profiles/<name>` 下、描述一份可启动组合的目录。它的 manifest 声明 `dsh.profile`,回答的是"这套配置由哪些组合包按什么顺序组成?"。
|
||||
|
||||
组合包是你编写并分发的东西;profile 是用户用 `dsh --profile <name>` 启动的东西。没有东西同时是两者。
|
||||
|
||||
@@ -98,7 +98,8 @@ dsh --profile demo
|
||||
2. profile 自己的 `cordis.patch.yml`。
|
||||
3. home 级的 `$DSH_HOME/cordis.patch.yml`——各 profile 共享的机器本地偏好。
|
||||
4. 每个 `--patch <path>` overlay,按 argv 顺序。
|
||||
5. 启动器 flag patch(例如 `dsh web --port`)。
|
||||
|
||||
应用参数不是另一层 patch。表层组合包可以通过下文所述的普通应用自有服务解析它们。
|
||||
|
||||
后应用的层按行胜出,且 patch 会替换目标行的整个 `config` 值,而不是深度合并各键。这给组合包作者带来两个推论:
|
||||
|
||||
@@ -107,6 +108,29 @@ dsh --profile demo
|
||||
|
||||
内置组合包名称始终从 dsh 安装目录本身解析;pnpm 只管理树外的包,所以你的组合包可以放心依赖 `@deepseek-ai/dsh-base` 存在且与安装保持一致。
|
||||
|
||||
## 让表层组合包持有自己的命令行
|
||||
|
||||
定义了可运行应用的组合包挂载一个普通提供方插件:
|
||||
|
||||
```yaml
|
||||
- id: hello-startup
|
||||
name: 'dsh-hello-plugin/startup'
|
||||
```
|
||||
|
||||
该插件导出 `inject = ['cmdlineArgs']`,使用自己的 commander program 调用 [`@deepseek-ai/dsh-cmdline`](../../../../packages/boot/cmdline/README.md) 中的 `parseCmdline`,再把返回值作为应用自有服务提供出去。启动器把自身 flag 之后的同一份不可变参数交给每个插件,因此添加应用专属 flag 无需修改启动器,多个插件也可以解析该快照。Loader 行不需要启动器标记或特殊类型。
|
||||
|
||||
受这些参数配置的行会注入提供方服务,并在自己的 `!!js` 选项中读取它,同时把部署取值写在旁边作为回退:
|
||||
|
||||
```yaml
|
||||
- id: my-app
|
||||
name: '@example/my-app'
|
||||
inject: [myAppStartup]
|
||||
config:
|
||||
port: !!js ctx.myAppStartup.port ?? 8080
|
||||
```
|
||||
|
||||
遇到 `--help` 时,提供方不会发布该服务,所以这些行不会激活。Loader 只挂载一次组合,等待每一行的普通注入,再基于其已注入的上下文求值该行的 `!!js` 配置。
|
||||
|
||||
## 从 GitHub 安装:构建脚本这道坎
|
||||
|
||||
发布到注册表不是必须的——用户可以直接从 git 托管安装:
|
||||
@@ -127,7 +151,7 @@ dsh plugin --profile demo add github:you/hello-plugin
|
||||
|
||||
然后重新执行 `add`。
|
||||
|
||||
请如实看待这项授权:**允许该包的代码在安装时于你的机器上执行**,且不在 agent(智能体)运行的任何沙箱之内。只对源码可信的包授权,并锁定 commit(`github:you/hello-plugin#<sha>`),让后续推送无法悄悄改变实际运行的内容。
|
||||
请如实看待这项授权:**允许该包的代码在安装时于你的机器上执行**,且不在 agent 运行的任何沙箱之内。只对源码可信的包授权,并锁定 commit(`github:you/hello-plugin#<sha>`),让后续推送无法悄悄改变实际运行的内容。
|
||||
|
||||
如果不想让用户做这项授权,就改为分发构建产物——以下两种形式都不需要任何构建权限:
|
||||
|
||||
|
||||
@@ -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: cd778065801ae58a46703ae3447f835f80abf062
|
||||
config.zh.md: 6f6d37bfe8f7ad29c154d65c1763279655006435
|
||||
config.md: 1d3ad5ce36d4b360ba5156b6be28a6caae4a23d4
|
||||
config.zh.md: 7f8bfaa77066f2976a5667e3ac402814a7afdf96
|
||||
|
||||
@@ -18,6 +18,10 @@ A minimal configuration is a list of plugin entries:
|
||||
```yaml
|
||||
- id: llm-deepseek
|
||||
name: '@deepseek-ai/dsh-llm-deepseek'
|
||||
config:
|
||||
apiKey: !!js process.env.DEEPSEEK_API_KEY
|
||||
models:
|
||||
- deepseek-v4-flash
|
||||
|
||||
- id: bash
|
||||
name: '@deepseek-ai/dsh-bash-local'
|
||||
@@ -47,16 +51,17 @@ Cordis starts sibling entries concurrently. A plugin declares required services
|
||||
|
||||
## CLI patch layers
|
||||
|
||||
`dsh --profile <name>` composes the profile's bundle patch layers (its manifest's `dsh.profile.bundles` list, in order) over an empty root, then the profile's own `~/.dsh/profiles/<name>/cordis.patch.yml`, then each `--patch <path>` overlay, then CLI-flag patches. Later layers win per row.
|
||||
`dsh --profile <name>` composes the profile's bundle patch layers (its manifest's `dsh.profile.bundles` list, in order) over an empty root, then the profile's own `~/.dsh/profiles/<name>/cordis.patch.yml`, the home-level `$DSH_HOME/cordis.patch.yml`, and each `--patch <path>` overlay. Later layers win per row. App flags are not another patch layer: an ordinary bundle plugin injects `cmdlineArgs` and provides parsed values as its own service, while rows that inject and retain a `!!js` read of that service give the invocation value precedence.
|
||||
|
||||
A patch replaces a row's entire `config` value; it does not deep-merge keys. For example, patching `llm-deepseek` with only `config: { thinking: disabled }` also removes that row's configured `apiKeyEnv` and `baseURL`, so restate every key the row must retain.
|
||||
A patch replaces a row's entire `config` value; it does not deep-merge keys. For example, patching `llm-deepseek` with only `config: { thinking: disabled }` also removes that row's configured `apiKey` and `baseURL`, so restate every key the row must retain.
|
||||
|
||||
## JavaScript values and environment variables
|
||||
|
||||
The Cordis loader evaluates runtime expressions tagged with `!!js` for non-secret runtime values. Bundled LLM adapters carry credential references such as `apiKeyEnv`; the value belongs in an environment layer or `$DSH_HOME/.credentials.yaml`, not Cordis configuration.
|
||||
The Cordis loader evaluates runtime expressions tagged with `!!js`. Keep API keys and other secrets in the gitignored `.env` file at the repository root, never in committed configuration.
|
||||
|
||||
```yaml
|
||||
config:
|
||||
apiKey: !!js process.env.DEEPSEEK_API_KEY
|
||||
cwd: !!js process.cwd()
|
||||
```
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@ Harness 使用 `cordis.yml` 描述 agent(智能体)加载哪些插件以及
|
||||
```yaml
|
||||
- id: llm-deepseek
|
||||
name: '@deepseek-ai/dsh-llm-deepseek'
|
||||
config:
|
||||
apiKey: !!js process.env.DEEPSEEK_API_KEY
|
||||
models:
|
||||
- deepseek-v4-flash
|
||||
|
||||
- id: bash
|
||||
name: '@deepseek-ai/dsh-bash-local'
|
||||
@@ -47,16 +51,17 @@ Cordis 会并发启动同级配置项。插件通过 `inject` 声明必需服务
|
||||
|
||||
## CLI 补丁层
|
||||
|
||||
`dsh --profile <name>` 按该 profile 的 manifest(元数据清单)中 `dsh.profile.bundles` 列表的顺序,在空根之上组合各组合包补丁层,随后依次应用该 profile 自己的 `~/.dsh/profiles/<name>/cordis.patch.yml`、home 级 `$DSH_HOME/cordis.patch.yml`、每个 `--patch <path>` overlay,最后是 CLI(命令行界面)标志补丁。同一行以较后的层为准。
|
||||
`dsh --profile <name>` 按该 profile 的 manifest(元数据清单)中 `dsh.profile.bundles` 列表的顺序,在空根之上组合各组合包补丁层,随后依次应用该 profile 自己的 `~/.dsh/profiles/<name>/cordis.patch.yml`、home 级的 `$DSH_HOME/cordis.patch.yml` 与每个 `--patch <path>` overlay。同一行以较后的层为准。应用 flag 并不是另一层 patch:组合包中的普通插件注入 `cmdlineArgs`,再把解析值作为自身服务提供;注入该服务并保留其 `!!js` 读取的行会让本次调用的取值优先。
|
||||
|
||||
补丁会替换目标行的整个 `config` 值,而不是深度合并各个键。例如,只用 `config: { thinking: disabled }` 修补 `llm-deepseek`,也会移除该行原有的 `apiKeyEnv` 与 `baseURL`;因此必须重新写出该行需要保留的全部键。
|
||||
补丁会替换目标行的整个 `config` 值,而不是深度合并各个键。例如,只用 `config: { thinking: disabled }` 修补 `llm-deepseek`,也会移除该行原有的 `apiKey` 与 `baseURL`;因此必须重新写出该行需要保留的全部键。
|
||||
|
||||
## JavaScript 值和环境变量
|
||||
|
||||
Cordis loader 会求值以 `!!js` 标记的运行时表达式,用于非机密的运行时值。仓库内置的 LLM(大语言模型)适配器携带 `apiKeyEnv` 等凭据引用;对应的值应放在环境层或 `$DSH_HOME/.credentials.yaml`,而不是 Cordis 配置中。
|
||||
Cordis loader 使用 `!!js` 标签读取运行时表达式。API key 等凭据应放在仓库根目录、已被 Git 忽略的 `.env` 中,不能提交到配置文件。
|
||||
|
||||
```yaml
|
||||
config:
|
||||
apiKey: !!js process.env.DEEPSEEK_API_KEY
|
||||
cwd: !!js process.cwd()
|
||||
```
|
||||
|
||||
@@ -64,4 +69,4 @@ config:
|
||||
|
||||
## 精确配置参考
|
||||
|
||||
每个插件当前支持的字段、类型和默认值见自动生成的[插件配置目录](../../config-catalog.md)。理解插件如何组合可继续阅读[架构说明](../../architecture.md)和[能力 seam](../../capability-seams.md);要创建自己的配置,优先复制并修改[示例目录说明](../../../examples/README.md)中最接近的例子。
|
||||
每个插件当前支持的字段、类型和默认值见自动生成的[插件配置目录](../../config-catalog.md)。理解插件如何组合可继续阅读[架构说明](../../architecture.md)和[能力接口](../../capability-seams.md);要创建自己的配置,优先复制并修改[示例目录说明](../../../examples/README.md)中最接近的例子。
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/user/guide/quickstart.md
|
||||
quickstart.md: 6a0b292ce12b32b7993b7de56b35f1df2e7a7153
|
||||
quickstart.zh.md: 008245f136e28630c7e8368eeec536e11112a885
|
||||
quickstart.md: 8e883efd470fef329a7308f1017cab0b7afcdd67
|
||||
quickstart.zh.md: e0e3f4e4754bca588831b6d204f77d1c97a140b3
|
||||
|
||||
@@ -36,10 +36,10 @@ DEEPSEEK_API_KEY=sk-your-key-here
|
||||
Run a non-interactive task and print its final answer:
|
||||
|
||||
```sh
|
||||
pnpm run dsh run "summarize the architecture of this workspace"
|
||||
pnpm run dsh --profile headless "summarize the architecture of this workspace"
|
||||
```
|
||||
|
||||
`dsh run` creates and persists a fresh session, prints the final assistant answer, and exits. It starts no Web server or listening port, and a successful run leaves stderr empty.
|
||||
`dsh --profile headless` creates and persists a fresh session, prints the final assistant answer, and exits. It starts no Web server or listening port, and a successful run leaves stderr empty.
|
||||
|
||||
## Step 3: use the Web UI
|
||||
|
||||
@@ -53,7 +53,7 @@ Open `http://127.0.0.1:3080`. The agent can read and write files, run commands,
|
||||
|
||||
## What happened
|
||||
|
||||
`dsh run` boots the `headless` profile: [`dsh-base`](../../../packages/bundle/base/cordis.patch.yml) and [`dsh-headless`](../../../packages/bundle/headless/cordis.patch.yml) compose over an empty root, then the runner drives the core Agent and Session services directly. `dsh web` instead composes `dsh-base` with [`dsh-web-app`](../../../packages/bundle/web-app/cordis.patch.yml), which owns the Host, HTTP, and browser layers. Both read the same default DeepSeek model route from `dsh-base`.
|
||||
`dsh --profile headless` boots the `headless` profile: [`dsh-base`](../../../packages/bundle/base/cordis.patch.yml) and [`dsh-headless`](../../../packages/bundle/headless/cordis.patch.yml) compose over an empty root, then the runner drives the core Agent and Session services directly. `dsh web` instead composes `dsh-base` with [`dsh-web-app`](../../../packages/bundle/web-app/cordis.patch.yml), which owns the Host, HTTP, and browser layers. Both read the same default DeepSeek model route from `dsh-base`.
|
||||
|
||||
## Next steps
|
||||
|
||||
|
||||
@@ -36,10 +36,10 @@ DEEPSEEK_API_KEY=sk-your-key-here
|
||||
运行一个非交互式任务并打印最终回答:
|
||||
|
||||
```sh
|
||||
pnpm run dsh run "summarize the architecture of this workspace"
|
||||
pnpm run dsh --profile headless "summarize the architecture of this workspace"
|
||||
```
|
||||
|
||||
`dsh run` 创建并持久化一个新会话,打印最终助手回答,然后退出。它不会启动 Web 服务器或监听端口;成功运行时 stderr 为空。
|
||||
`dsh --profile headless` 创建并持久化一个新会话,打印最终助手回答,然后退出。它不会启动 Web 服务器或监听端口;成功运行时 stderr 为空。
|
||||
|
||||
## 第三步:使用 Web UI
|
||||
|
||||
@@ -53,7 +53,7 @@ pnpm run dsh web
|
||||
|
||||
## 运行原理
|
||||
|
||||
`dsh run` 启动 `headless` profile:[`dsh-base`](../../../packages/bundle/base/cordis.patch.yml) 和 [`dsh-headless`](../../../packages/bundle/headless/cordis.patch.yml) 在空根之上组合,随后 runner 直接驱动 core Agent 与 Session 服务。`dsh web` 则由 `dsh-base` 与 [`dsh-web-app`](../../../packages/bundle/web-app/cordis.patch.yml) 组合,后者拥有 Host、HTTP 与浏览器层。二者都从 `dsh-base` 读取同一个默认 DeepSeek 模型路由。
|
||||
`dsh --profile headless` 启动 `headless` profile:[`dsh-base`](../../../packages/bundle/base/cordis.patch.yml) 和 [`dsh-headless`](../../../packages/bundle/headless/cordis.patch.yml) 在空根之上组合,随后 runner 直接驱动 core Agent 与 Session 服务。`dsh web` 则由 `dsh-base` 与 [`dsh-web-app`](../../../packages/bundle/web-app/cordis.patch.yml) 组合,后者拥有 Host、HTTP 与浏览器层。二者都从 `dsh-base` 读取同一个默认 DeepSeek 模型路由。
|
||||
|
||||
## 下一步
|
||||
|
||||
|
||||
Reference in New Issue
Block a user