Merge remote-tracking branch 'origin/master' into claude/unified-environment-credentials-c8841a

# Conflicts:
#	apps/cli/README.i18n.yaml
#	apps/cli/README.md
#	apps/cli/README.zh.md
#	docs/user/guide/config.i18n.yaml
#	packages/client/ui-models/src/client/ModelsSection.module.css
#	packages/cordis/repository-plugin/README.i18n.yaml
#	packages/cordis/repository-plugin/README.md
#	packages/cordis/repository-plugin/README.zh.md
#	packages/credentials/README.i18n.yaml
#	packages/credentials/README.md
#	packages/credentials/README.zh.md
#	packages/llm/llm-deepseek/README.i18n.yaml
#	packages/llm/llm-deepseek/README.zh.md
#	packages/ui/app-boot/README.i18n.yaml
#	packages/ui/app-boot/README.md
#	packages/ui/app-boot/README.zh.md
#	packages/ui/app-boot/src/index.ts
#	packages/ui/app-boot/tests/config-reload.spec.ts
#	packages/ui/app-boot/tests/personal-config.spec.ts
This commit is contained in:
Yichen Jiang
2026-08-05 18:25:14 +08:00
729 changed files with 7372 additions and 4407 deletions

View File

@@ -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 apps/cli/README.md
README.md: 190a68f9e9bc9a2fea09b94afff55351aa6362de
README.zh.md: b0560bd579ddba871cd9851f54b310abbaac8d1c
README.md: ce7af5a299e45d6f107686aff043246914dce8ed
README.zh.md: e97fec9d6bb726cb1e419a1ca2fa1871d4d203ca

View File

