refactor(cmdline): make command providers ordinary

This commit is contained in:
Turtle
2026-08-10 23:45:05 +08:00
parent 668bdb3d8e
commit 09e2d2ddc1
46 changed files with 400 additions and 742 deletions
+2 -2
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 docs/user/develop/basic/publish.md
publish.md: 04520b0fb7d30c716e3c87761bd38f0c25824739
publish.zh.md: 7b0e0141dc0522bb5ec356aa8cba1618c9517f09
publish.md: 8437c7ea5c4cb966f9f3d68977949c78986ec9a5
publish.zh.md: 4409dbfda060a84b316029d87ec985209cfa286a
+5 -6
View File
@@ -99,7 +99,7 @@ The effective configuration composes over an empty root by applying, in order:
3. The home-level `$DSH_HOME/cordis.patch.yml` — machine-local preferences shared by every profile.
4. Each `--patch <path>` overlay, in argv order.
App arguments are not another patch layer. A surface bundle can resolve them through a startup service, described below.
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:
@@ -110,17 +110,16 @@ In-box bundle names always resolve from the dsh installation itself; pnpm manage
## Give a surface bundle its own command line
A bundle that defines a runnable app marks its startup row through the injection it already requires:
A bundle that defines a runnable app mounts an ordinary provider plugin:
```yaml
- id: hello-startup
name: 'dsh-hello-plugin/startup'
inject: [cmdlineArgs]
```
That row calls `runStartup` from [`@deepseek-ai/dsh-cmdline`](../../../../packages/boot/cmdline/README.md) with the app's own commander program. The launcher hands it every argument after the launcher flags, so app-specific flags need no launcher change. Loader mounts the composition once, waits for each row's injections, and only then evaluates that row's `!!js` config against its injected context.
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 startup service and read it from their own `!!js` options, with the deployment value beside it as the fallback:
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
@@ -130,7 +129,7 @@ Rows configured by those arguments inject the startup service and read it from t
port: !!js ctx.myAppStartup.port ?? 8080
```
On `--help`, the service is not provided, so those rows never activate. An app layered over another app disables the lower startup row, because one composition has one command-line owner.
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
+5 -6
View File
@@ -99,7 +99,7 @@ dsh --profile demo
3. home 级的 `$DSH_HOME/cordis.patch.yml`——各 profile 共享的机器本地偏好。
4. 每个 `--patch <path>` overlay,按 argv 顺序。
应用参数不是另一层 patch。表层组合包可以通过下文所述的启动服务解析它们。
应用参数不是另一层 patch。表层组合包可以通过下文所述的普通应用自有服务解析它们。
后应用的层按行胜出,且 patch 会替换目标行的整个 `config` 值,而不是深度合并各键。这给组合包作者带来两个推论:
@@ -110,17 +110,16 @@ dsh --profile demo
## 让表层组合包持有自己的命令行
定义了可运行应用的组合包可以通过启动行本来就需要的注入来标记它
定义了可运行应用的组合包挂载一个普通提供方插件
```yaml
- id: hello-startup
name: 'dsh-hello-plugin/startup'
inject: [cmdlineArgs]
```
行使用应用自己的 commander program 调用 [`@deepseek-ai/dsh-cmdline`](../../../../packages/boot/cmdline/README.md) 中的 `runStartup`。启动器把自身 flag 之后的所有参数交给它,因此添加应用专属 flag 无需修改启动器。Loader 只挂载一次组合,等待每一行的注入,再基于其已注入的上下文求值该行的 `!!js` 配置
插件导出 `inject = ['cmdlineArgs']`,使用自己的 commander program 调用 [`@deepseek-ai/dsh-cmdline`](../../../../packages/boot/cmdline/README.md) 中的 `parseCmdline`,再把返回值作为应用自有服务提供出去。启动器把自身 flag 之后的同一份不可变参数交给每个插件,因此添加应用专属 flag 无需修改启动器,多个插件也可以解析该快照。Loader 行不需要启动器标记或特殊类型
受这些参数配置的行会注入启动服务,并在自己的 `!!js` 选项中读取它,同时把部署取值写在旁边作为回退:
受这些参数配置的行会注入提供方服务,并在自己的 `!!js` 选项中读取它,同时把部署取值写在旁边作为回退:
```yaml
- id: my-app
@@ -130,7 +129,7 @@ dsh --profile demo
port: !!js ctx.myAppStartup.port ?? 8080
```
遇到 `--help` 时,该服务不会被提供,所以这些行不会激活。叠加在另一应用之上的应用会禁用下层启动行,因为一套组合只能有一个命令行所有者
遇到 `--help` 时,提供方不会发布该服务,所以这些行不会激活。Loader 只挂载一次组合,等待每一行的普通注入,再基于其已注入的上下文求值该行的 `!!js` 配置
## 从 GitHub 安装:构建脚本这道坎