@deepseek-ai/dsh-experimental-webworker-runtime 0.1.7-rc.2 → 0.2.0-rc.2
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 +4 -4
- package/README.md +5 -4
- package/README.zh.md +5 -4
- package/lib/client.js +93 -0
- package/lib/index.js +30 -7
- package/lib/types/client/client.d.ts +1 -0
- package/lib/types/client/text-viewer.d.ts +8 -0
- package/lib/types/node/external_packages/got.d.ts +8 -0
- package/lib/types/node/globals/process.d.ts +1 -1
- package/lib/types/shell/process/xdg-open.d.ts +11 -0
- package/lib/types/transport/frames.d.ts +8 -1
- package/lib/types/transport/tunnel.d.ts +6 -0
- package/lib/worker.js +87 -8
- package/package.json +21 -21
package/README.i18n.yaml
CHANGED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
en: 4e53164159b5ce41
|
|
16
16
|
zh: 89582dc0294d0776
|
|
17
17
|
/deepseek-ai-dsh-experimental-webworker-runtime/use-this-package:
|
|
18
|
-
en:
|
|
19
|
-
zh:
|
|
18
|
+
en: 7c80a0d046f93fb1
|
|
19
|
+
zh: a9fdcc7a9f9a8828
|
|
20
20
|
/deepseek-ai-dsh-experimental-webworker-runtime/model-experience:
|
|
21
21
|
en: 61fce9b4c7dc96e6
|
|
22
22
|
zh: dc2d931063a38327
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
en: ca75c51c89c2c9b0
|
|
25
25
|
zh: 64715dc7e6d02f71
|
|
26
26
|
/deepseek-ai-dsh-experimental-webworker-runtime/known-limitations-and-deferred-work:
|
|
27
|
-
en:
|
|
28
|
-
zh:
|
|
27
|
+
en: 6fe586817a42fdad
|
|
28
|
+
zh: c19ab678d61e82d3
|
|
29
29
|
/deepseek-ai-dsh-experimental-webworker-runtime/known-limitations-and-deferred-work/dev-note:
|
|
30
30
|
en: f14ab6f2449c3c53
|
|
31
31
|
zh: e3f7d3a3d772c0b7
|
package/README.md
CHANGED
|
@@ -27,10 +27,10 @@ The public npm package exposes the runtime library at its root, the self-contain
|
|
|
27
27
|
|
|
28
28
|
Three build artifacts and one source-owned process layer:
|
|
29
29
|
|
|
30
|
-
- **`lib/index.js` (assembly library)** — `createWorkerHost`/`startWorkerHost` mount the base image and any ordered data overlays (`storage/`), install the module loader (`module-system/`) and the `process` shim, boot the tree through the image's own `dsh-app-boot`, and hand the tunnel its serving seams. Overlays may replace files only under `home/` and `workspace/`; they cannot replace the base manifest, configuration, or modules. The image layout contract (`image-layout.ts`: virtual root, config/manifest paths, empty directories, the `lowered` wrapper-contract gate) is shared with the packer. The Worker supplies `profileContext` for an editable profile at `home/profiles/preview/`: the packed rows seed its insertion patch, and ConfigEditor persists overrides in that VFS patch. ConfigEditor reconciles each write and Loader commits live values
|
|
30
|
+
- **`lib/index.js` (assembly library)** — `createWorkerHost`/`startWorkerHost` mount the base image and any ordered data overlays (`storage/`), install the module loader (`module-system/`) and the `process` shim, boot the tree through the image's own `dsh-app-boot`, and hand the tunnel its serving seams. Overlays may replace files only under `home/` and `workspace/`; they cannot replace the base manifest, configuration, or modules. The image layout contract (`image-layout.ts`: virtual root, config/manifest paths, empty directories, the `lowered` wrapper-contract gate) is shared with the packer. The Worker supplies `profileContext` for an editable profile at `home/profiles/preview/`: the packed rows seed its insertion patch, and ConfigEditor persists overrides in that VFS patch. ConfigEditor reconciles each write and Loader commits live values. The Worker commits `appReady` once the tunnel serves, so HMR loads and queues profile configuration changes; the `process` shim reports no entry script, so HMR performs no Node module-cache classification. Plugin management loads and edits the profile, and its package operations fail with the `execa` refusal. Deployment overlays keep JSONL session logs plaintext and preset roots at the image's `config/agent-presets`. Configuration edits last for the current Worker lifetime.
|
|
31
31
|
- **`lib/worker.js` (worker bundle)** — the assembly plus this package's Node-compatibility layer as one self-contained ES module. The module proxy table (`module-proxies.ts`) is the only platform fork: `node:*` builtins over VFS/tunnel/browser primitives, structural stubs that fail loud on the console for what a browser cannot do, and native/binary package replacements. `node:module` supplies `createRequire().resolve` and `.resolve.paths()` over the image package root, so unchanged packages can discover manifests without evaluating their modules. The `node:util` JSON-data comparator compares own enumerable properties, preserving Node admission decisions for recorded fields such as `__proto__`. The global `process` shim carries Node detection fields including `title`, preventing Worker execution from entering DOM-only branches. The pack-time parser reports statically named module requests, including module-scope direct calls of the form `createRequire(import.meta.url)('pkg')` through a named `node:module` or `module` import, to the packer's reachability walk. Stored, CommonJS-obtained, and rebased `createRequire` calls require image entry seeds. VFS mutations drive `node:fs` callback, polling, and promise watchers; open descriptors retain file identity and access mode across rename, replacement, and unlink, `FileHandle.stat({ bigint: true })` reports the same device and inode identity as a path stat while the name still refers to that file, and `FileHandle.chmod()` updates the opened file identity; `readable-stream` supplies `node:stream/promises` completion and pipeline helpers and the stream state machine used by file streams and unchanged image packages such as Chokidar and readdirp. AsyncLocalStorage carries sync-stack causality across `await` through the snapshot/restore faces the pack-time lowering injects. The worker holds no compiler: an image the packer did not lower is refused at mount. The callback `fs.realpath.native` alias resolves within the mounted VFS and supports `util.promisify`.
|
|
32
|
-
- **`src/shell/` (the worker's own process layer)** — a browser worker cannot fork, so `node:child_process` is not a stub but an implementation: `spawn` starts the command in its own Web Worker — this same bundle, told by its first frame to be a shell process — and reports it through the `ChildProcess` surface the subprocess service consumes. The command runs off the host's thread, `SIGKILL` terminates it whatever it is doing, and it reaches the VFS only by message (the host serves those frames). Worker platform executables preserve native-package protocols such as Landlock without replacing their JavaScript packages or coupling their implementations to `node:child_process`; ordinary commands use the package's evaluator and coreutils command table. The grammar is `@yarnpkg/parsers`' `parseShell`, while `execSync`/`fork` still refuse because they need a real process.
|
|
33
|
-
- **`lib/client.js` (page half)** — startup has two independent stages. `chooseWorkerHostSource({ image?, fixtureManifest? })` optionally owns the boot barrier and fixture manifest: without `preview-fixture` it waits at the source chooser, while a valid query selects directly; either path returns ordered overlays. `connectWorkerHost(worker, { image?, overlays? })` remains the public base-runtime connector; callers that skip the chooser get an empty overlay list. `apps/web` invokes both and supplies its statically bundled Worker. The opening `init` frame carries the base and ordered overlay URLs, the boot payload delivers the structured index-injection table, and `applyIndexInjections` executes it before the shell entry runs. Script preload rows are advisory and skipped because `/plugins` resources resolve only through the tunnel; `loadBundle` fetches each combo on first demand, embeds its tunnel-only source map as a Base64 data URL, and executes the script as a Blob. The tunnel also exposes fetch-shaped transport, the independent file-upload carrier, and the API client. Request frames preserve Blob bodies through structured clone and transfer `ReadableStream<Uint8Array>` ownership. The Host Worker streams both forms into the route, so neither browser thread creates a complete byte array for a generic-file upload. A Remote stream's uplink crosses as `stream-uplink-item` / `stream-uplink-end` frames into an unbounded `TunnelUplink` that drops items arriving after `end`: the page and its worker are one trusted same-origin boundary, so the Host inbox cap does not apply.
|
|
32
|
+
- **`src/shell/` (the worker's own process layer)** — a browser worker cannot fork, so `node:child_process` is not a stub but an implementation: `spawn` starts the command in its own Web Worker — this same bundle, told by its first frame to be a shell process — and reports it through the `ChildProcess` surface the subprocess service consumes. The command runs off the host's thread, `SIGKILL` terminates it whatever it is doing, and it reaches the VFS only by message (the host serves those frames). Worker platform executables preserve native-package protocols such as Landlock without replacing their JavaScript packages or coupling their implementations to `node:child_process`; `xdg-open` sends one VFS text file to the page's read-only viewer, so desktop-opener actions such as **Open configuration file** show the file in the page; ordinary commands use the package's evaluator and coreutils command table. The grammar is `@yarnpkg/parsers`' `parseShell`, while `execSync`/`fork` still refuse because they need a real process.
|
|
33
|
+
- **`lib/client.js` (page half)** — startup has two independent stages. `chooseWorkerHostSource({ image?, fixtureManifest? })` optionally owns the boot barrier and fixture manifest: without `preview-fixture` it waits at the source chooser, while a valid query selects directly; either path returns ordered overlays. `connectWorkerHost(worker, { image?, overlays? })` remains the public base-runtime connector; callers that skip the chooser get an empty overlay list. `apps/web` invokes both and supplies its statically bundled Worker. The opening `init` frame carries the base and ordered overlay URLs, the boot payload delivers the structured index-injection table, and `applyIndexInjections` executes it before the shell entry runs. Script preload rows are advisory and skipped because `/plugins` resources resolve only through the tunnel; `loadBundle` fetches each combo on first demand, embeds its tunnel-only source map as a Base64 data URL, and executes the script as a Blob. The worker's unsolicited `view-text` frame opens the page's modal text viewer. The tunnel also exposes fetch-shaped transport, the independent file-upload carrier, and the API client. Request frames preserve Blob bodies through structured clone and transfer `ReadableStream<Uint8Array>` ownership. The Host Worker streams both forms into the route, so neither browser thread creates a complete byte array for a generic-file upload. A Remote stream's uplink crosses as `stream-uplink-item` / `stream-uplink-end` frames into an unbounded `TunnelUplink` that drops items arriving after `end`: the page and its worker are one trusted same-origin boundary, so the Host inbox cap does not apply.
|
|
34
34
|
|
|
35
35
|
Acceptance lives in `apps/web/tests/preview-boot.e2e.ts`, which serves the real built pages and drives the pre-boot chooser plus Worker activation in headless Chromium. The empty selection exercises first-run startup. The `vfs-example` overlay supplies ordinary workspace files and plaintext persistence artifacts for cold Workspace/Session discovery, tool presentation, subagent navigation, and history paging without a model request. The [packer](../webworker-packer/README.md) prepares current-generation successors from committed historical logs in Node; those source logs remain byte-identical in the overlay. The fixture generator owns the acceptance test's current projection cache. The chooser reserves WebFS as a separate user-authorized source; that provider does not read the built-in fixture.
|
|
36
36
|
|
|
@@ -53,7 +53,8 @@ None; this package neither assembles nor sends a provider request.
|
|
|
53
53
|
|
|
54
54
|
- **The worker composition writes plaintext session logs** (`compression: 'none'` boot patch): it carries no Zstandard codec, so exported logs are `.jsonl`, never `.jsonl.zstd`.
|
|
55
55
|
- **`node:dns/promises`, `node:vm`, `node:net`, `node:sqlite`, `node:worker_threads` are structural stubs**: every call reports its refusal on the console and throws. Rows needing native DNS, a real process, or realm isolation cannot run here.
|
|
56
|
-
- **
|
|
56
|
+
- **Desktop product telemetry is unavailable**: `got.post` reports an explicit worker-host refusal. Got and its Node HTTP dependencies are excluded from the browser image; Desktop reporting remains disabled in the preview composition.
|
|
57
|
+
- **Host package commands are unavailable**: `execa` reports an explicit worker-host refusal; the preview cannot run pnpm, install plugins, or install native dependencies.
|
|
57
58
|
- **PTC Node programs are unavailable**: the process shim exposes `/dsh/bin/node` as its executable identity so the provider can activate, but the Worker has neither a Node executable nor `stripTypeScriptTypes`. Program execution fails before launching a child.
|
|
58
59
|
- **Office conversion requires a Node Host**: the LibreOffice kit replacement rejects converter creation with `unavailable`. The browser image excludes the kit and its engine dependencies; the Office preview reports that conversion is unavailable.
|
|
59
60
|
- **Filesystem watchers observe only the mounted VFS**: image seeding is silent and the VFS has no symlinks or external writers. `persistent`, `ref()`, and `unref()` preserve the Node API but cannot control a dedicated Worker's lifetime because browsers expose no ref-counted event loop.
|
package/README.zh.md
CHANGED
|
@@ -27,10 +27,10 @@ kind: "package-library"
|
|
|
27
27
|
|
|
28
28
|
一条 tsdown 管线产出三个构建产物;另有一层由源码维护的进程实现:
|
|
29
29
|
|
|
30
|
-
- **`lib/index.js`(装配库)**——`createWorkerHost`/`startWorkerHost` 挂载基础镜像和按序排列的数据 overlays(`storage/`)、安装模块加载器(`module-system/`)与 `process` shim、经镜像自带的 `dsh-app-boot` 启动插件树,并把服务 seam 交给隧道。Overlay 只能替换 `home/` 与 `workspace/` 下的文件,不能替换基础 manifest、配置或模块。镜像布局契约(`image-layout.ts`:虚拟根、config/manifest 路径、空目录、`lowered` 包装契约门)与 packer 共享。Worker 为 `home/profiles/preview/` 下可编辑的 profile 提供 `profileContext`:打包行初始化其插入 patch,ConfigEditor 将覆盖值持久化到该 VFS patch。ConfigEditor 协调每次写入,Loader
|
|
30
|
+
- **`lib/index.js`(装配库)**——`createWorkerHost`/`startWorkerHost` 挂载基础镜像和按序排列的数据 overlays(`storage/`)、安装模块加载器(`module-system/`)与 `process` shim、经镜像自带的 `dsh-app-boot` 启动插件树,并把服务 seam 交给隧道。Overlay 只能替换 `home/` 与 `workspace/` 下的文件,不能替换基础 manifest、配置或模块。镜像布局契约(`image-layout.ts`:虚拟根、config/manifest 路径、空目录、`lowered` 包装契约门)与 packer 共享。Worker 为 `home/profiles/preview/` 下可编辑的 profile 提供 `profileContext`:打包行初始化其插入 patch,ConfigEditor 将覆盖值持久化到该 VFS patch。ConfigEditor 协调每次写入,Loader 提交实时值。Worker 在隧道开始服务后提交 `appReady`,因此 HMR 可以加载并排队处理 profile 配置变更;`process` shim 不报告入口脚本,因此 HMR 不做 Node 模块缓存分类。插件管理可以加载并编辑 profile,其包操作会因 `execa` 拒绝而失败。部署 overlay 保持 JSONL 会话日志为明文,preset 根指向镜像内 `config/agent-presets`。配置修改在当前 Worker 生命周期内有效。预设声明包含在组合后的配置中。
|
|
31
31
|
- **`lib/worker.js`(worker 束)**——装配库加本包的 Node 兼容层,合成一个自含 ES module。模块代理表(`module-proxies.ts`)是唯一平台叉口:`node:*` 内建走 VFS、隧道和浏览器原语,浏览器做不到的走结构化 stub(调用即在 console 报错并抛出),native/binary 包则替换执行后端。`node:module` 在镜像 package 根之上提供 `createRequire().resolve` 与 `.resolve.paths()`,使未修改的包无需执行目标模块即可发现 manifest。`node:util` 的 JSON 数据比较器检查可枚举的自有属性,使 `__proto__` 等记录字段的准入判定与 Node 一致。全局 `process` shim 带有包括 `title` 在内的 Node 环境识别字段,避免 Worker 执行误入仅适用于 DOM 的分支。pack 期解析器会把名称静态可知的模块请求报告给 packer 的可达性遍历,其中包括通过 `node:module` 或 `module` 具名导入在模块作用域直接发起的 `createRequire(import.meta.url)('pkg')` 调用。保存、经 CommonJS 获取或另设基准的 `createRequire` 调用需要镜像入口种子。VFS mutation 驱动 `node:fs` 的 callback、polling 和 promise watcher;打开的 descriptor 在 rename、replacement 和 unlink 后仍保留文件身份与访问模式,只要文件名仍指向该文件,`FileHandle.stat({ bigint: true })` 报告的 device 与 inode 身份就与路径 stat 相同,`FileHandle.chmod()` 则更新打开文件身份的权限;`readable-stream` 提供 `node:stream/promises` 的完成等待与管道方法,以及文件流以及 Chokidar、readdirp 等未修改镜像包所用的流状态机。AsyncLocalStorage 经 pack 时降低注入的 snapshot/restore 面在 `await` 间携带同步栈因果。worker 不带编译器:packer 未降低的镜像在挂载时被拒。回调式 `fs.realpath.native` 别名在已挂载的 VFS 内解析路径,并支持 `util.promisify`。
|
|
32
|
-
- **`src/shell/`(worker 自己的进程层)**——浏览器 worker 无法 fork,所以 `node:child_process` 不是 stub 而是实现:`spawn` 把命令放进它自己的 Web Worker——就是这同一个束,由首帧告诉它「你是 shell 进程」——并以 subprocess 服务消费的 `ChildProcess` 面报告结果。命令不占宿主线程,`SIGKILL` 不管它在干什么都能终止它,而它只能靠消息触达 VFS(由宿主应答这些帧)。Worker 平台 executable 在不替换 JavaScript 包、也不把具体实现耦合进 `node:child_process` 的情况下保持 Landlock 等 native
|
|
33
|
-
- **`lib/client.js`(页面半)**——启动分为相互独立的两段。`chooseWorkerHostSource({ image?, fixtureManifest? })` 可选地拥有 boot barrier 与 fixture manifest:没有 `preview-fixture` 时停在来源选择面板,合法 query 则直接选择;两条路径都返回按序排列的 overlays。`connectWorkerHost(worker, { image?, overlays? })` 仍是公开的基础运行态连接器;调用方跳过选择器时 overlay 列表为空。`apps/web` 调用这两段并提供静态打包的 Worker。开局 `init` 帧携带基础镜像与按序排列的 overlay URL,boot 载荷送达结构化 index 注入表,`applyIndexInjections` 在壳入口运行前逐行执行。脚本 preload 行只是提示,因此会被跳过:`/plugins` 资源只能经 tunnel 解析,`loadBundle` 会在首次需要时获取 combo、把仅 tunnel 可达的 sourcemap 内嵌为 Base64 data URL,再以 Blob 执行脚本。Tunnel 还暴露 fetch 形式的传输、独立文件上传载体和 API 客户端。请求帧通过结构化克隆保留 Blob 请求体,并转移 `ReadableStream<Uint8Array>` 的所有权。Host Worker 将两种请求体都逐块送入路由,因此通用文件上传不会在任何浏览器线程创建完整字节数组。Remote 流的上行以 `stream-uplink-item` / `stream-uplink-end` 帧进入没有上限的 `TunnelUplink`,`end` 之后到达的项被丢弃:页面与其 worker 是同一个可信的同源边界,Host 的 inbox 上限在此不适用。
|
|
32
|
+
- **`src/shell/`(worker 自己的进程层)**——浏览器 worker 无法 fork,所以 `node:child_process` 不是 stub 而是实现:`spawn` 把命令放进它自己的 Web Worker——就是这同一个束,由首帧告诉它「你是 shell 进程」——并以 subprocess 服务消费的 `ChildProcess` 面报告结果。命令不占宿主线程,`SIGKILL` 不管它在干什么都能终止它,而它只能靠消息触达 VFS(由宿主应答这些帧)。Worker 平台 executable 在不替换 JavaScript 包、也不把具体实现耦合进 `node:child_process` 的情况下保持 Landlock 等 native 包协议;`xdg-open` 把一个 VFS 文本文件交给页面的只读查看器,因此 **打开配置文件** 等桌面打开操作会在页面内显示该文件;普通命令使用本包的求值器与 coreutils 命令表。语法来自 `@yarnpkg/parsers` 的 `parseShell`,而 `execSync`/`fork` 依然拒绝,因为它们需要真进程。
|
|
33
|
+
- **`lib/client.js`(页面半)**——启动分为相互独立的两段。`chooseWorkerHostSource({ image?, fixtureManifest? })` 可选地拥有 boot barrier 与 fixture manifest:没有 `preview-fixture` 时停在来源选择面板,合法 query 则直接选择;两条路径都返回按序排列的 overlays。`connectWorkerHost(worker, { image?, overlays? })` 仍是公开的基础运行态连接器;调用方跳过选择器时 overlay 列表为空。`apps/web` 调用这两段并提供静态打包的 Worker。开局 `init` 帧携带基础镜像与按序排列的 overlay URL,boot 载荷送达结构化 index 注入表,`applyIndexInjections` 在壳入口运行前逐行执行。脚本 preload 行只是提示,因此会被跳过:`/plugins` 资源只能经 tunnel 解析,`loadBundle` 会在首次需要时获取 combo、把仅 tunnel 可达的 sourcemap 内嵌为 Base64 data URL,再以 Blob 执行脚本。worker 主动发出的 `view-text` 帧会打开页面的模态文本查看器。Tunnel 还暴露 fetch 形式的传输、独立文件上传载体和 API 客户端。请求帧通过结构化克隆保留 Blob 请求体,并转移 `ReadableStream<Uint8Array>` 的所有权。Host Worker 将两种请求体都逐块送入路由,因此通用文件上传不会在任何浏览器线程创建完整字节数组。Remote 流的上行以 `stream-uplink-item` / `stream-uplink-end` 帧进入没有上限的 `TunnelUplink`,`end` 之后到达的项被丢弃:页面与其 worker 是同一个可信的同源边界,Host 的 inbox 上限在此不适用。
|
|
34
34
|
|
|
35
35
|
验收在 `apps/web/tests/preview-boot.e2e.ts`:静态服务真实构建页面,在 headless Chromium 里驱动 pre-boot 选择面板与 Worker 激活。空白选择验证首次启动;`vfs-example` overlay 提供普通 workspace 文件与明文 persistence 产物,无需模型请求即可验证 Workspace/Session 冷发现、工具呈现、subagent 导航和历史分页。[打包器](../webworker-packer/README.zh.md)在 Node 中根据已提交的历史日志准备当前代后继文件;这些源日志在 overlay 中逐字节保持不变。fixture 生成器负责验收测试的当前投影缓存。选择面板为 WebFS 保留独立的用户授权来源;该 provider 不读取内置 fixture。
|
|
36
36
|
|
|
@@ -53,7 +53,8 @@ kind: "package-library"
|
|
|
53
53
|
|
|
54
54
|
- **worker 组合写明文会话日志**(`compression: 'none'` boot patch):不带 Zstandard 编解码器,导出日志是 `.jsonl`,不会是 `.jsonl.zstd`。
|
|
55
55
|
- **`node:dns/promises`、`node:vm`、`node:net`、`node:sqlite`、`node:worker_threads` 是结构化 stub**:每次调用在 console 报告拒绝并抛出。需要原生 DNS、真进程或真 realm 隔离的行在此无法运行。
|
|
56
|
-
-
|
|
56
|
+
- **桌面产品埋点不可用**:`got.post` 明确报告 worker host 不支持该调用。浏览器镜像不包含 Got 及其 Node HTTP 依赖;预览组合不启用桌面上报。
|
|
57
|
+
- **宿主包管理命令不可用**:`execa` 明确报告 worker host 不支持该调用;预览无法运行 pnpm、安装插件或安装原生依赖。
|
|
57
58
|
- **PTC Node 程序不可用**:process shim 用 `/dsh/bin/node` 表示可执行文件身份,使 provider 能够激活,但 Worker 既没有 Node 可执行文件,也没有 `stripTypeScriptTypes`。程序执行会在启动子进程前失败。
|
|
58
59
|
- **Office 转换需要 Node Host**:LibreOffice kit 的替代模块以 `unavailable` 拒绝创建转换器。浏览器镜像排除 kit 及其引擎依赖;Office 预览提示转换不可用。
|
|
59
60
|
- **文件 watcher 只能观察已挂载的 VFS**:镜像 seed 不产生事件,VFS 也没有符号链接或外部写入方。`persistent`、`ref()` 和 `unref()` 保留 Node API,但浏览器没有引用计数事件循环,因此这些接口不能控制 dedicated Worker 的生存期。
|
package/lib/client.js
CHANGED
|
@@ -52,6 +52,96 @@ function parsePreviewFixtureManifest(value) {
|
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
//#endregion
|
|
55
|
+
//#region src/client/text-viewer.ts
|
|
56
|
+
/** Read-only text viewer the page shows when the worker's `xdg-open` names a VFS file. */
|
|
57
|
+
const VIEWER_STYLE = `
|
|
58
|
+
[data-preview-text-viewer] {
|
|
59
|
+
width: min(960px, calc(100vw - 32px));
|
|
60
|
+
height: min(720px, calc(100dvh - 32px));
|
|
61
|
+
padding: 0;
|
|
62
|
+
box-sizing: border-box;
|
|
63
|
+
border: 1px solid var(--dsw-alias-border-l2, rgb(0 0 0 / 10%));
|
|
64
|
+
border-radius: var(--dsw-radius-lg, 16px);
|
|
65
|
+
color: var(--dsw-alias-label-primary, #0f1115);
|
|
66
|
+
background: var(--dsw-alias-bg-base, #fff);
|
|
67
|
+
font-family: var(--dsw-font-family, inherit);
|
|
68
|
+
}
|
|
69
|
+
[data-preview-text-viewer][open] { display: flex; flex-direction: column; }
|
|
70
|
+
[data-preview-text-viewer]::backdrop { background: rgb(0 0 0 / 32%); }
|
|
71
|
+
[data-preview-text-viewer] header {
|
|
72
|
+
display: flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
gap: 12px;
|
|
75
|
+
padding: 12px 16px;
|
|
76
|
+
border-bottom: 1px solid var(--dsw-alias-border-l1, rgb(0 0 0 / 6%));
|
|
77
|
+
}
|
|
78
|
+
[data-preview-text-viewer] h2 {
|
|
79
|
+
flex: 1;
|
|
80
|
+
min-width: 0;
|
|
81
|
+
margin: 0;
|
|
82
|
+
overflow: hidden;
|
|
83
|
+
font-size: 14px;
|
|
84
|
+
line-height: 22px;
|
|
85
|
+
font-weight: 500;
|
|
86
|
+
text-overflow: ellipsis;
|
|
87
|
+
white-space: nowrap;
|
|
88
|
+
}
|
|
89
|
+
[data-preview-text-viewer] button {
|
|
90
|
+
height: 28px;
|
|
91
|
+
padding: 0 12px;
|
|
92
|
+
border: 1px solid var(--dsw-alias-border-l2, rgb(0 0 0 / 10%));
|
|
93
|
+
border-radius: var(--dsw-radius-sm, 8px);
|
|
94
|
+
color: inherit;
|
|
95
|
+
background: transparent;
|
|
96
|
+
font: inherit;
|
|
97
|
+
cursor: pointer;
|
|
98
|
+
}
|
|
99
|
+
[data-preview-text-viewer] pre {
|
|
100
|
+
flex: 1;
|
|
101
|
+
margin: 0;
|
|
102
|
+
padding: 16px;
|
|
103
|
+
overflow: auto;
|
|
104
|
+
background: var(--dsw-alias-markdown-code-block, transparent);
|
|
105
|
+
font: 13px/20px ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
106
|
+
white-space: pre;
|
|
107
|
+
}
|
|
108
|
+
`;
|
|
109
|
+
/**
|
|
110
|
+
* Show one file in the page's modal viewer, replacing any file it already shows.
|
|
111
|
+
* @param path - Absolute VFS path used as the title.
|
|
112
|
+
* @param text - File contents, rendered as plain text.
|
|
113
|
+
*/
|
|
114
|
+
function showTextViewer(path, text) {
|
|
115
|
+
let dialog = document.querySelector("dialog[data-preview-text-viewer]");
|
|
116
|
+
if (dialog === null) {
|
|
117
|
+
const style = document.createElement("style");
|
|
118
|
+
style.textContent = VIEWER_STYLE;
|
|
119
|
+
document.head.append(style);
|
|
120
|
+
dialog = document.createElement("dialog");
|
|
121
|
+
dialog.dataset.previewTextViewer = "";
|
|
122
|
+
const header = document.createElement("header");
|
|
123
|
+
const title = document.createElement("h2");
|
|
124
|
+
const close = document.createElement("button");
|
|
125
|
+
close.type = "button";
|
|
126
|
+
close.textContent = "Close";
|
|
127
|
+
const shown = dialog;
|
|
128
|
+
close.addEventListener("click", () => {
|
|
129
|
+
shown.close();
|
|
130
|
+
});
|
|
131
|
+
dialog.addEventListener("keydown", (event) => {
|
|
132
|
+
event.stopPropagation();
|
|
133
|
+
});
|
|
134
|
+
header.append(title, close);
|
|
135
|
+
dialog.append(header, document.createElement("pre"));
|
|
136
|
+
document.body.append(dialog);
|
|
137
|
+
}
|
|
138
|
+
const title = dialog.querySelector("h2");
|
|
139
|
+
title.textContent = path;
|
|
140
|
+
title.title = path;
|
|
141
|
+
dialog.querySelector("pre").textContent = text;
|
|
142
|
+
if (!dialog.open) dialog.showModal();
|
|
143
|
+
}
|
|
144
|
+
//#endregion
|
|
55
145
|
//#region src/client/client.ts
|
|
56
146
|
/** Error carrying stream semantics across independently bundled Client code. */
|
|
57
147
|
var TunnelLogicalStreamError = class extends Error {
|
|
@@ -538,6 +628,9 @@ var WorkerTunnel = class {
|
|
|
538
628
|
controller.error(reason);
|
|
539
629
|
return;
|
|
540
630
|
}
|
|
631
|
+
case "view-text":
|
|
632
|
+
showTextViewer(frame.path, frame.text);
|
|
633
|
+
return;
|
|
541
634
|
case "stream-item":
|
|
542
635
|
case "stream-end":
|
|
543
636
|
case "stream-error": {
|
package/lib/index.js
CHANGED
|
@@ -745,6 +745,7 @@ const MODULE_PROXIES = {
|
|
|
745
745
|
"sharp": "./node/external_packages/sharp.ts",
|
|
746
746
|
"node-pty": "./node/external_packages/node-pty.ts",
|
|
747
747
|
"execa": "./node/external_packages/execa.ts",
|
|
748
|
+
"got": "./node/external_packages/got.ts",
|
|
748
749
|
"@vscode/ripgrep": "./node/external_packages/ripgrep.ts",
|
|
749
750
|
"@earendil-works/pi-ai": "./node/external_packages/pi-ai.ts",
|
|
750
751
|
"ws": "./node/external_packages/ws.ts"
|
|
@@ -768,6 +769,7 @@ const REPLACED_EXTERNAL_PACKAGES = [
|
|
|
768
769
|
"koffi",
|
|
769
770
|
"node-pty",
|
|
770
771
|
"execa",
|
|
772
|
+
"got",
|
|
771
773
|
"sharp",
|
|
772
774
|
"ws"
|
|
773
775
|
];
|
|
@@ -1657,6 +1659,18 @@ var TunnelServer = class {
|
|
|
1657
1659
|
this.failure = message;
|
|
1658
1660
|
for (const frame of this.queue.splice(0)) this.refuse(frame, message);
|
|
1659
1661
|
}
|
|
1662
|
+
/**
|
|
1663
|
+
* Ask the page to show one text file in its read-only viewer.
|
|
1664
|
+
* @param path - Absolute VFS path the viewer names.
|
|
1665
|
+
* @param text - File contents.
|
|
1666
|
+
*/
|
|
1667
|
+
viewText(path, text) {
|
|
1668
|
+
this.send({
|
|
1669
|
+
t: "view-text",
|
|
1670
|
+
path,
|
|
1671
|
+
text
|
|
1672
|
+
});
|
|
1673
|
+
}
|
|
1660
1674
|
send(frame, transfer) {
|
|
1661
1675
|
this.port.postMessage(frame, transfer);
|
|
1662
1676
|
}
|
|
@@ -1979,6 +1993,8 @@ function signalProcess(pid, signal) {
|
|
|
1979
1993
|
* packages use the presence of `process.title` to avoid browser-only globals.
|
|
1980
1994
|
* @module @deepseek-ai/dsh-experimental-webworker-runtime/src/node/globals/process
|
|
1981
1995
|
*/
|
|
1996
|
+
/** Virtual executable identity; the worker has no Node binary behind it. */
|
|
1997
|
+
const EXEC_PATH = "/dsh/bin/node";
|
|
1982
1998
|
/**
|
|
1983
1999
|
* Publish `globalThis.process`.
|
|
1984
2000
|
*
|
|
@@ -1996,9 +2012,9 @@ function installProcessGlobal(options) {
|
|
|
1996
2012
|
};
|
|
1997
2013
|
const shim = {
|
|
1998
2014
|
env: { ...options.env },
|
|
1999
|
-
argv: [...options.argv ?? [
|
|
2015
|
+
argv: [...options.argv ?? [EXEC_PATH]],
|
|
2000
2016
|
execArgv: [],
|
|
2001
|
-
execPath:
|
|
2017
|
+
execPath: EXEC_PATH,
|
|
2002
2018
|
title: "dsh-webworker",
|
|
2003
2019
|
platform: "linux",
|
|
2004
2020
|
arch: "x64",
|
|
@@ -3373,6 +3389,7 @@ function createWorkerHost(options) {
|
|
|
3373
3389
|
const require = loader.requireFrom(dirname(configPath));
|
|
3374
3390
|
const appBoot = require("@deepseek-ai/dsh-app-boot");
|
|
3375
3391
|
const cmdline = require("@deepseek-ai/dsh-cmdline");
|
|
3392
|
+
const started = Promise.withResolvers();
|
|
3376
3393
|
const { patches, profile } = bootPatches(loader, mounted, configPath, root);
|
|
3377
3394
|
const profileConfig = join(profile.dir, "cordis.yml");
|
|
3378
3395
|
const ctx = await appBoot.boot("dsh-webworker", profileConfig, patches, (hostCtx) => {
|
|
@@ -3389,7 +3406,16 @@ function createWorkerHost(options) {
|
|
|
3389
3406
|
]],
|
|
3390
3407
|
exit: (code) => {
|
|
3391
3408
|
console.warn(`webworker host: tree requested exit(${String(code)})`);
|
|
3392
|
-
}
|
|
3409
|
+
},
|
|
3410
|
+
ready: { onReady: (listener) => {
|
|
3411
|
+
let pending = true;
|
|
3412
|
+
started.promise.then(() => {
|
|
3413
|
+
if (pending) listener();
|
|
3414
|
+
});
|
|
3415
|
+
return () => {
|
|
3416
|
+
pending = false;
|
|
3417
|
+
};
|
|
3418
|
+
} }
|
|
3393
3419
|
});
|
|
3394
3420
|
});
|
|
3395
3421
|
context = ctx;
|
|
@@ -3406,6 +3432,7 @@ function createWorkerHost(options) {
|
|
|
3406
3432
|
openStream: (endpoint, payload, uplink, signal) => typertGateway.wireStream.open(endpoint, payload, uplink, void 0, signal),
|
|
3407
3433
|
streamFailure: typertGateway.wireStream.failure
|
|
3408
3434
|
});
|
|
3435
|
+
started.resolve();
|
|
3409
3436
|
} catch (reason) {
|
|
3410
3437
|
tunnel.fail(reason);
|
|
3411
3438
|
throw reason;
|
|
@@ -3501,10 +3528,6 @@ function bootPatches(loader, vfs, configPath, root) {
|
|
|
3501
3528
|
};
|
|
3502
3529
|
const configOf = (row) => typeof row.config === "object" && row.config !== null && !Array.isArray(row.config) ? row.config : {};
|
|
3503
3530
|
const patches = [];
|
|
3504
|
-
for (const id of ["hmr", "plugin-manager"]) if (find(rows, id) !== void 0) patches.push({
|
|
3505
|
-
id,
|
|
3506
|
-
disabled: true
|
|
3507
|
-
});
|
|
3508
3531
|
const jsonl = find(rows, "session-persistence-jsonl");
|
|
3509
3532
|
if (jsonl !== void 0) patches.push({
|
|
3510
3533
|
id: "session-persistence-jsonl",
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* turns fetch-shaped calls into `req` frames and rebuilds Responses from the
|
|
4
4
|
* worker's `res` / `res-head`+`res-chunk`+`res-end` frames, so every consumer
|
|
5
5
|
* (boot payload, bundle transport, ApiClient, Typert RPC) speaks plain HTTP.
|
|
6
|
+
* The worker's unsolicited `view-text` frame opens the page's text viewer.
|
|
6
7
|
*/
|
|
7
8
|
import type { IndexInjection } from '@deepseek-ai/dsh-host-webserver';
|
|
8
9
|
/** Boot payload of the tunnel bootstrap route. */
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Read-only text viewer the page shows when the worker's `xdg-open` names a VFS file. */
|
|
2
|
+
/**
|
|
3
|
+
* Show one file in the page's modal viewer, replacing any file it already shows.
|
|
4
|
+
* @param path - Absolute VFS path used as the title.
|
|
5
|
+
* @param text - File contents, rendered as plain text.
|
|
6
|
+
*/
|
|
7
|
+
export declare function showTextViewer(path: string, text: string): void;
|
|
8
|
+
//# sourceMappingURL=text-viewer.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** CommonJS interop marker for the worker loader's default import. */
|
|
2
|
+
export declare const __esModule = true;
|
|
3
|
+
/** Reject product telemetry HTTP requests without opening a connection. */
|
|
4
|
+
declare const got: {
|
|
5
|
+
post: (...args: never[]) => never;
|
|
6
|
+
};
|
|
7
|
+
export default got;
|
|
8
|
+
//# sourceMappingURL=got.d.ts.map
|
|
@@ -4,7 +4,7 @@ export interface ProcessShimOptions {
|
|
|
4
4
|
readonly cwd: string;
|
|
5
5
|
/** Environment the tree reads; `DSH_HOME` belongs here. */
|
|
6
6
|
readonly env: Readonly<Record<string, string>>;
|
|
7
|
-
/** Argument vector reported to the tree. */
|
|
7
|
+
/** Argument vector reported to the tree; defaults to the executable alone, since no entry script exists. */
|
|
8
8
|
readonly argv?: readonly string[];
|
|
9
9
|
}
|
|
10
10
|
/** The members this shim publishes. */
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { VirtualExecutable } from './virtual-executables.ts';
|
|
2
|
+
/** Page-side display of one text file. */
|
|
3
|
+
export type TextViewer = (path: string, text: string) => void;
|
|
4
|
+
/**
|
|
5
|
+
* Install the page viewer `xdg-open` reports to; the worker host calls this once its tunnel exists.
|
|
6
|
+
* @param next - Viewer that forwards to the page.
|
|
7
|
+
*/
|
|
8
|
+
export declare function setTextViewer(next: TextViewer): void;
|
|
9
|
+
/** Virtual executable replacing the desktop opener with the page's text viewer. */
|
|
10
|
+
export declare const XDG_OPEN_EXECUTABLE: VirtualExecutable;
|
|
11
|
+
//# sourceMappingURL=xdg-open.d.ts.map
|
|
@@ -108,8 +108,15 @@ export interface TunnelStreamErrorFrame {
|
|
|
108
108
|
readonly message: string;
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
|
+
/** Worker request to show one VFS text file in the page's read-only viewer; no reply follows. */
|
|
112
|
+
export interface TunnelViewTextFrame {
|
|
113
|
+
readonly t: 'view-text';
|
|
114
|
+
/** Absolute VFS path, shown as the viewer title. */
|
|
115
|
+
readonly path: string;
|
|
116
|
+
readonly text: string;
|
|
117
|
+
}
|
|
111
118
|
/** Frames the worker emits. */
|
|
112
|
-
export type TunnelOutboundFrame = TunnelResponseFrame | TunnelResponseHeadFrame | TunnelResponseChunkFrame | TunnelResponseEndFrame | TunnelResponseErrorFrame | TunnelStreamItemFrame | TunnelStreamEndFrame | TunnelStreamErrorFrame;
|
|
119
|
+
export type TunnelOutboundFrame = TunnelViewTextFrame | TunnelResponseFrame | TunnelResponseHeadFrame | TunnelResponseChunkFrame | TunnelResponseEndFrame | TunnelResponseErrorFrame | TunnelStreamItemFrame | TunnelStreamEndFrame | TunnelStreamErrorFrame;
|
|
113
120
|
/**
|
|
114
121
|
* Validate a `postMessage` payload as a tunnel frame.
|
|
115
122
|
* @param data - Message data received by the worker.
|
|
@@ -107,6 +107,12 @@ export declare class TunnelServer {
|
|
|
107
107
|
* @param reason - Boot failure to report.
|
|
108
108
|
*/
|
|
109
109
|
fail(reason: unknown): void;
|
|
110
|
+
/**
|
|
111
|
+
* Ask the page to show one text file in its read-only viewer.
|
|
112
|
+
* @param path - Absolute VFS path the viewer names.
|
|
113
|
+
* @param text - File contents.
|
|
114
|
+
*/
|
|
115
|
+
viewText(path: string, text: string): void;
|
|
110
116
|
private send;
|
|
111
117
|
private refuse;
|
|
112
118
|
private dispatchFrame;
|
package/lib/worker.js
CHANGED
|
@@ -619,6 +619,8 @@ function signalProcess(pid, signal) {
|
|
|
619
619
|
* packages use the presence of `process.title` to avoid browser-only globals.
|
|
620
620
|
* @module @deepseek-ai/dsh-experimental-webworker-runtime/src/node/globals/process
|
|
621
621
|
*/
|
|
622
|
+
/** Virtual executable identity; the worker has no Node binary behind it. */
|
|
623
|
+
const EXEC_PATH = "/dsh/bin/node";
|
|
622
624
|
/**
|
|
623
625
|
* Publish `globalThis.process`.
|
|
624
626
|
*
|
|
@@ -636,9 +638,9 @@ function installProcessGlobal(options) {
|
|
|
636
638
|
};
|
|
637
639
|
const shim = {
|
|
638
640
|
env: { ...options.env },
|
|
639
|
-
argv: [...options.argv ?? [
|
|
641
|
+
argv: [...options.argv ?? [EXEC_PATH]],
|
|
640
642
|
execArgv: [],
|
|
641
|
-
execPath:
|
|
643
|
+
execPath: EXEC_PATH,
|
|
642
644
|
title: "dsh-webworker",
|
|
643
645
|
platform: "linux",
|
|
644
646
|
arch: "x64",
|
|
@@ -1098,6 +1100,18 @@ var TunnelServer = class {
|
|
|
1098
1100
|
this.failure = message;
|
|
1099
1101
|
for (const frame of this.queue.splice(0)) this.refuse(frame, message);
|
|
1100
1102
|
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Ask the page to show one text file in its read-only viewer.
|
|
1105
|
+
* @param path - Absolute VFS path the viewer names.
|
|
1106
|
+
* @param text - File contents.
|
|
1107
|
+
*/
|
|
1108
|
+
viewText(path, text) {
|
|
1109
|
+
this.send({
|
|
1110
|
+
t: "view-text",
|
|
1111
|
+
path,
|
|
1112
|
+
text
|
|
1113
|
+
});
|
|
1114
|
+
}
|
|
1101
1115
|
send(frame, transfer) {
|
|
1102
1116
|
this.port.postMessage(frame, transfer);
|
|
1103
1117
|
}
|
|
@@ -2546,6 +2560,50 @@ function requireActiveVfs() {
|
|
|
2546
2560
|
if (active === void 0) throw new Error("webworker vfs: no filesystem is mounted; the worker entry must call setActiveVfs before any node:fs access");
|
|
2547
2561
|
return active;
|
|
2548
2562
|
}
|
|
2563
|
+
//#endregion
|
|
2564
|
+
//#region src/shell/process/xdg-open.ts
|
|
2565
|
+
/**
|
|
2566
|
+
* The Worker's `xdg-open`: hands one VFS text file to the page's read-only
|
|
2567
|
+
* viewer, the only desktop a preview has. Exit statuses follow xdg-open(1):
|
|
2568
|
+
* 1 usage, 2 missing file, 3 no viewer for the target, 4 action failed.
|
|
2569
|
+
*/
|
|
2570
|
+
let viewer;
|
|
2571
|
+
/**
|
|
2572
|
+
* Install the page viewer `xdg-open` reports to; the worker host calls this once its tunnel exists.
|
|
2573
|
+
* @param next - Viewer that forwards to the page.
|
|
2574
|
+
*/
|
|
2575
|
+
function setTextViewer(next) {
|
|
2576
|
+
viewer = next;
|
|
2577
|
+
}
|
|
2578
|
+
function exit(exitCode, stderr = "") {
|
|
2579
|
+
return {
|
|
2580
|
+
kind: "exit",
|
|
2581
|
+
exitCode,
|
|
2582
|
+
stdout: "",
|
|
2583
|
+
stderr
|
|
2584
|
+
};
|
|
2585
|
+
}
|
|
2586
|
+
/** Virtual executable replacing the desktop opener with the page's text viewer. */
|
|
2587
|
+
const XDG_OPEN_EXECUTABLE = {
|
|
2588
|
+
name: "xdg-open",
|
|
2589
|
+
async prepare(args, context) {
|
|
2590
|
+
if (args.length !== 1) return exit(1, "xdg-open: usage: xdg-open { file | URL }\n");
|
|
2591
|
+
const path = resolve$2(context.cwd, args[0]);
|
|
2592
|
+
const stats = await context.filesystem.stat(path);
|
|
2593
|
+
if (stats === void 0) return exit(2, `xdg-open: file '${path}' does not exist\n`);
|
|
2594
|
+
if (stats.directory) return exit(3, `xdg-open: no viewer for directory '${path}'\n`);
|
|
2595
|
+
if (viewer === void 0) return exit(3, "xdg-open: no page viewer is attached\n");
|
|
2596
|
+
try {
|
|
2597
|
+
viewer(path, await context.filesystem.readText(path));
|
|
2598
|
+
} catch (error) {
|
|
2599
|
+
return exit(4, `xdg-open: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
2600
|
+
}
|
|
2601
|
+
return exit(0);
|
|
2602
|
+
},
|
|
2603
|
+
runSync() {
|
|
2604
|
+
return { kind: "asynchronous" };
|
|
2605
|
+
}
|
|
2606
|
+
};
|
|
2549
2607
|
function requireGlobalPort(channel) {
|
|
2550
2608
|
if (channel !== void 0) return channel;
|
|
2551
2609
|
const post = globalThis.postMessage;
|
|
@@ -2576,6 +2634,9 @@ function createWorkerHost(options) {
|
|
|
2576
2634
|
...options.privilegedMethods === void 0 ? {} : { privilegedMethods: options.privilegedMethods },
|
|
2577
2635
|
...options.unaryApiLane === void 0 ? {} : { unaryApiLane: options.unaryApiLane }
|
|
2578
2636
|
});
|
|
2637
|
+
setTextViewer((path, text) => {
|
|
2638
|
+
tunnel.viewText(path, text);
|
|
2639
|
+
});
|
|
2579
2640
|
let vfs;
|
|
2580
2641
|
let modules;
|
|
2581
2642
|
let context;
|
|
@@ -2611,6 +2672,7 @@ function createWorkerHost(options) {
|
|
|
2611
2672
|
const require = loader.requireFrom(dirname$1(configPath));
|
|
2612
2673
|
const appBoot = require("@deepseek-ai/dsh-app-boot");
|
|
2613
2674
|
const cmdline = require("@deepseek-ai/dsh-cmdline");
|
|
2675
|
+
const started = Promise.withResolvers();
|
|
2614
2676
|
const { patches, profile } = bootPatches(loader, mounted, configPath, root);
|
|
2615
2677
|
const profileConfig = join$1(profile.dir, "cordis.yml");
|
|
2616
2678
|
const ctx = await appBoot.boot("dsh-webworker", profileConfig, patches, (hostCtx) => {
|
|
@@ -2627,7 +2689,16 @@ function createWorkerHost(options) {
|
|
|
2627
2689
|
]],
|
|
2628
2690
|
exit: (code) => {
|
|
2629
2691
|
console.warn(`webworker host: tree requested exit(${String(code)})`);
|
|
2630
|
-
}
|
|
2692
|
+
},
|
|
2693
|
+
ready: { onReady: (listener) => {
|
|
2694
|
+
let pending = true;
|
|
2695
|
+
started.promise.then(() => {
|
|
2696
|
+
if (pending) listener();
|
|
2697
|
+
});
|
|
2698
|
+
return () => {
|
|
2699
|
+
pending = false;
|
|
2700
|
+
};
|
|
2701
|
+
} }
|
|
2631
2702
|
});
|
|
2632
2703
|
});
|
|
2633
2704
|
context = ctx;
|
|
@@ -2644,6 +2715,7 @@ function createWorkerHost(options) {
|
|
|
2644
2715
|
openStream: (endpoint, payload, uplink, signal) => typertGateway.wireStream.open(endpoint, payload, uplink, void 0, signal),
|
|
2645
2716
|
streamFailure: typertGateway.wireStream.failure
|
|
2646
2717
|
});
|
|
2718
|
+
started.resolve();
|
|
2647
2719
|
} catch (reason) {
|
|
2648
2720
|
tunnel.fail(reason);
|
|
2649
2721
|
throw reason;
|
|
@@ -2739,10 +2811,6 @@ function bootPatches(loader, vfs, configPath, root) {
|
|
|
2739
2811
|
};
|
|
2740
2812
|
const configOf = (row) => typeof row.config === "object" && row.config !== null && !Array.isArray(row.config) ? row.config : {};
|
|
2741
2813
|
const patches = [];
|
|
2742
|
-
for (const id of ["hmr", "plugin-manager"]) if (find(rows, id) !== void 0) patches.push({
|
|
2743
|
-
id,
|
|
2744
|
-
disabled: true
|
|
2745
|
-
});
|
|
2746
2814
|
const jsonl = find(rows, "session-persistence-jsonl");
|
|
2747
2815
|
if (jsonl !== void 0) patches.push({
|
|
2748
2816
|
id: "session-persistence-jsonl",
|
|
@@ -20711,7 +20779,7 @@ const LANDLOCK_EXECUTABLE = {
|
|
|
20711
20779
|
//#endregion
|
|
20712
20780
|
//#region src/shell/process/virtual-executables.ts
|
|
20713
20781
|
/** Virtual executable registry used by the Worker process launcher. */
|
|
20714
|
-
const EXECUTABLES = new Map([[LANDLOCK_EXECUTABLE.name, LANDLOCK_EXECUTABLE]]);
|
|
20782
|
+
const EXECUTABLES = new Map([[LANDLOCK_EXECUTABLE.name, LANDLOCK_EXECUTABLE], [XDG_OPEN_EXECUTABLE.name, XDG_OPEN_EXECUTABLE]]);
|
|
20715
20783
|
/**
|
|
20716
20784
|
* Resolve a Worker platform executable by logical name.
|
|
20717
20785
|
* @param path - Bare name or executable path passed to `spawn`.
|
|
@@ -21539,6 +21607,15 @@ var execa_exports = /* @__PURE__ */ __exportAll({ execa: () => execa });
|
|
|
21539
21607
|
/** Refuse external package commands in the worker host. */
|
|
21540
21608
|
const execa = notImplementedFail("execa", "execa");
|
|
21541
21609
|
//#endregion
|
|
21610
|
+
//#region src/node/external_packages/got.ts
|
|
21611
|
+
/** Node HTTP product telemetry is unavailable in the browser preview. */
|
|
21612
|
+
var got_exports = /* @__PURE__ */ __exportAll({
|
|
21613
|
+
__esModule: () => true,
|
|
21614
|
+
default: () => got
|
|
21615
|
+
});
|
|
21616
|
+
/** Reject product telemetry HTTP requests without opening a connection. */
|
|
21617
|
+
const got = { post: notImplementedFail("got", "post") };
|
|
21618
|
+
//#endregion
|
|
21542
21619
|
//#region src/node/external_packages/pi-ai.ts
|
|
21543
21620
|
/**
|
|
21544
21621
|
* `@earendil-works/pi-ai` stub, including its `/providers/all` and `/api/*.lazy`
|
|
@@ -21768,6 +21845,7 @@ const REPLACED_EXTERNAL_PACKAGES = [
|
|
|
21768
21845
|
"koffi",
|
|
21769
21846
|
"node-pty",
|
|
21770
21847
|
"execa",
|
|
21848
|
+
"got",
|
|
21771
21849
|
"sharp",
|
|
21772
21850
|
"ws"
|
|
21773
21851
|
];
|
|
@@ -21833,6 +21911,7 @@ const EXTERNALS = {
|
|
|
21833
21911
|
"sharp": () => sharp_exports,
|
|
21834
21912
|
"node-pty": () => node_pty_exports,
|
|
21835
21913
|
"execa": () => execa_exports,
|
|
21914
|
+
"got": () => got_exports,
|
|
21836
21915
|
"ws": () => ws_exports,
|
|
21837
21916
|
"@vscode/ripgrep": () => ripgrep_exports,
|
|
21838
21917
|
"@earendil-works/pi-ai": () => pi_ai_exports
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-experimental-webworker-runtime",
|
|
3
3
|
"description": "Browser-only harness runtime: in-memory VFS, module transform and loader, postMessage tunnel, and the dedicated Web Worker assembly, with the Node-compatibility layer that lets the host tree run unchanged",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0-rc.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -34,15 +34,15 @@
|
|
|
34
34
|
"buffer": "^6.0.3",
|
|
35
35
|
"picomatch": "^4.0.4",
|
|
36
36
|
"readable-stream": "^4.7.0",
|
|
37
|
-
"@deepseek-ai/dsh-
|
|
38
|
-
"@deepseek-ai/dsh-
|
|
37
|
+
"@deepseek-ai/dsh-util-crypto": "0.2.0-rc.2",
|
|
38
|
+
"@deepseek-ai/dsh-client-web": "0.2.0-rc.2"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@deepseek-ai/cordis": "~4.0.4",
|
|
42
|
-
"@deepseek-ai/
|
|
43
|
-
"@deepseek-ai/dsh-client-
|
|
44
|
-
"@deepseek-ai/dsh-
|
|
45
|
-
"@deepseek-ai/
|
|
42
|
+
"@deepseek-ai/cordis-plugin-loader": "~1.0.5",
|
|
43
|
+
"@deepseek-ai/dsh-client-connection": "0.2.0-rc.2",
|
|
44
|
+
"@deepseek-ai/dsh-client-modules": "0.2.0-rc.2",
|
|
45
|
+
"@deepseek-ai/dsh-host-webserver": "0.2.0-rc.2"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/picomatch": "^3.0.2",
|
|
@@ -50,20 +50,20 @@
|
|
|
50
50
|
"chokidar": "^5.0.0",
|
|
51
51
|
"@deepseek-ai/cordis": "~4.0.4",
|
|
52
52
|
"@deepseek-ai/cordis-plugin-loader": "~1.0.5",
|
|
53
|
-
"@deepseek-ai/dsh-api-gateway": "0.
|
|
54
|
-
"@deepseek-ai/dsh-app-boot": "0.
|
|
55
|
-
"@deepseek-ai/dsh-
|
|
56
|
-
"@deepseek-ai/dsh-
|
|
57
|
-
"@deepseek-ai/dsh-client-file-upload": "0.
|
|
58
|
-
"@deepseek-ai/dsh-client-modules": "0.
|
|
59
|
-
"@deepseek-ai/dsh-host-webserver": "0.
|
|
60
|
-
"@deepseek-ai/dsh-sandbox-local": "0.
|
|
61
|
-
"@deepseek-ai/dsh-sandbox-policy": "0.
|
|
62
|
-
"@deepseek-ai/dsh-session": "0.
|
|
63
|
-
"@deepseek-ai/dsh-session-projection": "0.
|
|
64
|
-
"@deepseek-ai/dsh-session-persistence-jsonl": "0.
|
|
65
|
-
"@deepseek-ai/dsh-subagent": "0.
|
|
66
|
-
"@deepseek-ai/dsh-subprocess-local": "0.
|
|
53
|
+
"@deepseek-ai/dsh-api-gateway": "0.2.0-rc.2",
|
|
54
|
+
"@deepseek-ai/dsh-app-boot": "0.2.0-rc.2",
|
|
55
|
+
"@deepseek-ai/dsh-client-connection": "0.2.0-rc.2",
|
|
56
|
+
"@deepseek-ai/dsh-bash-sandbox": "0.2.0-rc.2",
|
|
57
|
+
"@deepseek-ai/dsh-client-file-upload": "0.2.0-rc.2",
|
|
58
|
+
"@deepseek-ai/dsh-client-modules": "0.2.0-rc.2",
|
|
59
|
+
"@deepseek-ai/dsh-host-webserver": "0.2.0-rc.2",
|
|
60
|
+
"@deepseek-ai/dsh-sandbox-local": "0.2.0-rc.2",
|
|
61
|
+
"@deepseek-ai/dsh-sandbox-policy": "0.2.0-rc.2",
|
|
62
|
+
"@deepseek-ai/dsh-session": "0.2.0-rc.2",
|
|
63
|
+
"@deepseek-ai/dsh-session-projection": "0.2.0-rc.2",
|
|
64
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": "0.2.0-rc.2",
|
|
65
|
+
"@deepseek-ai/dsh-subagent": "0.2.0-rc.2",
|
|
66
|
+
"@deepseek-ai/dsh-subprocess-local": "0.2.0-rc.2",
|
|
67
67
|
"@deepseek-ai/node-addon-system": "~0.1.2"
|
|
68
68
|
},
|
|
69
69
|
"files": [
|