@deepseek-ai/dsh-web-app 0.2.0-rc.2 → 0.2.1-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -9,8 +9,8 @@
9
9
  en: a85684740ecd278a
10
10
  zh: 7c54099b9edccf01
11
11
  /deepseek-ai-dsh-web-app/summary:
12
- en: 0ebb6c3ca8c0a84e
13
- zh: 4d85e02c769ddae0
12
+ en: fd97ee0c14fb5378
13
+ zh: 0e1ccba47bc408d9
14
14
  /deepseek-ai-dsh-web-app/table-of-contents:
15
15
  en: d152484eb41ac6b4
16
16
  zh: 09388d293f9be9cb
@@ -21,23 +21,26 @@
21
21
  en: b7ab01cfe9fed40f
22
22
  zh: 23703ab7727c3ab5
23
23
  /deepseek-ai-dsh-web-app/use-this-package/configuration:
24
- en: a93760e9e451faa6
25
- zh: 5dab82dd20aa952f
26
- /deepseek-ai-dsh-web-app/use-this-package/lan-access-and-trusted-hosts:
27
- en: 2522c806db384ddc
28
- zh: 7e96f11194af9f9f
24
+ en: a9ee366c5af68a6c
25
+ zh: 2711d7a3926e1101
26
+ /deepseek-ai-dsh-web-app/use-this-package/listening-trust-and-public-deployments:
27
+ en: a79add86cb73d966
28
+ zh: 78b58259f98ed063
29
29
  /deepseek-ai-dsh-web-app/use-this-package/running-over-ssh:
30
- en: 1fe96dde34f21b23
31
- zh: 5689c4f4186805c1
30
+ en: 45db677dcc91c5c9
31
+ zh: 75b765f7f1e15035
32
32
  /deepseek-ai-dsh-web-app/use-this-package/per-session-agent-setup:
33
33
  en: ccd6fc264b51e44b
34
34
  zh: 3265c68477a89ec9
35
35
  /deepseek-ai-dsh-web-app/understand-the-implementation:
36
- en: 4eb00d95238e3b92
37
- zh: 0d6ca9e1a3e7db84
36
+ en: fb819d10930089a8
37
+ zh: f2dee0ff170a4d41
38
38
  /deepseek-ai-dsh-web-app/understand-the-implementation/patch-semantics:
39
- en: f0078127aa8dd273
40
- zh: c954c137599b486f
39
+ en: 954a424ea7182c8f
40
+ zh: 9339bc21dba44d40
41
+ /deepseek-ai-dsh-web-app/understand-the-implementation/advertised-application-url:
42
+ en: ca977d2b2bcf72c5
43
+ zh: 2b81b377c133c1a8
41
44
  /deepseek-ai-dsh-web-app/understand-the-implementation/readiness:
42
45
  en: 973128fd346869df
43
46
  zh: 54e6792f9f82a192
@@ -45,11 +48,8 @@
45
48
  en: b5ed8ff0056ca9da
46
49
  zh: fdc1fa4f14cb00b3
47
50
  /deepseek-ai-dsh-web-app/understand-the-implementation/source-map:
48
- en: 0d08e95f0a5543cb
49
- zh: 5a3e8e4102678cb7
50
- /deepseek-ai-dsh-web-app/understand-the-implementation/invariant-ownership:
51
- en: 34767bb4c0471622
52
- zh: e6d76e7c7a0b9ce8
51
+ en: e41444bed021a121
52
+ zh: 44088a90df50d5b4
53
53
  /deepseek-ai-dsh-web-app/further-exploration:
54
54
  en: f81694f7424e2988
55
55
  zh: 6643f9227039e228
@@ -60,17 +60,17 @@
60
60
  en: e6febc53efe0f51d
61
61
  zh: 9177816a8678d65d
62
62
  /deepseek-ai-dsh-web-app/model-experience/harness-source-and-web-surface-context/what-the-model-sees:
63
- en: 359b949dd483477f
64
- zh: 1476006614a82282
63
+ en: 583592075e04687d
64
+ zh: 9defddfd77bab0f7
65
65
  /deepseek-ai-dsh-web-app/model-experience/harness-source-and-web-surface-context/token-effect:
66
66
  en: 908fc84d6849a830
67
67
  zh: 56fe5e418bab60ba
68
68
  /deepseek-ai-dsh-web-app/model-experience/harness-source-and-web-surface-context/kv-cache-effect:
69
- en: da0f568d6d661c5e
70
- zh: 606919b7d37c95bf
69
+ en: 1d7d87f54b20b563
70
+ zh: d150a51615d278e8
71
71
  /deepseek-ai-dsh-web-app/known-limitations-and-deferred-work:
72
- en: fead2f7bcd17e1ab
73
- zh: 80949c203c0a0732
72
+ en: d6de1d07249ef3b0
73
+ zh: 49d01329256e2eb3
74
74
  /deepseek-ai-dsh-web-app/known-limitations-and-deferred-work/dev-note:
75
75
  en: 3f81b4f3beb74a0d
76
76
  zh: 2e377ca40822d093
package/README.md CHANGED
@@ -13,7 +13,7 @@ Desktop analytics schedules partial batches every 30 seconds, with a 15-second e
13
13
 
14
14
  ## Summary
15
15
 
16
- Run `dsh --profile web` to open an interactive browser GUI with chat, model and settings management, and session history. It uses the same model access, tools, and safety defaults as other dsh surfaces. Startup prints an authenticated URL and normally opens it in the default browser; SSH sessions and `--no-open` leave the URL for manual opening. You can change the port and allow extra hosts, but cannot bind all network interfaces. Choose this package for interactive browser work; use `dsh-headless` for one-shot command-line tasks.
16
+ Run `dsh --profile web` for browser chat, model and settings management, and session history, using the same model access, tools, and safety defaults as other dsh surfaces. Startup prints a tokenized URL and normally opens the default browser; SSH sessions and `--no-open` require manual opening. You can change the port and allow extra hosts, but cannot bind all network interfaces. Remote access supports an advertised public HTTP(S) URL behind a prefix-stripping proxy. For one-shot command-line tasks, use `dsh-headless`.
17
17
 
18
18
  ## Table of Contents
19
19
 
@@ -46,24 +46,30 @@ Saved model selections override the composition default. The settings card accep
46
46
 
47
47
  ### Configuration
48
48
 
49
- Most users never set these; the command-line flags feed the four settings below — `--host`, `--port`, and `--trusted-host` come from the invocation, and `--no-open` turns the browser handoff off for that invocation:
49
+ `--host` and `--port` configure the listener; `--public-url` names the advertised public HTTP(S) root the GUI is reached at behind a prefix-stripping proxy, and `--trusted-host` adds further accepted authorities. All are described under [Listening, trust, and public deployments](#public-deployments):
50
50
 
51
51
  | Field | Default | Meaning |
52
52
  |---|---|---|
53
53
  | `openBrowser` | `true` | Open the default browser after startup; SSH launches suppress it |
54
54
  | `printUrl` | `true` | Print the `dsh web:` URL line at startup |
55
55
  | `surfaceContext` | `true` | Give the agent GUI-orientation context and expose `DSH_WEB_URL` to its shell commands |
56
+ | `publicUrl` | Unset | Advertised HTTP(S) application root; otherwise announce the listener's loopback URL |
56
57
  | `trustedHosts` | `[]` | Extra hosts allowed to reach the GUI from the network |
57
58
 
58
- The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-web-app) is the exhaustive source for every accepted field and its JSDoc. The shipped composition carries no `time-context`, `schedule`, or `ui-schedule` row; the optional experimental bundle `@deepseek-ai/dsh-experimental-schedule-bundle` inserts those three rows from the Plugins page.
59
+ The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-web-app) lists this runtime plugin's accepted fields and their JSDoc. The shipped composition inserts the `schedule` service row and the `ui-schedule` task page row, while the clock reading and the four reminder tools belong to the `standard`, `cordis`, and `ptc` presets. The `tool-subagent` and `tool-subagent-fork` rows in those presets deny the four tools, so a delegated child's scope never lists them.
59
60
 
60
- ### LAN access and trusted hosts
61
+ <a id="public-deployments"></a>
62
+ ### Listening, trust, and public deployments
61
63
 
62
- By default the GUI accepts connections from this machine only. A deployment that binds all network interfaces also allows browsers from the LAN, and the printed URL then includes a LAN address; `--trusted-host` adds extra hosts in either case. Host and Origin checks control reachability, while the token exchange authenticates every Host API method and WebSocket stream. The LAN addresses are sampled once at startup, so a network change later is not picked up — restart the GUI to re-advertise.
64
+ By default the GUI listens on loopback and accepts connections from this machine only; repeatable `--trusted-host` adds the authorities its Host/Origin fence accepts, so a remote browser reaches it behind a prefix-stripping proxy or through a port-forwarding client that presents a trusted hostname.
65
+
66
+ `--public-url` advertises the HTTP(S) root browsers use — the printed and opened startup URL, `DSH_WEB_URL`, and the web-surface orientation. Advertisement grants no trust: the browser-visible authority must also be named with `--trusted-host`. The flag configures no listener, routing, or cookie scope, because the proxy owns the external leg: [Publish the Web UI behind a reverse proxy](../../../docs/user/guide/public-deployments.md) lists what such a deployment must provide.
67
+
68
+ The printed URL contains a process credential; share it only with intended users, and `printUrl: false` suppresses the line with or without `--public-url`.
63
69
 
64
70
  ### Running over SSH
65
71
 
66
- When you launch `dsh --profile web` over SSH, the URL line still prints but the browser is not opened for you: the SSH client or editor owns the local forwarding address. Open the forwarded URL on your machine yourself; the printed URL names the remote host's loopback endpoint.
72
+ When you launch `dsh --profile web` over SSH, the URL line still prints but the browser is not opened for you: the SSH client or editor owns the local forwarding address. Without an advertised root the printed URL names the remote host's loopback endpoint, which you reach through your forwarding address. With `--public-url` the printed URL is the authenticated advertised root; the browser handoff stays suppressed, because opening a browser on the remote host cannot reach your screen.
67
73
 
68
74
  ### Per-session agent setup
69
75
 
@@ -77,11 +83,15 @@ Each browser session selects a shipped preset (`standard` by default). The Agent
77
83
  <details>
78
84
  <summary>Implementation internals — click to expand</summary>
79
85
 
