better-dsh 0.3.0 → 0.3.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.md +49 -178
- package/cordis.patch.yml +4 -35
- package/docs/adr/0015-independent-bundles-agent-remote.md +40 -0
- package/docs/remote-tools.md +56 -0
- package/docs/specs/omp-python-repl-port/runtime-guide.md +33 -0
- package/docs/specs/omp-python-repl-port/spec.md +61 -0
- package/docs/specs/remote-tool-enhancement/spec.md +203 -0
- package/dsh-docs/baseline.md +13 -0
- package/dsh-docs/subsystems/invariants.md +3 -0
- package/dsh-docs/subsystems/invariants.zh.md +3 -0
- package/eval-description.md +7 -3
- package/lib/{LaunchOptions-kGXcZOe0.js → LaunchOptions-5eg7E0ye.js} +1 -1
- package/lib/LaunchOptions-DxQQ0s-A.js +4 -0
- package/lib/{bidi-BalpKaJc.js → bidi-CwabFH07.js} +1 -1
- package/lib/client/index.js +30 -6
- package/lib/failover/index.js +1 -1
- package/lib/fs-aware/sandbox-plugin.js +3 -3
- package/lib/{index-browser-CysrjMyM.js → index-browser-B-9jm12n.js} +4 -4
- package/lib/index.d.ts +17 -41
- package/lib/index.js +473 -1678
- package/lib/kernel-env-BOF0fNHn.js +91 -0
- package/lib/kernel-env.d.ts +4 -58
- package/lib/kernel-env.js +2 -2
- package/lib/{lsp-server-registry-BXvUTBY7.js → lsp-server-registry-BcdkHROD.js} +1 -1
- package/lib/{lsp-server-registry-CH9WNFFt.js → lsp-server-registry-D4VLs1Sm.js} +1 -1
- package/lib/{main-CupOhMp5.js → main-BeCgUd20.js} +8 -6
- package/lib/{main-BQeFrBM1.js → main-Dv_UQqG2.js} +1 -1
- package/lib/mobile/plugin.d.ts +1 -1
- package/lib/omp-python/DILL-LICENSE +35 -0
- package/lib/omp-python/OMP-LICENSE +23 -0
- package/lib/omp-python/better_snapshot.py +391 -0
- package/lib/omp-python/better_support.py +425 -0
- package/lib/omp-python/dill-provenance.json +55 -0
- package/lib/omp-python/provenance.json +13 -0
- package/lib/omp-python/runner.py +2499 -0
- package/lib/omp-python/vendor/dill/__diff.py +234 -0
- package/lib/omp-python/vendor/dill/__info__.py +291 -0
- package/lib/omp-python/vendor/dill/__init__.py +119 -0
- package/lib/omp-python/vendor/dill/_dill.py +2265 -0
- package/lib/omp-python/vendor/dill/_objects.py +545 -0
- package/lib/omp-python/vendor/dill/_shims.py +193 -0
- package/lib/omp-python/vendor/dill/detect.py +287 -0
- package/lib/omp-python/vendor/dill/logger.py +285 -0
- package/lib/omp-python/vendor/dill/objtypes.py +24 -0
- package/lib/omp-python/vendor/dill/pointers.py +122 -0
- package/lib/omp-python/vendor/dill/session.py +612 -0
- package/lib/omp-python/vendor/dill/settings.py +25 -0
- package/lib/omp-python/vendor/dill/source.py +1025 -0
- package/lib/omp-python/vendor/dill/temp.py +252 -0
- package/lib/{puppeteer-core-CSk2PtSm.js → puppeteer-core-Dnd7eqel.js} +9 -9
- package/lib/remote/plugin.d.ts +459 -5
- package/lib/remote/plugin.js +2389 -210
- package/lib/url-schemes/index.d.ts +11 -11
- package/lib/url-schemes/index.js +12 -12
- package/lib/web-password.d.ts +8 -8
- package/lib/web-password.js +5 -1
- package/lib/{web-trust-Dej_RI2B.d.ts → web-trust-CwZrTBcl.d.ts} +11 -11
- package/lib/web-trust.d.ts +1 -2
- package/lib/welcome-notice.d.ts +5 -7
- package/lib/welcome-notice.js +9 -48
- package/lib/{wrap-T4I0nfPM.js → wrap-0VA0uFx8.js} +1 -1
- package/package.json +6 -23
- package/scripts/kernel-provision.mjs +4 -34
- package/lib/LaunchOptions-B874eBu2.js +0 -4
- package/lib/bundle-delivery.d.ts +0 -20
- package/lib/bundle-delivery.js +0 -209
- package/lib/hmr.d.ts +0 -32
- package/lib/hmr.js +0 -49
- package/lib/kernel-bridge.py +0 -172
- package/lib/kernel-env-D8UOWeji.js +0 -195
- package/lib/webserver.d.ts +0 -10
- package/lib/webserver.js +0 -19
- package/scripts/register-bundle.mjs +0 -80
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# Remote 工具 enhancement — 交付、生命周期与传输规格
|
|
2
|
+
|
|
3
|
+
- 日期:2026-10-10(Asia/Hong_Kong)
|
|
4
|
+
- 状态:2026-10-10 user 已审阅并明确授权执行;Task0–7 已独立审阅通过;Task8 完整双包消费者验收进行中,L 实装暴露的 worker/SSH cleanup 缺陷已进入修复验证。用户亲验与发布尚未放行。
|
|
5
|
+
- 输入:[2026-10-09 方向稿](../../10_plans/2026-10-09-remote-tool-optimization-directions.md)及 2026-10-10 会话裁决。
|
|
6
|
+
- 执行计划:[2026-10-10-remote-tool-enhancement.md](../../superpowers/plans/2026-10-10-remote-tool-enhancement.md)。本规格优先于方向稿的冲突条款。
|
|
7
|
+
|
|
8
|
+
## 1. 目标与本轮范围
|
|
9
|
+
|
|
10
|
+
为 Agent 提供省步骤、减少转义和连接错误的 remote 便利层。一个 `remote` 工具覆盖 SSH、Docker、Incus、BYO-PTY,以及 Super 在场时的 Hub machine。Super 和 Better 分别可独立交付,不因另一包关闭或卸载丢失自身代码。
|
|
11
|
+
|
|
12
|
+
本轮实现 P0/P1:
|
|
13
|
+
|
|
14
|
+
1. Better 单一源码、Super 构建副本;两条插件行默认开启,Agent 实例级一次注册竞争。
|
|
15
|
+
2. 可选 Hub 接入、动态 machine 清单;无远端机器时 Hub 清单为空,不执行本机。
|
|
16
|
+
3. oneshot `script` 文件载体与 Hub oneshot stdin parity。
|
|
17
|
+
4. 取消 Hub 模型工具缺省/显式本机执行入口,保留执行服务端与本地文件端点。
|
|
18
|
+
5. BYO-SSH 注册、复用及连接参数;BYO-PTY 保持既有语义。
|
|
19
|
+
6. oneshot 后台作业复用 DSH 原生 jobs 的 identity、pull-delta、完成通知及取消。
|
|
20
|
+
7. `copy` 跨受支持端点的二进制传输、校验与暂存清理。
|
|
21
|
+
8. `rsync` 仅 SSH;两个远端经发起机的 SSH 隧道中继,身份不下放。
|
|
22
|
+
9. 真实双包交付和模型 Surface 验收。
|
|
23
|
+
|
|
24
|
+
后续范围,不在本轮实现:P2 PTY 已完成命令的 backlog/offset 续读;P3 运行中 probe。取消:3.5M 提醒、一次性 `ssh://` target、`cmd[]` fan-out、push stdout、非 SSH/混合 transport rsync、BYO-WebSocket/Docker/Incus、命令黑名单、额外文件管理工具、inline cmd 扩容。
|
|
25
|
+
|
|
26
|
+
## 2. 包归属与交付
|
|
27
|
+
|
|
28
|
+
- 唯一可编辑源码:`better-dsh/src/remote/`。
|
|
29
|
+
- Super 构建时从该源码生成独立 remote 交付闭包,导出 `super-dsh/remote`。不复制 Better 整包、客户端、REPL、文档或其他工具;不建立 Super→Better 的 npm dependency/optional/peer 边。
|
|
30
|
+
- 生成目录及 provenance manifest 不手改;构建必须检查源码哈希与输出闭包,防止旧副本或跨包裸 import。
|
|
31
|
+
- Better 行保留 `id: dashr-remote`、`name: better-dsh/remote`;Super 新行 `id: superd-remote`、`name: super-dsh/remote`。两个 YAML id 不相同,两行默认开,模型工具名相同:`remote`。
|
|
32
|
+
- 不在 Super YAML 中禁用 Better remote,不写安装时脚本化的 profile enable/disable;已存在的用户开关选择保留。
|
|
33
|
+
- Super 的 companion 原生安装流程不改变;remote 是“Super 不携带 Better 文件”契约的窄范围自有源码复用例外,而不是恢复整包捆绑。
|
|
34
|
+
- 宿主模块继续 optional peer、真实类型和单实例契约;私有 schema 真实构建输入在生成闭包内解决,消费者不解析 Better 的 `#schemastery`。
|
|
35
|
+
- 根、Better、Super 同步版本;实现轮经 `npm run version:release -- <同步字母版本>` 和双 tarball 通道,不发布 registry。
|
|
36
|
+
|
|
37
|
+
## 3. Agent 实例级注册
|
|
38
|
+
|
|
39
|
+
### 3.1 上游事实
|
|
40
|
+
|
|
41
|
+
当前上游 `tools.register()` 同步插入 scoped registry,同 scope 同名立即抛错,不是先收集后统一去重。`agent/created` 是 setup 完成后、首轮工作放行前的 serial lifecycle 事件。preset revision/generation 被多个 Agent 复用,不能假设每个 session 重跑 preset 插件。
|
|
42
|
+
|
|
43
|
+
证据位置:
|
|
44
|
+
|
|
45
|
+
- `upstream/deepseek-harness/packages/core/tools/src/index.ts:1063`。
|
|
46
|
+
- `upstream/deepseek-harness/packages/core/scope/src/store.ts:43`。
|
|
47
|
+
- `upstream/deepseek-harness/packages/core/agent/src/runtime-types.ts:250`。
|
|
48
|
+
- `upstream/deepseek-harness/packages/preset/agent-preset-registry/src/index.ts:104`。
|
|
49
|
+
- `upstream/deepseek-harness/packages/api/session-controller/src/agent.ts:185`。
|
|
50
|
+
|
|
51
|
+
### 3.2 行为
|
|
52
|
+
|
|
53
|
+
- host 插件行只安装生命周期监听器,不在全局工具作用域注册 `remote`。
|
|
54
|
+
- 每次 `agent/created`,两份行各自在该 Agent 的真实 scope 尝试注册工具。先成功者供该 Agent 使用,后者只跳过该实例。
|
|
55
|
+
- 不自行判断 new/cold resume,不存 session 启动类型、不记录“已退出/待命”状态;官方创建事件本身给出尝试时机。必要改动仅为把现有 host 全局注册移到此事件的 scoped 注册,并局部处理同名冲突。
|
|
56
|
+
- 不保证 Super 优先,不按 UI/YAML 展示顺序推断赢家。两份相同源码均可接入 Hub,赢家不影响能力集合。
|
|
57
|
+
- 只处理实际的 `remote` 重名冲突,其他 schema、生命周期、服务异常继续抛出;不吞掉所有错误。
|
|
58
|
+
- 重名跳过不写 `disabled`,不让 host 行变成失败状态,也不使 Agent 创建失败。
|
|
59
|
+
- 注册、driver、PTY、BYO-SSH label 及 jobs 同时归该 Agent scope 和来源插件行所有:任一 owner 退出都撤注册并清理资源;不能仅依附 Agent 而留下已卸载包的执行闭包。
|
|
60
|
+
- 不轮询、不设接管队列、不在空位出现时重试。已存活 Agent 中途卸载赢家,当前实例不自动补位。
|
|
61
|
+
- new session 和 cold resume 创建新 Agent 时重新尝试;hot continuation、重开页面、给存活会话发消息不重试。
|
|
62
|
+
- 首轮插件热安装不追溯给既有 Agent 补注册,Surface 提示新建会话或 cold resume;普通 disable→enable 若该插件本身支持恢复,须记录实际窗口,不承诺热接管。
|
|
63
|
+
- foreign runtime 的既有 Hub 注入面与 native `remote` 不混淆:本轮不宣称所有 foreign agent 直接拥有 DSH scoped remote 工具。
|
|
64
|
+
|
|
65
|
+
## 4. 可选 Hub 能力
|
|
66
|
+
|
|
67
|
+
Better 不 import Super 包。共享 remote 定义 owned structural contract;Super 在官方 Cordis scope 提供 `superdRemoteTransport`,remote 用 `ctx.get()` 在能力消费时可选取得。absence 不形成硬 inject 等待,不修改宿主。
|
|
68
|
+
|
|
69
|
+
- provider 在场 → 工具描述与 roster 说明 `hub:<machineId>`;机器目录可为空。机器变化只改变 roster,不增删 target 字段。
|
|
70
|
+
- provider 不在场 → SSH/Docker/Incus/BYO 继续可用,Hub target 返回有恢复提示的 unavailable 错误,不静默改走 SSH。
|
|
71
|
+
- provider 的出现/消失通过官方服务通知更新模型 Surface;不检查 npm 包目录,不轮询各机器可达性。
|
|
72
|
+
- roster 来自 pairing 表中的远端 m4,排除 self;执行时检查 unknown machine、`execEnabled` 与连接错误,保留原始原因。
|
|
73
|
+
- 远端执行服务端和文件 transport 随 Hub 本体提供,不依附模型侧 remote 行。关闭某台机器的工具行不应拆掉别人访问它的服务端。
|
|
74
|
+
- PTY 沿用现有 pairing cookie、auth/Host/Origin fence 与 WS executor。oneshot 沿用既有 authenticated RPC,不声称现有 HTTP exec 已改为 WS。
|
|
75
|
+
- 文件独立使用 binary WS lane;文本 PTY 不作为二进制文件通道。
|
|
76
|
+
- 对端旧版本无文件 lane 时明确 unsupported;不以 base64 手搓冒充新增能力。
|
|
77
|
+
|
|
78
|
+
## 5. 执行入口
|
|
79
|
+
|
|
80
|
+
### 5.1 script 与 stdin
|
|
81
|
+
|
|
82
|
+
`{ target, script: "/abs/local/script.sh", mode: "oneshot" }`:从工具所在运行时读文件,原文作为 `bash -s` 的 stdin。文件不要求能在目标机直接访问,不把源码拼入 argv。
|
|
83
|
+
|
|
84
|
+
- `script`、`cmd`、`stdin` 的选择:script 与 cmd 互斥,script 与 stdin 互斥;stdin+cmd 沿用现有模式。
|
|
85
|
+
- script 首轮仅 oneshot,BYO-PTY 或 mode pty 请求在读文件/拨号前拒绝。
|
|
86
|
+
- 本地路径必须绝对、无 NUL;文件读取失败在连接/执行前报告。
|
|
87
|
+
- 不做 script 自带业务 stdin 的第二通道;需要数据时用文件/参数,或用 cmd+stdin。
|
|
88
|
+
- 保留 Hub inline cmd 4096 字符上限;script 固定命令短于上限,正文走 stdin。
|
|
89
|
+
- Hub API、wire sender、legacy Hub tool exec Surface 同步支持 string stdin;PTY 不把 legacy stdin 支持悄悄扩成 script 模式。
|
|
90
|
+
|
|
91
|
+
### 5.2 local
|
|
92
|
+
|
|
93
|
+
- Hub 模型工具 exec 不再缺省本机;未传 machine 返回“请选择远端”提示,显式 self 默认也拒绝。
|
|
94
|
+
- `localExec` 配置默认 false,可作为显式兼容入口,但不替正常消费者加入测试专用业务守卫。
|
|
95
|
+
- 接收对端请求的本地 oneshot/PTY executor 保留;copy 的本地文件端点及读取 script 保留。
|
|
96
|
+
|
|
97
|
+
### 5.3 输出
|
|
98
|
+
|
|
99
|
+
- native/PTy 现有 4,000,000 UTF-16 code units 与 Hub oneshot 4MiB byte ring 是不同单位,回执必须真实说明;本轮不配置化,不凭文案把两者说成同一精确 4MB。
|
|
100
|
+
- 保留约 30k 返回尾窗;统计总输出、保留量、已丢头部,超限明确标注。修复 native oneshot 现有收头却被上层当作尾窗的偏差。
|
|
101
|
+
- 单次 dispatch 重新计数;达到上限不要求重启 PTY,重启不能找回已丢数据。
|
|
102
|
+
- 不新增 3.5M 预警、输出预测或 push 监控。
|
|
103
|
+
|
|
104
|
+
## 6. BYO-SSH
|
|
105
|
+
|
|
106
|
+
调用形态:`{target:"byossh:label", ssh:{host,user?,port?,key?,proxyJump?}, cmd}`;首次注册连接,随后只用 target 复用。使用 `ssh` 字段而非复用现有 string `spawn`,避免破坏 BYO-PTY schema。
|
|
107
|
+
|
|
108
|
+
- label 归 Agent 实例;不改 `~/.ssh/config`,不持久化凭据,不接受 inline 私钥内容;key 是发起机已有文件路径。
|
|
109
|
+
- 首次可登记后执行或仅登记;复用相同参数幂等,不同参数给出冲突与换 label 提示。
|
|
110
|
+
- host、user、port、key、proxyJump 通过参数数组、受控 config 文件或官方 SSH options 编排,不能拼出第二层任意 shell。
|
|
111
|
+
- 所有执行、copy、rsync 和中继复用同一已解析 SSH connection spec,不能 rsync 又退回只读系统 alias。
|
|
112
|
+
- roster 区分 SSH config 与 byossh labels,不导出密钥、cookie 或完整凭据。
|
|
113
|
+
|
|
114
|
+
## 7. oneshot jobs
|
|
115
|
+
|
|
116
|
+
`{target, cmd|script, run_in_background:true}` → 原生 jobId;读取/取消使用 DSH `job_output` / `job_kill`,完成由宿主通知。PTY mode 明确拒绝此选项。
|
|
117
|
+
|
|
118
|
+
- 使用官方 `ctx.jobs.start`、owner、JobHooks、output source/pump;不自建第二份 job registry、poller 或通知渠道。
|
|
119
|
+
- 子进程/远端任务在 job admission 后启动;启动被拒不能留下已经运行的进程。
|
|
120
|
+
- job 输出必须运行中真实增量可读,不能等 command 完成后才一次 append 全量。
|
|
121
|
+
- done 等到进程、远端任务及资源释放后结算;cancel 终止真实本地组/远端 job,不只把本地 Promise 标为取消。
|
|
122
|
+
- provider 需要对 Hub oneshot 提供 job-owned start/read/cancel/done 协议;仅 abort HTTP fetch 不视为远端取消。
|
|
123
|
+
- jobs service 不在场时同步 exec 仍可用,background 请求 fail-loud 并说明缺失的官方能力。
|
|
124
|
+
- 前台 timeout 保持现有上限;background 无前台等待截止但受 owner cancellation 和 job kill 管理。
|
|
125
|
+
|
|
126
|
+
## 8. 文件操作
|
|
127
|
+
|
|
128
|
+
### 8.1 寻址及能力边界
|
|
129
|
+
|
|
130
|
+
`{action:"copy", src, dst, verify:true, mkdir:true}` 与 `{action:"rsync", src, dst, delete:false, excludes:[], dryRun:true, preserve:true}`。
|
|
131
|
+
|
|
132
|
+
端点使用 `[target:]绝对路径`;例如 `/tmp/a`、`ssh:dev3:/data/a`、`byossh:review:/data/a`、`docker:build:/data/a`、`hub:skc8:/data/a`。按最后一个 `:/` 边界解析 target/path,避免把 transport 前缀冒充 host。裸 label 的兼容解析复用 remote roster 规则,不另建命名系统。
|
|
133
|
+
|
|
134
|
+
- copy 首轮支持文件与目录的 local、SSH/byossh、Docker、Incus、Hub 端点;每条腿使用实际 binary stream,保持精确路径与明确的内容/目录语义。
|
|
135
|
+
- byop 是任意交互 shell,不保证 binary I/O 或 filesystem;copy/rsync 不承诺可用,拒绝并建议用显式 transport target。
|
|
136
|
+
- rm/mv/mkdir/chmod/stat 不增加 action;mkdir 仅 copy 的建父目录选项。
|
|
137
|
+
- 校验使用 SHA-256;目录使用排序、长度编码的相对路径/条目类型/内容 manifest,明确 symlink 不跟随,避免文件名含空白/换行破坏回执。
|
|
138
|
+
- 覆盖默认允许普通文件,目录合并无删除;不得悄悄把 copy 变为 rsync delete。路径/type 不兼容返回错误。
|
|
139
|
+
|
|
140
|
+
### 8.2 copy 中转
|
|
141
|
+
|
|
142
|
+
任意两远端通过工具所在发起机中转,各腿使用其已有 target 通道,不向其中一端复制另一端连接身份。中转采用任务级 `.scratch` 暂存,先收完整载体,再向目标发送;不宣称提供源到目标流式复制、delta 或断点恢复。
|
|
143
|
+
|
|
144
|
+
- 二进制 lane 需要 backpressure、传输错误/关闭、显式完成帧、有限 metadata/frame buffer 和 cancellation。
|
|
145
|
+
- tar/archive 或等价 carrier 在解包前验证成员路径,不接受绝对成员、`..` 出界或借 symlink 写出目标目录。
|
|
146
|
+
- `verify:true` 返回独立源/目标 hash 或 manifest digest、条目/字节统计、校验结果;数据端失败不能给成功回执。
|
|
147
|
+
- 中转任务成功后清理 owned 暂存;失败保留可诊断载体,回执给出位置和原因。保留不意味着自动重试。
|
|
148
|
+
- 远端临时进程、监听/临时接收文件必须取消/结束清理,不能因为“失败保留诊断”而留后台服务。
|
|
149
|
+
- `verify:false` 不显示已校验;successful transfer 也清理中转载体,不无限堆垃圾。
|
|
150
|
+
|
|
151
|
+
### 8.3 SSH-only rsync
|
|
152
|
+
|
|
153
|
+
- 支持 local↔SSH,以及 SSH↔SSH;目标连接来自系统 SSH config 或 byossh 注册。
|
|
154
|
+
- 两个 remote 参数不能直接传给普通 rsync;工具负责变成原生 rsync 可接受的一端本地视角。
|
|
155
|
+
- remote↔remote 通过发起机建 SSH 隧道中继;一种实现为目标端短命 loopback rsync daemon + 发起机 local forward + 源端 reverse forward。rsync delta 算法仍为原生实现。
|
|
156
|
+
- 两端 identity 仅由发起机 SSH 进程使用;禁止复制 private key、导出登录凭据、ssh-agent forwarding 或修改远端 SSH config。
|
|
157
|
+
- daemon 仅绑定 loopback、模块限定目标目录,以当前登录用户启动;不安装永久 daemon,不公开监听。SSH 禁止 forwarding 时返回原始拒绝。
|
|
158
|
+
- `dryRun` 默认 true、`delete` 默认 false;`excludes`、preserve、trailing slash 内容语义通过参数表达。真正传输显式 dryRun false。
|
|
159
|
+
- 预检两端 rsync 和所需 SSH forwarding;缺失不静默 fallback copy,更不能对 delete/excludes 回报假成功。
|
|
160
|
+
- 捕获 rsync 原始退出码与 itemized changes,保持 stderr;非零不标成成功。
|
|
161
|
+
- 无论成功、失败、cancel 都清理 tunnel、短命 daemon 与本任务临时 config;复用 transport 不等于关掉用户既有 SSH 会话。
|
|
162
|
+
|
|
163
|
+
## 9. 验收和完成定义
|
|
164
|
+
|
|
165
|
+
代码、传统测试、打包成功只说明阶段进度,不等于产品验收。
|
|
166
|
+
|
|
167
|
+
1. scoped 真实 Cordis/Agent fixture:双包仅一个 remote;Agent 创建不失败;非重名异常不被吞;不同 Agent 互不争抢;赢家卸载当前实例不补位;new/cold resume 可恢复;hot continuation 不假装恢复;退出清理。
|
|
168
|
+
2. 单包 Better tarball:无 Super import/安装,SSH/Docker/Incus/BYO 按已有能力工作;jobs 缺失错误真实。
|
|
169
|
+
3. Super tarball:禁用/卸载 Better 后 remote 仍可用;两包启用顺序相反都可用;Hub 存在但 machine 清单空的 Surface 正确;关闭模型工具行不拆 Hub executor。
|
|
170
|
+
4. 4999 完整 launcher:安装双 tarball、真实模型 roster/script/stdin/PTY/后台任务/job_output/job_kill/copy/rsync 与错误恢复;工具 catalog 和 REPL 路由属于验收。
|
|
171
|
+
5. dev3 同版本实际安装:配对但无 SSH 的 Hub PTY 与 binary copy;dev3↔另一 SSH 目标经发起机中继,远端无对方 key/config;第二次改少量内容证明真实 rsync delta;cancel/异常证明无残留。
|
|
172
|
+
6. 记录上游实际 checkout、目标宿主版本、同步版本、tarball SHA-256、安装步骤、模型可见 Surface 和失败证据至 `docs/test-reports/`。
|
|
173
|
+
7. Web 测试线保持运行,报告真实访问 URL,供 user 亲验。
|
|
174
|
+
8. 不触碰生产 home/3080/3081/Caddy,不修改上游,不 npm publish、不 commit/tag/push 定版。发布需要本次单独放行。
|
|
175
|
+
|
|
176
|
+
## 10. 书面确认边界
|
|
177
|
+
|
|
178
|
+
本稿实现上述会话裁决,没有把 P2/P3、非 SSH rsync 或热接管重新塞入首轮。字段 `ssh`、端点解析、copy 的 BYO-PTY 不支持回执是保持已有接口并使交付可实现的具体化;user 可在书面规格审阅时修订。收到书面审阅后,按执行计划进入实现,不再为已批准的 routine 实现步骤重复请求授权。
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
### 2026-10-10 consumer worker delivery correction
|
|
182
|
+
|
|
183
|
+
The generated Super `remote/` contains exactly `plugin.js`, `plugin.d.ts`, private `file-worker.js`, and `provenance.json`. The worker leaf is built solely from canonical `better-dsh/src/remote/file-worker.ts`, has Node-builtins-only imports, and is hashed/checked with the closure. It has no public package export, host peer imports, duplicated host modules, source loader or Better dependency. The public plugin contract remains unchanged. The existing owned child-process/group cleanup remains the receiver boundary; no worker-thread lifecycle replacement. This narrow extra generated leaf fixes actual installed receiver resolution, not a general guarantee that host plugins import outside their host resolver.
|
|
184
|
+
|
|
185
|
+
### Task8 delivery correction: owned SSH oneshots (Ruling22)
|
|
186
|
+
|
|
187
|
+
Real consumer job-kill exposed local-only SSH termination. Foreground/background/script/stdin SSH oneshots therefore reuse the portable receiving sideband owner, preserving native literal stdio and connection normalization. Remote Bash4.1+, Python3.7+ (macOS3.10+), shared non-adjustable cross-process monotonic clock, Unix fcntl.flock and mktemp/mv/rm/sleep are required. Ordinary commands never require rsync; origin needs no Python, and this path needs no Linux/pidfd. Three SSH startups (clock, control, work), with authenticated same-identity cleanup reconnect after ambiguous startup; existing lease/bounds remain. Receiver helper/group cleanup precedes settlement, followed by up to2500ms work-stream drain; unavailable drain explicitly marks incomplete received output without fabricated counters. PTY/BYOPTY and rsync-specific restrictions remain unchanged. No second jobs registry or availability polling.
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
### Task8 container oneshot ownership correction (Rulings23–24)
|
|
191
|
+
|
|
192
|
+
Actual installed Docker/Incus native job cancellation reported killed while receiving children remained live. Canonical oneshot foreground/background/script/stdin therefore share the SSH portable receiving gate/control/work barrier through native container exec argv, not local CLI termination. Each command requires three native exec startups (clock, owner, literal-stdio work), remote Bash4.1+, Python3.7+, Unix fcntl.flock/shared non-adjustable cross-process monotonic clock, mktemp/mv/rm/sleep. Linux containers additionally require stdlib ctypes and permitted unprivileged PR_SET_CHILD_SUBREAPER before business admission; the work helper reaps only its own/adopted children and stays alive until its work group is absent. This supports ordinary non-reaping PID1 containers without forcing --init, privilege/capability, image/config mutation, rsync, pidfd or origin Python. PTY/BYOPTY stay unchanged; SSH portable prerequisites are not broadened. The same eight-second counted lease, gate recovery, actual cleanup barrier and 2500ms honest final-output drain apply, with no enlarged grace, second job registry or availability polling. Consumer iteration N must prove real native killed status together with owned process/group/helper/state absence; M failures remain historical evidence.
|
|
193
|
+
|
|
194
|
+
Ruling25 supersedes the original two-remote source -R/private-master/sshd-FD/pidfd design after actual default dev3 source failed its permission requirement. A task-owned portable Python loopback proxy, inside the existing receiving helper/group/lease, carries bounded binary frames over authenticated SSH work stdio to an origin TCP bridge into the destination -L tunnel. A real full-route @RSYNCD greeting precedes business admission. No source Linux /proc, pidfd, privileged sshd access or source forwarding permission is required; native find, native rsync and the existing portable Bash/Python/fcntl/shared-monotonic prerequisites remain. No origin Python, credentials on peers, copy fallback, lease increase or second registry. Five-byte type/length frames cap data at64KiB and Python queues at256KiB; one active connection, real backpressure and half-close, prior reader/socket close before next OPEN. Ordinary two-remote transfer measures12 SSH startups: source preflight+inspection clock/work3, relay source/destination preflight2, destination clock/daemon+tunnel2, source proxy clock/owner/work3, native source rsync clock/work2. Fault recovery adds only task-owned authenticated cleanup reconnects, never transfer retries. Same real helper/listener/group/metadata/tunnel/socket cleanup barrier; receiving progress remains an explicit assumption. Historical M permission failure remains in the acceptance report; current default-dev3-source source test passes, installed next-artifact proof is separate.
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
### CLI binary receiving ownership (consumer correction, Ruling26)
|
|
198
|
+
|
|
199
|
+
Actual N native SSH copy cancellation settled while the remote import process and its unnamed staging file remained live under a finite work-channel EOF hold. CLI export/import/digest now reuse the canonical portable receiving owner, with raw binary work streams and the same counted lease, admission gate and authenticated recovery. Cancellation/failure waits for receiving helper/group/temp cleanup before local transport teardown/settlement. Normal success must completely drain the binary stream; the oneshot text lane's 2500ms incomplete-output rule does not apply. Archive validation, selected manifest digests, merge/no-delete behavior and canonical SSH identity/ProxyJump are unchanged. Local and Hub file lanes are unchanged.
|
|
200
|
+
|
|
201
|
+
This intentionally replaces the former Python-only minimum for CLI peers: Bash4.1+, Python3.7+ (macOS3.10+), Unix fcntl.flock/shared non-adjustable cross-process monotonic clock, mktemp/mv/rm/sleep; Linux containers also need stdlib ctypes and permitted unprivileged PR_SET_CHILD_SUBREAPER. No rsync or origin Python requirement, auto-install, second registry, fallback, peer polling or increased lease. Minimal Python-only peers no longer support this CLI lane; use a supported peer or authenticated Hub.
|
|
202
|
+
|
|
203
|
+
Each remote export/import/digest costs three native transport starts: clock, independent owner/control, literal binary work. Thus verified local→CLI or CLI→local costs six; CLI→CLI twelve. verify:false skips digest operations, reducing counts to three/three/six. Local/Hub operations do not contribute CLI starts. Fault recovery may add same-identity authenticated cleanup starts and may remain pending until genuine cleanup observation is possible. Artifact O must re-prove installed cancellation and complete binary integrity; N failures remain historical evidence.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# DSH runtime compatibility
|
|
2
|
+
|
|
3
|
+
Better Dash and Super Dash use the same DSH host APIs. The verified upstream source baseline for this alignment is `dsh-v0.2.1-alpha.1` (`5badb15009ae1756c3afe0ae0cef1faafc290ccc`). The pages in this directory include older official reference snapshots; check this baseline before using an API described by a snapshot.
|
|
4
|
+
|
|
5
|
+
On `0.2.1-alpha.1`:
|
|
6
|
+
|
|
7
|
+
- The runtime `dsh-invariants` plugin, `ctx.invariants`, and companion `./invariant` exports are removed. The archived invariant reference does not define an available extension API.
|
|
8
|
+
- Plugin subpaths provide display text through `<specifier>/locale/en.json` and localized sibling exports, and icons through `<specifier>/icon`. Subpaths do not read a separate `package.json`.
|
|
9
|
+
- Composer statistics use separate `activity` and `usage` entries.
|
|
10
|
+
- The native Plugin Manager refreshes profile package resolution when bundles are installed, enabled, disabled or removed. Replacing installed package code still requires a restart.
|
|
11
|
+
- Automation is part of the Web composition. Reminder tools depend on agent mode; they are absent in Minimal mode and subagents.
|
|
12
|
+
|
|
13
|
+
See the [official release notes](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.2.1-alpha.1) and the actual host package exports for the complete interface contract.
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Runtime Invariants
|
|
2
2
|
|
|
3
|
+
> DSH `0.2.1-alpha.1` removes this plugin and all companion `./invariant` exports. This page is an older reference snapshot; use the [runtime compatibility baseline](../baseline.md) for the current host contract.
|
|
4
|
+
|
|
5
|
+
|
|
3
6
|
English | [中文](invariants.zh.md)
|
|
4
7
|
|
|
5
8
|
[dsh-invariants](../../packages/runtime-diagnostics/invariants) is the configurable registry service (`ctx.invariants`) for package-owned runtime invariant checks. It is one support-group package, not a three-package capability seam, and not part of the agent-loop spine: the registry owns selection, name reservation, child-fiber lifecycle, and package-attributed failure, while every workspace package publishes a `./invariant` companion plugin that registers checks under its exact npm package name. What a check may assert — authoritative event streams or mutable data, never service or method presence — is the runtime-invariants convention in [AGENTS.md](../../AGENTS.md#conventions); the registry design is owned by the [invariant-service Agent Note](../../.agents/notes/implemented/architecture/2026-07-19-package-owned-invariant-service.md).
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# 运行时不变式
|
|
2
2
|
|
|
3
|
+
> DSH `0.2.1-alpha.1` 已移除此插件及所有配套 `./invariant` 导出。本页保留旧版参考快照;当前宿主契约见[运行时兼容基线](../baseline.md)。
|
|
4
|
+
|
|
5
|
+
|
|
3
6
|
[English](invariants.md) | 中文
|
|
4
7
|
|
|
5
8
|
[dsh-invariants](../../packages/runtime-diagnostics/invariants) 是面向包自有运行时不变式检查的可配置注册表服务(`ctx.invariants`)。它是一个 support 组的包,不是三包能力 seam,也不属于 agent loop(智能体循环)主干:注册表拥有选择逻辑、名称保留、子 fiber 生命周期和归因到包的失败,而每个工作区包发布一个 `./invariant` 配套插件,以自己确切的 npm 包名注册检查。检查可以断言什么(权威事件流或可变数据,绝不是服务或方法是否存在)是 [AGENTS.md](../../AGENTS.md#conventions) 中的运行时不变式约定;注册表设计由[不变式服务 Agent Note](../../.agents/notes/implemented/architecture/2026-07-19-package-owned-invariant-service.zh.md)规定。
|
package/eval-description.md
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
Run one Python cell on a session-persistent scripting pad. One `eval` call = one cell; the pad's state persists across calls and turns — variables, imports, and definitions from earlier cells stay alive.
|
|
2
2
|
|
|
3
|
-
Work incrementally: imports → define → test → use, each its own cell.
|
|
3
|
+
Work incrementally: imports → define → test → use, each its own cell. The pad uses an OMP-backed Python interpreter; Python must be available on the host. Better supplies its runner and checkpoint serializer without installing Jupyter or Python packages.
|
|
4
|
+
|
|
5
|
+
After a restart, read the recovery notice before relying on earlier variables. Checkpoints restore Python scratchpad values on a best-effort basis; notices identify the last saved cell and any omitted values. Open files, sockets, subprocesses, locks and other live resources must be recreated. A checkpoint does not restore files, undo tool calls or recover the entire Python process.
|
|
6
|
+
|
|
7
|
+
An interrupted or dying cell may already have changed variables, files or external systems. It is never automatically retried. Inspect the reported checkpoint and actual external state before deciding what to run again. A failed checkpoint leaves the previous valid checkpoint available; a failed restore starts with empty state and reports the reason.
|
|
4
8
|
|
|
5
9
|
## Arguments
|
|
6
10
|
|
|
7
11
|
- `cell` (required): one Python program body. Top-level `await` works; top-level `return` is a SyntaxError — the cell runs in module scope (REPL semantics, not a function body).
|
|
8
12
|
- `description` (required): a short summary of what the cell does — shown as the call's title in the UI.
|
|
9
13
|
- `timeout` (optional): wall-clock budget in seconds; the cell is interrupted (then force-stopped) when exceeded. Omit for the runtime default.
|
|
10
|
-
- `reset` (optional): restart the pad EMPTY first — earlier state is discarded.
|
|
14
|
+
- `reset` (optional): restart the pad EMPTY first and delete its checkpoints — earlier state is discarded.
|
|
11
15
|
|
|
12
16
|
## Direct calls vs cells
|
|
13
17
|
|
|
@@ -20,7 +24,7 @@ Delegation: `agent` is the unified agent-spawn entry; `subagent` is its native a
|
|
|
20
24
|
Every session tool is callable from a cell as `await tool.<name>(args)` with ONE positional argument: `args` is the tool's parameter object written as a Python dict literal, same field names (`true`/`false`/`null` become `True`/`False`/`None`). A failed call raises `ToolCallError` with `.toolName` naming the tool. Tool names that are not plain identifiers (e.g. contain hyphens) have no `tool.<name>` member — call those as direct tool calls.
|
|
21
25
|
|
|
22
26
|
```python
|
|
23
|
-
print(await tool.read({"
|
|
27
|
+
print(await tool.read({"file_path": "docs/README.md", "limit": 5}))
|
|
24
28
|
|
|
25
29
|
r = await tool.bash({"command": "ls -la src/", "description": "List source directory"})
|
|
26
30
|
print(r["stdout"]["text"])
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as __require } from "./chunk-DQxbwPpZ.js";
|
|
2
2
|
import { A as stringToTypedArray, G as first, H as delayWhen, K as firstValueFrom, L as combineLatest, M as assert, Q as map, S as timeout, St as debug, Tt as environment, V as defer, W as filter, at as race, b as isString, bt as TouchError, c as evaluationString, d as fromEmitterEvent, g as isDate, gt as ProtocolError, h as getSourceUrlComment, ht as ConnectionClosedError, i as SOURCE_URL_REGEX, k as stringToBase64, lt as switchMap, m as getSourcePuppeteerURLIfAvailable, o as debugCatchError, ot as raceWith, q as from, r as PuppeteerURL, rt as of, s as debugError, u as fromAbortSignal, v as isPlainObject, vt as TargetCloseError, x as parsePDFOptions, xt as UnsupportedOperation, y as isRegExp, yt as TimeoutError } from "./util-BHL_dfV_.js";
|
|
3
|
-
import { $n as Deferred, $t as scriptInjector, Bt as throwIfDetached, Ct as WebWorkerEvent, Dn as DeviceRequestPrompt, Dt as normalizeHeaderValue, Fn as Browser, Hn as DisposableStack, Ht as bindIsolatedHandle, In as WEB_PERMISSION_TO_PROTOCOL_PERMISSION, It as Dialog, Jn as CallbackRegistry, Kn as disposeSymbol, Ln as CDPSession, Lt as Accessibility, Mn as invokeAtMostOnceForArguments, Mt as InterceptResolutionAction, Nn as throwIfDisposed, Nt as STATUS_TEXTS, On as BrowserContext, Ot as SecurityDetails, Pt as handleError, Rt as Frame, St as WebWorker, Ut as JSHandle, Vt as ElementHandle, Zn as isErrorLike, _t as Mouse, an as stringifyFunction, cn as Tracing, dt as ConsoleMessage, en as ARIAQueryHandler, fn as Coverage, gt as Keyboard, ht as TargetType, in as interpolateFunction, jn as inertIfDisposed, jt as HTTPRequest, kn as bubble, kt as HTTPResponse, mn as Page, mt as Target, nn as LazyArg, on as AsyncIterableUtil, sn as FileChooser, un as EmulationManager, vt as MouseButton, wt as Realm, yt as Touchscreen, zn as EventEmitter } from "./index-browser-
|
|
3
|
+
import { $n as Deferred, $t as scriptInjector, Bt as throwIfDetached, Ct as WebWorkerEvent, Dn as DeviceRequestPrompt, Dt as normalizeHeaderValue, Fn as Browser, Hn as DisposableStack, Ht as bindIsolatedHandle, In as WEB_PERMISSION_TO_PROTOCOL_PERMISSION, It as Dialog, Jn as CallbackRegistry, Kn as disposeSymbol, Ln as CDPSession, Lt as Accessibility, Mn as invokeAtMostOnceForArguments, Mt as InterceptResolutionAction, Nn as throwIfDisposed, Nt as STATUS_TEXTS, On as BrowserContext, Ot as SecurityDetails, Pt as handleError, Rt as Frame, St as WebWorker, Ut as JSHandle, Vt as ElementHandle, Zn as isErrorLike, _t as Mouse, an as stringifyFunction, cn as Tracing, dt as ConsoleMessage, en as ARIAQueryHandler, fn as Coverage, gt as Keyboard, ht as TargetType, in as interpolateFunction, jn as inertIfDisposed, jt as HTTPRequest, kn as bubble, kt as HTTPResponse, mn as Page, mt as Target, nn as LazyArg, on as AsyncIterableUtil, sn as FileChooser, un as EmulationManager, vt as MouseButton, wt as Realm, yt as Touchscreen, zn as EventEmitter } from "./index-browser-B-9jm12n.js";
|
|
4
4
|
import "./BrowserWebSocketTransport-wm99h94r.js";
|
|
5
5
|
|
|
6
6
|
//#region node_modules/mitt/dist/mitt.mjs
|
package/lib/client/index.js
CHANGED
|
@@ -613,7 +613,7 @@ function CompactionRow({ t, loadConfig, save }) {
|
|
|
613
613
|
* Register the dictionaries and the General settings row.
|
|
614
614
|
*
|
|
615
615
|
* Called from the plugin's client entry, which already injects `locale`,
|
|
616
|
-
* `slots` and `
|
|
616
|
+
* `slots`, `remote.settings` and `configForms`.
|
|
617
617
|
*
|
|
618
618
|
* @param ctx - client root context.
|
|
619
619
|
*/
|
|
@@ -622,7 +622,7 @@ function setupCompactionRow(ctx) {
|
|
|
622
622
|
zh: zh$1,
|
|
623
623
|
en: en$1
|
|
624
624
|
}), "compaction-tuning: dictionaries");
|
|
625
|
-
ctx.slots.inject("settings.general.item", function* () {
|
|
625
|
+
ctx.effect(() => ctx.configForms.whileServed([COMPACTION_SETTINGS_ENTRY], () => ctx.slots.inject("settings.general.item", function* () {
|
|
626
626
|
yield ctx.slots.register({
|
|
627
627
|
name: "settings.general.item",
|
|
628
628
|
id: COMPACTION_SETTINGS_NS,
|
|
@@ -647,7 +647,29 @@ function setupCompactionRow(ctx) {
|
|
|
647
647
|
}
|
|
648
648
|
})
|
|
649
649
|
}, CompactionRow);
|
|
650
|
-
});
|
|
650
|
+
})), "compaction-tuning: served settings row");
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
//#endregion
|
|
654
|
+
//#region src/welcome-notice/client/index.ts
|
|
655
|
+
/** Complete each newly selected notice without persisting native acknowledgement state. */
|
|
656
|
+
function SkipWelcomeNotice({ complete }) {
|
|
657
|
+
const completed = (0, react.useRef)(false);
|
|
658
|
+
(0, react.useEffect)(() => {
|
|
659
|
+
if (completed.current) return;
|
|
660
|
+
completed.current = true;
|
|
661
|
+
complete();
|
|
662
|
+
}, [complete]);
|
|
663
|
+
return null;
|
|
664
|
+
}
|
|
665
|
+
/** A package client can outlive this independently toggleable Host component. */
|
|
666
|
+
function setupWelcomeNotice(ctx) {
|
|
667
|
+
ctx.effect(() => ctx.configForms.whileServed(["dashr-welcome-notice"], () => ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
|
|
668
|
+
name: "settings.onboarding",
|
|
669
|
+
id: "welcome-notice",
|
|
670
|
+
priority: -1,
|
|
671
|
+
order: -100
|
|
672
|
+
}, SkipWelcomeNotice))), "welcome notice: served skip policy");
|
|
651
673
|
}
|
|
652
674
|
|
|
653
675
|
//#endregion
|
|
@@ -658,7 +680,8 @@ const inject = [
|
|
|
658
680
|
"locale",
|
|
659
681
|
"remote",
|
|
660
682
|
"remote.settings",
|
|
661
|
-
"remote.session"
|
|
683
|
+
"remote.session",
|
|
684
|
+
"configForms"
|
|
662
685
|
];
|
|
663
686
|
/**
|
|
664
687
|
* Register the `failover` dictionaries and the General settings row.
|
|
@@ -671,7 +694,8 @@ function apply(ctx) {
|
|
|
671
694
|
}), "llm-failover: dictionaries");
|
|
672
695
|
setupMobileLayout(ctx);
|
|
673
696
|
setupCompactionRow(ctx);
|
|
674
|
-
ctx
|
|
697
|
+
setupWelcomeNotice(ctx);
|
|
698
|
+
ctx.effect(() => ctx.configForms.whileServed([FAILOVER_SETTINGS_ENTRY], () => ctx.slots.inject("settings.general.item", function* () {
|
|
675
699
|
yield ctx.slots.register({
|
|
676
700
|
name: "settings.general.item",
|
|
677
701
|
id: "failover",
|
|
@@ -702,7 +726,7 @@ function apply(ctx) {
|
|
|
702
726
|
}
|
|
703
727
|
})
|
|
704
728
|
}, FailoverRow);
|
|
705
|
-
});
|
|
729
|
+
})), "llm-failover: served settings row");
|
|
706
730
|
}
|
|
707
731
|
|
|
708
732
|
//#endregion
|
package/lib/failover/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as Schema } from "../lib-C8_jXvwA.js";
|
|
2
|
-
import { randomUUID } from "node:crypto";
|
|
3
2
|
import { Context } from "@deepseek-ai/cordis";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
4
|
import { RetryId } from "@deepseek-ai/dsh-llm-retry";
|
|
5
5
|
|
|
6
6
|
//#region src/failover/config.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { f as UrlSchemesError, t as buildFsLayerResolver } from "../wrap-
|
|
2
|
-
import { stat } from "node:fs/promises";
|
|
3
|
-
import { dirname, sep } from "node:path";
|
|
1
|
+
import { f as UrlSchemesError, t as buildFsLayerResolver } from "../wrap-0VA0uFx8.js";
|
|
4
2
|
import { Context } from "@deepseek-ai/cordis";
|
|
3
|
+
import { dirname, sep } from "node:path";
|
|
4
|
+
import { stat } from "node:fs/promises";
|
|
5
5
|
import { LocalFileSystem } from "@deepseek-ai/dsh-fs-local";
|
|
6
6
|
import { FsError } from "@deepseek-ai/dsh-fs";
|
|
7
7
|
import { writableRoots } from "@deepseek-ai/dsh-sandbox";
|
|
@@ -20792,7 +20792,7 @@ async function _connectToBiDiBrowser(connectionTransport, url, options) {
|
|
|
20792
20792
|
const { bidiConnection, cdpConnection, closeCallback } = await getBiDiConnection(connectionTransport, url, options);
|
|
20793
20793
|
return await (await import(
|
|
20794
20794
|
/* webpackIgnore: true */
|
|
20795
|
-
"./bidi-
|
|
20795
|
+
"./bidi-CwabFH07.js"
|
|
20796
20796
|
)).BidiBrowser.create({
|
|
20797
20797
|
connection: bidiConnection,
|
|
20798
20798
|
cdpConnection,
|
|
@@ -20815,7 +20815,7 @@ async function _connectToBiDiBrowser(connectionTransport, url, options) {
|
|
|
20815
20815
|
async function getBiDiConnection(connectionTransport, url, options) {
|
|
20816
20816
|
const BiDi = await import(
|
|
20817
20817
|
/* webpackIgnore: true */
|
|
20818
|
-
"./bidi-
|
|
20818
|
+
"./bidi-CwabFH07.js"
|
|
20819
20819
|
);
|
|
20820
20820
|
const { slowMo = 0, protocolTimeout, idGenerator = createIncrementalIdGenerator() } = options;
|
|
20821
20821
|
const pureBidiConnection = new BiDi.BidiConnection(url, connectionTransport, idGenerator, slowMo, protocolTimeout);
|
|
@@ -20887,10 +20887,10 @@ async function getConnectionTransport(options) {
|
|
|
20887
20887
|
endpointUrl: connectionURL
|
|
20888
20888
|
};
|
|
20889
20889
|
} else if (options.channel && isNode) {
|
|
20890
|
-
const { detectBrowserPlatform, resolveDefaultUserDataDir, Browser: Browser$1 } = await import("./main-
|
|
20890
|
+
const { detectBrowserPlatform, resolveDefaultUserDataDir, Browser: Browser$1 } = await import("./main-Dv_UQqG2.js");
|
|
20891
20891
|
const platform = detectBrowserPlatform();
|
|
20892
20892
|
if (!platform) throw new Error("Could not detect required browser platform");
|
|
20893
|
-
const { convertPuppeteerChannelToBrowsersChannel } = await import("./LaunchOptions-
|
|
20893
|
+
const { convertPuppeteerChannelToBrowsersChannel } = await import("./LaunchOptions-DxQQ0s-A.js");
|
|
20894
20894
|
const { join } = await import("node:path");
|
|
20895
20895
|
const portPath = join(resolveDefaultUserDataDir(Browser$1.CHROME, platform, convertPuppeteerChannelToBrowsersChannel(options.channel)), "DevToolsActivePort");
|
|
20896
20896
|
try {
|
package/lib/index.d.ts
CHANGED
|
@@ -379,7 +379,7 @@ interface ReplRuntimeSurface {
|
|
|
379
379
|
//#region src/runtime.d.ts
|
|
380
380
|
/** Plugin config: every tunable, changeable from `cordis.yml` (no hardcoded tunables). */
|
|
381
381
|
interface Config$1 {
|
|
382
|
-
/** Python interpreter
|
|
382
|
+
/** Python >=3.9 interpreter. The bare sentinel `python3` (or absent) selects a managed venv under {@link Config.kernelEnvDir}. */
|
|
383
383
|
python?: string;
|
|
384
384
|
/** Budget for kernel spawn → ready, in milliseconds. */
|
|
385
385
|
startupTimeoutMs?: number;
|
|
@@ -388,8 +388,7 @@ interface Config$1 {
|
|
|
388
388
|
/** Grace between a timeout/abort interrupt and the force-settle, in milliseconds. */
|
|
389
389
|
interruptGraceMs?: number;
|
|
390
390
|
/**
|
|
391
|
-
* Confirm window
|
|
392
|
-
* escalation, in milliseconds; must stay below {@link Config.interruptGraceMs}.
|
|
391
|
+
* Confirm window before repeating SIGINT, in milliseconds; must stay below {@link Config.interruptGraceMs}.
|
|
393
392
|
* See the bridge's two-phase interrupt for why the escalation is deferred.
|
|
394
393
|
*/
|
|
395
394
|
interruptConfirmMs?: number;
|
|
@@ -399,15 +398,15 @@ interface Config$1 {
|
|
|
399
398
|
snapshotTimeoutMs?: number;
|
|
400
399
|
/** Hard cap for serialized log-array, completion-value, and failure-message payloads. */
|
|
401
400
|
maxOutputBytes?: number;
|
|
402
|
-
/**
|
|
401
|
+
/** Per-session immutable checkpoints. Defaults to the official profile home; empty string disables, standalone callers opt in. */
|
|
403
402
|
snapshotDir?: string;
|
|
404
|
-
/** Serialized
|
|
403
|
+
/** Serialized graph cap in bytes; each over-cap attempt reports the last successful checkpoint. */
|
|
405
404
|
snapshotSizeCapBytes?: number;
|
|
406
405
|
/** Managed venv directory (used when `python` is absent/`python3`); defaults to `<package>/.venv-kernel`. */
|
|
407
406
|
kernelEnvDir?: string;
|
|
408
407
|
/** Preferred CPython version for a managed venv. */
|
|
409
408
|
kernelPythonVersion?: string;
|
|
410
|
-
/** Provision
|
|
409
|
+
/** Provision a stdlib-only managed venv on first use; default true. */
|
|
411
410
|
kernelAutoInstall?: boolean;
|
|
412
411
|
username?: string;
|
|
413
412
|
}
|
|
@@ -428,6 +427,7 @@ declare class DashrRuntime extends ReplRuntime {
|
|
|
428
427
|
/** One entry per session principal that has run code (lazy — never pre-seeded). */
|
|
429
428
|
private readonly kernels;
|
|
430
429
|
private disposed;
|
|
430
|
+
private readonly transactions;
|
|
431
431
|
/** Lazily-resolved (and, when managed, provisioned) kernel interpreter. */
|
|
432
432
|
private kernelEnvPromise;
|
|
433
433
|
constructor(ctx: Context, config: Config$1);
|
|
@@ -446,7 +446,9 @@ declare class DashrRuntime extends ReplRuntime {
|
|
|
446
446
|
* @param request - the program, its bindings, and the abort signal.
|
|
447
447
|
* @returns the run's outcome per the seam contract.
|
|
448
448
|
*/
|
|
449
|
+
private transaction;
|
|
449
450
|
run(request: CodeRunRequest): Promise<CodeRunResult>;
|
|
451
|
+
private runTransaction;
|
|
450
452
|
/**
|
|
451
453
|
* Read one user-namespace variable by name on the session's kernel. A
|
|
452
454
|
* bare/empty name lists the namespace's user-variable names; a
|
|
@@ -459,6 +461,7 @@ declare class DashrRuntime extends ReplRuntime {
|
|
|
459
461
|
* @param principal - the session key (absent → the shared default).
|
|
460
462
|
*/
|
|
461
463
|
queryVar(name: string, principal?: string): Promise<ReplVarQuery>;
|
|
464
|
+
private queryTransaction;
|
|
462
465
|
/**
|
|
463
466
|
* Assign one lossless-JSON value into the user namespace under `name` on
|
|
464
467
|
* the session's kernel. `name` must be a usable identifier (and not a
|
|
@@ -470,6 +473,7 @@ declare class DashrRuntime extends ReplRuntime {
|
|
|
470
473
|
* @param principal - the session key (absent → the shared default).
|
|
471
474
|
*/
|
|
472
475
|
setVar(name: string, value: unknown, principal?: string): Promise<void>;
|
|
476
|
+
private setTransaction;
|
|
473
477
|
/** Map one cell outcome onto the seam's result shape under the output ledger. */
|
|
474
478
|
private assembleResult;
|
|
475
479
|
/** Reject malformed binding globals or typed-error declarations as contract misuse. */
|
|
@@ -486,40 +490,14 @@ declare class DashrRuntime extends ReplRuntime {
|
|
|
486
490
|
* @param key - the run principal (or the agentless default).
|
|
487
491
|
*/
|
|
488
492
|
private ensureKernel;
|
|
489
|
-
/**
|
|
490
|
-
* Restore a key's on-disk snapshot into a freshly booted kernel, when one
|
|
491
|
-
* exists and its manifest is plausible. Called once per entry boot. The
|
|
492
|
-
* kernel-side restore cell performs the authoritative environment checks
|
|
493
|
-
* (python version, interpreter identity, skills); this method only gates on
|
|
494
|
-
* the manifest the host can read cheaply, then records the turn so the
|
|
495
|
-
* first-run notice and the revive chain can name it.
|
|
496
|
-
*/
|
|
493
|
+
/** Restore once before user admission; any degraded load retires that child. */
|
|
497
494
|
private restoreEntry;
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
/**
|
|
501
|
-
* Revive one session's kernel after death: respawn a fresh kernel, restore
|
|
502
|
-
* the nearest replayable snapshot onto it (the normal restore path), and
|
|
503
|
-
* return the death-observing run's explicit error naming the turn. When no
|
|
504
|
-
* replayable snapshot exists the message falls back to M3-A's fresh-empty
|
|
505
|
-
* contract. The run itself does NOT execute — an error that lies about a
|
|
506
|
-
* NameError costs the model more than one dropped cell (blueprint §8.3).
|
|
507
|
-
* @param key - the run principal.
|
|
508
|
-
* @param dead - the entry that died (its `turn` is the last completed turn).
|
|
509
|
-
*/
|
|
495
|
+
private omissionNotice;
|
|
496
|
+
/** Restore a fresh child and report whether the observing call had started. */
|
|
510
497
|
private reviveAfterDeath;
|
|
511
|
-
/**
|
|
512
|
-
* Write one key's turn-end snapshot, when a snapshot directory is
|
|
513
|
-
* configured. A size-cap skip is reported (so the run can warn the model
|
|
514
|
-
* once); other failures log without disturbing the run.
|
|
515
|
-
*/
|
|
498
|
+
/** Save completed mutations and expose partial/failed coverage within output limits. */
|
|
516
499
|
private snapshotTurnEnd;
|
|
517
|
-
/**
|
|
518
|
-
* Dispose to quiescence: snapshot every live key's namespace when a
|
|
519
|
-
* snapshot directory is configured (each under its own per-key
|
|
520
|
-
* subdirectory), then shut the subprocesses down. Registered as the
|
|
521
|
-
* plugin's `ctx.effect` disposer.
|
|
522
|
-
*/
|
|
500
|
+
/** Cancel active work, drain admitted transactions, and reap every owned child. */
|
|
523
501
|
private teardown;
|
|
524
502
|
/**
|
|
525
503
|
* Tear one session's kernel down (session end via the `agent/disposed`
|
|
@@ -530,11 +508,9 @@ declare class DashrRuntime extends ReplRuntime {
|
|
|
530
508
|
/**
|
|
531
509
|
* Reset one session's kernel to a fresh, empty namespace: dispose the live
|
|
532
510
|
* subprocess WITHOUT a turn-end snapshot and clear its on-disk snapshot, so
|
|
533
|
-
* the next ensureKernel spawns empty (restore finds
|
|
511
|
+
* the next ensureKernel spawns empty (restore finds no checkpoint).
|
|
534
512
|
*/
|
|
535
513
|
private resetKey;
|
|
536
|
-
/** Snapshot (when configured) then dispose one key's kernel; failures log, never throw into a listener. */
|
|
537
|
-
private teardownKernel;
|
|
538
514
|
}
|
|
539
515
|
//#endregion
|
|
540
516
|
//#region src/tool-call-id.d.ts
|
|
@@ -619,7 +595,7 @@ declare function resolveMaxParallelSubCalls(value: number | undefined): number;
|
|
|
619
595
|
* `dashr/repl-dispatch-log` waterfall — dashr's OWN dispatch-log event,
|
|
620
596
|
* self-registered via the cordis Events merge below. Decoupled from
|
|
621
597
|
* upstream's `tools/ptc-dispatch-log` (PTC `run_code` sub-dispatches): `eval`
|
|
622
|
-
* is a broader session-persistent REPL (
|
|
598
|
+
* is a broader session-persistent REPL (OMP Python child) than upstream's
|
|
623
599
|
* `run_code` TS-worker tool, so its durable-log reshape extension point is
|
|
624
600
|
* dashr-owned and version-independent — no coupling to upstream's
|
|
625
601
|
* `CodeDispatchLog`/`PtcDispatchLog` rename or the PTC tool's event name.
|