@@ -2,75 +2,24 @@
English | [中文](README.zh.md)
The `dsh` command has three entry modes: a required raw config overlay, a one-shot headless prompt, and the Web UI. [`src/args.ts`](src/args.ts) owns the Commander grammar, and [`src/bin.ts`](src/bin.ts) dynamically imports only the selected runner. Unknown commands and leaked options fail with a nonzero exit code.
The `dsh` command is the product launcher for raw Cordis configurations, the Web UI, and one-shot headless tasks. [`src/args.ts`](src/args.ts) owns the command grammar, and [`src/bin.ts`](src/bin.ts) loads only the selected runner. Invalid commands, options from another mode, configuration errors, and boot failures exit nonzero.
## Entry modes
| Command | Purpose |
|---|---|
| `dsh --config ./app.cordis.yml` | Run an explicit patch-list configuration over the shipped base. |
| `dsh web` | Start the browser UI with the shipped Web composition and optional personal configuration. |
| `dsh -p "task"` | Run one fresh persisted session, print the final answer, and exit. |
The invoking directory is the default workspace root. Web and headless share the shipped provider, persistence, policy, tool, repository Plugin, and telemetry composition; raw config selects its own deployment-specific front door.
## Raw config
Raw `dsh` requires an explicit patch-list config:
Raw `dsh` requires `--config`. The named patch list is applied directly over [`config/base.cordis.yml`](config/base.cordis.yml); it is not a complete replacement tree and does not add a surface overlay or personal `$DSH_HOME/config.yaml`. Use `--dump-default-config` and `--dump-config` to inspect the resulting tree without booting it.
```sh
dsh --config ./app.cordis.yml
```
The [CLI behavior reference](reference/README.md) owns exact overlay precedence, flags, shutdown behavior, deployment defaults, and the source launcher.
The named file is applied directly over [`config/base.cordis.yml`](config/base.cordis.yml) through the Include plugin's patch algorithm. It is not a complete replacement tree, and no surface overlay is added. The base deliberately contains no startup agent or interaction front door; the required overlay selects those deployment details. Relative config paths resolve from the invoking directory. A parse, schema, resolution, or plugin boot failure is reported and exits nonzero. SIGINT and SIGTERM dispose the mounted root before exit.
## Development
A patch targets a base row by `id` and replaces that row's complete `config` value rather than deep-merging keys. Patch lists may also insert new rows whose plugin modules the shipped Loader can resolve:
```yaml
- id: agent-loop
config:
agents:
- id: main
provider: deepseek-official
model: deepseek-v4-flash
```
Inspect the effective tree without booting it:
```sh
dsh --dump-default-config
dsh --config ./app.cordis.yml --dump-config
```
`--dump-default-config` prints only the shipped base. `--dump-config` requires `--config` and prints base plus overlay with provenance comments. Composition uses `applyEntryPatches` and `entryListSchema` from `@cordisjs/plugin-include`; `!!js` expressions remain unevaluated, and unmatched patch targets are reported on stderr.
## Web and headless
`dsh web` boots `base.cordis.yml` plus [`config/web.cordis.yml`](config/web.cordis.yml), followed by an explicit `dsh web --config <path>` patch list when given. Nothing is discovered on disk: an overlay reaches a launch only by being named. `--host`, `--port`, `--workspace-root`, and repeatable `--trusted-host` values become Web host patches; their owning plugin schemas validate them at boot. `--dev` mounts the client-plugin HMR receiver and expects a separate `pnpm run dev:web` watcher for no-refresh client bundle updates.
```sh
dsh web
dsh web --config ./web-profile.cordis.yml
dsh web --dump-default-config
dsh web --dump-config
```
The production Web runner needs built package and frontend artifacts (`pnpm run build`). It serves `http://127.0.0.1:3080` by default. Binding all interfaces also trusts the machine's discovered LAN IP literals; `--trusted-host` adds named authorities accepted by the `/api` browser-trust fence.
`dsh -p "task"` uses the same base and Web composition, starts its Web host on an OS-assigned port, runs one fresh persisted session, prints the final answer, and exits. It takes `--config <path>` like every other surface — an automated run names its composition rather than depending on machine state — and rejects the raw config-dump flags.
Web and headless process shutdown gives the plugin tree up to five seconds to dispose. The first `SIGINT`/`SIGTERM` starts that graceful drain; a second signal forces immediate exit. If headless normal completion is already stuck in disposal, the first `Ctrl+C` is the escalation and exits immediately instead of being swallowed.
Both modes treat the invoking directory as the default workspace root, load applicable `AGENTS.md` or `CLAUDE.md` instructions with a 65,536-byte render budget, and use an in-memory SQLite session content index. Each reads its overlay once at startup. The [app-boot Harness-home contract](../../packages/ui/app-boot/README.md#the-harness-home) owns environment layering and `$DSH_HOME` resolution; the [credentials provider](../../packages/credentials/credentials-local/README.md) owns credential storage.
New sessions default to the `workspace-write` permission preset. Bash and filesystem mutations are restricted to the session workspace and platform temporary roots; reads, network access, and process visibility are not confined. `DSH_PERMISSION_MODE` changes the process fallback. Stored General-settings permissions affect later Web sessions, not an already-open one.
`DSH_TOOLS_MODE` selects `native`, `code`, or `both` for the Web/headless process; another value fails at boot. [`config/core-web.cordis.yml`](config/core-web.cordis.yml) is an optional Web overlay that reduces the native model surface to persistent `bash` and `str_replace_editor` while retaining the shipped host, browser, workspace, persistence, and permission composition.
## Shared deployment behavior
The base mounts the native DeepSeek adapter, settings and credential providers, stable `web_search`, repository Plugin support, and session telemetry. Provider credentials live in `$DSH_HOME/.credentials.yaml` or the environment and remain rotatable because the launcher never hoists that document into `process.env`; `$DSH_HOME/.env` is the user's ordinary environment layer, beneath the invoking directory's `.env` and the inherited environment. Search uses `DEEPSEEK_API_KEY` and accepts `DEEPSEEK_SEARCH_BASE_URL`; `web_fetch` is disabled unless an overlay inserts a provider and enables it.
Session events stream as OTLP/HTTP logs by default. `DSH_TELEMETRY_OTLP_URL` selects another collector. Any non-empty `DSH_TELEMETRY_DISABLED` disables the telemetry row before boot. The shipped base has no telemetry redaction rule, so exported records can contain message text, tool arguments and results, and workspace paths; the [telemetry Agent Note](../../.agents/notes/implemented/feature/2026-07-31-web-telemetry-default-mount.md) owns that deployment decision.
The empty `repository-plugins` row lets any named overlay mount prepared immutable repository Plugin generations. See the [repository Plugin contract](../../packages/cordis/repository-plugin/README.md#standalone-app-configuration). The CLI also ships `@deepseek-ai/dsh-mcp-client` as a dependency for overlays, but no MCP server is enabled by default because each server command is trusted executable code outside the agent sandbox.
## Source launcher
Link the source-running launcher onto PATH:
```sh
ln -sf "$(pwd)/bin/dsh" ~/.local/bin/dsh
```
It resolves the checkout through its real path and launches `apps/cli/src/bin.ts` with `node --import tsx/esm`. `TSX_TSCONFIG_PATH` is pinned to the checkout root, so workspace package resolution is independent of the invoking directory. `pnpm run dsh` uses the same entry and forwards arguments. The built form is `apps/cli/lib/bin.js` after `pnpm run build`.
Production Web and headless runs require built package and frontend artifacts. From a checkout, `pnpm run dsh` runs the TypeScript entry and forwards arguments; the [source-launcher reference](reference/README.md#source-launcher) describes the PATH symlink and module-resolution contract.

View File

@@ -2,75 +2,24 @@
[English](README.md) | 中文
`dsh` 命令有三种入口模式:必需的原始配置 overlay、一次性 headless 提示词,以及 Web UI。[`src/args.ts`](src/args.ts) 拥有 Commander 命令语法,[`src/bin.ts`](src/bin.ts) 只会动态导入选中模式的运行器。未知命令和误传入其他模式的选项都会以非零代码退出。
`dsh` 命令是原始 Cordis 配置、Web UI 和一次性无头任务的产品启动器。[`src/args.ts`](src/args.ts) 负责命令语法,[`src/bin.ts`](src/bin.ts) 只加载选中的运行器。无效命令、来自其他模式的选项、配置错误和启动失败都会以非零状态退出。
## 入口模式
| 命令 | 用途 |
|---|---|
| `dsh --config ./app.cordis.yml` | 在随附基础配置之上运行显式 patch 列表配置。 |
| `dsh web` | 使用随附 Web 组合和可选个人配置启动浏览器 UI。 |
| `dsh -p "task"` | 运行一个新的持久化会话,打印最终答案并退出。 |
调用目录是默认 workspace 根目录。Web 与无头模式共享随附的提供方、持久化、策略、工具、repository Plugin 和遥测组合;原始配置自行选择部署专用前端入口。
## 原始配置
原始 `dsh` 要求显式传入一份 patch 列表配置:
原始 `dsh` 必须提供 `--config`。指定的 patch 列表直接应用到 [`config/base.cordis.yml`](config/base.cordis.yml) 之上;它不是完整替代树,也不会添加 surface overlay 或个人 `$DSH_HOME/config.yaml`。使用 `--dump-default-config``--dump-config` 可在不启动的情况下检查生成的配置树。
```sh
dsh --config ./app.cordis.yml
```
[CLI命令行界面行为参考](reference/README.md)负责确切的 overlay 优先级、flag、关闭行为、部署默认值和源码启动器。
指定文件会通过 Include 插件的 patch 算法,直接应用在 [`config/base.cordis.yml`](config/base.cordis.yml) 之上。它不是完整替换树,系统也不会添加任何 surface overlay。base 有意不包含启动 agent智能体或交互入口必需的 overlay 负责选择这些部署细节。相对配置路径以调用目录为基准解析。配置解析、schema 校验、模块解析或插件启动失败都会被报告并以非零代码退出。SIGINT 和 SIGTERM 会在退出前 dispose资源释放已挂载的根上下文。
## 开发
patch 通过 `id` 定位 base 配置项,并替换该配置项的完整 `config` 值,而不是深度合并各个键。它也可以插入新配置项:
```yaml
- id: agent-loop
config:
agents:
- id: main
provider: deepseek-official
model: deepseek-v4-flash
```
可以在不启动应用的情况下检查有效配置树:
```sh
dsh --dump-default-config
dsh --config ./app.cordis.yml --dump-config
```
`--dump-default-config` 只打印随附 base。`--dump-config` 要求提供 `--config`,并打印带来源注释的 base 与 overlay。组合过程使用 `@cordisjs/plugin-include``applyEntryPatches``entryListSchema``!!js` 表达式保持未求值状态,未匹配的 patch 目标会报告到 stderr。
## Web 与 headless
`dsh web` 会启动 `base.cordis.yml` 加 [`config/web.cordis.yml`](config/web.cordis.yml),随后在给出 `dsh web --config <path>` 时应用该显式 patch 列表。磁盘上不会自动发现任何东西overlay 只有被点名才会抵达一次启动。`--host``--port``--workspace-root` 和可重复的 `--trusted-host` 值会转为 Web 宿主 patch各自所属插件的 schema 会在启动时校验它们。`--dev` 会挂载客户端插件 HMR热模块替换接收器要实现无需刷新的客户端 bundle 更新,还需单独运行 `pnpm run dev:web` watcher。
```sh
dsh web
dsh web --config ./web-profile.cordis.yml
dsh web --dump-default-config
dsh web --dump-config
```
生产 Web 运行器需要已构建的包package与前端产物`pnpm run build`)。它默认通过 `http://127.0.0.1:3080` 提供服务。绑定所有网络接口时,系统也会信任本机探测到的 LAN IP 字面量;`--trusted-host` 可添加 `/api` 浏览器信任边界所接受的具名权威。
`dsh -p "task"` 使用相同的 base 与 Web 组合,在由操作系统分配的端口上启动 Web 宿主,运行一个全新的持久会话,打印最终答案后退出。它像其他每个界面一样接受 `--config <path>`——自动化运行应当点名自己的组合,而不是依赖机器状态——并拒绝原始配置输出标志。
Web 与 headless 的进程关闭流程最多给插件树 5 秒执行 dispose。第一次 `SIGINT`/`SIGTERM` 会启动这次优雅排空;第二次信号会立即强制退出。如果 headless 的正常完成流程已经卡在 dispose 中,第一次 `Ctrl+C` 就会触发强制退出:进程立即结束,该信号不再被吞掉。
两种模式都以调用目录作为默认 workspace 根目录,加载适用的 `AGENTS.md``CLAUDE.md` 指令,渲染预算为 65,536 字节,并使用内存 SQLite 会话内容索引。两者都只在启动时读取各自的 overlay 一次。环境分层与 `$DSH_HOME` 解析由 [app-boot 的 Harness home 契约](../../packages/ui/app-boot/README.md#the-harness-home) 定义;凭据存储由[凭据 provider](../../packages/credentials/credentials-local/README.md) 定义。
新会话默认使用 `workspace-write` 权限 preset。Bash 和文件系统写操作受限于会话 workspace 与平台临时根目录;读取、网络访问与进程可见性不受限制。`DSH_PERMISSION_MODE` 会改变进程回退值。已存储的常规设置权限会影响之后的 Web 会话,不会更改已打开的会话。
`DSH_TOOLS_MODE` 为 Web/headless 进程选择 `native``code``both`;其他值会在启动时失败。[`config/core-web.cordis.yml`](config/core-web.cordis.yml) 是可选的 Web overlay它在保留随附宿主、浏览器、workspace、持久化与权限组合的同时将面向原生模型的工具缩减为持久 `bash``str_replace_editor`
## 共享部署行为
base 会挂载原生 DeepSeek 适配器、设置与凭据提供方、稳定的 `web_search`、仓库插件支持与会话遥测。提供方凭据位于 `$DSH_HOME/.credentials.yaml` 或环境中,且仍可轮换,因为启动器绝不会把该文档提升进 `process.env``$DSH_HOME/.env` 是用户的普通环境层,位于调用目录 `.env` 与继承环境之下。搜索使用 `DEEPSEEK_API_KEY` 并接受 `DEEPSEEK_SEARCH_BASE_URL`;除非 overlay 插入提供方并启用 `web_fetch`,否则后者处于禁用状态。
会话事件默认以 OTLP/HTTP 日志的形式流式发送。`DSH_TELEMETRY_OTLP_URL` 用于选择其他 collector。`DSH_TELEMETRY_DISABLED` 的任何非空值都会在启动前禁用遥测配置项。随附 base 没有遥测脱敏规则,因此导出记录可能包含消息文本、工具参数与结果,以及 workspace 路径;该部署决策由[遥测 Agent Note](../../.agents/notes/implemented/feature/2026-07-31-web-telemetry-default-mount.md) 统一定义。
空的 `repository-plugins` 配置项允许任何被点名的 overlay 挂载已准备的不可变仓库插件 generation。详见[仓库插件契约](../../packages/cordis/repository-plugin/README.md#standalone-app-configuration)。CLI命令行界面还将 `@deepseek-ai/dsh-mcp-client` 作为 overlay 依赖发布,但默认不启用任何 MCP 服务器,因为每条服务器命令都是 agent 沙箱之外的受信任可执行代码。
## 源码启动器
将以源码运行的启动器链接到 PATH
```sh
ln -sf "$(pwd)/bin/dsh" ~/.local/bin/dsh
```
它会通过自身实际路径解析该检出,并使用 `node --import tsx/esm` 启动 `apps/cli/src/bin.ts``TSX_TSCONFIG_PATH` 固定指向检出根目录,因此 workspace 包解析不受调用目录影响。`pnpm run dsh` 使用同一入口并转发参数。构建后的形式是执行 `pnpm run build` 后的 `apps/cli/lib/bin.js`
生产环境的 Web 和无头运行需要已构建的包与前端产物。在 checkout 中,`pnpm run dsh` 会运行 TypeScript 入口并转发参数;[源码启动器参考](reference/README.md#source-launcher)说明 PATH 符号链接和模块解析契约。

View 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 apps/cli/reference/README.md
README.md: 5aa1b4c23e74d007911effab4f5172838d49c964
README.zh.md: bba4a0b0471ab0fcd345175205f25e08748a94a4

View File

@@ -0,0 +1,76 @@
# `dsh` CLI behavior reference
English | [中文](README.zh.md)
This reference defines the raw-config, Web, and headless command modes. Argv is parsed once through [`src/args.ts`](../src/args.ts), and [`src/bin.ts`](../src/bin.ts) dynamically imports only the selected runner.
## Raw config
Raw `dsh` requires an explicit patch-list config:
```sh
dsh --config ./app.cordis.yml
```
The named file is applied directly over [`config/base.cordis.yml`](../config/base.cordis.yml) through the Include plugin's patch algorithm. It is not a complete replacement tree, and no surface overlay is added. The base deliberately contains no startup agent or interaction front door; the required overlay selects those deployment details. Relative config paths resolve from the invoking directory. A parse, schema, resolution, or plugin boot failure is reported and exits nonzero. SIGINT and SIGTERM dispose the mounted root before exit.
A patch targets a base row by `id` and replaces that row's complete `config` value rather than deep-merging keys. Patch lists may also insert new rows whose plugin modules the shipped Loader can resolve:
```yaml
- id: agent-loop
config:
agents:
- id: main
provider: deepseek-official
model: deepseek-v4-flash
```
Inspect the effective tree without booting it:
```sh
dsh --dump-default-config
dsh --config ./app.cordis.yml --dump-config
```
`--dump-default-config` prints only the shipped base. `--dump-config` requires `--config` and prints base plus overlay with provenance comments. Composition uses `applyEntryPatches` and `entryListSchema` from `@cordisjs/plugin-include`; `!!js` expressions remain unevaluated, and unmatched patch targets are reported on stderr.
## Web and headless
`dsh web` boots `base.cordis.yml` plus [`config/web.cordis.yml`](../config/web.cordis.yml), followed by an explicit `dsh web --config <path>` patch list when given. Nothing is discovered on disk: an overlay reaches a launch only by being named. `--host`, `--port`, `--workspace-root`, and repeatable `--trusted-host` values become Web host patches; their owning plugin schemas validate them at boot. `--dev` mounts the client-plugin HMR receiver and expects a separate `pnpm run dev:web` watcher for no-refresh client bundle updates.
```sh
dsh web
dsh web --config ./web-profile.cordis.yml
dsh web --dump-default-config
dsh web --dump-config
```
The production Web runner needs built package and frontend artifacts (`pnpm run build`). It serves `http://127.0.0.1:3080` by default. Binding all interfaces also trusts the machine's discovered LAN IP literals; `--trusted-host` adds named authorities accepted by the `/api` browser-trust fence.
`dsh -p "task"` uses the same base and Web composition, starts its Web host on an OS-assigned port, runs one fresh persisted session, prints the final answer, and exits. It takes `--config <path>` like every other surface — an automated run names its composition rather than depending on machine state — and rejects the raw config-dump flags.
Web and headless process shutdown gives the plugin tree up to five seconds to dispose. The first `SIGINT`/`SIGTERM` starts that graceful drain; a second signal forces immediate exit. If headless normal completion is already stuck in disposal, the first `Ctrl+C` is the escalation and exits immediately instead of being swallowed.
Both modes treat the invoking directory as the default workspace root, load applicable `AGENTS.md` or `CLAUDE.md` instructions with a 65,536-byte render budget, and use an in-memory SQLite session content index. Each reads its overlay once at startup. The [app-boot Harness-home contract](../../../packages/ui/app-boot/README.md#the-harness-home) owns environment layering and `$DSH_HOME` resolution; the [credentials provider](../../../packages/credentials/credentials-local/README.md) owns credential storage.
New sessions default to the `workspace-write` permission preset. Bash and filesystem mutations are restricted to the session workspace and platform temporary roots; reads, network access, and process visibility are not confined. `DSH_PERMISSION_MODE` changes the process fallback. Stored General-settings permissions affect later Web sessions, not an already-open one.
`DSH_TOOLS_MODE` selects `native`, `code`, or `both` for the Web/headless process; another value fails at boot. [`config/core-web.cordis.yml`](../config/core-web.cordis.yml) is an optional Web overlay that reduces the native model surface to persistent `bash` and `str_replace_editor` while retaining the shipped host, browser, workspace, persistence, and permission composition.
## Shared deployment behavior
The base mounts the native DeepSeek adapter, settings and credential providers, stable `web_search`, repository Plugin support, and session telemetry. Provider credentials live in `$DSH_HOME/.credentials.yaml` or the environment and remain rotatable because the launcher never hoists that document into `process.env`; `$DSH_HOME/.env` is the user's ordinary environment layer, beneath the invoking directory's `.env` and the inherited environment. Search uses `DEEPSEEK_API_KEY` and accepts `DEEPSEEK_SEARCH_BASE_URL`; `web_fetch` is disabled unless an overlay inserts a provider and enables it.
Session events stream as OTLP/HTTP logs by default. `DSH_TELEMETRY_OTLP_URL` selects another collector. Any non-empty `DSH_TELEMETRY_DISABLED` disables the telemetry row before boot. The shipped base has no telemetry redaction rule, so exported records can contain message text, tool arguments and results, and workspace paths; the [telemetry Agent Note](../../../.agents/notes/implemented/feature/2026-07-31-web-telemetry-default-mount.md) owns that deployment decision.
The empty `repository-plugins` row lets any named overlay mount prepared immutable repository Plugin generations. See the [repository Plugin contract](../../../packages/cordis/repository-plugin/README.md#standalone-app-configuration). The CLI also ships `@deepseek-ai/dsh-mcp-client` as a dependency for overlays, but no MCP server is enabled by default because each server command is trusted executable code outside the agent sandbox.
## Source launcher
Link the source-running launcher onto PATH:
```sh
ln -sf "$(pwd)/bin/dsh" ~/.local/bin/dsh
```
It resolves the checkout through its real path and launches `apps/cli/src/bin.ts` with `node --import tsx/esm`. `TSX_TSCONFIG_PATH` is pinned to the checkout root, so workspace package resolution is independent of the invoking directory. `pnpm run dsh` uses the same entry and forwards arguments. The built form is `apps/cli/lib/bin.js` after `pnpm run build`.

View File

@@ -0,0 +1,76 @@
# `dsh` CLI命令行界面行为参考
[English](README.md) | 中文
本参考定义原始配置、Web 和无头命令模式。参数由 [`src/args.ts`](../src/args.ts) 统一解析,[`src/bin.ts`](../src/bin.ts) 只动态导入选中的运行器。
## 原始配置
原始 `dsh` 必须提供显式 patch 列表配置:
```sh
dsh --config ./app.cordis.yml
```
指定文件通过 Include 插件的 patch 算法直接应用到 [`config/base.cordis.yml`](../config/base.cordis.yml) 之上。它不是完整替代树,也不会添加任何 surface overlay。基础配置刻意不包含启动 agent智能体或交互前端入口必填 overlay 负责选择这些部署细节。相对配置路径从调用目录解析。配置解析、schema 校验、模块解析或插件启动失败会得到报告并以非零状态退出。收到 SIGINT 或 SIGTERM 时,挂载的根节点会先 dispose资源释放再退出。
patch 通过 `id` 定位基础配置行,并替换该行完整的 `config`而不是深度合并各键。patch 列表也可插入新行,只要随附 Loader 能解析其插件模块:
```yaml
- id: agent-loop
config:
agents:
- id: main
provider: deepseek-official
model: deepseek-v4-flash
```
可在不启动的情况下检查生效的配置树:
```sh
dsh --dump-default-config
dsh --config ./app.cordis.yml --dump-config
```
`--dump-default-config` 只打印随附基础配置。`--dump-config` 必须与 `--config` 同时使用,并打印基础配置和带来源注释的 overlay。组合使用 `@cordisjs/plugin-include``applyEntryPatches``entryListSchema``!!js` 表达式保持未求值,找不到目标的 patch 会报告到 stderr。
## Web 与无头模式
`dsh web` 启动 `base.cordis.yml` 加 [`config/web.cordis.yml`](../config/web.cordis.yml),随后在给出 `dsh web --config <path>` 时应用该显式 patch 列表。磁盘上不会自动发现任何东西overlay 只有被点名才会抵达一次启动。`--host``--port``--workspace-root` 和可重复的 `--trusted-host` 值会成为 Web 宿主 patch负责这些值的插件 schema 会在启动时验证它们。`--dev` 挂载客户端插件 HMR热模块替换接收器若要无刷新更新客户端 bundle还需单独运行 `pnpm run dev:web` watcher。
```sh
dsh web
dsh web --config ./web-profile.cordis.yml
dsh web --dump-default-config
dsh web --dump-config
```
生产 Web 运行器需要已构建的包和前端产物(`pnpm run build`)。默认服务地址是 `http://127.0.0.1:3080`。绑定所有接口时,还会信任机器自动发现的 LAN IP 字面量;`--trusted-host` 可添加 `/api` 浏览器信任围栏接受的具名 authority。
`dsh -p "task"` 使用同一基础配置和 Web 组合,在 OS 分配的端口上启动 Web 宿主,运行一个新的持久化会话,打印最终答案并退出。它像其他每个界面一样接受 `--config <path>`——自动化运行应当点名自己的组合,而不是依赖机器状态——并拒绝原始配置 dump flag。
Web 和无头进程关闭时会给插件树最多 5 秒完成 dispose。第一次 `SIGINT`/`SIGTERM` 启动该优雅排空;第二次信号强制立即退出。如果无头模式正常结束时已经卡在 dispose 中,第一次 `Ctrl+C` 就会升格并立即退出,而不会被吞掉。
两种模式都将调用目录作为默认 workspace 根目录,以 65,536 字节渲染预算加载适用的 `AGENTS.md``CLAUDE.md` 指令,并使用内存 SQLite 会话内容索引。两者都只在启动时读取各自的 overlay 一次。[app-boot 的 Harness home 契约](../../../packages/ui/app-boot/README.md#the-harness-home)负责环境分层和 `$DSH_HOME` 解析;[凭据 provider](../../../packages/credentials/credentials-local/README.md)负责凭据存储。
新会话默认使用 `workspace-write` 权限预设。Bash 和文件系统修改仅限于会话 workspace 与平台临时根目录;读取、网络访问和进程可见性不受限制。`DSH_PERMISSION_MODE` 更改进程后备值。General settings 中存储的权限影响后续 Web 会话,不改变已打开的会话。
`DSH_TOOLS_MODE` 为 Web无头进程选择 `native``code``both`;其他值会导致启动失败。[`config/core-web.cordis.yml`](../config/core-web.cordis.yml) 是可选 Web overlay它在保留随附宿主、浏览器、workspace、持久化和权限组合的同时把原生模型 surface 缩减为持久 `bash``str_replace_editor`
## 共享部署行为
基础配置挂载原生 DeepSeek 适配器、settings 与凭据提供方、稳定的 `web_search`、repository Plugin 支持和会话遥测。提供方凭据存放在 `$DSH_HOME/.credentials.yaml` 或环境中;启动器从不把该文档提升到 `process.env`,因此凭据可以轮换。`$DSH_HOME/.env` 是用户的普通环境层,位于调用目录的 `.env` 与继承环境之下。搜索使用 `DEEPSEEK_API_KEY` 并接受 `DEEPSEEK_SEARCH_BASE_URL`;只有 overlay 插入提供方并启用 `web_fetch` 后,该工具才可用。
会话事件默认作为 OTLP/HTTP 日志流式发送。`DSH_TELEMETRY_OTLP_URL` 选择其他 collector。任何非空 `DSH_TELEMETRY_DISABLED` 都会在启动前禁用遥测配置行。随附基础配置没有遥测脱敏规则,因此导出的记录可能包含消息文本、工具参数与结果以及 workspace 路径;该部署决策由[遥测 Agent Note](../../../.agents/notes/implemented/feature/2026-07-31-web-telemetry-default-mount.md)负责。
`repository-plugins` 行让任何被点名的 overlay 挂载已准备的不可变 repository Plugin generation。参见 [repository Plugin 契约](../../../packages/cordis/repository-plugin/README.md#standalone-app-configuration)。CLI 还随附 `@deepseek-ai/dsh-mcp-client` 作为 overlay 的依赖,但默认不启用 MCP 服务器,因为每条服务器命令都是 agent 沙箱之外的受信任可执行代码。
## 源码启动器
把源码运行启动器链接到 PATH
```sh
ln -sf "$(pwd)/bin/dsh" ~/.local/bin/dsh
```
它通过 real path 解析 checkout并使用 `node --import tsx/esm` 启动 `apps/cli/src/bin.ts``TSX_TSCONFIG_PATH` 固定到 checkout 根目录,因此 workspace 包解析不依赖调用目录。`pnpm run dsh` 使用同一入口并转发参数。运行 `pnpm run build` 后,构建形式为 `apps/cli/lib/bin.js`

View File

@@ -66,10 +66,7 @@ async function runHeadlessPtySmoke(): Promise<string> {
try {
const home = join(cwd, '.dsh')
await mkdir(home, { recursive: true })
// The overlay is named, not discovered: nothing is auto-loaded from the
// Harness home, and `-p` takes `--config` for exactly this reason.
const overlay = join(cwd, 'never-dispose.cordis.yml')
await writeFile(overlay, [
await writeFile(join(home, 'config.yaml'), [
'- insert:',
' - id: never-dispose',
` name: '${neverDisposePlugin}'`,
@@ -77,7 +74,7 @@ async function runHeadlessPtySmoke(): Promise<string> {
].join('\n'))
const launch = resolveExampleLaunch({
srcBin: dshBinScript,
configArgs: ['-p', 'never complete', '--config', overlay],
configArgs: ['-p', 'never complete'],
tsconfigPath,
env: {
DSH_HOME: home,