80
- The bundle is one patch layer of five files plus one runtime glue plugin: `cordis.patch.yml` carries the host rows and the preset registry, and each `presets/<id>.patch.yml` inserts one shipped preset declaration, applied in the order `dsh.bundle.patch` lists them. The storage stack and projection cache come from `dsh-base`; the web overlay's workspace and message-feedback rows consume that shared `storageDomain` service. The patch restates the surface-specific values the base deliberately omits, inserts the web-only host rows and browser roster, then moves the agent plane behind presets. The glue plugin owns dist serving, trust sampling, prompt sections, the bash variable, and the readiness announcements. The `office-to-pdf` row mounts one lazy [Office conversion provider](../../document/office-to-pdf/README.md) for Host consumers, including Desktop compositions using this bundle. The conversion service's Remote methods authorize preview reads, while Document Preview owns the Office viewer and Client cache.
86
+ The bundle is one patch layer of five files plus one runtime glue plugin: `cordis.patch.yml` carries the host rows and the preset registry, and each `presets/<id>.patch.yml` inserts one shipped preset declaration, applied in the order `dsh.bundle.patch` lists them. The storage stack and projection cache come from `dsh-base`; the web overlay's workspace and message-feedback rows consume that shared `storageDomain` service. The patch restates the surface-specific values the base deliberately omits, inserts the web-only host rows and browser roster, then moves the agent plane behind presets. The glue plugin owns dist serving, the advertised application URL, trust sampling, prompt sections, the bash variable, and the readiness announcements. The `office-to-pdf` row mounts one lazy [Office conversion provider](../../document/office-to-pdf/README.md) for Host consumers, including Desktop compositions using this bundle. The conversion service's Remote methods authorize preview reads, while Document Preview owns the Office viewer and Client cache.
81
87
 
82
88
  ### Patch semantics
83
89
 
84
- A patch replaces the targeted row's whole `config`, so each web row restates every key it owns: the persona prefix and suffix templates, the `DSH_TOOLS_MODE` PTC mode opt-in, and the `session-query-sqlite` values on the base rows, then `insert` adds the web host rows, transport, and browser roster. The per-agent tool rows the base mounts process-wide are disabled here and the preset roster takes over; the reasoning for each host-plane versus preset-plane decision is inline in the patch.
90
+ A patch replaces the targeted row's whole `config`, so each web row restates every key it owns: the persona prefix and suffix templates, the `DSH_TOOLS_MODE` PTC mode opt-in, and the `session-query-sqlite` values on the base rows, then `insert` adds the web host rows, transport, and browser roster. The `webserver` and `web-runtime` rows inject the `webStartup` provider and read their invocation values directly; the `connection` row instead reads the bind-dependent `webRuntime` values the web-runtime row publishes, which are that provider's authorities plus the LAN literals of an all-interfaces bind. The per-agent tool rows the base mounts process-wide are disabled here and the preset roster takes over; the reasoning for each host-plane versus preset-plane decision is inline in the patch.
91
+
92
+ ### Advertised application URL
93
+
94
+ Startup display and browser handoff receive the advertised root with its launch token; the web-surface prompt and `DSH_WEB_URL` receive it clean. The root itself is defined under [Listening, trust, and public deployments](#public-deployments).
85
95
 
86
96
  ### Readiness
87
97
 
@@ -95,20 +105,17 @@ The URL line and browser handoff are readiness signals: supervisors RPC as soon
95
105
 
96
106
  | File | Role |
97
107
  |---|---|
98
- | [`src/index.ts`](src/index.ts) | The `web-app` glue plugin: dist resolution, LAN trust sampling, prompt sections, bash variable, URL line, browser handoff |
99
- | [`src/startup.ts`](src/startup.ts) | The `web-startup` provider: `--host`, `--port`, `--trusted-host`, `--no-open`, `--help` |
108
+ | [`src/index.ts`](src/index.ts) | The `web-app` glue plugin: dist resolution, advertised application URL, LAN trust sampling, prompt sections, bash variable, URL line, browser handoff |
109
+ | [`src/public-url.ts`](src/public-url.ts) | Advertised-root validation and trailing-slash normalization; a leaf module for local imports, not package API |
110
+ | [`src/startup.ts`](src/startup.ts) | The `web-startup` provider: `--host`, `--port`, `--public-url`, `--trusted-host`, `--no-open`, `--help` |
100
111
  | [`cordis.patch.yml`](cordis.patch.yml) | The web patch: restated base values, web host rows, browser roster, preset registry |
101
112
  | [`presets/`](presets) | One `@deepseek-ai/dsh-agent-preset` declaration per shipped preset (`standard`, `ptc`, `minimal`, `cordis`), each its own patch file |
102
- | — | No runtime invariant companion is published; every contribution (frontend-static child plugin, prompt section, bashEnv registration) is registry-disposed with the fiber, and each owning registry's package carries that relation's invariant; the package holds no mutable state of its own to audit. |
103
- | [`tests/web-app.spec.ts`](tests/web-app.spec.ts) | Dist resolution, fallback seat, prompt sections, readiness |
113
+ | [`tests/web-app.spec.ts`](tests/web-app.spec.ts) | Dist resolution, fallback seat, prompt sections, readiness, advertised URL publication |
104
114
  | [`tests/startup.spec.ts`](tests/startup.spec.ts) | Command-line parsing over a real Loader tree |
115
+ | [`tests/public-url.spec.ts`](tests/public-url.spec.ts) | Advertised-root parsing and normalization |
105
116
  | [`tests/trusted-hosts.spec.ts`](tests/trusted-hosts.spec.ts) | LAN-trust sampling |
106
117
  | [`tests/browser-open.spec.ts`](tests/browser-open.spec.ts) | Default-browser handoff after the page is reachable |
107
118
 
108
- ### Invariant ownership
109
-
110
- No invariant companion is published because every contribution — the frontend-static child plugin, the prompt sections, and the bash variable registration — is registry-disposed with the fiber, and each owning registry package carries that relation's invariant.
111
-
112
119
  </details>
113
120
 
114
121
  -----
@@ -133,7 +140,7 @@ Read these pages when you want to go deeper into the shared core, the browser re
133
140
 
134
141
  #### What the model sees
135
142
 
136
- 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 (first-party order 10100, after reusable instructions) orients the model to the GUI: the canonical local URL, the "this page" referent, the update contract (the reload receiver is always on; no-refresh reloads additionally need the `pnpm run dev:web` watcher), and the instruction not to start replacement servers. `DSH_WEB_URL` additionally appears in the managed bash environment with its description, resolved per invocation from the live server. When it is false, neither section nor the variable is registered.
143
+ 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 (first-party order 10100, after reusable instructions) orients the model to the GUI: the advertised application URL (defined under Listening, trust, and public deployments above), the "this page" referent, the update contract (the reload receiver is always on; no-refresh reloads additionally need the `pnpm run dev:web` watcher), and the instruction not to start replacement servers. `DSH_WEB_URL` additionally appears in the managed bash environment with its description, resolved per invocation from the live server. When it is false, neither section nor the variable is registered.
137
144
 
138
145
  #### Token effect
139
146
 
@@ -141,7 +148,7 @@ One source line and one prompt paragraph per session plus two managed-environmen
141
148
 
142
149
  #### KV Cache effect
143
150
 
144
- Source and Web sections follow first-party reusable instructions. Different checkout paths or local ports leave that preceding prefix unchanged when tools and configuration match; provider cache reuse is not guaranteed.
151
+ Source and Web sections follow first-party reusable instructions. Different checkout paths or application URLs leave that preceding prefix unchanged when tools and configuration match; provider cache reuse is not guaranteed.
145
152
 
146
153
  ## Known Limitations and Deferred Work
147
154
 
@@ -151,9 +158,10 @@ Source and Web sections follow first-party reusable instructions. Different chec
151
158
  These limits tell you what to expect in unusual setups — a source checkout, SSH sessions, or strict networks. They are current package constraints, not a general browser comparison or a task backlog.
152
159
 
153
160
  - **The frontend must be built** — a source checkout needs `pnpm run build` first; startup stops with a build hint when the dist is missing, and there is no source-serving fallback.
161
+ - **The listener has no TLS** — protect the external leg with a TLS-terminating proxy; an HTTP advertised root sends credentials without encryption.
154
162
  - **LAN addresses are sampled once at startup** — interface changes after boot are not re-advertised; the printed LAN URL always matches what was sampled.
155
163
  - **Only the handoff start is observable** — the GUI reports that the browser was asked to open, not that it actually opened; a later browser exit is never reported, and the printed URL is your manual fallback.
156
- - **SSH sessions keep the URL but skip the browser handoff** — the printed URL names the remote host's loopback endpoint; the SSH client or editor must expose and open the local forwarded address.
164
+ - **SSH sessions keep the URL but skip the browser handoff** — without an advertised root the printed URL names the remote host's loopback endpoint; the SSH client or editor must expose and open the local forwarded address.
157
165
  - **`BROWSER` overrides only come from the environment** — a discovered `.env` cannot set `BROWSER`; only an inherited value can choose the executable for the automatic handoff.
158
166
  - **Binding all network interfaces is not supported** — `--host 0.0.0.0` is rejected at startup for safety; use the default loopback host.
159
167
 
package/README.zh.md CHANGED
@@ -13,7 +13,7 @@ kind: "package-bundle"
13
13
 
14
14
  ## 概述
15
15
 
16
- 运行 `dsh --profile web`,打开提供聊天、模型与设置管理以及会话历史的交互式浏览器 GUI。它使用与其他 dsh 表层相同的模型访问、工具与安全默认值。启动时会打印带认证信息的 URL,通常还会在默认浏览器中打开;SSH 会话和 `--no-open` 会保留该 URL,供你手动打开。你可以更改端口并允许额外主机,但不能绑定所有网络接口。需要在浏览器中交互式工作时选择本包;一次性的命令行任务应使用 `dsh-headless`。
16
+ 运行 `dsh --profile web`,获得浏览器内的聊天、模型与设置管理以及会话历史,并与其他 dsh 表层共用同一套模型访问、工具与安全默认值。启动时会打印带 token 的 URL,通常还会在默认浏览器中打开;SSH 会话和 `--no-open` 需要手动打开。你可以更改端口并允许额外主机,但不能绑定所有网络接口。跨机访问支持在剥离前缀的代理之后公告一个公开的 HTTP(S) URL。一次性的命令行任务应使用 `dsh-headless`。
17
17
 
18
18
  ## 目录
19
19
 
@@ -46,24 +46,30 @@ dsh --profile web --no-open --port 8080
46
46
 
47
47
  ### 配置
48
48
 
49
- 大多数用户不需要设置这些;命令行 flag 会提供给下面四个设置——`--host`、`--port` 与 `--trusted-host` 来自本次调用,`--no-open` 仅对本次调用关闭浏览器交接:
49
+ `--host` 与 `--port` 配置监听器;`--public-url` 指定 GUI 在剥离前缀的代理之后对外公告的公开 HTTP(S) 根,`--trusted-host` 则添加更多被接受的 authority。两者都在[监听、信任与公开部署](#public-deployments)中说明:
50
50
 
51
51
  | 字段 | 默认值 | 含义 |
52
52
  |---|---|---|
53
53
  | `openBrowser` | `true` | 启动后用默认浏览器打开;SSH 启动会抑制它 |
54
54
  | `printUrl` | `true` | 启动时打印 `dsh web:` URL 行 |
55
55
  | `surfaceContext` | `true` | 给 agent 提供 GUI 定位上下文,并把 `DSH_WEB_URL` 暴露给其 shell 命令 |
56
+ | `publicUrl` | 未设置 | 对外公告的 HTTP(S) 应用根;否则公告监听器的 loopback URL |
56
57
  | `trustedHosts` | `[]` | 允许从网络访问 GUI 的额外主机 |
57
58
 
58
- 生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-web-app)是每个受支持字段及其 JSDoc 的穷尽式真源。 随发行版交付的组合不含 `time-context`、`schedule` 和 `ui-schedule` 行,可选实验性 bundle `@deepseek-ai/dsh-experimental-schedule-bundle` 可在插件管理页插入这三行。
59
+ 生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-web-app)列出了本运行时插件接受的字段及其 JSDoc。随发行版交付的组合插入 `schedule` 服务行与 `ui-schedule` 任务页面行,时钟读数与四个提醒工具则属于 `standard`、`cordis` 与 `ptc` 三个 preset。这三个 preset 的 `tool-subagent` 与 `tool-subagent-fork` 两行都 deny 这四个工具,因此被委派子 agent 的作用域不会列出它们。
59
60
 
