refactor(cli)!: complete app-owned profile startup
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 packages/bundle/web-app/README.md
|
||||
README.md: 1b54e6d29ad49c62b7862bf7fffcd6d24831c643
|
||||
README.zh.md: 82b7c4c2574aa93697e8483c362cf4ec75630f34
|
||||
README.md: fb6a1a3ee5293c7e90afae11a76fe5a8598f3ee8
|
||||
README.zh.md: d8276514d94e658788371034795a073abefbf6ac
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
The dsh browser-surface bundle. [`cordis.patch.yml`](cordis.patch.yml) rides over [`dsh-base`](../base/README.md): it sets the coding persona, inserts the Web host rows (webserver, API gateway, workspace, projection cache, storage) and the browser plugin roster, and mounts this package's `web-runtime` glue plugin (config `{mode, printUrl, surfaceContext, lanAddresses}`). That plugin resolves the built frontend dist through `@deepseek-ai/dsh-frontend`'s exports, mounts the [`frontend-static`](../../host/frontend-static/README.md) fallback owner over it, registers the web-surface prompt section and the bash-visible `DSH_WEB_URL`/`DSH_WEB_MODE` runtime variables when `surfaceContext` is true, and prints the `dsh web:` URL line when `printUrl` is true. This bundle also owns the app command line: the `web-startup` row ([`src/startup.ts`](src/startup.ts)) parses `--host`, `--port`, `--dev`, `--workspace-root`, and repeatable `--trusted-host` from `ctx.cmdlineArgs` ([`dsh-cmdline`](../../boot/cmdline/README.md)) and prints the app's `--help`. Every row it configures injects `webStartup`, so nothing binds a port before argument resolution and `dsh --profile web --help` starts no server. `mode` and `lanAddresses` resolve on every boot because they describe the invocation. [`dsh-headless`](../headless/README.md) is a sibling surface over the same base and does not mount this bundle.
|
||||
The dsh browser-surface bundle. [`cordis.patch.yml`](cordis.patch.yml) rides over [`dsh-base`](../base/README.md): it sets the coding persona, inserts the Web host rows (webserver, API gateway, workspace, projection cache, storage) and the browser plugin roster, and mounts this package's `web-runtime` glue plugin (config `{mode, printUrl, surfaceContext, lanAddresses}`). That plugin resolves the built frontend dist through `@deepseek-ai/dsh-frontend`'s exports, mounts the [`frontend-static`](../../host/frontend-static/README.md) fallback owner over it, registers the harness-source and web-surface prompt sections plus the bash-visible `DSH_WEB_URL`/`DSH_WEB_MODE` runtime variables when `surfaceContext` is true, and prints the `dsh web:` URL line when `printUrl` is true. This bundle also owns the app command line: the `web-startup` row ([`src/startup.ts`](src/startup.ts)) parses `--host`, `--port`, `--dev`, and repeatable `--trusted-host` from `ctx.cmdlineArgs` ([`dsh-cmdline`](../../boot/cmdline/README.md)) and prints the app's `--help`. Every row it configures injects `webStartup`, so nothing binds a port before argument resolution and `dsh --profile web --help` starts no server. `mode` and `lanAddresses` resolve on every boot because they describe the invocation. [`dsh-headless`](../headless/README.md) is a sibling surface over the same base and does not mount this bundle.
|
||||
|
||||
## Model Experience
|
||||
|
||||
### Web-surface prompt section and bash runtime variables
|
||||
### Harness-source and Web-surface context
|
||||
|
||||
#### What the model sees
|
||||
|
||||
When `surfaceContext` is true, the `app:web-surface` global section (order −98) orients the model to the GUI: the canonical local URL, the "this page" referent, the HMR/rebuild update contract for the active mode, and the instruction not to start replacement servers. `DSH_WEB_URL` and `DSH_WEB_MODE` additionally appear in the managed bash environment with their descriptions, resolved per invocation from the live server. When it is false, neither the section nor the variables are registered.
|
||||
When `surfaceContext` is true, the `harness:source` section identifies the on-disk Harness implementation without claiming it is the working directory, and the `app:web-surface` global section (order −98) orients the model to the GUI: the canonical local URL, the "this page" referent, the HMR/rebuild update contract for the active mode, and the instruction not to start replacement servers. `DSH_WEB_URL` and `DSH_WEB_MODE` additionally appear in the managed bash environment with their descriptions, resolved per invocation from the live server. When it is false, neither section nor the variables are registered.
|
||||
|
||||
#### Token effect
|
||||
|
||||
One prompt paragraph per session plus two managed-environment variable lines; constant per process.
|
||||
One source line and one prompt paragraph per session plus two managed-environment variable lines; constant per process.
|
||||
|
||||
#### KV Cache effect
|
||||
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
dsh 浏览器表层组合包。[`cordis.patch.yml`](cordis.patch.yml) 叠加在 [`dsh-base`](../base/README.md) 之上:设置 coding persona,插入 Web 宿主行(webserver、API 网关、workspace、投影缓存、存储)与浏览器插件名录,并挂载本包的 `web-runtime` 粘合插件(配置为 `{mode, printUrl, surfaceContext, lanAddresses}`)。该插件通过 `@deepseek-ai/dsh-frontend` 的 exports 解析已构建的前端 dist,挂载 [`frontend-static`](../../host/frontend-static/README.md) 回退席位所有者,在 `surfaceContext` 为 true 时注册 web 表层提示词段落和 bash 可见的 `DSH_WEB_URL`/`DSH_WEB_MODE` 运行时变量,并在 `printUrl` 为 true 时打印 `dsh web:` URL 行。本组合包还持有应用命令行:`web-startup` 行([`src/startup.ts`](src/startup.ts))从 `ctx.cmdlineArgs`([`dsh-cmdline`](../../boot/cmdline/README.md))解析 `--host`、`--port`、`--dev`、`--workspace-root` 以及可重复的 `--trusted-host`,并打印应用自己的 `--help`。它所配置的每一行都注入 `webStartup`,因此在参数解析完成之前不会有任何东西绑定端口,`dsh --profile web --help` 也不会启动服务器。`mode` 与 `lanAddresses` 在每次 boot 时解析,因为它们描述的是本次调用。[`dsh-headless`](../headless/README.md) 是同一 base 之上的同级表层,不挂载本组合包。
|
||||
dsh 浏览器表层组合包。[`cordis.patch.yml`](cordis.patch.yml) 叠加在 [`dsh-base`](../base/README.md) 之上:设置 coding persona,插入 Web 宿主行(webserver、API 网关、workspace、投影缓存、存储)与浏览器插件名录,并挂载本包的 `web-runtime` 粘合插件(配置为 `{mode, printUrl, surfaceContext, lanAddresses}`)。该插件通过 `@deepseek-ai/dsh-frontend` 的 exports 解析已构建的前端 dist,挂载 [`frontend-static`](../../host/frontend-static/README.md) 回退席位所有者,在 `surfaceContext` 为 true 时注册 Harness 源码与 Web 表层提示词段落,以及 bash 可见的 `DSH_WEB_URL`/`DSH_WEB_MODE` 运行时变量,并在 `printUrl` 为 true 时打印 `dsh web:` URL 行。本组合包还持有应用命令行:`web-startup` 行([`src/startup.ts`](src/startup.ts))从 `ctx.cmdlineArgs`([`dsh-cmdline`](../../boot/cmdline/README.md))解析 `--host`、`--port`、`--dev` 以及可重复的 `--trusted-host`,并打印应用自己的 `--help`。它所配置的每一行都注入 `webStartup`,因此在参数解析完成之前不会有任何东西绑定端口,`dsh --profile web --help` 也不会启动服务器。`mode` 与 `lanAddresses` 在每次 boot 时解析,因为它们描述的是本次调用。[`dsh-headless`](../headless/README.md) 是同一 base 之上的同级表层,不挂载本组合包。
|
||||
|
||||
## 模型体验
|
||||
|
||||
### Web 表层提示词段落与 bash 运行时变量
|
||||
### Harness 源码与 Web 表层上下文
|
||||
|
||||
#### 模型看到的内容
|
||||
|
||||
当 `surfaceContext` 为 true 时,全局段落 `app:web-surface`(顺序 −98)向模型说明 GUI:规范的本地 URL、「this page」指代什么、当前模式下 HMR(热模块替换)/重建的更新约定,以及不要启动替代服务器的指令。`DSH_WEB_URL` 与 `DSH_WEB_MODE` 还会连同各自描述出现在受管 bash 环境中,每次调用时从运行中的服务器解析。当它为 false 时,该提示词段和这些变量都不会注册。
|
||||
当 `surfaceContext` 为 true 时,`harness:source` 段落标明磁盘上的 Harness 实现,但不会声称它就是工作目录;全局段落 `app:web-surface`(顺序 −98)则向模型说明 GUI:规范的本地 URL、「this page」指代什么、当前模式下 HMR(热模块替换)/重建的更新约定,以及不要启动替代服务器的指令。`DSH_WEB_URL` 与 `DSH_WEB_MODE` 还会连同各自描述出现在受管 bash 环境中,每次调用时从运行中的服务器解析。当它为 false 时,这两个段落和这些变量都不会注册。
|
||||
|
||||
#### Token 影响
|
||||
|
||||
每个会话一段提示词,外加两行受管环境变量;每个进程内保持恒定。
|
||||
每个会话一行源码说明和一段提示词,外加两行受管环境变量;每个进程内保持恒定。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
|
||||
@@ -80,9 +80,6 @@
|
||||
# shares. The base layer's agent-default-model service owns the default model.
|
||||
- id: api-gateway
|
||||
name: '@deepseek-ai/dsh-host-apiproxy'
|
||||
inject: [webStartup]
|
||||
config:
|
||||
workspaceRoot: !!js ctx.get('webStartup')?.workspaceRoot
|
||||
|
||||
# This app's command-line startup row. It owns the web flag family and its
|
||||
# --help, and provides webStartup to the rows that inject it.
|
||||
@@ -92,9 +89,9 @@
|
||||
|
||||
# ── layer 2: transport/service ──────────────────────────────────────────────
|
||||
|
||||
# Plain route-registration carrier; host and port arrive as `dsh web`
|
||||
# flag patches over these defaults. The dist is served by the web-runtime
|
||||
# row below through the fallback seat.
|
||||
# Plain route-registration carrier; host and port come from the app's
|
||||
# startup service, with these deployment fallbacks. The dist is served by
|
||||
# the web-runtime row below through the fallback seat.
|
||||
- id: webserver
|
||||
name: '@deepseek-ai/dsh-host-webserver'
|
||||
inject: [webStartup]
|
||||
@@ -119,7 +116,7 @@
|
||||
lanAddresses: !!js ctx.get('webStartup')?.lanAddresses ?? []
|
||||
|
||||
# The client-plugin reload chain: a dev-only row this bundle ships off,
|
||||
# which the entrypoint turns on for `--dev`. It is a row rather than a
|
||||
# which the runtime row turns on for `--dev`. It is a row rather than a
|
||||
# child of web-runtime because its node half is a client-side package,
|
||||
# which a host-side bundle cannot import.
|
||||
- id: client-hmr
|
||||
|
||||
@@ -38,8 +38,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@deepseek-ai/dsh-agent-presets": "workspace:^",
|
||||
"@deepseek-ai/dsh-app-boot": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-connection": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-agent-preset": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-hmr": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-locale": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-modules": "workspace:^",
|
||||
|
||||
@@ -41,12 +41,12 @@ export type WebMode = 'production' | 'development'
|
||||
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
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/**
|
||||
* The web app's startup row: it owns the `dsh --profile web` flag family
|
||||
* (`--host`, `--port`, `--dev`, `--workspace-root`, `--trusted-host`) and its
|
||||
* `--help` text, turns those flags into changes on the rows that inject
|
||||
* {@link WEB_STARTUP_SERVICE}, and then provides it. Until it does, no web row
|
||||
* starts, so `dsh --profile web --help` prints this command's help and the
|
||||
* server never binds.
|
||||
* (`--host`, `--port`, `--dev`, `--trusted-host`) and its `--help` text,
|
||||
* turns those flags into changes on the rows that inject
|
||||
* {@link WEB_STARTUP_SERVICE}, and then provides it. Until it does, no
|
||||
* flag-configured web row starts, so `dsh --profile web --help` prints this
|
||||
* command's help and the server never binds.
|
||||
* @module @deepseek-ai/dsh-web-app/startup
|
||||
*/
|
||||
|
||||
@@ -33,8 +33,6 @@ export interface WebStartupValues {
|
||||
host?: string
|
||||
/** `--port`, absent when the invocation did not name one. */
|
||||
port?: number
|
||||
/** `--workspace-root`, absent when the invocation did not name one. */
|
||||
workspaceRoot?: string
|
||||
/** Web runtime mode; `--dev` selects development, which also mounts the client-plugin reload chain. */
|
||||
mode: 'production' | 'development'
|
||||
/**
|
||||
@@ -101,7 +99,6 @@ interface WebOptions {
|
||||
host?: string
|
||||
port?: string
|
||||
dev?: boolean
|
||||
workspaceRoot?: string
|
||||
trustedHost?: string[]
|
||||
}
|
||||
|
||||
@@ -117,14 +114,13 @@ function webCommand(): Command {
|
||||
.option('--host <host>', 'bind host; pass 0.0.0.0 to reach it from another machine')
|
||||
.option('--port <port>', 'listen port; pass 0 to let the OS pick a free one')
|
||||
.option('--dev', 'mount the client-plugin HMR receiver (run pnpm run dev:web separately to rebuild bundles)')
|
||||
.option('--workspace-root <path>', 'parent directory for workspaces created from the browser UI')
|
||||
.option('--trusted-host <authority...>', 'extra authority the /api browser-trust fence accepts (host or host:port; repeatable)')
|
||||
.addHelpText('after', `
|
||||
Examples:
|
||||
dsh web serve on the composed host and port
|
||||
dsh web --port 8080 serve on another port
|
||||
dsh web --host 0.0.0.0 reach it from another machine on the LAN
|
||||
dsh web --dev mount the client-plugin HMR receiver
|
||||
dsh --profile web serve on the composed host and port
|
||||
dsh --profile web --port 8080 serve on another port
|
||||
dsh --profile web --host 0.0.0.0 reach it from another machine on the LAN
|
||||
dsh --profile web --dev mount the client-plugin HMR receiver
|
||||
`)
|
||||
}
|
||||
|
||||
@@ -146,7 +142,6 @@ function planWebStartup(program: Command, rows: readonly EntryOptions[], ctx: Co
|
||||
return found
|
||||
}
|
||||
const webserver = row('webserver')
|
||||
row('api-gateway')
|
||||
row('web-runtime')
|
||||
const connection = row('connection')
|
||||
// Include preserves nested row expressions until their own injections are
|
||||
@@ -162,7 +157,6 @@ function planWebStartup(program: Command, rows: readonly EntryOptions[], ctx: Co
|
||||
return {
|
||||
...options.host !== undefined && { host: options.host },
|
||||
...options.port !== undefined && { port: Number(options.port) },
|
||||
...options.workspaceRoot !== undefined && { workspaceRoot: options.workspaceRoot },
|
||||
// mode and lanAddresses describe this invocation, never the deployment, so
|
||||
// they are resolved on every boot.
|
||||
mode: options.dev === true ? 'development' : 'production',
|
||||
|
||||
@@ -80,10 +80,6 @@ export const apply = ctx => globalThis.__webStartupApply(ctx)
|
||||
' config:',
|
||||
` trustedHosts: !!js ctx.get('${WEB_STARTUP_SERVICE}')?.trustedHosts ?? ${JSON.stringify(trustedHosts)}`,
|
||||
],
|
||||
'- id: api-gateway',
|
||||
` name: ${rowUrl}`,
|
||||
` inject: [${WEB_STARTUP_SERVICE}]`,
|
||||
' disabled: true',
|
||||
// A second reader keeps the composition honest when the webserver row is
|
||||
// the one under test: the service must still have someone to serve.
|
||||
'- id: web-runtime',
|
||||
@@ -118,10 +114,9 @@ export const apply = ctx => globalThis.__webStartupApply(ctx)
|
||||
|
||||
describe('web startup', () => {
|
||||
it('resolves each flag into the value its row reads', async () => {
|
||||
const { values } = await bootStartup(['--port', '8080', '--workspace-root', '/w'])
|
||||
const { values } = await bootStartup(['--port', '8080'])
|
||||
expect(values).toEqual({
|
||||
port: 8080,
|
||||
workspaceRoot: '/w',
|
||||
mode: 'production',
|
||||
trustedHosts: [],
|
||||
lanAddresses: [],
|
||||
|
||||
@@ -18,7 +18,10 @@
|
||||
"path": "../../../vendor/loader"
|
||||
},
|
||||
{
|
||||
"path": "../../ui/cmdline"
|
||||
"path": "../../boot/app-boot"
|
||||
},
|
||||
{
|
||||
"path": "../../boot/cmdline"
|
||||
},
|
||||
{
|
||||
"path": "../../host/frontend-static"
|
||||
|
||||
Reference in New Issue
Block a user