@deepseek-ai/dsh-web-app 0.1.0-rc.7 → 0.1.1-rc.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 +2 -2
- package/README.md +8 -1
- package/README.zh.md +8 -1
- package/cordis.patch.yml +27 -6
- package/lib/index.js +109 -10
- package/lib/startup.js +4 -2
- package/lib/types/index.d.ts +8 -4
- package/lib/types/startup.d.ts +3 -1
- package/package.json +76 -66
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/bundle/web-app/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: c8a6874bc01696fc7c9ca65faf772da81ac1e964
|
|
6
|
+
README.zh.md: cb58177daa9eb166e29e4169409bbc6a558437e0
|
package/README.md
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
English | [中文](README.zh.md)
|
|
4
4
|
|
|
5
|
-
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, the always-on client-plugin reload chain ([`dsh-client-hmr`](../../client/hmr/README.md), idle until a rebuild watcher rewrites client bundles), and mounts this package's `web-runtime` glue plugin (config `{printUrl, surfaceContext, trustedHosts}`). That plugin resolves the built frontend dist through `@deepseek-ai/dsh-web-frontend`'s exports, samples bind-dependent LAN trust once, provides it as `webRuntime` to the browser-trust fence and client roster, mounts the [`frontend-static`](../../host/frontend-static/README.md) fallback owner, registers the harness-source and web-surface prompt sections plus the bash-visible `DSH_WEB_URL` runtime variable when `surfaceContext` is true,
|
|
5
|
+
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, the always-on client-plugin reload chain ([`dsh-client-hmr`](../../client/hmr/README.md), idle until a rebuild watcher rewrites client bundles), and mounts this package's `web-runtime` glue plugin (config `{openBrowser, printUrl, surfaceContext, trustedHosts}`). That plugin resolves the built frontend dist through `@deepseek-ai/dsh-web-frontend`'s exports, samples bind-dependent LAN trust once, provides it as `webRuntime` to the browser-trust fence and client roster, mounts the [`frontend-static`](../../host/frontend-static/README.md) fallback owner, and registers the harness-source and web-surface prompt sections plus the bash-visible `DSH_WEB_URL` runtime variable when `surfaceContext` is true. After its Loader tree settles, it prints the `dsh web:` URL line when `printUrl` is true and opens the canonical host URL in the default browser when `openBrowser` is true and the inherited `SSH_CONNECTION` and `SSH_TTY` are blank or absent. An SSH launch keeps the URL line but suppresses browser handoff because the SSH client or editor owns the local forwarded address. Immediately before a handoff, the runtime prints `dsh web: opening the default browser; pass --no-open to disable`. A short-lived Node helper runs the maintained platform opener with the canonical scrubbed child environment. On Windows it stays alive until the short-lived PowerShell launcher exits, because `open` reports spawn before that launcher has handed the URL to the shell; elsewhere the helper stops after the opener accepts spawn. A helper failure writes a diagnostic with its reason and the manual URL to stderr without stopping the server, and no path waits for the browser to exit. This bundle also owns the app command line: the ordinary `web-startup` provider ([`src/startup.ts`](src/startup.ts)) injects `ctx.cmdlineArgs` ([`dsh-cmdline`](../../boot/cmdline/README.md)), parses `--host`, `--port`, repeatable `--trusted-host`, `--no-open`, and the app's `--help`, then provides `webStartup`; browser opening defaults on for local launches, and `--no-open` turns it off for this invocation. It rejects `--host 0.0.0.0` before publishing that service because the CLI intentionally does not support all-interfaces binding yet. Flag-configured rows inject the service and read it directly from lazy config, so nothing binds a port before argument resolution and `dsh --profile web --help` starts no server. [`dsh-headless`](../headless/README.md) is a sibling surface over the same base and does not mount this bundle.
|
|
6
|
+
|
|
7
|
+
## Model retry defaults
|
|
8
|
+
|
|
9
|
+
Web uses the shared bounded normal default of five eligible retries after the initial request. The `deepseek-official` route and settings-added pi-ai routes use that default when they omit `retryPolicy`; explicit provider policies still win. Web adds no retry-specific composition override, so the same omission behavior applies to non-Web profiles.
|
|
6
10
|
|
|
7
11
|
## Model Experience
|
|
8
12
|
|
|
@@ -24,3 +28,6 @@ The prompt section sits near the system prompt's head and is stable for the life
|
|
|
24
28
|
|
|
25
29
|
- **The frontend dist must be built** — `require.resolve` of the dist fails loud at activation with a build hint; there is no source-serving fallback.
|
|
26
30
|
- **`lanAddresses` is a boot-time snapshot** — interface changes after boot are not re-advertised; the printed LAN URL always matches the configured trust fence.
|
|
31
|
+
- **Only handoff startup is observable** — observation ends when the platform opener accepts spawn, except that Windows waits for its short-lived PowerShell launcher to exit; a later browser exit is not reported, and the printed URL remains the manual fallback.
|
|
32
|
+
- **SSH forwarding owns the browser URL** — the printed canonical URL names the remote host's loopback endpoint; automatic handoff is suppressed, and the SSH client or editor must expose and open its local forwarded address.
|
|
33
|
+
- **Browser command overrides are launch-only** — a discovered `.env` may not set `BROWSER`; only an inherited value may reach an opener path that honors the variable, so a checkout cannot choose an executable for automatic handoff.
|
package/README.zh.md
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) | 中文
|
|
4
4
|
|
|
5
|
-
dsh 浏览器表层组合包。[`cordis.patch.yml`](cordis.patch.yml) 叠加在 [`dsh-base`](../base/README.md) 之上:设置 coding persona,插入 Web 宿主行(webserver、API 网关、workspace、投影缓存、存储)、浏览器插件名录与始终挂载的客户端插件重载链([`dsh-client-hmr`](../../client/hmr/README.md),在重建 watcher 改写客户端 bundle 之前保持空闲),并挂载本包的 `web-runtime` 粘合插件(配置为 `{printUrl, surfaceContext, trustedHosts}`)。该插件通过 `@deepseek-ai/dsh-web-frontend` 的 exports 解析已构建的前端 dist,只采样一次依赖 bind 的 LAN 信任信息并将其作为 `webRuntime` 提供给浏览器信任栅栏和客户端名录,挂载 [`frontend-static`](../../host/frontend-static/README.md)
|
|
5
|
+
dsh 浏览器表层组合包。[`cordis.patch.yml`](cordis.patch.yml) 叠加在 [`dsh-base`](../base/README.zh.md) 之上:设置 coding persona,插入 Web 宿主行(webserver、API 网关、workspace、投影缓存、存储)、浏览器插件名录与始终挂载的客户端插件重载链([`dsh-client-hmr`](../../client/hmr/README.zh.md),在重建 watcher 改写客户端 bundle 之前保持空闲),并挂载本包的 `web-runtime` 粘合插件(配置为 `{openBrowser, printUrl, surfaceContext, trustedHosts}`)。该插件通过 `@deepseek-ai/dsh-web-frontend` 的 exports 解析已构建的前端 dist,只采样一次依赖 bind 的 LAN 信任信息并将其作为 `webRuntime` 提供给浏览器信任栅栏和客户端名录,挂载 [`frontend-static`](../../host/frontend-static/README.zh.md) 回退席位所有者,并在 `surfaceContext` 为 true 时注册 Harness 源码与 Web 表层提示词段落,以及 bash 可见的 `DSH_WEB_URL` 运行时变量。自身 Loader 配置树结算后,它在 `printUrl` 为 true 时打印 `dsh web:` URL 行;`openBrowser` 为 true 且继承的 `SSH_CONNECTION` 与 `SSH_TTY` 均为空或不存在时,才会用默认浏览器打开规范宿主机 URL。SSH 启动仍保留 URL 行,但会跳过浏览器交接,因为本地转发地址由 SSH 客户端或编辑器持有。交接前,运行时会打印英文提示 `dsh web: opening the default browser; pass --no-open to disable`。短生命周期 Node helper 使用规范的脱敏子进程环境运行受维护的平台 opener。在 Windows 上,helper 会保持存活,直至短生命周期的 PowerShell launcher 退出,因为 `open` 会在 launcher 把 URL 交给 shell 之前、仅在 spawn 时返回;其他平台则在 opener 接受 spawn 后结束。helper 失败时会向 stderr 写入包含原因和手动访问 URL 的诊断,不会停止服务器,且任何路径都不会等待浏览器退出。本组合包还持有应用命令行:普通 `web-startup` 提供方([`src/startup.ts`](src/startup.ts))注入 `ctx.cmdlineArgs`([`dsh-cmdline`](../../boot/cmdline/README.zh.md)),解析 `--host`、`--port`、可重复的 `--trusted-host`、`--no-open` 以及应用自己的 `--help`,再提供 `webStartup`;本机启动默认会打开浏览器,`--no-open` 则只对本次调用关闭该行为。它会在发布该服务前拒绝 `--host 0.0.0.0`,因为 CLI 目前有意不支持绑定所有网络接口。由 flag 配置的行会注入该服务,并在惰性配置中直接读取它,因此参数解析完成前不会有任何东西绑定端口,`dsh --profile web --help` 也不会启动服务器。[`dsh-headless`](../headless/README.zh.md) 是同一 base 之上的同级表层,不挂载本组合包。
|
|
6
|
+
|
|
7
|
+
## 模型重试默认值
|
|
8
|
+
|
|
9
|
+
Web 使用共享的有界 normal 默认值,在首次请求后最多再重试五次符合条件的失败。`deepseek-official` 与由 settings 新增的 pi-ai 路由在省略 `retryPolicy` 时使用该默认值;显式提供方策略仍然优先。Web 不再增加重试专用的组合覆盖,因此非 Web profile 的省略行为与之相同。
|
|
6
10
|
|
|
7
11
|
## 模型体验
|
|
8
12
|
|
|
@@ -24,3 +28,6 @@ dsh 浏览器表层组合包。[`cordis.patch.yml`](cordis.patch.yml) 叠加在
|
|
|
24
28
|
|
|
25
29
|
- **前端 dist 必须已构建**:对 dist 的 `require.resolve` 在激活时明确报错并给出构建提示;没有从源码直接服务的回退路径。
|
|
26
30
|
- **`lanAddresses` 是启动期快照**:启动后的网卡变化不会重新公告;打印的 LAN URL 始终与配置的信任栅栏一致。
|
|
31
|
+
- **只观测交接启动**:平台 opener 接受 spawn 后即结束观察,但 Windows 会等待其短生命周期 PowerShell launcher 退出;之后的浏览器退出不会上报,已打印 URL 仍是手动访问的回退路径。
|
|
32
|
+
- **SSH 转发持有浏览器 URL**:打印出的规范 URL 指向远端宿主机 loopback 端点;自动交接会被跳过,SSH 客户端或编辑器必须暴露并打开其本地转发地址。
|
|
33
|
+
- **浏览器命令覆盖只能来自启动环境**:被发现的 `.env` 不得设置 `BROWSER`;只有继承值可以抵达会读取该变量的 opener 路径,避免 checkout 为自动交接选择可执行文件。
|
package/cordis.patch.yml
CHANGED
|
@@ -79,6 +79,12 @@
|
|
|
79
79
|
writeEveryEvents: 200
|
|
80
80
|
writeIntervalMs: 5000
|
|
81
81
|
|
|
82
|
+
- id: session-reference
|
|
83
|
+
name: '@deepseek-ai/dsh-session-reference'
|
|
84
|
+
|
|
85
|
+
- id: file-reference-local
|
|
86
|
+
name: '@deepseek-ai/dsh-file-reference-local'
|
|
87
|
+
|
|
82
88
|
# Whole-log turn/step counts for the chat stats strip (the sessionStats
|
|
83
89
|
# projection key); the projection registry itself is a base-layer row.
|
|
84
90
|
- id: session-stats
|
|
@@ -122,15 +128,17 @@
|
|
|
122
128
|
# Web glue owned by this bundle: resolves the built frontend dist (an
|
|
123
129
|
# assembly fact of dsh-web-app, never user config), mounts the
|
|
124
130
|
# frontend-static fallback owner, registers the web-surface prompt
|
|
125
|
-
# section and the bash runtime variable,
|
|
126
|
-
#
|
|
127
|
-
#
|
|
128
|
-
#
|
|
129
|
-
# agent while retaining the host-owned
|
|
131
|
+
# section and the bash runtime variable, prints the URL line, and opens the
|
|
132
|
+
# canonical local URL after the full tree settles. The webStartup provider
|
|
133
|
+
# supplies invocation-only values; after the server binds, this row samples
|
|
134
|
+
# LAN trust once and provides `webRuntime`. A complete agent-preset persona
|
|
135
|
+
# suppresses the prompt section for that agent while retaining the host-owned
|
|
136
|
+
# shell variable.
|
|
130
137
|
- id: web-runtime
|
|
131
138
|
name: '@deepseek-ai/dsh-web-app'
|
|
132
139
|
inject: [webStartup]
|
|
133
140
|
config:
|
|
141
|
+
openBrowser: !!js ctx.webStartup.openBrowser
|
|
134
142
|
printUrl: true
|
|
135
143
|
surfaceContext: true
|
|
136
144
|
trustedHosts: !!js ctx.webStartup.trustedHosts
|
|
@@ -180,6 +188,9 @@
|
|
|
180
188
|
- id: ui-layout
|
|
181
189
|
name: '@deepseek-ai/dsh-client-ui-layout'
|
|
182
190
|
|
|
191
|
+
- id: ui-renderer
|
|
192
|
+
name: '@deepseek-ai/dsh-client-ui-renderer'
|
|
193
|
+
|
|
183
194
|
- id: ui-sidebar
|
|
184
195
|
name: '@deepseek-ai/dsh-client-ui-sidebar'
|
|
185
196
|
|
|
@@ -198,6 +209,13 @@
|
|
|
198
209
|
- id: ui-conversation
|
|
199
210
|
name: '@deepseek-ai/dsh-client-ui-conversation'
|
|
200
211
|
|
|
212
|
+
# Official occupants for the generic sidebar and conversation brand slots.
|
|
213
|
+
- id: ui-brand-official
|
|
214
|
+
name: '@deepseek-ai/dsh-client-ui-brand-official'
|
|
215
|
+
|
|
216
|
+
- id: ui-attachment
|
|
217
|
+
name: '@deepseek-ai/dsh-client-ui-attachment'
|
|
218
|
+
|
|
201
219
|
# Tool call tree, generic fallback, and keyed business Tool views.
|
|
202
220
|
- id: ui-tool
|
|
203
221
|
name: '@deepseek-ai/dsh-client-ui-tool'
|
|
@@ -220,7 +238,7 @@
|
|
|
220
238
|
name: '@deepseek-ai/dsh-client-ui-workspace'
|
|
221
239
|
|
|
222
240
|
# Input triggers: the '/' | '@' pipeline (ui-input-trigger), the command surface over
|
|
223
|
-
# it (ui-commands), and the
|
|
241
|
+
# it (ui-commands), and the reference sources (ui-skill / ui-reference).
|
|
224
242
|
- id: ui-input-trigger
|
|
225
243
|
name: '@deepseek-ai/dsh-client-ui-input-trigger'
|
|
226
244
|
|
|
@@ -233,6 +251,9 @@
|
|
|
233
251
|
- id: ui-subagent
|
|
234
252
|
name: '@deepseek-ai/dsh-client-ui-subagent'
|
|
235
253
|
|
|
254
|
+
- id: ui-reference
|
|
255
|
+
name: '@deepseek-ai/dsh-client-ui-reference'
|
|
256
|
+
|
|
236
257
|
# Background jobs: the session-header list over the jobsBySession mirror.
|
|
237
258
|
- id: ui-jobs
|
|
238
259
|
name: '@deepseek-ai/dsh-client-ui-jobs'
|
package/lib/index.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
2
3
|
import { networkInterfaces } from "node:os";
|
|
3
4
|
import { fileURLToPath } from "node:url";
|
|
4
5
|
import z from "@deepseek-ai/schemastery";
|
|
5
6
|
import { addHarnessSourceSection } from "@deepseek-ai/dsh-app-boot";
|
|
6
7
|
import * as FrontendStatic from "@deepseek-ai/dsh-host-frontend-static";
|
|
8
|
+
import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment";
|
|
9
|
+
import { scrubbedParentEnv } from "@deepseek-ai/dsh-subprocess";
|
|
7
10
|
//#region lib/types/index.js
|
|
8
11
|
/**
|
|
9
12
|
* @deepseek-ai/dsh-web-app — the browser-surface bundle's runtime glue plugin
|
|
@@ -12,8 +15,9 @@ import * as FrontendStatic from "@deepseek-ai/dsh-host-frontend-static";
|
|
|
12
15
|
* the built frontend dist (workspace knowledge of this bundle, never user
|
|
13
16
|
* config), mounts the `frontend-static` fallback owner over it, registers the
|
|
14
17
|
* harness-source and web-surface prompt sections, the bash-visible web runtime
|
|
15
|
-
* variable, and the
|
|
16
|
-
* `webStartup` service expressions in the bundle
|
|
18
|
+
* variable, the URL line, and the default-browser handoff. App command-line
|
|
19
|
+
* values arrive through the `webStartup` service expressions in the bundle
|
|
20
|
+
* patch.
|
|
17
21
|
* @module @deepseek-ai/dsh-web-app
|
|
18
22
|
*/
|
|
19
23
|
/** Stable Cordis plugin name. */
|
|
@@ -25,6 +29,7 @@ const WEB_RUNTIME_SERVICE = "webRuntime";
|
|
|
25
29
|
/** Services required before the web runtime can mount. */
|
|
26
30
|
const inject = ["webServer"];
|
|
27
31
|
const Config = z.object({
|
|
32
|
+
openBrowser: z.boolean().default(true),
|
|
28
33
|
printUrl: z.boolean().default(true),
|
|
29
34
|
surfaceContext: z.boolean().default(true),
|
|
30
35
|
trustedHosts: z.array(String).default([])
|
|
@@ -34,6 +39,43 @@ const DSH_WEB_URL = "DSH_WEB_URL";
|
|
|
34
39
|
const LOOPBACK_HOST = "127.0.0.1";
|
|
35
40
|
/** The webserver schema's all-interfaces bind literal. */
|
|
36
41
|
const ALL_INTERFACES_HOST = "0.0.0.0";
|
|
42
|
+
/** Whether this process was launched through SSH, including a forwarded-port session. */
|
|
43
|
+
function launchedThroughSsh(ctx) {
|
|
44
|
+
const environment = launchEnvironmentOf(ctx);
|
|
45
|
+
return ["SSH_CONNECTION", "SSH_TTY"].some((name) => {
|
|
46
|
+
const value = environment.getFrom(name, ["process"])?.value;
|
|
47
|
+
return value !== void 0 && value !== "";
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const BROWSER_OPENER_MODULE = import.meta.resolve("open");
|
|
51
|
+
const BROWSER_OPENER_PROGRAM = `
|
|
52
|
+
try {
|
|
53
|
+
const { default: open } = await import(${JSON.stringify(BROWSER_OPENER_MODULE)})
|
|
54
|
+
const launcher = await open(process.argv[1])
|
|
55
|
+
if (process.platform === 'win32') {
|
|
56
|
+
// open resolves at PowerShell spawn; keep it referenced until that launcher hands the URL to Windows.
|
|
57
|
+
const code = launcher.exitCode ?? await new Promise((resolve, reject) => {
|
|
58
|
+
function onError(error) {
|
|
59
|
+
launcher.off('close', onClose)
|
|
60
|
+
reject(error)
|
|
61
|
+
}
|
|
62
|
+
function onClose(code) {
|
|
63
|
+
launcher.off('error', onError)
|
|
64
|
+
resolve(code)
|
|
65
|
+
}
|
|
66
|
+
launcher.ref()
|
|
67
|
+
launcher.once('error', onError)
|
|
68
|
+
launcher.once('close', onClose)
|
|
69
|
+
})
|
|
70
|
+
if (code !== 0) throw new Error('browser operating-system launcher exited with code ' + String(code))
|
|
71
|
+
}
|
|
72
|
+
process.exitCode = 0
|
|
73
|
+
} catch (error) {
|
|
74
|
+
// The parent turns this exit into the manual-URL warning.
|
|
75
|
+
console.error(error)
|
|
76
|
+
process.exitCode = 1
|
|
77
|
+
}
|
|
78
|
+
`;
|
|
37
79
|
/**
|
|
38
80
|
* Resolve one LAN-trust snapshot from the active server bind.
|
|
39
81
|
*
|
|
@@ -71,16 +113,65 @@ function resolveDistIndex() {
|
|
|
71
113
|
throw new Error("web-app: frontend dist not built; run pnpm run build from the repository root first");
|
|
72
114
|
}
|
|
73
115
|
}
|
|
74
|
-
/**
|
|
75
|
-
|
|
116
|
+
/** Start the maintained platform opener without forwarding Harness credentials. */
|
|
117
|
+
function spawnBrowserLauncher(url) {
|
|
118
|
+
return spawn(process.execPath, [
|
|
119
|
+
"--input-type=module",
|
|
120
|
+
"--eval",
|
|
121
|
+
BROWSER_OPENER_PROGRAM,
|
|
122
|
+
"--",
|
|
123
|
+
url
|
|
124
|
+
], {
|
|
125
|
+
env: scrubbedParentEnv(),
|
|
126
|
+
stdio: [
|
|
127
|
+
"ignore",
|
|
128
|
+
"inherit",
|
|
129
|
+
"pipe"
|
|
130
|
+
]
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/** Hand one URL to the operating system's default browser. */
|
|
134
|
+
async function openBrowser(url) {
|
|
135
|
+
const launcher = spawnBrowserLauncher(url);
|
|
136
|
+
let launcherStderr = "";
|
|
137
|
+
launcher.stderr?.setEncoding("utf8");
|
|
138
|
+
launcher.stderr?.on("data", (chunk) => {
|
|
139
|
+
launcherStderr += chunk;
|
|
140
|
+
});
|
|
141
|
+
await new Promise((resolve, reject) => {
|
|
142
|
+
function onError(error) {
|
|
143
|
+
launcher.off("close", onClose);
|
|
144
|
+
reject(error);
|
|
145
|
+
}
|
|
146
|
+
function onClose(code) {
|
|
147
|
+
launcher.off("error", onError);
|
|
148
|
+
if (code !== 0) {
|
|
149
|
+
const firstLine = launcherStderr.trim().split(/\r?\n/u)[0];
|
|
150
|
+
const reason = firstLine === void 0 || firstLine === "" ? `browser launcher exited with code ${String(code)}` : firstLine.replace(/^(?:[A-Za-z]*Error):\s*/u, "");
|
|
151
|
+
reject(new Error(reason));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (launcherStderr !== "") process.stderr.write(launcherStderr);
|
|
155
|
+
resolve();
|
|
156
|
+
}
|
|
157
|
+
launcher.once("error", onError);
|
|
158
|
+
launcher.once("close", onClose);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/** Test hooks for the built dist and native browser handoff; production never mutates them. */
|
|
162
|
+
const internals = {
|
|
163
|
+
resolveDistIndex,
|
|
164
|
+
openBrowser
|
|
165
|
+
};
|
|
76
166
|
/**
|
|
77
167
|
* Mount the Web runtime: dist serving, surface prompt, the bash runtime
|
|
78
|
-
* variable, and the
|
|
168
|
+
* variable, the URL line, and the default-browser handoff.
|
|
79
169
|
* @param ctx - plugin context carrying the webServer service.
|
|
80
170
|
* @param config - validated {@link Config}.
|
|
81
171
|
*/
|
|
82
172
|
function apply(ctx, config) {
|
|
83
173
|
const runtime = resolveLanTrust(ctx.webServer.host, config.trustedHosts);
|
|
174
|
+
const handoffBrowser = config.openBrowser && !launchedThroughSsh(ctx);
|
|
84
175
|
ctx.provide(WEB_RUNTIME_SERVICE, runtime);
|
|
85
176
|
ctx.plugin(FrontendStatic, { distIndex: internals.resolveDistIndex() });
|
|
86
177
|
if (config.surfaceContext) {
|
|
@@ -100,16 +191,24 @@ function apply(ctx, config) {
|
|
|
100
191
|
});
|
|
101
192
|
});
|
|
102
193
|
}
|
|
103
|
-
if (config.printUrl) {
|
|
104
|
-
const
|
|
194
|
+
if (config.printUrl || handoffBrowser) {
|
|
195
|
+
const announceReady = () => {
|
|
196
|
+
const webUrl = localWebUrl(ctx);
|
|
105
197
|
const lanCandidate = runtime.lanAddresses[0];
|
|
106
198
|
const port = ctx.webServer.port;
|
|
107
|
-
console.log(`dsh web: ${
|
|
199
|
+
if (config.printUrl) console.log(`dsh web: ${webUrl}${lanCandidate === void 0 ? "" : ` (LAN: http://${lanCandidate}:${String(port)})`}`);
|
|
200
|
+
if (handoffBrowser) {
|
|
201
|
+
console.log("dsh web: opening the default browser; pass --no-open to disable");
|
|
202
|
+
internals.openBrowser(webUrl).catch((error) => {
|
|
203
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
204
|
+
console.error(`web-app: could not open the default browser because ${reason}; visit ${webUrl} manually`);
|
|
205
|
+
});
|
|
206
|
+
}
|
|
108
207
|
};
|
|
109
208
|
const settled = ctx.get("loader")?.await();
|
|
110
|
-
if (settled === void 0)
|
|
209
|
+
if (settled === void 0) announceReady();
|
|
111
210
|
else settled.then(() => {
|
|
112
|
-
if (ctx.get("webServer") !== void 0)
|
|
211
|
+
if (ctx.get("webServer") !== void 0) announceReady();
|
|
113
212
|
}, () => {});
|
|
114
213
|
}
|
|
115
214
|
}
|
package/lib/startup.js
CHANGED
|
@@ -3,7 +3,7 @@ import { parseCmdline } from "@deepseek-ai/dsh-cmdline";
|
|
|
3
3
|
//#region lib/types/startup.js
|
|
4
4
|
/**
|
|
5
5
|
* The web app's command-line provider: it parses the `dsh --profile web` flag
|
|
6
|
-
* family (`--host`, `--port`, `--trusted-host`) and its `--help`
|
|
6
|
+
* family (`--host`, `--port`, `--trusted-host`, `--no-open`) and its `--help`
|
|
7
7
|
* text, then provides the immutable values as {@link WEB_STARTUP_SERVICE}.
|
|
8
8
|
* Ordinary rows inject that service before reading it from lazy config.
|
|
9
9
|
* @module @deepseek-ai/dsh-web-app/startup
|
|
@@ -19,9 +19,10 @@ const WEB_STARTUP_SERVICE = "webStartup";
|
|
|
19
19
|
* @returns a fresh program, so one process can parse more than once (tests).
|
|
20
20
|
*/
|
|
21
21
|
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("--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", `
|
|
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", `
|
|
23
23
|
Examples:
|
|
24
24
|
dsh --profile web serve on the composed host and port
|
|
25
|
+
dsh --profile web --no-open serve without opening a browser
|
|
25
26
|
dsh --profile web --port 8080 serve on another port
|
|
26
27
|
`);
|
|
27
28
|
}
|
|
@@ -39,6 +40,7 @@ function apply(ctx) {
|
|
|
39
40
|
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");
|
|
40
41
|
if (options.port !== void 0 && !/^\d+$/.test(options.port)) program.error(`error: --port must be a number, got ${JSON.stringify(options.port)}`);
|
|
41
42
|
ctx.provide(WEB_STARTUP_SERVICE, {
|
|
43
|
+
openBrowser: options.open,
|
|
42
44
|
...options.host !== void 0 && { host: options.host },
|
|
43
45
|
...options.port !== void 0 && { port: Number(options.port) },
|
|
44
46
|
trustedHosts: options.trustedHost ?? []
|
package/lib/types/index.d.ts
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
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, and the
|
|
9
|
-
* `webStartup` service expressions in the bundle
|
|
8
|
+
* variable, the URL line, and the default-browser handoff. App command-line
|
|
9
|
+
* values arrive through the `webStartup` service expressions in the bundle
|
|
10
|
+
* patch.
|
|
10
11
|
* @module @deepseek-ai/dsh-web-app
|
|
11
12
|
*/
|
|
12
13
|
import type { Context } from '@deepseek-ai/cordis';
|
|
@@ -17,6 +18,8 @@ export declare const name = "web-app";
|
|
|
17
18
|
export declare const inject: string[];
|
|
18
19
|
/** Plugin config: composed deployment settings plus per-invocation command-line values. */
|
|
19
20
|
export interface Config {
|
|
21
|
+
/** Permit default-browser handoff after the Loader tree settles; an SSH launch suppresses it. */
|
|
22
|
+
openBrowser: boolean;
|
|
20
23
|
/** Print the URL line on activation; a non-interactive layer can turn it off. */
|
|
21
24
|
printUrl: boolean;
|
|
22
25
|
/**
|
|
@@ -48,13 +51,14 @@ export interface WebRuntimeValues {
|
|
|
48
51
|
* @returns the LAN display addresses and invocation-derived fence authorities.
|
|
49
52
|
*/
|
|
50
53
|
export declare function resolveLanTrust(bindHost: string, extra: readonly string[]): WebRuntimeValues;
|
|
51
|
-
/** Test
|
|
54
|
+
/** Test hooks for the built dist and native browser handoff; production never mutates them. */
|
|
52
55
|
export declare const internals: {
|
|
53
56
|
resolveDistIndex: () => string;
|
|
57
|
+
openBrowser: (url: string) => Promise<void>;
|
|
54
58
|
};
|
|
55
59
|
/**
|
|
56
60
|
* Mount the Web runtime: dist serving, surface prompt, the bash runtime
|
|
57
|
-
* variable, and the
|
|
61
|
+
* variable, the URL line, and the default-browser handoff.
|
|
58
62
|
* @param ctx - plugin context carrying the webServer service.
|
|
59
63
|
* @param config - validated {@link Config}.
|
|
60
64
|
*/
|
package/lib/types/startup.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The web app's command-line provider: it parses the `dsh --profile web` flag
|
|
3
|
-
* family (`--host`, `--port`, `--trusted-host`) and its `--help`
|
|
3
|
+
* family (`--host`, `--port`, `--trusted-host`, `--no-open`) and its `--help`
|
|
4
4
|
* text, then provides the immutable values as {@link WEB_STARTUP_SERVICE}.
|
|
5
5
|
* Ordinary rows inject that service before reading it from lazy config.
|
|
6
6
|
* @module @deepseek-ai/dsh-web-app/startup
|
|
@@ -14,6 +14,8 @@ export declare const inject: string[];
|
|
|
14
14
|
export declare const WEB_STARTUP_SERVICE = "webStartup";
|
|
15
15
|
/** What the web rows read from {@link WEB_STARTUP_SERVICE}. */
|
|
16
16
|
export interface WebStartupValues {
|
|
17
|
+
/** Whether this invocation opens the default browser after startup. */
|
|
18
|
+
openBrowser: boolean;
|
|
17
19
|
/** `--host`, absent when the invocation did not name one. */
|
|
18
20
|
host?: string;
|
|
19
21
|
/** `--port`, absent when the invocation did not name one. */
|
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.1.
|
|
4
|
+
"version": "0.1.1-rc.1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -45,77 +45,87 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"commander": "^15.0.0",
|
|
48
|
-
"
|
|
49
|
-
"@deepseek-ai/dsh-
|
|
50
|
-
"@deepseek-ai/dsh-
|
|
51
|
-
"@deepseek-ai/dsh-
|
|
52
|
-
"@deepseek-ai/dsh-
|
|
53
|
-
"@deepseek-ai/dsh-client-
|
|
54
|
-
"@deepseek-ai/dsh-client-
|
|
55
|
-
"@deepseek-ai/dsh-client-ui-
|
|
56
|
-
"@deepseek-ai/dsh-client-
|
|
57
|
-
"@deepseek-ai/dsh-client-
|
|
58
|
-
"@deepseek-ai/dsh-client-ui-
|
|
59
|
-
"@deepseek-ai/dsh-client-ui-
|
|
60
|
-
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.
|
|
61
|
-
"@deepseek-ai/dsh-client-ui-
|
|
62
|
-
"@deepseek-ai/dsh-client-ui-
|
|
63
|
-
"@deepseek-ai/dsh-client-ui-
|
|
64
|
-
"@deepseek-ai/dsh-client-ui-directory-picker-native": "^0.1.
|
|
65
|
-
"@deepseek-ai/dsh-client-ui-
|
|
66
|
-
"@deepseek-ai/dsh-client-ui-
|
|
67
|
-
"@deepseek-ai/dsh-client-ui-
|
|
68
|
-
"@deepseek-ai/dsh-client-ui-
|
|
69
|
-
"@deepseek-ai/dsh-client-ui-settings-
|
|
70
|
-
"@deepseek-ai/dsh-client-ui-
|
|
71
|
-
"@deepseek-ai/dsh-client-ui-
|
|
72
|
-
"@deepseek-ai/dsh-client-ui-
|
|
73
|
-
"@deepseek-ai/dsh-client-ui-
|
|
74
|
-
"@deepseek-ai/dsh-client-ui-
|
|
75
|
-
"@deepseek-ai/dsh-client-ui-
|
|
76
|
-
"@deepseek-ai/dsh-client-ui-
|
|
77
|
-
"@deepseek-ai/dsh-client-ui-
|
|
78
|
-
"@deepseek-ai/dsh-client-ui-
|
|
79
|
-
"@deepseek-ai/dsh-client-ui-
|
|
80
|
-
"@deepseek-ai/dsh-client-ui-
|
|
81
|
-
"@deepseek-ai/dsh-client-ui-
|
|
82
|
-
"@deepseek-ai/dsh-client-ui-
|
|
83
|
-
"@deepseek-ai/dsh-client-ui-
|
|
84
|
-
"@deepseek-ai/dsh-
|
|
85
|
-
"@deepseek-ai/dsh-
|
|
86
|
-
"@deepseek-ai/dsh-
|
|
87
|
-
"@deepseek-ai/dsh-client-ui-workspace": "^0.1.
|
|
88
|
-
"@deepseek-ai/dsh-
|
|
89
|
-
"@deepseek-ai/dsh-
|
|
90
|
-
"@deepseek-ai/dsh-
|
|
91
|
-
"@deepseek-ai/dsh-
|
|
92
|
-
"@deepseek-ai/dsh-host-
|
|
93
|
-
"@deepseek-ai/dsh-host-
|
|
94
|
-
"@deepseek-ai/dsh-host-
|
|
95
|
-
"@deepseek-ai/dsh-
|
|
96
|
-
"@deepseek-ai/dsh-
|
|
97
|
-
"@deepseek-ai/dsh-
|
|
98
|
-
"@deepseek-ai/dsh-
|
|
99
|
-
"@deepseek-ai/dsh-
|
|
100
|
-
"@deepseek-ai/dsh-
|
|
101
|
-
"@deepseek-ai/dsh-
|
|
102
|
-
"@deepseek-ai/dsh-
|
|
48
|
+
"open": "^11.0.0",
|
|
49
|
+
"@deepseek-ai/dsh-api-remotes": "^0.1.1-rc.1",
|
|
50
|
+
"@deepseek-ai/dsh-app-boot": "^0.1.1-rc.1",
|
|
51
|
+
"@deepseek-ai/dsh-client-connection": "^0.1.1-rc.1",
|
|
52
|
+
"@deepseek-ai/dsh-client-hmr": "^0.1.1-rc.1",
|
|
53
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.1-rc.1",
|
|
54
|
+
"@deepseek-ai/dsh-client-modules": "^0.1.1-rc.1",
|
|
55
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.1-rc.1",
|
|
56
|
+
"@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.1",
|
|
57
|
+
"@deepseek-ai/dsh-client-ui-attachment": "^0.1.1-rc.1",
|
|
58
|
+
"@deepseek-ai/dsh-client-ui-brand-official": "^0.1.1-rc.1",
|
|
59
|
+
"@deepseek-ai/dsh-client-ui-commands": "^0.1.1-rc.1",
|
|
60
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.1-rc.1",
|
|
61
|
+
"@deepseek-ai/dsh-client-ui-cordis": "^0.1.1-rc.1",
|
|
62
|
+
"@deepseek-ai/dsh-client-ui-deliverables": "^0.1.1-rc.1",
|
|
63
|
+
"@deepseek-ai/dsh-client-ui-directory-picker-browse": "^0.1.1-rc.1",
|
|
64
|
+
"@deepseek-ai/dsh-client-ui-directory-picker-native": "^0.1.1-rc.1",
|
|
65
|
+
"@deepseek-ai/dsh-client-ui-message-feedback": "^0.1.1-rc.1",
|
|
66
|
+
"@deepseek-ai/dsh-client-ui-goal": "^0.1.1-rc.1",
|
|
67
|
+
"@deepseek-ai/dsh-client-ui-layout": "^0.1.1-rc.1",
|
|
68
|
+
"@deepseek-ai/dsh-client-ui-model-selection": "^0.1.1-rc.1",
|
|
69
|
+
"@deepseek-ai/dsh-client-ui-settings-models": "^0.1.1-rc.1",
|
|
70
|
+
"@deepseek-ai/dsh-client-ui-settings-plugin-inventory": "^0.1.1-rc.1",
|
|
71
|
+
"@deepseek-ai/dsh-client-ui-permission-presets": "^0.1.1-rc.1",
|
|
72
|
+
"@deepseek-ai/dsh-client-ui-agent-preset": "^0.1.1-rc.1",
|
|
73
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.1-rc.1",
|
|
74
|
+
"@deepseek-ai/dsh-client-ui-user-questions": "^0.1.1-rc.1",
|
|
75
|
+
"@deepseek-ai/dsh-client-ui-plan": "^0.1.1-rc.1",
|
|
76
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.1-rc.1",
|
|
77
|
+
"@deepseek-ai/dsh-client-ui-settings-general": "^0.1.1-rc.1",
|
|
78
|
+
"@deepseek-ai/dsh-client-ui-sidebar": "^0.1.1-rc.1",
|
|
79
|
+
"@deepseek-ai/dsh-client-ui-skill": "^0.1.1-rc.1",
|
|
80
|
+
"@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.1-rc.1",
|
|
81
|
+
"@deepseek-ai/dsh-client-ui-reference": "^0.1.1-rc.1",
|
|
82
|
+
"@deepseek-ai/dsh-client-ui-subagent": "^0.1.1-rc.1",
|
|
83
|
+
"@deepseek-ai/dsh-client-ui-jobs": "^0.1.1-rc.1",
|
|
84
|
+
"@deepseek-ai/dsh-client-ui-theme": "^0.1.1-rc.1",
|
|
85
|
+
"@deepseek-ai/dsh-client-ui-workflow-run": "^0.1.1-rc.1",
|
|
86
|
+
"@deepseek-ai/dsh-client-ui-trajectory": "^0.1.1-rc.1",
|
|
87
|
+
"@deepseek-ai/dsh-client-ui-workspace": "^0.1.1-rc.1",
|
|
88
|
+
"@deepseek-ai/dsh-client-ui-tool": "^0.1.1-rc.1",
|
|
89
|
+
"@deepseek-ai/dsh-cmdline": "^0.1.1-rc.1",
|
|
90
|
+
"@deepseek-ai/dsh-code-runtime-worker-thread": "^0.1.1-rc.1",
|
|
91
|
+
"@deepseek-ai/dsh-cordis-client-runner": "^0.1.1-rc.1",
|
|
92
|
+
"@deepseek-ai/dsh-cordis-host-runner": "^0.1.1-rc.1",
|
|
93
|
+
"@deepseek-ai/dsh-host-frontend-static": "^0.1.1-rc.1",
|
|
94
|
+
"@deepseek-ai/dsh-host-apiproxy": "^0.1.1-rc.1",
|
|
95
|
+
"@deepseek-ai/dsh-host-directory-picker-auto": "^0.1.1-rc.1",
|
|
96
|
+
"@deepseek-ai/dsh-host-directory-picker-browse": "^0.1.1-rc.1",
|
|
97
|
+
"@deepseek-ai/dsh-web-frontend": "^0.1.1-rc.1",
|
|
98
|
+
"@deepseek-ai/dsh-host-directory-picker-native": "^0.1.1-rc.1",
|
|
99
|
+
"@deepseek-ai/dsh-host-plugin-inventory": "^0.1.1-rc.1",
|
|
100
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.1-rc.1",
|
|
101
|
+
"@deepseek-ai/dsh-file-reference": "^0.1.1-rc.1",
|
|
102
|
+
"@deepseek-ai/dsh-file-reference-local": "^0.1.1-rc.1",
|
|
103
|
+
"@deepseek-ai/dsh-launch-environment": "^0.1.1-rc.1",
|
|
104
|
+
"@deepseek-ai/dsh-agent-presets": "^0.1.1-rc.1",
|
|
105
|
+
"@deepseek-ai/dsh-message-feedback": "^0.1.1-rc.1",
|
|
106
|
+
"@deepseek-ai/dsh-session-projection-cache": "^0.1.1-rc.1",
|
|
107
|
+
"@deepseek-ai/dsh-session-reference": "^0.1.1-rc.1",
|
|
108
|
+
"@deepseek-ai/dsh-session-log-export": "^0.1.1-rc.1",
|
|
109
|
+
"@deepseek-ai/dsh-storage": "^0.1.1-rc.1",
|
|
110
|
+
"@deepseek-ai/dsh-session-stats": "^0.1.1-rc.1",
|
|
111
|
+
"@deepseek-ai/dsh-subprocess": "^0.1.1-rc.1",
|
|
112
|
+
"@deepseek-ai/dsh-workspace": "^0.1.1-rc.1",
|
|
113
|
+
"@deepseek-ai/dsh-storage-json": "^0.1.1-rc.1",
|
|
103
114
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
104
|
-
"@deepseek-ai/dsh-
|
|
105
|
-
"@deepseek-ai/dsh-host-frontend-static": "^0.1.0-rc.7"
|
|
115
|
+
"@deepseek-ai/dsh-storage-domain": "^0.1.1-rc.1"
|
|
106
116
|
},
|
|
107
117
|
"peerDependencies": {
|
|
108
118
|
"@deepseek-ai/cordis-plugin-loader": "^1.0.2",
|
|
109
|
-
"@deepseek-ai/dsh-shell-env": "^0.1.
|
|
110
|
-
"@deepseek-ai/dsh-
|
|
111
|
-
"@deepseek-ai/dsh-
|
|
119
|
+
"@deepseek-ai/dsh-shell-env": "^0.1.1-rc.1",
|
|
120
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.1-rc.1",
|
|
121
|
+
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.1",
|
|
112
122
|
"@deepseek-ai/cordis": "^4.0.1"
|
|
113
123
|
},
|
|
114
124
|
"devDependencies": {
|
|
115
|
-
"@deepseek-ai/
|
|
116
|
-
"@deepseek-ai/dsh-
|
|
117
|
-
"@deepseek-ai/
|
|
118
|
-
"@deepseek-ai/dsh-
|
|
119
|
-
"@deepseek-ai/cordis
|
|
125
|
+
"@deepseek-ai/cordis-plugin-loader": "^1.0.2",
|
|
126
|
+
"@deepseek-ai/dsh-shell-env": "^0.1.1-rc.1",
|
|
127
|
+
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.1",
|
|
128
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.1-rc.1",
|
|
129
|
+
"@deepseek-ai/cordis": "^4.0.1"
|
|
120
130
|
}
|
|
121
131
|
}
|