60
- ### LAN 访问与可信主机
61
+ <a id="public-deployments"></a>
62
+ ### 监听、信任与公开部署
61
63
 
62
- 默认情况下 GUI 只接受本机的连接。绑定所有网络接口的部署也会允许 LAN 内的浏览器访问,此时打印的 URL 会附带一个 LAN 地址;`--trusted-host` 在两种情况下都能添加额外主机。Host 与 Origin 检查控制可达性,token 交换则认证每个 Host API 方法与 WebSocket 流。LAN 地址只在启动时采样一次,因此之后的网络变化不会被感知——重启 GUI 以重新公告。
64
+ 默认情况下 GUI 只在 loopback 上监听,只接受本机的连接;可重复的 `--trusted-host` 会添加其 Host/Origin 栅栏接受的 authority,因此远端浏览器要么经由剥离前缀的代理访问,要么通过以可信主机名呈现的端口转发客户端访问。
65
+
66
+ `--public-url` 公告浏览器使用的 HTTP(S) 根——打印与打开的启动 URL、`DSH_WEB_URL` 与 web 表层定位。公告不授予任何信任:浏览器可见的 authority 还必须用 `--trusted-host` 点名。该 flag 不配置监听器、路由或 cookie 作用域,因为外部链路归代理所有:[在反向代理之后发布 Web UI](../../../docs/user/guide/public-deployments.zh.md)列出了这样的部署必须提供什么。
67
+
68
+ 打印的 URL 包含进程凭据,只应与预期用户分享;`printUrl: false` 无论是否配置 `--public-url` 都会抑制该行。
63
69
 
64
70
  ### 通过 SSH 运行
65
71
 
66
- 通过 SSH 启动 `dsh --profile web` 时,URL 行仍会打印,但不会为你打开浏览器:本地转发地址由 SSH 客户端或编辑器持有。请在自己的机器上打开转发后的 URL;打印出的 URL 指向远端宿主机 loopback 端点。
72
+ 通过 SSH 启动 `dsh --profile web` 时,URL 行仍会打印,但不会为你打开浏览器:本地转发地址由 SSH 客户端或编辑器持有。没有公告根时,打印的 URL 指向远端宿主机 loopback 端点,你通过自己的转发地址访问它。配置了 `--public-url` 时,打印的 URL 是带认证的公告根;浏览器交接仍被抑制,因为在远端宿主机上打开浏览器无法到达你的屏幕。
67
73
 
68
74
  ### 按会话的 agent 设置
69
75
 
@@ -77,11 +83,15 @@ dsh --profile web --no-open --port 8080
77
83
  <details>
78
84
  <summary>实现细节——点击展开</summary>
79
85
 
80
- 此 bundle 由一层五个文件的补丁和一个运行时胶水插件组成:`cordis.patch.yml` 承载宿主行和 preset 注册表,每个 `presets/<id>.patch.yml` 插入一条随发行版交付的 preset 声明,按 `dsh.bundle.patch` 列出的顺序应用。存储栈与投影缓存来自 `dsh-base`;Web 叠加层的工作区和消息反馈条目消费共享的 `storageDomain` 服务。补丁重述 base 有意省略的界面专用值,插入 Web 专用宿主条目和浏览器插件列表,再将 Agent 层移到预设后面。胶水插件负责 dist 服务、信任采样、提示词段落、bash 变量和就绪通知。`office-to-pdf` 条目为宿主消费者挂载一个延迟创建引擎的 [Office 转换提供方](../../document/office-to-pdf/README.zh.md),使用此 bundle 的 Desktop 组合也共享该提供方。 转换服务的 Remote 方法负责预览读取授权,Document Preview 负责 Office 查看器和客户端缓存。
86
+ 此 bundle 由一层五个文件的补丁和一个运行时胶水插件组成:`cordis.patch.yml` 承载宿主行和 preset 注册表,每个 `presets/<id>.patch.yml` 插入一条随发行版交付的 preset 声明,按 `dsh.bundle.patch` 列出的顺序应用。存储栈与投影缓存来自 `dsh-base`;Web 叠加层的工作区和消息反馈条目消费共享的 `storageDomain` 服务。补丁重述 base 有意省略的界面专用值,插入 Web 专用宿主条目和浏览器插件列表,再将 Agent 层移到预设后面。胶水插件负责 dist 服务、公告应用 URL、信任采样、提示词段落、bash 变量和就绪通知。`office-to-pdf` 条目为宿主消费者挂载一个延迟创建引擎的 [Office 转换提供方](../../document/office-to-pdf/README.zh.md),使用此 bundle 的 Desktop 组合也共享该提供方。 转换服务的 Remote 方法负责预览读取授权,Document Preview 负责 Office 查看器和客户端缓存。
81
87
 
82
88
  ### patch 语义
83
89
 
