kern-sandbox 0.2.38 → 0.2.40
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 +26 -12
- package/index.js +23 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<img src="https://raw.githubusercontent.com/getkern/kern/main/assets/brand/kern-logo.png" width="220" alt="kern">
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
interpreter starting inside it costs more than the box does. Both depend on your machine, so they are
|
|
7
|
-
measured under [Prewarming](https://github.com/getkern/kern/blob/main/bindings/node/README.md#prewarming-a-box-ready-before-the-call-arrives) with the machine and the method beside them, and the
|
|
8
|
-
runtime's own are in [BENCHMARKS.md](https://github.com/getkern/kern/blob/main/BENCHMARKS.md).
|
|
5
|
+
# Kern Sandbox
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
**Your model writes the code. This runs it where it can't touch your machine.**
|
|
8
|
+
|
|
9
|
+
<sub>**Works with** Claude Code · Cursor · Claude Desktop · LM Studio · LangChain · pi</sub>
|
|
10
|
+
|
|
11
|
+
[](https://www.npmjs.com/package/kern-sandbox)
|
|
12
|
+
[](https://pypi.org/project/kern-sandbox/)
|
|
13
|
+
[](https://github.com/getkern/kern/blob/main/LICENSE)
|
|
14
|
+
|
|
15
|
+
<sub>rootless · no daemon · no socket · no VM · no cloud · no account</sub>
|
|
16
|
+
|
|
17
|
+
**[The runtime](https://github.com/getkern/kern)** ·
|
|
18
|
+
**[MCP server](https://github.com/getkern/kern/blob/main/docs/MCP.md)** ·
|
|
19
|
+
**[Security model](https://github.com/getkern/kern/blob/main/SECURITY.md)** ·
|
|
20
|
+
**[Benchmarks](https://github.com/getkern/kern/blob/main/BENCHMARKS.md)**
|
|
21
|
+
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
An agent's tool-call, a generated snippet, a notebook cell, a CI step: it arrives, you run it, and
|
|
25
|
+
nobody has read it first.
|
|
26
|
+
|
|
27
|
+
`kern-sandbox` is the Node and TypeScript binding for **[kern](https://getkern.dev)**. Every call
|
|
28
|
+
gets its own box, thrown away after; when state has to carry across calls there is
|
|
15
29
|
[a session](#a-session-files-persist-processes-are-ephemeral) and a warm interpreter.
|
|
16
30
|
|
|
17
31
|
Network off, memory and PID caps the kernel enforces **where your host delegates them**,
|
|
@@ -288,7 +302,7 @@ RUN python3 -m compileall -q -j 0 /usr/local/lib/python3.12
|
|
|
288
302
|
|
|
289
303
|
Build it once and pass it: `run_code(..., image="my-python")`. The default stays the stock tag,
|
|
290
304
|
because an SDK that silently required a custom image would be worse than one that costs 29 ms and
|
|
291
|
-
says so. Measured on an
|
|
305
|
+
says so. Measured rootless on an idle machine; [BENCHMARKS.md](https://github.com/getkern/kern/blob/main/BENCHMARKS.md) has the method.
|
|
292
306
|
|
|
293
307
|
## Prewarming: a box ready before the call arrives
|
|
294
308
|
|
package/index.js
CHANGED
|
@@ -36,7 +36,7 @@ const crypto = require("crypto");
|
|
|
36
36
|
const zlib = require("zlib");
|
|
37
37
|
const { spawn, spawnSync } = require("child_process");
|
|
38
38
|
|
|
39
|
-
const VERSION = "0.2.
|
|
39
|
+
const VERSION = "0.2.40";
|
|
40
40
|
|
|
41
41
|
const DEFAULT_IMAGE = "python:3.12-slim";
|
|
42
42
|
const WORKSPACE = "/workspace"; // where the persistent workspace is mounted inside every box
|
|
@@ -285,9 +285,22 @@ function pycSourceId(image) {
|
|
|
285
285
|
const root = path.join(cacheHome(), "kern", "images");
|
|
286
286
|
const safe = sanitizeRef(image);
|
|
287
287
|
const h = crypto.createHash("sha256");
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
288
|
+
// THE CONFIG, which changes when ENTRYPOINT/ENV/WORKDIR/USER do.
|
|
289
|
+
h.update(fs.readFileSync(path.join(root, `${safe}.image`)).subarray(0, 4096));
|
|
290
|
+
// THE SENTINEL'S STAMP, NOT ITS BYTES. `.ok` holds the REFERENCE, so its contents are the tag and
|
|
291
|
+
// never move when the tag does: hashing them missed the commonest case there is, a rebuilt rootfs
|
|
292
|
+
// under an unchanged config. Its mtime and length are what kern ITSELF uses to decide an image's
|
|
293
|
+
// content changed, because a re-pull rewrites the sentinel last. Measured: a real re-pull leaves
|
|
294
|
+
// the config byte-identical and moves this.
|
|
295
|
+
const st = fs.statSync(path.join(root, `${safe}.ok`), { bigint: true });
|
|
296
|
+
h.update(`${st.mtimeNs}:${st.size}`);
|
|
297
|
+
// AND THE LAYER MANIFEST FOR A BUILT IMAGE, which names its layers by content. A pulled image has
|
|
298
|
+
// none, and that absence is part of the identity: an image that stops being layered is not the
|
|
299
|
+
// same image.
|
|
300
|
+
try {
|
|
301
|
+
h.update(fs.readFileSync(path.join(root, `${safe}.layers`)).subarray(0, 8192));
|
|
302
|
+
} catch {
|
|
303
|
+
h.update("\0no-layers");
|
|
291
304
|
}
|
|
292
305
|
return h.digest("hex").slice(0, 32);
|
|
293
306
|
} catch {
|
|
@@ -4411,5 +4424,11 @@ module.exports = {
|
|
|
4411
4424
|
_ociCanonicalRef: ociCanonicalRef,
|
|
4412
4425
|
_PYC_BUILD_CODE: PYC_BUILD_CODE,
|
|
4413
4426
|
_pycStartBuild: pycStartBuild,
|
|
4427
|
+
/** Await every build still in flight. FOR TESTS, and it removes a real race rather than masking
|
|
4428
|
+
* one: a test that removes its temp cache home while a background build is still writing into it
|
|
4429
|
+
* fails in `rimraf` with ENOTEMPTY, which is a teardown ordering bug and reads like a product
|
|
4430
|
+
* defect. Measured under the gate, where the machine is busy enough for the build to outlive the
|
|
4431
|
+
* test. */
|
|
4432
|
+
_pycSettle: () => Promise.allSettled([...PYC_BUILDS.values()]),
|
|
4414
4433
|
version: VERSION,
|
|
4415
4434
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kern-sandbox",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.40",
|
|
4
4
|
"description": "Your model writes the code. This runs it where it can't touch your machine: a rootless Linux container, no daemon, no VM, no cloud, no account. A kernel boundary, not a microVM: for deliberately hostile code, use one.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sandbox",
|