@hy-sde-org/dsh-code-runtime-kernels 0.1.0-rc.8
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/LICENSE +32 -0
- package/README.md +85 -0
- package/README.zh.md +85 -0
- package/cordis.patch.yml +34 -0
- package/dist/core/invariant.d.ts +16 -0
- package/dist/core/invariant.d.ts.map +1 -0
- package/dist/core/invariant.js +23 -0
- package/dist/core/invariant.js.map +1 -0
- package/dist/core/kernel.d.ts +133 -0
- package/dist/core/kernel.d.ts.map +1 -0
- package/dist/core/kernel.js +565 -0
- package/dist/core/kernel.js.map +1 -0
- package/dist/core/protocol.d.ts +115 -0
- package/dist/core/protocol.d.ts.map +1 -0
- package/dist/core/protocol.js +12 -0
- package/dist/core/protocol.js.map +1 -0
- package/dist/core/session.d.ts +49 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +153 -0
- package/dist/core/session.js.map +1 -0
- package/dist/index.d.ts +135 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +478 -0
- package/dist/index.js.map +1 -0
- package/dist/nodejs/runner.d.ts +26 -0
- package/dist/nodejs/runner.d.ts.map +1 -0
- package/dist/nodejs/runner.js +298 -0
- package/dist/nodejs/runner.js.map +1 -0
- package/dist/python/runner.d.ts +26 -0
- package/dist/python/runner.d.ts.map +1 -0
- package/dist/python/runner.js +615 -0
- package/dist/python/runner.js.map +1 -0
- package/package.json +85 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 hy-sde
|
|
4
|
+
|
|
5
|
+
This package ports the oh-my-pi (https://github.com/can1357/oh-my-pi)
|
|
6
|
+
persistent-eval-kernel concept onto DeepSeek Harness as a standalone plugin.
|
|
7
|
+
The ported portions are distributed under the same MIT license with their
|
|
8
|
+
original copyright held by their respective authors:
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2025 Mario Zechner
|
|
11
|
+
Copyright (c) 2025-2026 Can Bölük
|
|
12
|
+
|
|
13
|
+
See THIRD-PARTY-NOTICES.md at the repository root for full provenance per
|
|
14
|
+
module.
|
|
15
|
+
|
|
16
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
17
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
18
|
+
in the Software without restriction, including without limitation the rights
|
|
19
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
20
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
21
|
+
furnished to do so, subject to the following conditions:
|
|
22
|
+
|
|
23
|
+
The above copyright notice and this permission notice shall be included in all
|
|
24
|
+
copies or substantial portions of the Software.
|
|
25
|
+
|
|
26
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
27
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
28
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
29
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
30
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
31
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
32
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# @hy-sde-org/dsh-code-runtime-kernels
|
|
2
|
+
|
|
3
|
+
English | [中文](README.zh.md)
|
|
4
|
+
|
|
5
|
+
**Persistent Python and JavaScript kernels for DeepSeek Harness** — one self-contained plugin that gives the model a first-class `run_kernel_code` tool with session state that survives across calls. No upstream harness changes are required: it mounts as an ordinary Cordis plugin row (via `cordis.patch.yml`) and registers one tool on `ctx.tools`, exactly like the shipped tools.
|
|
6
|
+
|
|
7
|
+
Two long-lived kernel subprocesses share one host driver:
|
|
8
|
+
|
|
9
|
+
- **Python** — a long-lived `python3` subprocess running a [self-contained kernel](./src/python/runner.ts) (standard library only — no venv, no pip). Module-level variables and one asyncio event loop persist across cells; top-level `await` works; the last expression is the cell's value.
|
|
10
|
+
- **JavaScript** — a long-lived `node` subprocess running a [self-contained kernel](./src/nodejs/runner.ts) (Node builtins only). A persistent `state` object plus the process-global object carry values across cells; every cell runs as an async function body, so top-level `await` and `return` work; `return <json>` carries the completion value.
|
|
11
|
+
|
|
12
|
+
The wire protocol, kernel host driver (spawn + handshake, serialized writes, hostile-peer parsing, SIGINT with SIGTERM/SIGKILL escalation, shutdown-to-exit), session registry, binding validation, and output ledger are shared (`src/core/`), so both languages behave identically.
|
|
13
|
+
|
|
14
|
+
This is **process confinement, not a security boundary**: program source has bash-equivalent trust, exactly like the harness's own `process`-isolated backends. The driver's job is robustness — a forged frame never crashes the host, an unresponsive kernel is graded up to termination — not isolation.
|
|
15
|
+
|
|
16
|
+
## Mounting
|
|
17
|
+
|
|
18
|
+
Add the bundle row (or a similar row in any `cordis.yml`):
|
|
19
|
+
|
|
20
|
+
```yaml
|
|
21
|
+
- insert:
|
|
22
|
+
- id: hy-sde-kernels
|
|
23
|
+
name: '@hy-sde-org/dsh-code-runtime-kernels'
|
|
24
|
+
config:
|
|
25
|
+
languages: ['python', 'typescript']
|
|
26
|
+
maxWallMs: 600000
|
|
27
|
+
maxOutputBytes: 67108864
|
|
28
|
+
sessionIdleMs: 0
|
|
29
|
+
interruptEscalationMs: 5000
|
|
30
|
+
startupTimeoutMs: 15000
|
|
31
|
+
shutdownGraceMs: 1000
|
|
32
|
+
toolTimeoutMs: 30000
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
All row ids carry the `hy-sde-` prefix so they never clash with shipped rows (a duplicate loader id fails the boot). Then the model sees the `run_kernel_code` tool.
|
|
36
|
+
|
|
37
|
+
## Config
|
|
38
|
+
|
|
39
|
+
| Key | Default | Meaning |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `languages` | `['python', 'typescript']` | Enabled languages; a call to a disabled language is refused at call time. |
|
|
42
|
+
| `pythonPath` | `python3` | Explicit python executable (PATH discovery by default; fails loud at first spawn when absent). |
|
|
43
|
+
| `nodePath` | `node` | Explicit node executable (PATH discovery by default). |
|
|
44
|
+
| `toolTimeoutMs` | `30000` | Cooperative tool-call timeout (`exec.signal` becomes the per-run abort). |
|
|
45
|
+
| `maxWallMs` | `600000` | Per-run wall-clock budget; interrupt gradates SIGINT → SIGTERM → SIGKILL when the kernel does not respond. |
|
|
46
|
+
| `maxOutputBytes` | `67108864` | Combined serialized log-, completion-, and failure-message byte cap (an `'output-limit'` failure). |
|
|
47
|
+
| `sessionIdleMs` | `0` | Reap a session whose kernel sits unused for this long (`0` disables; state loss is the explicit cost). |
|
|
48
|
+
| `interruptEscalationMs` | `5000` | Wait after SIGINT before SIGTERM, then the same again before SIGKILL. |
|
|
49
|
+
| `startupTimeoutMs` | `15000` | Wait for the bootstrap `ready` handshake before failing the kernel. |
|
|
50
|
+
| `shutdownGraceMs` | `1000` | Grace for the kernel to exit after an `exit` frame. |
|
|
51
|
+
|
|
52
|
+
## Tool surface
|
|
53
|
+
|
|
54
|
+
`run_kernel_code` takes:
|
|
55
|
+
|
|
56
|
+
| Parameter | Meaning |
|
|
57
|
+
|---|---|
|
|
58
|
+
| `language` | `python` or `typescript`. |
|
|
59
|
+
| `code` | Program source: for `typescript` an async-function body (top-level `await`/`return` work); for `python` a module (top-level `await` works, the last expression is the completion value — a top-level `return` is invalid Python and is reported as an `exception`). |
|
|
60
|
+
| `session` | Optional non-empty id; calls sharing one id keep kernel state. Omit for a one-shot run in fresh state. |
|
|
61
|
+
| `reset` | Discard the session's prior kernel state before this run (one reset instead of many retries). |
|
|
62
|
+
|
|
63
|
+
It resolves the seam's result envelope — `value` (JSON completion), `logs`, `executionCount`, and `error { kind, message }` — so the vocabulary matches the harness's own `run_code` (`exception` / `timeout` / `abort` / `worker-exit` / `invalid-output` / `output-limit`), but with the persistent-session fields this plugin owns (`session`, `reset`, `executionCount`).
|
|
64
|
+
|
|
65
|
+
## Semantics
|
|
66
|
+
|
|
67
|
+
- **Sessions.** A call with a non-empty `session` runs in that session's kernel; `executionCount` reports the running count. `reset: true` shuts the old kernel down before a fresh one answers.
|
|
68
|
+
- **One-shot.** Without `session`, a fresh kernel is spawned, exactly one program runs, and the kernel is shut down.
|
|
69
|
+
- **Persistence.** Python: module-level variables and loop state survive across cells. JavaScript: `state` (a long-lived shared object) and sloppy-mode global assignments survive; `const`/`let`/`function`/`class` at cell top level are per-cell (async body), so persistent definitions go on `state`. A cell completes `return <json>` for a completion value, or with no `return` for a no-value run; non-lossless completions (cycles, `BigInt`, sets) are `'invalid-output'`.
|
|
70
|
+
- **Budgets and failure kinds.** Wall-clock expiry → `'timeout'`; cancellation or a kernel that had to die → `'abort'`; thrown exceptions → `'exception'`; non-JSON completions → `'invalid-output'`; combined output overflow → `'output-limit'`; kernel death → the session registry replaces the kernel and retries once. All are result FIELDS, never rejections of the tool.
|
|
71
|
+
|
|
72
|
+
## Model experience
|
|
73
|
+
|
|
74
|
+
The system-prompt guide tells the model to prefer `run_kernel_code` over scratch files for computation with intermediate results, to omit `session` for one-offs, to reuse a `session` id for related calls, and to pass `reset: true` when a session's state is corrupted or unwanted. The terminal card presentation shows language + session on each call and the captured output + failure line on completion.
|
|
75
|
+
|
|
76
|
+
## Known limitations
|
|
77
|
+
|
|
78
|
+
- **A busy synchronous cell resists SIGINT.** A `while (true) {}`/`while True:` loop never yields to the event loop, so the interrupt handler cannot run and the escalation ladder (SIGTERM then SIGKILL) is what actually stops it — costing the kernel's state, hence the session. Cells that yield (async `await` on timers/I/O/tool calls) cancel cleanly and the kernel survives (the wall-clock/timeout tests cover this split).
|
|
79
|
+
- **State can be poisoned.** A buggy program can corrupt the session's state at any time; `reset: true` is the intended recovery primitive.
|
|
80
|
+
- **No security boundary.** Kernel code has bash-equivalent trust, matching the harness's own process backends.
|
|
81
|
+
- **Idle kernels hold a process.** With `sessionIdleMs: 0` (default), session kernels stay alive until reset or plugin teardown, so long-lived work should resume promptly or persist to disk.
|
|
82
|
+
|
|
83
|
+
## Development
|
|
84
|
+
|
|
85
|
+
`pnpm check` (tsc), `pnpm test` (vitest; real `python3`/`node` subprocesses), `pnpm build` (tsc → ESModules under `dist/`), `pnpm pack` smoke. Layout: shared host driver in [`src/core/`](./src/core/) (protocol, kernel host, session registry, ledger), languages in [`src/python/runner.ts`](./src/python/runner.ts) (embedded source, staged per spawn) and [`src/nodejs/runner.ts`](./src/nodejs/runner.ts) (compiled file, spawned with `node --no-warnings`), the plugin/tool in [`src/index.ts`](./src/index.ts). Tests: [`tests/kernels.spec.ts`](./tests/kernels.spec.ts) drives both kernels through `KernelManager`; [`tests/tool.spec.ts`](./tests/tool.spec.ts) mounts the plugin on a real Cordis context and executes `run_kernel_code` through `ctx.tools.execute`.
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# @hy-sde-org/dsh-code-runtime-kernels
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 中文
|
|
4
|
+
|
|
5
|
+
为 DeepSeek Harness 提供**持久化 Python 与 JavaScript 内核**——一个自包含插件,给模型一个一等公民的 `run_kernel_code` 工具,跨调用保留会话状态。无需改动上游 Harness:它以普通 Cordis 插件行(通过 `cordis.patch.yml`)挂载,并在 `ctx.tools` 上注册一个工具,与内置工具完全一致。
|
|
6
|
+
|
|
7
|
+
两个长期存活的 kernel 子进程共享同一个 host 驱动:
|
|
8
|
+
|
|
9
|
+
- **Python** —— 一个长寿命 `python3` 子进程,运行[自包含内核](./src/python/runner.ts)(仅标准库,无需 venv/pip)。模块级变量与一个 asyncio 事件循环跨 cell 保留;支持顶层 `await`;最后一个表达式即 cell 的值。
|
|
10
|
+
- **JavaScript** —— 一个长寿命 `node` 子进程,运行[自包含内核](./src/nodejs/runner.ts)(仅 Node 内置)。持久 `state` 对象与进程全局对象携带跨 cell 的值;每个 cell 以 async 函数体运行,支持顶层 `await`/`return`;`return <json>` 携带完成值。
|
|
11
|
+
|
|
12
|
+
线上协议、kernel host 驱动(spawn + 握手、串行写入、敌对对端解析、SIGINT→SIGTERM→SIGKILL 升级、退出握手)、会话注册表、绑定校验与输出账本全部共享(`src/core/`),两个语言的语义完全一致。
|
|
13
|
+
|
|
14
|
+
这是**进程隔离,而非安全边界**:程序源码拥有与内置 `process` 隔离后端相同的 bash 级信任。驱动的职责是健壮性——伪造帧不会弄崩 host,无响应的 kernel 会被逐步升级到终止——而非隔离。
|
|
15
|
+
|
|
16
|
+
## 挂载
|
|
17
|
+
|
|
18
|
+
在任意 `cordis.yml` 中添加 bundle 行(或类似行):
|
|
19
|
+
|
|
20
|
+
```yaml
|
|
21
|
+
- insert:
|
|
22
|
+
- id: hy-sde-kernels
|
|
23
|
+
name: '@hy-sde-org/dsh-code-runtime-kernels'
|
|
24
|
+
config:
|
|
25
|
+
languages: ['python', 'typescript']
|
|
26
|
+
maxWallMs: 600000
|
|
27
|
+
maxOutputBytes: 67108864
|
|
28
|
+
sessionIdleMs: 0
|
|
29
|
+
interruptEscalationMs: 5000
|
|
30
|
+
startupTimeoutMs: 15000
|
|
31
|
+
shutdownGraceMs: 1000
|
|
32
|
+
toolTimeoutMs: 30000
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
所有行 id 带 `hy-sde-` 前缀以避免与内置行冲突(重复的 loader id 会导致启动失败)。随后模型即看到 `run_kernel_code` 工具。
|
|
36
|
+
|
|
37
|
+
## 配置
|
|
38
|
+
|
|
39
|
+
| 键 | 默认 | 含义 |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `languages` | `['python', 'typescript']` | 启用的语言;调用未启用语言会被拒绝。 |
|
|
42
|
+
| `pythonPath` | `python3` | 显式 python 可执行文件(默认走 PATH 发现;缺失时首次 spawn 即失败)。 |
|
|
43
|
+
| `nodePath` | `node` | 显式 node 可执行文件(默认走 PATH 发现)。 |
|
|
44
|
+
| `toolTimeoutMs` | `30000` | 协作式工具调用超时(`exec.signal` 变为每次运行的 abort 源)。 |
|
|
45
|
+
| `maxWallMs` | `600000` | 每次运行的墙钟预算;中断按 SIGINT→SIGTERM→SIGKILL 升级。 |
|
|
46
|
+
| `maxOutputBytes` | `67108864` | 日志、完成值与失败消息合并后的字节上限(触发 `'output-limit'`)。 |
|
|
47
|
+
| `sessionIdleMs` | `0` | 空闲超过该毫秒数的会话被回收(`0` 禁用;状态丢失是显式代价)。 |
|
|
48
|
+
| `interruptEscalationMs` | `5000` | SIGINT 后等待再发 SIGTERM,再等同样时长发 SIGKILL。 |
|
|
49
|
+
| `startupTimeoutMs` | `15000` | 等待启动 `ready` 握手,超时判失败。 |
|
|
50
|
+
| `shutdownGraceMs` | `1000` | `exit` 帧后等待 kernel 退出的宽限期。 |
|
|
51
|
+
|
|
52
|
+
## 工具面
|
|
53
|
+
|
|
54
|
+
`run_kernel_code` 参数:
|
|
55
|
+
|
|
56
|
+
| 参数 | 含义 |
|
|
57
|
+
|---|---|
|
|
58
|
+
| `language` | `python` 或 `typescript`。 |
|
|
59
|
+
| `code` | 程序源码,作为 async 函数体执行(可用顶层 `await`/`return`)。 |
|
|
60
|
+
| `session` | 可选非空 id;相同 id 的调用共享 kernel 状态。省略则为一次性运行。 |
|
|
61
|
+
| `reset` | 本次运行前丢弃该会话的旧 kernel 状态(一次 reset 胜过无尽重试)。 |
|
|
62
|
+
|
|
63
|
+
返回 seam 的结果信封——`value`(JSON 完成值)、`logs`、`executionCount` 与 `error { kind, message }`——错误词汇与内置 `run_code` 一致(`exception` / `timeout` / `abort` / `worker-exit` / `invalid-output` / `output-limit`),但带有本插件自有的持久会话字段(`session`、`reset`、`executionCount`)。
|
|
64
|
+
|
|
65
|
+
## 语义
|
|
66
|
+
|
|
67
|
+
- **会话**。带非空 `session` 的调用运行于该会话的 kernel;`executionCount` 报告累计次数。`reset: true` 先关旧 kernel 再开新 kernel 响应。
|
|
68
|
+
- **一次性**。没有 `session` 时,spawn 一个新 kernel,恰好运行一个程序后关闭。
|
|
69
|
+
- **持久化**。Python:模块级变量与循环状态跨 cell 保留。JavaScript:`state`(长寿命共享对象)与 sloppy 全局赋值跨 cell 保留;cell 顶层的 `const`/`let`/`function`/`class` 是每 cell 作用域(async 函数体),持久定义请放 `state`。cell 以 `return <json>` 携带完成值,或以无 `return` 结束为无值运行;非 lossless JSON 完成值(环、`BigInt`、集合)判为 `'invalid-output'`。
|
|
70
|
+
- **预算与失败种类**。墙钟超时 → `'timeout'`;取消或被迫终止 → `'abort'`;抛异常 → `'exception'`;非 JSON 完成 → `'invalid-output'`;合并输出溢出 → `'output-limit'`;kernel 死亡 → 会话注册表替换 kernel 并重试一次。全部是结果字段,绝不会 reject 工具调用。
|
|
71
|
+
|
|
72
|
+
## 模型体验
|
|
73
|
+
|
|
74
|
+
系统提示引导模型:计算且含中间结果时优先 `run_kernel_code` 而非读写草稿文件;一次性计算省略 `session`;相关调用复用同一 `session` id;会话状态损坏或不需要时传 `reset: true`。终端卡片展示每次调用的语言 + 会话,以及完成后的捕获输出与失败行。
|
|
75
|
+
|
|
76
|
+
## 已知限制
|
|
77
|
+
|
|
78
|
+
- **同步忙循环抗拒 SIGINT**。`while (true) {}` / `while True:` 永不交还事件循环,中断处理器无法运行,实际由升级梯(SIGTERM 再 SIGKILL)终止——代价是会话状态与 kernel。会让出事件循环的 cell(对定时器/IO/工具调用的 `await`)可被干净取消,kernel 存活(墙钟/中止测试即覆盖这一分界)。
|
|
79
|
+
- **状态可能被污染**。错误程序随时可能弄坏会话状态;`reset: true` 是设计的恢复原语。
|
|
80
|
+
- **无安全边界**。kernel 代码拥有与内置 process 后端相同的 bash 级信任。
|
|
81
|
+
- **空闲 kernel 占用进程**。默认 `sessionIdleMs: 0` 下,会话 kernel 会存活到 reset 或插件卸载;长任务应尽快续跑或落盘。
|
|
82
|
+
|
|
83
|
+
## 开发
|
|
84
|
+
|
|
85
|
+
`pnpm check`(tsc)、`pnpm test`(vitest,真实 `python3`/`node` 子进程)、`pnpm build`(tsc → `dist/` 下的 ESM)、`pnpm pack` 冒烟。布局:共享 host 驱动在 [`src/core/`](./src/core/)(协议、kernel host、会话注册表、账本),各语言在 [`src/python/runner.ts`](./src/python/runner.ts)(内嵌源码,每次 spawn 落地为临时 `.py`)与 [`src/nodejs/runner.ts`](./src/nodejs/runner.ts)(编译产物,`node --no-warnings` 启动),插件与工具在 [`src/index.ts`](./src/index.ts)。测试:[`tests/kernels.spec.ts`](./tests/kernels.spec.ts) 通过 `KernelManager` 驱动双内核;[`tests/tool.spec.ts`](./tests/tool.spec.ts) 在真实 Cordis 上下文挂载插件并经 `ctx.tools.execute` 执行 `run_kernel_code`。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# @hy-sde-org/dsh-code-runtime-kernels — persistent Python + JavaScript
|
|
2
|
+
# kernels for DeepSeek Harness, delivered as ONE self-contained plugin row.
|
|
3
|
+
#
|
|
4
|
+
# The kernel code is executed in real python3/node subprocesses (one long-lived
|
|
5
|
+
# subprocess per `session`), so no worker-thread seam or harness source change
|
|
6
|
+
# is involved: the tool registers on the host's `tools` service exactly like
|
|
7
|
+
# any other shipped tool row. This is process confinement, not a security
|
|
8
|
+
# boundary — model code has bash-equivalent trust.
|
|
9
|
+
#
|
|
10
|
+
# All row ids carry the `hy-sde-` prefix to avoid clashing with any shipped
|
|
11
|
+
# row of the same name (a duplicate loader id fails the boot).
|
|
12
|
+
#
|
|
13
|
+
# Override per deployment (e.g. pin the interpreter paths, shrink the wall
|
|
14
|
+
# clock) by patching the row by id:
|
|
15
|
+
#
|
|
16
|
+
# - id: hy-sde-kernels
|
|
17
|
+
# config:
|
|
18
|
+
# pythonPath: /usr/local/bin/python3
|
|
19
|
+
# maxWallMs: 120000
|
|
20
|
+
#
|
|
21
|
+
# To disable one language, set `languages: ['python']` (or
|
|
22
|
+
# `['typescript']`); a disabled language is refused at call time.
|
|
23
|
+
- insert:
|
|
24
|
+
- id: hy-sde-kernels
|
|
25
|
+
name: '@hy-sde-org/dsh-code-runtime-kernels'
|
|
26
|
+
config:
|
|
27
|
+
languages: ['python', 'typescript']
|
|
28
|
+
maxWallMs: 600000
|
|
29
|
+
maxOutputBytes: 67108864
|
|
30
|
+
sessionIdleMs: 0
|
|
31
|
+
interruptEscalationMs: 5000
|
|
32
|
+
startupTimeoutMs: 15000
|
|
33
|
+
shutdownGraceMs: 1000
|
|
34
|
+
toolTimeoutMs: 30000
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package-owned invariant companion for `@hy-sde-org/dsh-code-runtime-kernels`.
|
|
3
|
+
* @module @hy-sde-org/dsh-code-runtime-kernels/invariant
|
|
4
|
+
*/
|
|
5
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
6
|
+
/** Cordis companion plugin name. */
|
|
7
|
+
export declare const name = "code-runtime-nodejs-invariant";
|
|
8
|
+
/** Service required before the companion can reserve package ownership. */
|
|
9
|
+
export declare const inject: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Register this package's invariant companion.
|
|
12
|
+
* @param ctx - Cordis context carrying the invariant service.
|
|
13
|
+
* @returns the installed registration's disposer after setup succeeds.
|
|
14
|
+
*/
|
|
15
|
+
export declare const apply: (ctx: Context) => Promise<() => void>;
|
|
16
|
+
//# sourceMappingURL=invariant.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invariant.d.ts","sourceRoot":"","sources":["../../src/core/invariant.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAKlD,oCAAoC;AACpC,eAAO,MAAM,IAAI,kCAAkC,CAAA;AACnD,2EAA2E;AAC3E,eAAO,MAAM,MAAM,UAAiB,CAAA;AASpC;;;;GAIG;AACH,eAAO,MAAM,KAAK,GAAI,KAAK,OAAO,KAAG,OAAO,CAAC,MAAM,IAAI,CACU,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package-owned invariant companion for `@hy-sde-org/dsh-code-runtime-kernels`.
|
|
3
|
+
* @module @hy-sde-org/dsh-code-runtime-kernels/invariant
|
|
4
|
+
*/
|
|
5
|
+
const PACKAGE_NAME = '@hy-sde-org/dsh-code-runtime-kernels';
|
|
6
|
+
/** Cordis companion plugin name. */
|
|
7
|
+
export const name = 'code-runtime-nodejs-invariant';
|
|
8
|
+
/** Service required before the companion can reserve package ownership. */
|
|
9
|
+
export const inject = ['invariants'];
|
|
10
|
+
/**
|
|
11
|
+
* No runtime invariant: this process-boundary implementation exposes no
|
|
12
|
+
* same-process event relation; kernel protocol tests and provider integration
|
|
13
|
+
* tests cover it.
|
|
14
|
+
*/
|
|
15
|
+
const install = () => { };
|
|
16
|
+
/**
|
|
17
|
+
* Register this package's invariant companion.
|
|
18
|
+
* @param ctx - Cordis context carrying the invariant service.
|
|
19
|
+
* @returns the installed registration's disposer after setup succeeds.
|
|
20
|
+
*/
|
|
21
|
+
export const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
22
|
+
/* jscpd:ignore-end */
|
|
23
|
+
//# sourceMappingURL=invariant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invariant.js","sourceRoot":"","sources":["../../src/core/invariant.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,YAAY,GAAG,sCAAsC,CAAA;AAE3D,oCAAoC;AACpC,MAAM,CAAC,MAAM,IAAI,GAAG,+BAA+B,CAAA;AACnD,2EAA2E;AAC3E,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,YAAY,CAAC,CAAA;AAEpC;;;;GAIG;AACH,MAAM,OAAO,GAAuB,GAAG,EAAE,GAAE,CAAC,CAAA;AAE5C;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,GAAY,EAAuB,EAAE,CACzD,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAA;AACjE,sBAAsB"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-side driver for ONE persistent kernel subprocess, shared by the Python
|
|
3
|
+
* and JavaScript/SDK runners (a `KernelRuntimeProfile` describes how to spawn
|
|
4
|
+
* each). Owns the NDJSON wire: spawn + handshake, serialized outbound writes,
|
|
5
|
+
* hostile-peer inbound parsing, binding-call dispatch, SIGINT interrupt with
|
|
6
|
+
* SIGTERM/SIGKILL escalation, and shutdown-to-exit. This is process
|
|
7
|
+
* confinement, not a security boundary: model code has bash-equivalent trust,
|
|
8
|
+
* so the driver's job is robustness (a forged frame never crashes the host, an
|
|
9
|
+
* unresponsive kernel is graded up to termination) rather than isolation.
|
|
10
|
+
* @module @hy-sde-org/dsh-code-runtime-kernels/src/core/kernel
|
|
11
|
+
*/
|
|
12
|
+
import type { CodeBindingNamespace, CodeJsonValue } from '@deepseek-ai/dsh-code-runtime';
|
|
13
|
+
import type { DoneFrame, KernelFrame, KernelHostMessage } from './protocol.ts';
|
|
14
|
+
export type { DoneFrame, KernelFrame, KernelHostMessage };
|
|
15
|
+
/** How to spawn and label one language's kernel. */
|
|
16
|
+
export interface KernelRuntimeProfile {
|
|
17
|
+
/** The language descriptor this kernel presents (`'python'` | `'typescript'`). */
|
|
18
|
+
key: string;
|
|
19
|
+
/** The interpreter/executable to spawn. */
|
|
20
|
+
command: string;
|
|
21
|
+
/** argv placed before the runner argument. */
|
|
22
|
+
argvPrefix: string[];
|
|
23
|
+
/** Runner passed as the final argv (absolute path). */
|
|
24
|
+
runnerPath?: string;
|
|
25
|
+
/** Runner embedded as source, staged to a scratch file and passed as argv. */
|
|
26
|
+
stagedSource?: string;
|
|
27
|
+
/** File suffix for a staged runner (e.g. `.py`). */
|
|
28
|
+
stagedSuffix?: string;
|
|
29
|
+
/** Extra environment variables for the subprocess. */
|
|
30
|
+
env?: NodeJS.ProcessEnv;
|
|
31
|
+
/** Error-message prefix (`dsh-code-runtime-…`). */
|
|
32
|
+
prefix: string;
|
|
33
|
+
/** Kernel id prefix (`py-` / `js-`). */
|
|
34
|
+
idPrefix: string;
|
|
35
|
+
/** Human kernel label for messages (e.g. `python kernel`). */
|
|
36
|
+
label: string;
|
|
37
|
+
}
|
|
38
|
+
/** Per-kernel behavior knobs (validated + defaulted by the provider). */
|
|
39
|
+
export interface KernelStartConfig {
|
|
40
|
+
/** Working directory for the subprocess. */
|
|
41
|
+
cwd: string;
|
|
42
|
+
/** Environment to inherit (seam: model code has bash-equivalent trust). */
|
|
43
|
+
env?: NodeJS.ProcessEnv;
|
|
44
|
+
/** How long to wait for the bootstrap `ready` frame. */
|
|
45
|
+
startupTimeoutMs: number;
|
|
46
|
+
/** How long to wait after SIGINT before escalating to SIGTERM (then SIGKILL). */
|
|
47
|
+
interruptEscalationMs: number;
|
|
48
|
+
/** Grace period for the kernel to exit after an `exit` frame before SIGTERM/SIGKILL. */
|
|
49
|
+
shutdownGraceMs: number;
|
|
50
|
+
}
|
|
51
|
+
/** The outcome of one kernel execution; budgets and kind mapping stay with the provider. */
|
|
52
|
+
export interface KernelExecResult {
|
|
53
|
+
status: 'ok' | 'error';
|
|
54
|
+
/** Captured program output, in order. */
|
|
55
|
+
logs: Array<{
|
|
56
|
+
text: string;
|
|
57
|
+
stream: string;
|
|
58
|
+
}>;
|
|
59
|
+
/** The completion value on a clean run with one. */
|
|
60
|
+
value?: CodeJsonValue;
|
|
61
|
+
/** The session's execution count after this run. */
|
|
62
|
+
executionCount?: number;
|
|
63
|
+
/** True when the run was interrupted or cancelled. */
|
|
64
|
+
cancelled: boolean;
|
|
65
|
+
/** True when the completion was not lossless JSON. */
|
|
66
|
+
invalidOutput: boolean;
|
|
67
|
+
/** Failure or protocol message, when any. */
|
|
68
|
+
message: string;
|
|
69
|
+
/** True when the kernel had to be terminated to settle this run. */
|
|
70
|
+
killed: boolean;
|
|
71
|
+
}
|
|
72
|
+
/** The Node.js runner shipped as a package file (raw source in development, compiled ESM in the output). */
|
|
73
|
+
declare const RUNNER_PATH: string;
|
|
74
|
+
/** Profile for the JavaScript kernel; `command` is the resolved node executable. */
|
|
75
|
+
export declare function nodejsKernelProfile(command: string): KernelRuntimeProfile;
|
|
76
|
+
/**
|
|
77
|
+
* Distill a `done` frame into the failure taxonomy. A clean completion yields
|
|
78
|
+
* `ok`; an invalid completion (not lossless JSON) yields `'invalid-output'`;
|
|
79
|
+
* anything else is a program exception.
|
|
80
|
+
*/
|
|
81
|
+
export declare function doneFailure(frame: DoneFrame): {
|
|
82
|
+
ok: true;
|
|
83
|
+
} | {
|
|
84
|
+
ok: false;
|
|
85
|
+
error: {
|
|
86
|
+
kind: 'exception' | 'invalid-output';
|
|
87
|
+
message: string;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Parse one kernel frame. The peer runs MODEL CODE and can emit anything, so
|
|
92
|
+
* everything is re-validated and rebuilt field by field; junk returns
|
|
93
|
+
* `undefined` and is dropped (a throw here would crash the host).
|
|
94
|
+
*/
|
|
95
|
+
export declare function parseKernelFrame(raw: unknown): KernelFrame | undefined;
|
|
96
|
+
/** One kernel subprocess, session-agnostic (the registry adds sessions). */
|
|
97
|
+
export declare class KernelHost {
|
|
98
|
+
#private;
|
|
99
|
+
id: string;
|
|
100
|
+
pid: number | undefined;
|
|
101
|
+
readonly profile: KernelRuntimeProfile;
|
|
102
|
+
/**
|
|
103
|
+
* Spawn a kernel per the profile and wait for the bootstrap handshake.
|
|
104
|
+
* Rejects on spawn failure, startup timeout, or an early process exit
|
|
105
|
+
* (grading the fresh subprocess up to termination behind us).
|
|
106
|
+
*/
|
|
107
|
+
static start(profile: KernelRuntimeProfile, config: KernelStartConfig): Promise<KernelHost>;
|
|
108
|
+
private constructor();
|
|
109
|
+
/** The process is healthy and accepting runs. */
|
|
110
|
+
isAlive(): boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Execute one program against the given namespaces. Kernel state persists
|
|
113
|
+
* across calls, and only ONE exec may be in flight per kernel at a time —
|
|
114
|
+
* the session registry serializes; callers must not overlap. Must be called
|
|
115
|
+
* while {@link isAlive}. Resolves with a {@link KernelExecResult} whose
|
|
116
|
+
* flags the provider maps onto the failure kinds.
|
|
117
|
+
*/
|
|
118
|
+
execute(id: string, code: string, namespaces: CodeBindingNamespace[], options?: {
|
|
119
|
+
signal?: AbortSignal;
|
|
120
|
+
cwd?: string;
|
|
121
|
+
env?: Record<string, string>;
|
|
122
|
+
}): Promise<KernelExecResult>;
|
|
123
|
+
/** Request cancellation of the in-flight run via SIGINT, escalating to termination. */
|
|
124
|
+
interrupt(): Promise<void>;
|
|
125
|
+
/** Gracefully shut down: `exit` frame, then SIGTERM, then SIGKILL; waits for exit. */
|
|
126
|
+
shutdown(): Promise<{
|
|
127
|
+
confirmed: boolean;
|
|
128
|
+
}>;
|
|
129
|
+
/** Termination path for a startup that never completed. */
|
|
130
|
+
private killForFailedStart;
|
|
131
|
+
}
|
|
132
|
+
export { RUNNER_PATH };
|
|
133
|
+
//# sourceMappingURL=kernel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kernel.d.ts","sourceRoot":"","sources":["../../src/core/kernel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAExF,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAC9E,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAA;AAEzD,oDAAoD;AACpD,MAAM,WAAW,oBAAoB;IACnC,kFAAkF;IAClF,GAAG,EAAE,MAAM,CAAA;IACX,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAA;IACf,8CAA8C;IAC9C,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,sDAAsD;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAA;IACd,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAA;IAChB,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAA;CACd;AAED,yEAAyE;AACzE,MAAM,WAAW,iBAAiB;IAChC,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAA;IACX,2EAA2E;IAC3E,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,wDAAwD;IACxD,gBAAgB,EAAE,MAAM,CAAA;IACxB,iFAAiF;IACjF,qBAAqB,EAAE,MAAM,CAAA;IAC7B,wFAAwF;IACxF,eAAe,EAAE,MAAM,CAAA;CACxB;AAkBD,4FAA4F;AAC5F,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,IAAI,GAAG,OAAO,CAAA;IACtB,yCAAyC;IACzC,IAAI,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC7C,oDAAoD;IACpD,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,oDAAoD;IACpD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,sDAAsD;IACtD,SAAS,EAAE,OAAO,CAAA;IAClB,sDAAsD;IACtD,aAAa,EAAE,OAAO,CAAA;IACtB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,4GAA4G;AAC5G,QAAA,MAAM,WAAW,QAGf,CAAA;AAEF,oFAAoF;AACpF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB,CAUzE;AAiBD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE;QAAE,IAAI,EAAE,WAAW,GAAG,gBAAgB,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAY5I;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,GAAG,SAAS,CA2CtE;AAED,4EAA4E;AAC5E,qBAAa,UAAU;;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAA;IActC;;;;OAIG;WACU,KAAK,CAAC,OAAO,EAAE,oBAAoB,EAAE,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;IAyDjG,OAAO;IAqBP,iDAAiD;IACjD,OAAO,IAAI,OAAO;IAIlB;;;;;;OAMG;IACG,OAAO,CACX,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,oBAAoB,EAAE,EAClC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAO,GACjF,OAAO,CAAC,gBAAgB,CAAC;IAgE5B,uFAAuF;IACjF,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAkChC,sFAAsF;IAChF,QAAQ,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IAwBjD,2DAA2D;YAC7C,kBAAkB;CAiLjC;AAED,OAAO,EAAE,WAAW,EAAE,CAAA"}
|