84
- patch 会替换目标行的整个 `config`,因此每个 Web 行都重述自己拥有的每个键:基础行上的 persona 前缀与后缀模板、`DSH_TOOLS_MODE` PTC mode 开关与 `session-query-sqlite` 值,随后 `insert` 添加 Web 宿主行、传输层与浏览器名录。base 以进程级挂载的按 agent 工具行在这里被禁用,由 preset 名录接管;每项宿主层与 preset 层归属决策的理由以行内注释写在 patch 里。
90
+ patch 会替换目标行的整个 `config`,因此每个 Web 行都重述自己拥有的每个键:基础行上的 persona 前缀与后缀模板、`DSH_TOOLS_MODE` PTC mode 开关与 `session-query-sqlite` 值,随后 `insert` 添加 Web 宿主行、传输层与浏览器名录。`webserver` 与 `web-runtime` 行注入 `webStartup` 提供方并直接读取本次调用的取值;`connection` 行则改为读取 web-runtime 行发布的、与绑定相关的 `webRuntime` 值,即该提供方的 authority 加上全接口绑定的 LAN 字面量。base 以进程级挂载的按 agent 工具行在这里被禁用,由 preset 名录接管;每项宿主层与 preset 层归属决策的理由以行内注释写在 patch 里。
91
+
92
+ ### 公告应用 URL
93
+
94
+ 启动显示与浏览器交接接收附带启动 token 的公告根;web 表层提示词与 `DSH_WEB_URL` 接收不含凭据的形式。根本身由[监听、信任与公开部署](#public-deployments)定义。
85
95
 
86
96
  ### 就绪宣告
87
97
 
@@ -95,20 +105,17 @@ URL 行与浏览器交接都是就绪信号:监督方一观察到该行就发
95
105
 
96
106
  | 文件 | 职责 |
97
107
  |---|---|
98
- | [`src/index.ts`](src/index.ts) | `web-app` 粘合插件:dist 解析、LAN 信任采样、提示词段落、bash 变量、URL 行、浏览器交接 |
99
- | [`src/startup.ts`](src/startup.ts) | `web-startup` 提供方:`--host`、`--port`、`--trusted-host`、`--no-open`、`--help` |
108
+ | [`src/index.ts`](src/index.ts) | `web-app` 粘合插件:dist 解析、公告应用 URL、LAN 信任采样、提示词段落、bash 变量、URL 行、浏览器交接 |
109
+ | [`src/public-url.ts`](src/public-url.ts) | 公告根的校验与尾斜杠归一化;供本地导入的叶子模块,不属于包 API |
110
+ | [`src/startup.ts`](src/startup.ts) | `web-startup` 提供方:`--host`、`--port`、`--public-url`、`--trusted-host`、`--no-open`、`--help` |
100
111
  | [`cordis.patch.yml`](cordis.patch.yml) | Web patch:重述的基础值、Web 宿主行、浏览器名录、preset 注册表 |
101
112
  | [`presets/`](presets) | 每个随发行版交付的 preset(`standard`、`ptc`、`minimal`、`cordis`)各一条 `@deepseek-ai/dsh-agent-preset` 声明,各自一个补丁文件 |
102
- | — | 不发布运行时不变式伴生入口;每项贡献(frontend-static 子插件、提示词段落、bashEnv 注册)都会随 fiber 由注册表释放,且每个所属注册表的包负责该关系的不变式;本包不持有需要审计的可变状态。 |
103
- | [`tests/web-app.spec.ts`](tests/web-app.spec.ts) | dist 解析、回退席位、提示词段落、就绪宣告 |
113
+ | [`tests/web-app.spec.ts`](tests/web-app.spec.ts) | dist 解析、回退席位、提示词段落、就绪宣告、公告 URL 发布 |
104
114
  | [`tests/startup.spec.ts`](tests/startup.spec.ts) | 在真实 Loader 树上的命令行解析 |
115
+ | [`tests/public-url.spec.ts`](tests/public-url.spec.ts) | 公告根的解析与归一化 |
105
116
  | [`tests/trusted-hosts.spec.ts`](tests/trusted-hosts.spec.ts) | LAN 信任采样 |
106
117
  | [`tests/browser-open.spec.ts`](tests/browser-open.spec.ts) | 页面可达后的默认浏览器交接 |
107
118
 
108
- ### 不变式归属
109
-
110
- 不发布不变式伴生入口,因为每项贡献——frontend-static 子插件、提示词段落与 bash 变量注册——都会随 fiber 由注册表释放,且每个所属注册表的包负责该关系的不变式。
111
-
112
119
  </details>
113
120
 
114
121
  -----
@@ -133,7 +140,7 @@ URL 行与浏览器交接都是就绪信号:监督方一观察到该行就发
133
140
 
134
141
  #### 模型看到什么
135
142
 
136
- 当 `surfaceContext` 为 true 时,`harness:source` 段落标明磁盘上的 Harness 实现,但不会声称它就是工作目录;全局段落 `app:web-surface`(first-party 顺序 10100,位于可复用指令之后)则向模型说明 GUI:规范的本地 URL、「this page」指代什么、更新约定(重载接收端始终开启;无刷新重载还需要 `pnpm run dev:web` watcher),以及不要启动替代服务器的指令。`DSH_WEB_URL` 还会连同描述出现在受管 bash 环境中,每次调用时从运行中的服务器解析。当它为 false 时,这两个段落和该变量都不会注册。
143
+ 当 `surfaceContext` 为 true 时,`harness:source` 段落标明磁盘上的 Harness 实现,但不会声称它就是工作目录;全局段落 `app:web-surface`(first-party 顺序 10100,位于可复用指令之后)则向模型说明 GUI:公告应用 URL(定义见上文「监听、信任与公开部署」)、「this page」指代什么、更新约定(重载接收端始终开启;无刷新重载还需要 `pnpm run dev:web` watcher),以及不要启动替代服务器的指令。`DSH_WEB_URL` 还会连同描述出现在受管 bash 环境中,每次调用时从运行中的服务器解析。当它为 false 时,这两个段落和该变量都不会注册。
137
144
 
138
145
  #### Token 影响
139
146
 
@@ -141,7 +148,7 @@ URL 行与浏览器交接都是就绪信号:监督方一观察到该行就发
141
148
 
142
149
  #### KV Cache 影响
143
150
 
144
- 源码与 Web 段落位于第一方可复用指令之后。工具与配置一致时,不同 checkout 路径或本地端口不会改变前置前缀;不保证提供方复用缓存。
151
+ 源码与 Web 段落位于第一方可复用指令之后。工具与配置一致时,不同 checkout 路径或应用 URL 不会改变前置前缀;不保证提供方复用缓存。
145
152
 
146
153
  ## 已知限制与延期工作
147
154
 
@@ -151,9 +158,10 @@ URL 行与浏览器交接都是就绪信号:监督方一观察到该行就发
151
158
  这些限制告诉你在不常见的环境下会遇到什么——源码 checkout、SSH 会话或严格网络。它们是当前包约束,不是通用的浏览器对比或任务积压。
152
159
 
153
160
  - **前端必须已构建**——源码 checkout 需要先运行 `pnpm run build`;dist 缺失时启动会以构建提示停止,且没有从源码直接服务的回退路径。
161
+ - **监听器不提供 TLS**——请用终止 TLS 的代理保护外部链路;HTTP 公告根会以明文发送凭据。
154
162
  - **LAN 地址只在启动时采样一次**——启动后的网卡变化不会重新公告;打印的 LAN URL 始终与采样结果一致。
155
163
  - **只能观察到交接的启动**——GUI 只报告浏览器被请求打开,而不是它确实打开了;之后的浏览器退出永远不会上报,打印的 URL 是你的手动回退路径。
156
- - **SSH 会话保留 URL 但跳过浏览器交接**——打印的 URL 指向远端宿主机 loopback 端点;SSH 客户端或编辑器必须暴露并打开本地转发地址。
164
+ - **SSH 会话保留 URL 但跳过浏览器交接**——没有公告根时,打印的 URL 指向远端宿主机 loopback 端点;SSH 客户端或编辑器必须暴露并打开本地转发地址。
157
165
  - **`BROWSER` 覆盖只能来自环境**——被发现的 `.env` 不能设置 `BROWSER`;只有继承值能为自动交接选择可执行文件。
158
166
  - **不支持绑定所有网络接口**——出于安全考虑,`--host 0.0.0.0` 会在启动时被拒绝;请使用默认 loopback 主机。
159
167
 
package/cordis.patch.yml CHANGED
@@ -9,7 +9,7 @@
9
9
  # ordinary Cordis service. Rows configured from flags inject that service, so
10
10
  # Loader resolves their expressions only after it exists. The web runtime then
11
11
  # provides bind-dependent `webRuntime` values to the trust fence.
12
- # `dsh --profile web --help` provides neither service, so no server binds.
12
+ # `dsh --profile web --help` provides no `webStartup`, so no server binds.
13
13
 
14
14
  # ── surface-specific values the base deliberately omits ─────────────────────
15
15
 
@@ -132,6 +132,13 @@
132
132
  - id: workspace-files
133
133
  name: '@deepseek-ai/dsh-api-workspace-files'
134
134
 
135
+ # The Schedule service owns the task store and delivers each due occurrence
136
+ # as a follow-up in its original Session. The clock reading and the four
137
+ # reminder tools belong to the `standard`, `cordis`, and `ptc` presets,
138
+ # which declare them in their own scope.
139
+ - id: schedule
140
+ name: '@deepseek-ai/dsh-schedule'
141
+
135
142
  # Configuration-surface reads and writes over Typert Remote. Each method
136
143
  # reports an actionable error when its settings-domain provider is absent.
137
144
  - id: ui-settings-account
@@ -164,8 +171,10 @@
164
171
  # ── layer 2: transport/service ──────────────────────────────────────────────
165
172
 
166
173
  # Plain route-registration carrier; host and port come from the app's
167
- # webStartup provider, with these deployment fallbacks. The dist is served by
168
- # the web-runtime row below through the fallback seat.
174
+ # webStartup provider, with these deployment fallbacks. The dist is served
175
+ # by the web-runtime row below through the fallback seat. Routing and
176
+ # browser-facing asset paths do not depend on the advertised URL, which the
177
+ # web-runtime row owns.
169
178
  - id: webserver
170
179
  name: '@deepseek-ai/dsh-host-webserver'
171
180
  inject: [webStartup]
@@ -180,18 +189,20 @@
180
189
  # assembly fact of dsh-web-app, never user config), mounts the
181
190
  # frontend-static fallback owner, registers the web-surface prompt
182
191
  # section and the bash runtime variable, prints the URL line, and opens the
183
- # canonical local URL after the full Loader tree settles and the required-
184
- # entry audit passes. The
185
- # webStartup provider supplies invocation-only values; after the server binds, this row samples
186
- # LAN trust once and provides `webRuntime`. A complete agent-preset persona
187
- # suppresses the prompt section for that agent while retaining the host-owned
188
- # shell variable.
192
+ # canonical URL after the full Loader tree settles and the required-
193
+ # entry audit passes. Invocation-only values come from the webStartup
194
+ # provider; the advertised application URL is this row's `publicUrl` (the
195
+ # loopback URL when unset). After the server binds, this row samples LAN
196
+ # trust once and provides `webRuntime`. A complete agent-preset persona
197
+ # suppresses the prompt section for that agent while retaining the
198
+ # host-owned shell variable.
189
199
  - id: web-runtime
190
200
  name: '@deepseek-ai/dsh-web-app'
191
201
  inject: [webStartup]
192
202
  config:
193
203
  openBrowser: !!js ctx.webStartup.openBrowser
194
204
  printUrl: true
205
+ publicUrl: !!js ctx.webStartup.publicUrl
195
206
  surfaceContext: true
196
207
  trustedHosts: !!js ctx.webStartup.trustedHosts
197
208
 
@@ -212,7 +223,9 @@
212
223
  name: '@deepseek-ai/dsh-client-modules'
213
224
 
214
225
  # Owns both ends of the web transport: node half binds the gateway to the
215
- # webserver under /api; browser half is the fetch/SSE client.
226
+ # webserver under /api; browser half is the fetch/SSE client. Every API
227
+ # request and upgrade passes the loopback plus trustedHosts policy; an
228
+ # advertised public URL contributes nothing to it.
216
229
  - id: connection
217
230
  name: '@deepseek-ai/dsh-client-connection'
218
231
  inject: [webRuntime]
@@ -371,6 +384,11 @@
371
384
  - id: ui-jobs
372
385
  name: '@deepseek-ai/dsh-client-ui-jobs'
373
386
 
387
+ # Task management and Session reminder catalog over the Host Schedule
388
+ # service mounted above.
389
+ - id: ui-schedule
390
+ name: '@deepseek-ai/dsh-client-ui-schedule'
391
+
374
392
  # Goal surface: GoalBar in the input dock over the goal session projection.
375
393
  - id: ui-goal
376
394
  name: '@deepseek-ai/dsh-client-ui-goal'
package/lib/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { t as parsePublicUrl } from "./public-url-D_dMK-yI.js";
1
2
  import { createRequire } from "node:module";
2
3
  import { spawn } from "node:child_process";
3
4
  import { dirname, join } from "node:path";
@@ -16,9 +17,10 @@ import { scrubbedParentEnv } from "@deepseek-ai/dsh-subprocess";
16
17
  * the built frontend dist (workspace knowledge of this bundle, never user
17
18
  * config), mounts the `frontend-static` fallback owner over it, registers the
18
19
  * harness-source and web-surface prompt sections, the bash-visible web runtime
19
- * variable, the process-token URL line, and the default-browser handoff. The
20
- * model and shell retain the clean URL. App command-line values arrive through
21
- * the `webStartup` service expressions in the bundle patch.
20
+ * variable, the process-token URL line, and the default-browser handoff. An
21
+ * advertised `publicUrl` replaces the published root — the loopback URL
22
+ * otherwise. App command-line values arrive through the `webStartup` service
23
+ * expressions in the bundle patch.
22
24
  * @module @deepseek-ai/dsh-web-app
23
25
  */
24
26
  /** Stable Cordis plugin name. */
@@ -34,9 +36,10 @@ const Config = z.object({
34
36
  openBrowser: z.boolean().default(true),
35
37
  printUrl: z.boolean().default(true),
36
38
  surfaceContext: z.boolean().default(true),
39
+ publicUrl: z.transform(z.string(), (value) => parsePublicUrl(value).href),
37
40
  trustedHosts: z.array(String).default([])
38
41
  });
39
- /** Environment variable naming the canonical local URL of this Web GUI. */
42
+ /** Environment variable naming the advertised URL of this Web GUI. */
40
43
  const DSH_WEB_URL = "DSH_WEB_URL";
41
44
  const LOOPBACK_HOST = "127.0.0.1";
42
45
  /** The webserver schema's all-interfaces bind literal. */
@@ -97,6 +100,10 @@ function localWebUrl(ctx) {
97
100
  if (port === void 0) throw new Error("web-app: webServer service missing while resolving Web runtime");
98
101
  return `http://${LOOPBACK_HOST}:${String(port)}`;
99
102
  }
103
+ function appRootUrl(ctx, publicUrl) {
104
+ if (publicUrl !== void 0) return publicUrl;
105
+ return localWebUrl(ctx);
106
+ }
100
107
  /**
101
108
  * Dist location is workspace knowledge of this bundle: anchored on the
102
109
  * frontend package manifest, not configured. Existence is a request-time
@@ -171,6 +178,7 @@ const internals = {
171
178
  */
172
179
  function apply(ctx, config) {
173
180
  const runtime = resolveLanTrust(ctx.webServer.host, config.trustedHosts);
181
+ const publicUrl = config.publicUrl ?? void 0;
174
182
  const handoffBrowser = config.openBrowser && !launchedThroughSsh(launchEnvironmentOf(ctx));
175
183
  ctx.provide(WEB_RUNTIME_SERVICE, runtime);
176
184
  ctx.plugin(FrontendStatic, { distIndex: internals.resolveDistIndex() });
@@ -180,21 +188,21 @@ function apply(ctx, config) {
180
188
  promptCtx.systemPrompt.section({
181
189
  name: "app:web-surface",
182
190
  order: promptCtx.systemPrompt.getSectionOrder("WEB_SURFACE"),
183
- text: () => webSurfacePrompt(localWebUrl(promptCtx))
191
+ text: () => webSurfacePrompt(appRootUrl(promptCtx, publicUrl))
184
192
  });
185
193
  });
186
194
  ctx.inject(["shellEnv"], (runtimeCtx) => {
187
195
  runtimeCtx.shellEnv.register({
188
196
  name: "web-runtime",
189
- variables: { [DSH_WEB_URL]: { description: "Canonical local URL of the DeepSeek Harness Web GUI serving this session." } },
190
- resolve: () => ({ [DSH_WEB_URL]: localWebUrl(runtimeCtx) })
197
+ variables: { [DSH_WEB_URL]: { description: "Advertised URL of the DeepSeek Harness Web GUI serving this session." } },
198
+ resolve: () => ({ [DSH_WEB_URL]: appRootUrl(runtimeCtx, publicUrl) })
191
199
  });
192
200
  });
193
201
  }
194
202
  if (config.printUrl || handoffBrowser) ctx.inject(["connection"], (connectionCtx) => {
195
203
  const announceReady = () => {
196
204
  if (ANNOUNCED_ROOTS.has(connectionCtx.root)) return;
197
- const webUrl = localWebUrl(connectionCtx);
205
+ const webUrl = appRootUrl(connectionCtx, publicUrl);
198
206
  const authenticatedUrl = connectionCtx.connection.authenticatedUrl(webUrl);
199
207
  const lanCandidate = runtime.lanAddresses[0];
200
208
  const port = connectionCtx.webServer.port;
@@ -0,0 +1,29 @@
1
+ //#region lib/types/public-url.js
2
+ /**
3
+ * Canonical public HTTP(S) root parsing shared by this bundle's `publicUrl`
4
+ * config and its CLI startup provider.
5
+ * @module @deepseek-ai/dsh-web-app/public-url
6
+ */
7
+ /**
8
+ * Parse the advertised public HTTP(S) root of a prefix-stripping proxy
9
+ * deployment, rejecting the hazards WHATWG URL parsing would accept on its own,
10
+ * then normalize the path to end in `/`.
11
+ * @param value - advertised public HTTP(S) root.
12
+ * @param label - field name or CLI flag included in rejection messages.
13
+ * @returns the parsed URL with a trailing-slash pathname.
14
+ * @throws when the value is not a usable advertised root, naming the reason.
15
+ */
16
+ function parsePublicUrl(value, label = "publicUrl") {
17
+ if (/[\u0000-\u0020\u007f]/u.test(value)) throw new Error(`${label} must not contain ASCII whitespace or control characters`);
18
+ if (!/^https?:\/\//iu.test(value)) throw new Error(`${label} must be an absolute http or https URL of the form http(s)://host[/prefix]`);
19
+ if (value.includes("?") || value.includes("#")) throw new Error(`${label} must not include a query or fragment (? or #)`);
20
+ const [authority = ""] = value.slice(value.indexOf("://") + 3).split(/[/\\]/, 1);
21
+ if (authority === "") throw new Error(`${label} must name a host after http:// or https://`);
22
+ if (authority.includes("@")) throw new Error(`${label} must not include credentials (a username or password before @, including an empty user)`);
23
+ const url = URL.parse(value);
24
+ if (url === null) throw new Error(`${label} must be an absolute http or https URL`);
25
+ if (!url.pathname.endsWith("/")) url.pathname += "/";
26
+ return url;
27
+ }
28
+ //#endregion
29
+ export { parsePublicUrl as t };
package/lib/startup.js CHANGED
@@ -1,11 +1,13 @@
1
+ import { t as parsePublicUrl } from "./public-url-D_dMK-yI.js";
1
2
  import { Command } from "commander";
2
3
  import { parseCmdline } from "@deepseek-ai/dsh-cmdline";
3
4
  //#region lib/types/startup.js
4
5
  /**
5
6
  * The web app's command-line provider: it parses the `dsh --profile web` flag
6
- * family (`--host`, `--port`, `--trusted-host`, `--no-open`) and its `--help`
7
- * text, then provides the immutable values as {@link WEB_STARTUP_SERVICE}.
8
- * Ordinary rows inject that service before reading it from lazy config.
7
+ * family (`--host`, `--port`, `--public-url`, `--trusted-host`, `--no-open`)
8
+ * and its `--help` text, then provides the immutable values as
9
+ * {@link WEB_STARTUP_SERVICE}. Ordinary rows inject that service before
10
+ * reading it from lazy config.
9
11
  * @module @deepseek-ai/dsh-web-app/startup
10
12
  */
11
13
  /** Stable Cordis plugin name. */
@@ -19,18 +21,20 @@ const WEB_STARTUP_SERVICE = "webStartup";
19
21
  * @returns a fresh program, so one process can parse more than once (tests).
20
22
  */
21
23
  function webCommand() {
22
- return new Command().name("dsh --profile web").description("Serve the DeepSeek Harness browser UI.").helpOption("-h, --help", "show this help").option("--host <host>", "bind host").option("--no-open", "do not open the Web UI in the default browser").option("--port <port>", "listen port; pass 0 to let the OS pick a free one").option("--trusted-host <authority...>", "extra authority the /api browser-trust fence accepts (host or host:port; repeatable)").addHelpText("after", `
24
+ return new Command().name("dsh --profile web").description("Serve the DeepSeek Harness browser UI.").helpOption("-h, --help", "show this help").option("--host <host>", "bind host").option("--no-open", "do not open the Web UI in the default browser").option("--port <port>", "listen port; pass 0 to let the OS pick a free one").option("--public-url <url>", "advertise this HTTP(S) root in the printed, opened, web-surface, and DSH_WEB_URL forms; grants no trust").option("--trusted-host <authority...>", "extra authority the /api browser-trust fence accepts (host or host:port; repeatable)").addHelpText("after", `
23
25
  Examples:
24
26
  dsh --profile web serve on the composed host and port
25
27
  dsh --profile web --no-open serve without opening a browser
26
28
  dsh --profile web --port 8080 serve on another port
29
+ dsh --profile web --public-url https://app.example/ui/ --trusted-host app.example
30
+ advertise a prefix-stripping HTTPS proxy entry and admit its authority
27
31
  `);
28
32
  }
29
33
  /**
30
34
  * Parse and provide the Web invocation as an ordinary Cordis service. The
31
- * command's action publishes the flags this invocation named; `--host 0.0.0.0`
32
- * or a non-numeric `--port` is a usage error, so on rejection (and on `--help`)
33
- * nothing is provided.
35
+ * command's action publishes the flags this invocation named; `--host 0.0.0.0`,
36
+ * a non-numeric `--port`, or a malformed `--public-url` is a usage error, so on
37
+ * rejection (and on `--help`) nothing is provided.
34
38
  * @param ctx - plugin context carrying the command line.
35
39
  */
36
40
  function apply(ctx) {
@@ -39,10 +43,16 @@ function apply(ctx) {
39
43
  const options = program.opts();
40
44
  if (options.host === "0.0.0.0") program.error("error: --host 0.0.0.0 is intentionally not supported yet for safety: it would expose remote code execution to the network; use 127.0.0.1 instead");
41
45
  if (options.port !== void 0 && !/^\d+$/.test(options.port)) program.error(`error: --port must be a number, got ${JSON.stringify(options.port)}`);
46
+ if (options.publicUrl !== void 0) try {
47
+ parsePublicUrl(options.publicUrl, "--public-url");
48
+ } catch (error) {
49
+ program.error(`error: ${error.message}`);
50
+ }
42
51
  ctx.provide(WEB_STARTUP_SERVICE, {
43
52
  openBrowser: options.open,
44
53
  ...options.host !== void 0 && { host: options.host },
45
54
  ...options.port !== void 0 && { port: Number(options.port) },
55
+ ...options.publicUrl !== void 0 && { publicUrl: options.publicUrl },
46
56
  trustedHosts: options.trustedHost ?? []
47
57
  });
48
58
  });
@@ -5,9 +5,10 @@
5
5
  * the built frontend dist (workspace knowledge of this bundle, never user
6
6
  * config), mounts the `frontend-static` fallback owner over it, registers the
7
7
  * harness-source and web-surface prompt sections, the bash-visible web runtime
8
- * variable, the process-token URL line, and the default-browser handoff. The
9
- * model and shell retain the clean URL. App command-line values arrive through
10
- * the `webStartup` service expressions in the bundle patch.
8
+ * variable, the process-token URL line, and the default-browser handoff. An
9
+ * advertised `publicUrl` replaces the published root — the loopback URL
10
+ * otherwise. App command-line values arrive through the `webStartup` service
11
+ * expressions in the bundle patch.
11
12
  * @module @deepseek-ai/dsh-web-app
12
13
  */
13
14
  import type { Context } from '@deepseek-ai/cordis';
@@ -29,6 +30,14 @@ export interface Config {
29
30
  * orientation text would be false.
30
31
  */
31
32
  surfaceContext: boolean;
33
+ /**
34
+ * Canonical HTTP(S) root to advertise in the printed and opened URL,
35
+ * `DSH_WEB_URL`, and the web-surface orientation, e.g.
36
+ * `https://app.example/ui/`, normalized to end in `/`. Advertisement only;
37
+ * see [public deployments](../README.md#public-deployments). Absent or YAML
38
+ * `null` advertises the loopback URL.
39
+ */
40
+ publicUrl?: string;
32
41
  /** Explicit `--trusted-host` authorities from this invocation. */
33
42
  trustedHosts: string[];
34
43
  }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Canonical public HTTP(S) root parsing shared by this bundle's `publicUrl`
3
+ * config and its CLI startup provider.
4
+ * @module @deepseek-ai/dsh-web-app/public-url
5
+ */
6
+ /**
7
+ * Parse the advertised public HTTP(S) root of a prefix-stripping proxy
8
+ * deployment, rejecting the hazards WHATWG URL parsing would accept on its own,
9
+ * then normalize the path to end in `/`.
10
+ * @param value - advertised public HTTP(S) root.
11
+ * @param label - field name or CLI flag included in rejection messages.
12
+ * @returns the parsed URL with a trailing-slash pathname.
13
+ * @throws when the value is not a usable advertised root, naming the reason.
14
+ */
15
+ export declare function parsePublicUrl(value: string, label?: string): URL;
16
+ //# sourceMappingURL=public-url.d.ts.map
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * The web app's command-line provider: it parses the `dsh --profile web` flag
3
- * family (`--host`, `--port`, `--trusted-host`, `--no-open`) and its `--help`
4
- * text, then provides the immutable values as {@link WEB_STARTUP_SERVICE}.
5
- * Ordinary rows inject that service before reading it from lazy config.
3
+ * family (`--host`, `--port`, `--public-url`, `--trusted-host`, `--no-open`)
4
+ * and its `--help` text, then provides the immutable values as
5
+ * {@link WEB_STARTUP_SERVICE}. Ordinary rows inject that service before
6
+ * reading it from lazy config.
6
7
  * @module @deepseek-ai/dsh-web-app/startup
7
8
  */
8
9
  import type { Context } from '@deepseek-ai/cordis';
@@ -20,14 +21,19 @@ export interface WebStartupValues {
20
21
  host?: string;
21
22
  /** `--port`, absent when the invocation did not name one. */
22
23
  port?: number;
24
+ /**
25
+ * `--public-url`, absent when not specified: the advertised HTTP(S) root.
26
+ * See [public deployments](../README.md#public-deployments).
27
+ */
28
+ publicUrl?: string;
23
29
  /** Explicit `--trusted-host` authorities, in argument order. */
24
30
  trustedHosts: string[];
25
31
  }
26
32
  /**
27
33
  * Parse and provide the Web invocation as an ordinary Cordis service. The
28
- * command's action publishes the flags this invocation named; `--host 0.0.0.0`
29
- * or a non-numeric `--port` is a usage error, so on rejection (and on `--help`)
30
- * nothing is provided.
34
+ * command's action publishes the flags this invocation named; `--host 0.0.0.0`,
35
+ * a non-numeric `--port`, or a malformed `--public-url` is a usage error, so on
36
+ * rejection (and on `--help`) nothing is provided.
31
37
  * @param ctx - plugin context carrying the command line.
32
38
  */
33
39
  export declare function apply(ctx: Context): void;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-web-app",
3
3
  "description": "The dsh browser-surface bundle: the web patch layer over dsh-base plus the runtime glue plugin (frontend dist serving, web-surface prompt, bash runtime variables, URL line)",
4
- "version": "0.2.0-rc.2",
4
+ "version": "0.2.1-alpha.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -35,6 +35,7 @@
35
35
  "presets/ptc.patch.yml",
36
36
  "presets/minimal.patch.yml",
37
37
  "presets/cordis.patch.yml",
38
+ "lib/public-url-*.js",
38
39
  "lib/types/**/*.d.ts"
39
40
  ],
40
41
  "license": "MIT",
@@ -52,151 +53,155 @@
52
53
  "dependencies": {
53
54
  "commander": "^15.0.0",
54
55
  "open": "^11.0.0",
55
- "@deepseek-ai/dsh-agent-instructions": "0.2.0-rc.2",
56
- "@deepseek-ai/dsh-agent-preset": "0.2.0-rc.2",
57
- "@deepseek-ai/dsh-agent-preset-registry": "0.2.0-rc.2",
58
- "@deepseek-ai/dsh-api-job-controller": "0.2.0-rc.2",
59
- "@deepseek-ai/dsh-agent-tool-presentation": "0.2.0-rc.2",
60
- "@deepseek-ai/dsh-api-remotes": "0.2.0-rc.2",
61
- "@deepseek-ai/dsh-api-session-controller": "0.2.0-rc.2",
62
- "@deepseek-ai/dsh-api-settings-controller": "0.2.0-rc.2",
63
- "@deepseek-ai/dsh-api-terminal-controller": "0.2.0-rc.2",
64
- "@deepseek-ai/dsh-api-workspace-controller": "0.2.0-rc.2",
65
- "@deepseek-ai/dsh-api-workspace-files": "0.2.0-rc.2",
66
- "@deepseek-ai/dsh-app-boot": "0.2.0-rc.2",
67
- "@deepseek-ai/dsh-client-connection": "0.2.0-rc.2",
68
- "@deepseek-ai/dsh-client-file-upload": "0.2.0-rc.2",
69
- "@deepseek-ai/dsh-client-hmr": "0.2.0-rc.2",
70
- "@deepseek-ai/dsh-client-locale": "0.2.0-rc.2",
71
- "@deepseek-ai/dsh-client-modules": "0.2.0-rc.2",
72
- "@deepseek-ai/dsh-client-resources": "0.2.0-rc.2",
73
- "@deepseek-ai/dsh-client-ui-agent-preset": "0.2.0-rc.2",
74
- "@deepseek-ai/dsh-client-ui-approval": "0.2.0-rc.2",
75
- "@deepseek-ai/dsh-client-ui-attachment": "0.2.0-rc.2",
76
- "@deepseek-ai/dsh-client-ui-brand-official": "0.2.0-rc.2",
77
- "@deepseek-ai/dsh-client-ui-chat": "0.2.0-rc.2",
78
- "@deepseek-ai/dsh-client-ui-commands": "0.2.0-rc.2",
79
- "@deepseek-ai/dsh-client-ui-conversation": "0.2.0-rc.2",
80
- "@deepseek-ai/dsh-client-ui-cordis": "0.2.0-rc.2",
81
- "@deepseek-ai/dsh-client-ui-deliverables": "0.2.0-rc.2",
82
- "@deepseek-ai/dsh-client-ui-directory-picker-browse": "0.2.0-rc.2",
83
- "@deepseek-ai/dsh-client-ui-directory-picker-native": "0.2.0-rc.2",
84
- "@deepseek-ai/dsh-client-ui-goal": "0.2.0-rc.2",
85
- "@deepseek-ai/dsh-client-ui-input-trigger": "0.2.0-rc.2",
86
- "@deepseek-ai/dsh-client-ui-jobs": "0.2.0-rc.2",
87
- "@deepseek-ai/dsh-client-ui-layout": "0.2.0-rc.2",
88
- "@deepseek-ai/dsh-client-ui-message-feedback": "0.2.0-rc.2",
89
- "@deepseek-ai/dsh-client-ui-model-selection": "0.2.0-rc.2",
90
- "@deepseek-ai/dsh-client-ui-open-in-app": "0.2.0-rc.2",
91
- "@deepseek-ai/dsh-client-ui-plan": "0.2.0-rc.2",
92
- "@deepseek-ai/dsh-client-ui-plugin-manager": "0.2.0-rc.2",
93
- "@deepseek-ai/dsh-client-ui-reference": "0.2.0-rc.2",
94
- "@deepseek-ai/dsh-client-ui-renderer": "0.2.0-rc.2",
95
- "@deepseek-ai/dsh-client-ui-session": "0.2.0-rc.2",
96
- "@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.2",
97
- "@deepseek-ai/dsh-client-ui-settings-general": "0.2.0-rc.2",
98
- "@deepseek-ai/dsh-client-ui-settings-models": "0.2.0-rc.2",
99
- "@deepseek-ai/dsh-client-ui-settings-plugin-inventory": "0.2.0-rc.2",
100
- "@deepseek-ai/dsh-client-ui-settings-plugins": "0.2.0-rc.2",
101
- "@deepseek-ai/dsh-client-ui-permission-presets": "0.2.0-rc.2",
102
- "@deepseek-ai/dsh-client-ui-settings-agent-loop": "0.2.0-rc.2",
103
- "@deepseek-ai/dsh-client-ui-settings-subagent": "0.2.0-rc.2",
104
- "@deepseek-ai/dsh-client-ui-settings-web-search": "0.2.0-rc.2",
105
- "@deepseek-ai/dsh-client-ui-sidebar": "0.2.0-rc.2",
106
- "@deepseek-ai/dsh-client-ui-sidebar-browser": "0.2.0-rc.2",
107
- "@deepseek-ai/dsh-client-ui-settings-shell": "0.2.0-rc.2",
108
- "@deepseek-ai/dsh-client-ui-sidebar-documentpreview": "0.2.0-rc.2",
109
- "@deepseek-ai/dsh-client-ui-sidebar-files": "0.2.0-rc.2",
110
- "@deepseek-ai/dsh-client-ui-sidebar-right": "0.2.0-rc.2",
111
- "@deepseek-ai/dsh-client-ui-sidebar-terminal": "0.2.0-rc.2",
112
- "@deepseek-ai/dsh-client-ui-skill": "0.2.0-rc.2",
113
- "@deepseek-ai/dsh-client-ui-subagent": "0.2.0-rc.2",
114
- "@deepseek-ai/dsh-client-ui-tool": "0.2.0-rc.2",
115
- "@deepseek-ai/dsh-client-ui-trajectory": "0.2.0-rc.2",
116
- "@deepseek-ai/dsh-client-ui-user-questions": "0.2.0-rc.2",
117
- "@deepseek-ai/dsh-client-ui-workflow-run": "0.2.0-rc.2",
118
- "@deepseek-ai/dsh-client-ui-workspace": "0.2.0-rc.2",
119
- "@deepseek-ai/dsh-cmdline": "0.2.0-rc.2",
120
- "@deepseek-ai/dsh-command-compact": "0.2.0-rc.2",
121
- "@deepseek-ai/dsh-client-ui-theme": "0.2.0-rc.2",
122
- "@deepseek-ai/dsh-compaction-tool-result-pruner": "0.2.0-rc.2",
123
- "@deepseek-ai/dsh-cordis-client-runner": "0.2.0-rc.2",
124
- "@deepseek-ai/dsh-cordis-host-runner": "0.2.0-rc.2",
125
- "@deepseek-ai/dsh-file-reference": "0.2.0-rc.2",
126
- "@deepseek-ai/dsh-file-reference-local": "0.2.0-rc.2",
127
- "@deepseek-ai/dsh-command-goal": "0.2.0-rc.2",
128
- "@deepseek-ai/dsh-compaction-basic": "0.2.0-rc.2",
129
- "@deepseek-ai/dsh-host-directory-picker-auto": "0.2.0-rc.2",
130
- "@deepseek-ai/dsh-host-directory-picker-browse": "0.2.0-rc.2",
131
- "@deepseek-ai/dsh-host-directory-picker-native": "0.2.0-rc.2",
132
- "@deepseek-ai/dsh-host-frontend-static": "0.2.0-rc.2",
133
- "@deepseek-ai/dsh-host-open-in-app": "0.2.0-rc.2",
134
- "@deepseek-ai/dsh-host-plugin-inventory": "0.2.0-rc.2",
135
- "@deepseek-ai/dsh-host-webserver": "0.2.0-rc.2",
136
- "@deepseek-ai/dsh-launch-environment": "0.2.0-rc.2",
137
- "@deepseek-ai/dsh-message-feedback": "0.2.0-rc.2",
138
- "@deepseek-ai/dsh-office-to-pdf": "0.2.0-rc.2",
139
- "@deepseek-ai/dsh-persona": "0.2.0-rc.2",
140
- "@deepseek-ai/dsh-plan-mode": "0.2.0-rc.2",
141
- "@deepseek-ai/dsh-plugin-manager": "0.2.0-rc.2",
142
- "@deepseek-ai/dsh-session-reference": "0.2.0-rc.2",
143
- "@deepseek-ai/dsh-session-stats": "0.2.0-rc.2",
144
- "@deepseek-ai/dsh-session-turn-outline": "0.2.0-rc.2",
145
- "@deepseek-ai/dsh-skill-filesystem": "0.2.0-rc.2",
146
- "@deepseek-ai/dsh-subprocess": "0.2.0-rc.2",
147
- "@deepseek-ai/dsh-terminal": "0.2.0-rc.2",
148
- "@deepseek-ai/dsh-session-log-export": "0.2.0-rc.2",
149
- "@deepseek-ai/dsh-terminal-bash": "0.2.0-rc.2",
150
- "@deepseek-ai/dsh-tool-bash": "0.2.0-rc.2",
151
- "@deepseek-ai/dsh-tool-bash-persistent": "0.2.0-rc.2",
152
- "@deepseek-ai/dsh-tool-cordis": "0.2.0-rc.2",
153
- "@deepseek-ai/dsh-tool-fs": "0.2.0-rc.2",
154
- "@deepseek-ai/dsh-tool-goal": "0.2.0-rc.2",
155
- "@deepseek-ai/dsh-tool-jobs": "0.2.0-rc.2",
156
- "@deepseek-ai/dsh-tool-ask-user": "0.2.0-rc.2",
157
- "@deepseek-ai/dsh-tool-pwsh": "0.2.0-rc.2",
158
- "@deepseek-ai/dsh-tool-pwsh-persistent": "0.2.0-rc.2",
159
- "@deepseek-ai/dsh-tool-ralph": "0.2.0-rc.2",
160
- "@deepseek-ai/dsh-tool-skill": "0.2.0-rc.2",
161
- "@deepseek-ai/dsh-tool-subagent": "0.2.0-rc.2",
162
- "@deepseek-ai/dsh-tool-subagent-control": "0.2.0-rc.2",
163
- "@deepseek-ai/dsh-tool-present": "0.2.0-rc.2",
164
- "@deepseek-ai/dsh-tool-todo": "0.2.0-rc.2",
165
- "@deepseek-ai/dsh-tool-workflow": "0.2.0-rc.2",
166
- "@deepseek-ai/dsh-web-frontend": "0.2.0-rc.2",
167
- "@deepseek-ai/dsh-workflow-ptc": "0.2.0-rc.2",
168
- "@deepseek-ai/dsh-workspace": "0.2.0-rc.2",
169
- "@deepseek-ai/dsh-workspace-changes": "0.2.0-rc.2",
170
- "@deepseek-ai/schemastery": "~3.18.4",
171
- "@deepseek-ai/dsh-tool-web": "0.2.0-rc.2",
172
- "@deepseek-ai/dsh-client-ui-settings-account": "0.2.0-rc.2",
173
- "@deepseek-ai/dsh-client-shortcuts": "0.2.0-rc.2",
174
- "@deepseek-ai/dsh-client-ui-shortcuts": "0.2.0-rc.2",
175
- "@deepseek-ai/dsh-client-product-analytics": "0.2.0-rc.2",
176
- "@deepseek-ai/dsh-host-product-telemetry-otel": "0.2.0-rc.2",
177
- "@deepseek-ai/dsh-api-account-controller": "0.2.0-rc.2",
178
- "@deepseek-ai/dsh-client-ui-settings-session-log": "0.2.0-rc.2",
179
- "@deepseek-ai/dsh-tool-fs-search": "0.2.0-rc.2"
56
+ "@deepseek-ai/dsh-agent-instructions": "0.2.1-alpha.1",
57
+ "@deepseek-ai/dsh-agent-preset": "0.2.1-alpha.1",
58
+ "@deepseek-ai/dsh-agent-preset-registry": "0.2.1-alpha.1",
59
+ "@deepseek-ai/dsh-agent-tool-presentation": "0.2.1-alpha.1",
60
+ "@deepseek-ai/dsh-api-job-controller": "0.2.1-alpha.1",
61
+ "@deepseek-ai/dsh-api-remotes": "0.2.1-alpha.1",
62
+ "@deepseek-ai/dsh-api-session-controller": "0.2.1-alpha.1",
63
+ "@deepseek-ai/dsh-api-settings-controller": "0.2.1-alpha.1",
64
+ "@deepseek-ai/dsh-api-terminal-controller": "0.2.1-alpha.1",
65
+ "@deepseek-ai/dsh-api-workspace-controller": "0.2.1-alpha.1",
66
+ "@deepseek-ai/dsh-client-connection": "0.2.1-alpha.1",
67
+ "@deepseek-ai/dsh-client-file-upload": "0.2.1-alpha.1",
68
+ "@deepseek-ai/dsh-client-hmr": "0.2.1-alpha.1",
69
+ "@deepseek-ai/dsh-client-locale": "0.2.1-alpha.1",
70
+ "@deepseek-ai/dsh-api-workspace-files": "0.2.1-alpha.1",
71
+ "@deepseek-ai/dsh-app-boot": "0.2.1-alpha.1",
72
+ "@deepseek-ai/dsh-client-modules": "0.2.1-alpha.1",
73
+ "@deepseek-ai/dsh-client-resources": "0.2.1-alpha.1",
74
+ "@deepseek-ai/dsh-client-ui-agent-preset": "0.2.1-alpha.1",
75
+ "@deepseek-ai/dsh-client-ui-attachment": "0.2.1-alpha.1",
76
+ "@deepseek-ai/dsh-client-ui-brand-official": "0.2.1-alpha.1",
77
+ "@deepseek-ai/dsh-client-ui-chat": "0.2.1-alpha.1",
78
+ "@deepseek-ai/dsh-client-ui-commands": "0.2.1-alpha.1",
79
+ "@deepseek-ai/dsh-client-ui-conversation": "0.2.1-alpha.1",
80
+ "@deepseek-ai/dsh-client-ui-cordis": "0.2.1-alpha.1",
81
+ "@deepseek-ai/dsh-client-ui-deliverables": "0.2.1-alpha.1",
82
+ "@deepseek-ai/dsh-client-ui-directory-picker-browse": "0.2.1-alpha.1",
83
+ "@deepseek-ai/dsh-client-ui-directory-picker-native": "0.2.1-alpha.1",
84
+ "@deepseek-ai/dsh-client-ui-goal": "0.2.1-alpha.1",
85
+ "@deepseek-ai/dsh-client-ui-input-trigger": "0.2.1-alpha.1",
86
+ "@deepseek-ai/dsh-client-ui-jobs": "0.2.1-alpha.1",
87
+ "@deepseek-ai/dsh-client-ui-layout": "0.2.1-alpha.1",
88
+ "@deepseek-ai/dsh-client-ui-message-feedback": "0.2.1-alpha.1",
89
+ "@deepseek-ai/dsh-client-ui-model-selection": "0.2.1-alpha.1",
90
+ "@deepseek-ai/dsh-client-ui-open-in-app": "0.2.1-alpha.1",
91
+ "@deepseek-ai/dsh-client-ui-permission-presets": "0.2.1-alpha.1",
92
+ "@deepseek-ai/dsh-client-ui-approval": "0.2.1-alpha.1",
93
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.1-alpha.1",
94
+ "@deepseek-ai/dsh-client-ui-session": "0.2.1-alpha.1",
95
+ "@deepseek-ai/dsh-client-ui-schedule": "0.2.1-alpha.1",
96
+ "@deepseek-ai/dsh-client-ui-reference": "0.2.1-alpha.1",
97
+ "@deepseek-ai/dsh-client-ui-plan": "0.2.1-alpha.1",
98
+ "@deepseek-ai/dsh-client-ui-plugin-manager": "0.2.1-alpha.1",
99
+ "@deepseek-ai/dsh-client-ui-settings-general": "0.2.1-alpha.1",
100
+ "@deepseek-ai/dsh-client-ui-settings": "0.2.1-alpha.1",
101
+ "@deepseek-ai/dsh-client-ui-settings-models": "0.2.1-alpha.1",
102
+ "@deepseek-ai/dsh-client-ui-settings-plugin-inventory": "0.2.1-alpha.1",
103
+ "@deepseek-ai/dsh-client-ui-settings-plugins": "0.2.1-alpha.1",
104
+ "@deepseek-ai/dsh-client-ui-settings-shell": "0.2.1-alpha.1",
105
+ "@deepseek-ai/dsh-client-ui-settings-agent-loop": "0.2.1-alpha.1",
106
+ "@deepseek-ai/dsh-client-ui-settings-subagent": "0.2.1-alpha.1",
107
+ "@deepseek-ai/dsh-client-ui-settings-web-search": "0.2.1-alpha.1",
108
+ "@deepseek-ai/dsh-client-ui-sidebar-browser": "0.2.1-alpha.1",
109
+ "@deepseek-ai/dsh-client-ui-sidebar-documentpreview": "0.2.1-alpha.1",
110
+ "@deepseek-ai/dsh-client-ui-sidebar-files": "0.2.1-alpha.1",
111
+ "@deepseek-ai/dsh-client-ui-sidebar": "0.2.1-alpha.1",
112
+ "@deepseek-ai/dsh-client-ui-sidebar-terminal": "0.2.1-alpha.1",
113
+ "@deepseek-ai/dsh-client-ui-skill": "0.2.1-alpha.1",
114
+ "@deepseek-ai/dsh-client-ui-subagent": "0.2.1-alpha.1",
115
+ "@deepseek-ai/dsh-client-ui-theme": "0.2.1-alpha.1",
116
+ "@deepseek-ai/dsh-client-ui-user-questions": "0.2.1-alpha.1",
117
+ "@deepseek-ai/dsh-cmdline": "0.2.1-alpha.1",
118
+ "@deepseek-ai/dsh-command-compact": "0.2.1-alpha.1",
119
+ "@deepseek-ai/dsh-client-ui-workspace": "0.2.1-alpha.1",
120
+ "@deepseek-ai/dsh-client-ui-sidebar-right": "0.2.1-alpha.1",
121
+ "@deepseek-ai/dsh-command-goal": "0.2.1-alpha.1",
122
+ "@deepseek-ai/dsh-client-ui-workflow-run": "0.2.1-alpha.1",
123
+ "@deepseek-ai/dsh-client-ui-trajectory": "0.2.1-alpha.1",
124
+ "@deepseek-ai/dsh-client-ui-tool": "0.2.1-alpha.1",
125
+ "@deepseek-ai/dsh-compaction-basic": "0.2.1-alpha.1",
126
+ "@deepseek-ai/dsh-compaction-tool-result-pruner": "0.2.1-alpha.1",
127
+ "@deepseek-ai/dsh-cordis-client-runner": "0.2.1-alpha.1",
128
+ "@deepseek-ai/dsh-file-reference": "0.2.1-alpha.1",
129
+ "@deepseek-ai/dsh-cordis-host-runner": "0.2.1-alpha.1",
130
+ "@deepseek-ai/dsh-host-directory-picker-auto": "0.2.1-alpha.1",
131
+ "@deepseek-ai/dsh-host-directory-picker-browse": "0.2.1-alpha.1",
132
+ "@deepseek-ai/dsh-host-directory-picker-native": "0.2.1-alpha.1",
133
+ "@deepseek-ai/dsh-host-open-in-app": "0.2.1-alpha.1",
134
+ "@deepseek-ai/dsh-host-plugin-inventory": "0.2.1-alpha.1",
135
+ "@deepseek-ai/dsh-host-webserver": "0.2.1-alpha.1",
136
+ "@deepseek-ai/dsh-launch-environment": "0.2.1-alpha.1",
137
+ "@deepseek-ai/dsh-persona": "0.2.1-alpha.1",
138
+ "@deepseek-ai/dsh-office-to-pdf": "0.2.1-alpha.1",
139
+ "@deepseek-ai/dsh-message-feedback": "0.2.1-alpha.1",
140
+ "@deepseek-ai/dsh-plan-mode": "0.2.1-alpha.1",
141
+ "@deepseek-ai/dsh-plugin-manager": "0.2.1-alpha.1",
142
+ "@deepseek-ai/dsh-file-reference-local": "0.2.1-alpha.1",
143
+ "@deepseek-ai/dsh-session-log-export": "0.2.1-alpha.1",
144
+ "@deepseek-ai/dsh-host-frontend-static": "0.2.1-alpha.1",
145
+ "@deepseek-ai/dsh-session-stats": "0.2.1-alpha.1",
146
+ "@deepseek-ai/dsh-session-turn-outline": "0.2.1-alpha.1",
147
+ "@deepseek-ai/dsh-terminal": "0.2.1-alpha.1",
148
+ "@deepseek-ai/dsh-subprocess": "0.2.1-alpha.1",
149
+ "@deepseek-ai/dsh-skill-filesystem": "0.2.1-alpha.1",
150
+ "@deepseek-ai/dsh-terminal-bash": "0.2.1-alpha.1",
151
+ "@deepseek-ai/dsh-time-context": "0.2.1-alpha.1",
152
+ "@deepseek-ai/dsh-tool-ask-user": "0.2.1-alpha.1",
153
+ "@deepseek-ai/dsh-tool-bash": "0.2.1-alpha.1",
154
+ "@deepseek-ai/dsh-session-reference": "0.2.1-alpha.1",
155
+ "@deepseek-ai/dsh-tool-cordis": "0.2.1-alpha.1",
156
+ "@deepseek-ai/dsh-tool-fs": "0.2.1-alpha.1",
157
+ "@deepseek-ai/dsh-tool-fs-search": "0.2.1-alpha.1",
158
+ "@deepseek-ai/dsh-schedule": "0.2.1-alpha.1",
159
+ "@deepseek-ai/dsh-tool-bash-persistent": "0.2.1-alpha.1",
160
+ "@deepseek-ai/dsh-tool-goal": "0.2.1-alpha.1",
161
+ "@deepseek-ai/dsh-tool-jobs": "0.2.1-alpha.1",
162
+ "@deepseek-ai/dsh-tool-present": "0.2.1-alpha.1",
163
+ "@deepseek-ai/dsh-tool-pwsh": "0.2.1-alpha.1",
164
+ "@deepseek-ai/dsh-tool-pwsh-persistent": "0.2.1-alpha.1",
165
+ "@deepseek-ai/dsh-tool-ralph": "0.2.1-alpha.1",
166
+ "@deepseek-ai/dsh-tool-schedule": "0.2.1-alpha.1",
167
+ "@deepseek-ai/dsh-tool-skill": "0.2.1-alpha.1",
168
+ "@deepseek-ai/dsh-tool-subagent": "0.2.1-alpha.1",
169
+ "@deepseek-ai/dsh-tool-todo": "0.2.1-alpha.1",
170
+ "@deepseek-ai/dsh-tool-web": "0.2.1-alpha.1",
171
+ "@deepseek-ai/dsh-tool-subagent-control": "0.2.1-alpha.1",
172
+ "@deepseek-ai/dsh-tool-workflow": "0.2.1-alpha.1",
173
+ "@deepseek-ai/dsh-workspace": "0.2.1-alpha.1",
174
+ "@deepseek-ai/dsh-api-account-controller": "0.2.1-alpha.1",
175
+ "@deepseek-ai/dsh-workspace-changes": "0.2.1-alpha.1",
176
+ "@deepseek-ai/schemastery": "~3.18.5-alpha.1",
177
+ "@deepseek-ai/dsh-workflow-ptc": "0.2.1-alpha.1",
178
+ "@deepseek-ai/dsh-client-ui-settings-account": "0.2.1-alpha.1",
179
+ "@deepseek-ai/dsh-client-shortcuts": "0.2.1-alpha.1",
180
+ "@deepseek-ai/dsh-client-ui-shortcuts": "0.2.1-alpha.1",
181
+ "@deepseek-ai/dsh-client-product-analytics": "0.2.1-alpha.1",
182
+ "@deepseek-ai/dsh-host-product-telemetry-otel": "0.2.1-alpha.1",
183
+ "@deepseek-ai/dsh-client-ui-settings-session-log": "0.2.1-alpha.1",
184
+ "@deepseek-ai/dsh-web-frontend": "0.2.1-alpha.1"
180
185
  },
181
186
  "peerDependencies": {
182
- "@deepseek-ai/cordis-plugin-loader": "~1.0.5",
183
- "@deepseek-ai/cordis": "~4.0.4",
184
- "@deepseek-ai/dsh-shell-env": "0.2.0-rc.2",
185
- "@deepseek-ai/dsh-system-prompt": "0.2.0-rc.2"
187
+ "@deepseek-ai/cordis": "~4.0.5-alpha.1",
188
+ "@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.1",
189
+ "@deepseek-ai/dsh-shell-env": "0.2.1-alpha.1",
190
+ "@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.1"
186
191
  },
187
192
  "devDependencies": {
188
- "@deepseek-ai/libreoffice-kit": "^0.1.1",
189
- "@deepseek-ai/cordis": "~4.0.4",
190
- "@deepseek-ai/cordis-plugin-include": "~1.0.9",
191
- "@deepseek-ai/cordis-plugin-loader": "~1.0.5",
192
- "@deepseek-ai/dsh-fs": "0.2.0-rc.2",
193
- "@deepseek-ai/dsh-fs-local": "0.2.0-rc.2",
194
- "@deepseek-ai/dsh-sandbox-policy": "0.2.0-rc.2",
195
- "@deepseek-ai/dsh-session": "0.2.0-rc.2",
196
- "@deepseek-ai/dsh-session-projection": "0.2.0-rc.2",
197
- "@deepseek-ai/dsh-shell-env": "0.2.0-rc.2",
198
- "@deepseek-ai/dsh-system-prompt": "0.2.0-rc.2",
199
- "@deepseek-ai/dsh-otel": "0.2.0-rc.2",
200
- "@deepseek-ai/dsh-typert-registry": "0.2.0-rc.2"
193
+ "@deepseek-ai/libreoffice-kit": "^0.1.5",
194
+ "@deepseek-ai/cordis": "~4.0.5-alpha.1",
195
+ "@deepseek-ai/cordis-plugin-include": "~1.0.10-alpha.1",
196
+ "@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.1",
197
+ "@deepseek-ai/dsh-sandbox-policy": "0.2.1-alpha.1",
198
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.1",
199
+ "@deepseek-ai/dsh-fs": "0.2.1-alpha.1",
200
+ "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.1",
201
+ "@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.1",
202
+ "@deepseek-ai/dsh-fs-local": "0.2.1-alpha.1",
203
+ "@deepseek-ai/dsh-shell-env": "0.2.1-alpha.1",
204
+ "@deepseek-ai/dsh-typert-registry": "0.2.1-alpha.1",
205
+ "@deepseek-ai/dsh-otel": "0.2.1-alpha.1"
201
206
  }
202
207
  }
@@ -20,6 +20,8 @@
20
20
  name: '@deepseek-ai/dsh-agent-instructions'
21
21
  config:
22
22
  maxBytes: 65536
23
+ - id: time-context
24
+ name: '@deepseek-ai/dsh-time-context'
23
25
  - id: tool-bash
24
26
  name: '@deepseek-ai/dsh-tool-bash'
25
27
  disabled: !!js process.platform === 'win32'
@@ -34,6 +36,8 @@
34
36
  sampleOverCapGlobResults: false
35
37
  - id: tool-jobs
36
38
  name: '@deepseek-ai/dsh-tool-jobs'
39
+ - id: tool-schedule
40
+ name: '@deepseek-ai/dsh-tool-schedule'
37
41
  - id: command-goal
38
42
  name: '@deepseek-ai/dsh-command-goal'
39
43
  - id: tool-goal
@@ -93,12 +97,24 @@
93
97
  toolName: subagent
94
98
  modelSelectionSettings: true
95
99
  backgroundMode: continuable
100
+ toolFilter:
101
+ deny:
102
+ - schedule_create
103
+ - schedule_delete
104
+ - schedule_list
105
+ - schedule_update
96
106
  - id: tool-subagent-fork
97
107
  name: '@deepseek-ai/dsh-tool-subagent'
98
108
  config:
99
109
  provider: fork
100
110
  toolName: subagent_fork
101
111
  backgroundMode: continuable
112
+ toolFilter:
113
+ deny:
114
+ - schedule_create
115
+ - schedule_delete
116
+ - schedule_list
117
+ - schedule_update
102
118
  - id: tool-subagent-codex
103
119
  name: '@deepseek-ai/dsh-tool-subagent'
104
120
  disabled: true
@@ -17,6 +17,8 @@
17
17
  name: '@deepseek-ai/dsh-agent-instructions'
18
18
  config:
19
19
  maxBytes: 65536
20
+ - id: time-context
21
+ name: '@deepseek-ai/dsh-time-context'
20
22
  - id: tool-bash
21
23
  name: '@deepseek-ai/dsh-tool-bash'
22
24
  disabled: !!js process.platform === 'win32'
@@ -31,6 +33,8 @@
31
33
  sampleOverCapGlobResults: false
32
34
  - id: tool-jobs
33
35
  name: '@deepseek-ai/dsh-tool-jobs'
36
+ - id: tool-schedule
37
+ name: '@deepseek-ai/dsh-tool-schedule'
34
38
  - id: skill-filesystem
35
39
  name: '@deepseek-ai/dsh-skill-filesystem'
36
40
  - id: tool-skill
@@ -94,12 +98,24 @@
94
98
  toolName: subagent
95
99
  modelSelectionSettings: true
96
100
  backgroundMode: continuable
101
+ toolFilter:
102
+ deny:
103
+ - schedule_create
104
+ - schedule_delete
105
+ - schedule_list
106
+ - schedule_update
97
107
  - id: tool-subagent-fork
98
108
  name: '@deepseek-ai/dsh-tool-subagent'
99
109
  config:
100
110
  provider: fork
101
111
  toolName: subagent_fork
102
112
  backgroundMode: continuable
113
+ toolFilter:
114
+ deny:
115
+ - schedule_create
116
+ - schedule_delete
117
+ - schedule_list
118
+ - schedule_update
103
119
  - id: tool-subagent-codex
104
120
  name: '@deepseek-ai/dsh-tool-subagent'
105
121
  disabled: true
@@ -17,6 +17,8 @@
17
17
  name: '@deepseek-ai/dsh-agent-instructions'
18
18
  config:
19
19
  maxBytes: 65536
20
+ - id: time-context
21
+ name: '@deepseek-ai/dsh-time-context'
20
22
  - id: tool-bash
21
23
  name: '@deepseek-ai/dsh-tool-bash'
22
24
  disabled: !!js process.platform === 'win32'
@@ -31,6 +33,8 @@
31
33
  sampleOverCapGlobResults: false
32
34
  - id: tool-jobs
33
35
  name: '@deepseek-ai/dsh-tool-jobs'
36
+ - id: tool-schedule
37
+ name: '@deepseek-ai/dsh-tool-schedule'
34
38
  - id: skill-filesystem
35
39
  name: '@deepseek-ai/dsh-skill-filesystem'
36
40
  - id: tool-skill
@@ -94,12 +98,24 @@
94
98
  toolName: subagent
95
99
  modelSelectionSettings: true
96
100
  backgroundMode: continuable
101
+ toolFilter:
102
+ deny:
103
+ - schedule_create
104
+ - schedule_delete
105
+ - schedule_list
106
+ - schedule_update
97
107
  - id: tool-subagent-fork
98
108
  name: '@deepseek-ai/dsh-tool-subagent'
99
109
  config:
100
110
  provider: fork
101
111
  toolName: subagent_fork
102
112
  backgroundMode: continuable
113
+ toolFilter:
114
+ deny:
115
+ - schedule_create
116
+ - schedule_delete
117
+ - schedule_list
118
+ - schedule_update
103
119
  - id: tool-subagent-codex
104
120
  name: '@deepseek-ai/dsh-tool-subagent'
105
121
  disabled: true