deltabox-lite 0.0.0-stage → 0.1.0
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 +33 -2
- package/bin/deltabox.js +60 -0
- package/index.cjs +28 -0
- package/index.d.ts +161 -0
- package/package.json +29 -4
package/README.md
CHANGED
|
@@ -1,3 +1,34 @@
|
|
|
1
|
-
#
|
|
1
|
+
# deltabox-lite
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This package installs the native `deltabox` runtime for supported Linux and
|
|
4
|
+
macOS systems. The matching optional platform package carries the binary and
|
|
5
|
+
the Node-API addon; `bin/deltabox.js` is a thin launcher that executes that
|
|
6
|
+
binary in place, so `npm install --global deltabox-lite` puts a `deltabox`
|
|
7
|
+
command on the PATH. No prestarted service is installed.
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
const { binaryPath, loadNative } = require('deltabox-lite')
|
|
11
|
+
const { NativeDeltabox } = loadNative()
|
|
12
|
+
const runtime = new NativeDeltabox(process.cwd(), binaryPath(), {
|
|
13
|
+
fsMode: 'cbcow-through',
|
|
14
|
+
isolation: 'deltabox',
|
|
15
|
+
})
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Native methods return promises backed by the addon's Tokio blocking runtime.
|
|
19
|
+
The coordinator and active filesystem state stay resident in the Node process;
|
|
20
|
+
storage mode and command isolation are fixed at construction. The default
|
|
21
|
+
`cbcow-through` + `deltabox` pair runs commands under the session's own sandbox
|
|
22
|
+
and deny set, which is why `isolation: 'none'` has to be asked for by name:
|
|
23
|
+
those commands share the Node process ambient environment instead. File reads
|
|
24
|
+
and writes use `Buffer`, while session, checkpoint, diff, commit, abort, and
|
|
25
|
+
review calls return protocol-shaped typed objects. Every session record names
|
|
26
|
+
its `isolation` profile and the resolved `isolation_provider` (`sandlock` or
|
|
27
|
+
`seatbelt`).
|
|
28
|
+
|
|
29
|
+
Linux CB-CoW modes require `/dev/fuse` and `fusermount3` or `fusermount` on the
|
|
30
|
+
host. Deltabox otherwise reports the reason and falls back to `copy-private`
|
|
31
|
+
unless the requested mode is required.
|
|
32
|
+
|
|
33
|
+
See the [deltabox-lite repository](https://github.com/delta-box/deltabox-lite)
|
|
34
|
+
for usage and policy documentation.
|
package/bin/deltabox.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Launcher for the `deltabox` command. The real binary ships in the
|
|
3
|
+
// platform-specific optional dependency; npm only links the bins that the
|
|
4
|
+
// top-level package declares, so a global install of `deltabox-lite` gets
|
|
5
|
+
// its command from this shim rather than from the platform package.
|
|
6
|
+
//
|
|
7
|
+
// The child runs with inherited stdio (so `deltabox serve` can speak
|
|
8
|
+
// JSON-RPC over the launcher's own stdin/stdout), termination signals sent to
|
|
9
|
+
// the launcher are forwarded to it, and its exit status is mirrored.
|
|
10
|
+
"use strict";
|
|
11
|
+
|
|
12
|
+
const { spawn } = require("node:child_process");
|
|
13
|
+
const { constants } = require("node:os");
|
|
14
|
+
|
|
15
|
+
let binary;
|
|
16
|
+
try {
|
|
17
|
+
binary = require("../index.cjs").binaryPath();
|
|
18
|
+
} catch (error) {
|
|
19
|
+
process.stderr.write(
|
|
20
|
+
`deltabox-lite: cannot locate the deltabox binary for this platform.\n` +
|
|
21
|
+
`${error.message}\n` +
|
|
22
|
+
`Reinstall with optional dependencies enabled (npm install --include=optional).\n`,
|
|
23
|
+
);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const child = spawn(binary, process.argv.slice(2), { stdio: "inherit" });
|
|
28
|
+
|
|
29
|
+
// A supervisor that signals only the launcher (rather than the whole
|
|
30
|
+
// process group) must still stop the real deltabox, so relay termination
|
|
31
|
+
// signals instead of dying and leaving the child orphaned.
|
|
32
|
+
const relayed = ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
33
|
+
for (const signal of relayed) {
|
|
34
|
+
process.on(signal, () => {
|
|
35
|
+
if (child.exitCode === null && child.signalCode === null) child.kill(signal);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
child.on("error", (error) => {
|
|
40
|
+
process.stderr.write(`deltabox-lite: failed to launch ${binary}: ${error.message}\n`);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
child.on("exit", (code, signal) => {
|
|
45
|
+
if (signal) {
|
|
46
|
+
// Mirror the child's termination: raise the same signal on ourselves with
|
|
47
|
+
// the default disposition restored. Signals Node ignores (SIGPIPE) cannot
|
|
48
|
+
// terminate us that way, so fall back to the shell convention 128+n.
|
|
49
|
+
for (const relayedSignal of relayed) process.removeAllListeners(relayedSignal);
|
|
50
|
+
const number = constants.signals[signal];
|
|
51
|
+
process.exitCode = number ? 128 + number : 1;
|
|
52
|
+
try {
|
|
53
|
+
process.kill(process.pid, signal);
|
|
54
|
+
} catch {
|
|
55
|
+
// Unknown signal name: the fallback exit code above applies.
|
|
56
|
+
}
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
process.exit(code ?? 1);
|
|
60
|
+
});
|
package/index.cjs
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const { dirname, join } = require("node:path");
|
|
2
|
+
|
|
3
|
+
const packages = {
|
|
4
|
+
"darwin-arm64": "deltabox-lite-darwin-arm64",
|
|
5
|
+
"darwin-x64": "deltabox-lite-darwin-x64",
|
|
6
|
+
"linux-arm64": "deltabox-lite-linux-arm64",
|
|
7
|
+
"linux-x64": "deltabox-lite-linux-x64",
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
function platformPackageRoot() {
|
|
11
|
+
const name = packages[`${process.platform}-${process.arch}`];
|
|
12
|
+
if (!name) throw new Error(`deltabox-lite does not support ${process.platform}/${process.arch}`);
|
|
13
|
+
return dirname(require.resolve(`${name}/package.json`));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function binaryPath() {
|
|
17
|
+
return join(platformPackageRoot(), "bin", "deltabox");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function nativePath() {
|
|
21
|
+
return join(platformPackageRoot(), "native", "deltabox.node");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function loadNative() {
|
|
25
|
+
return require(nativePath());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports = { binaryPath, nativePath, loadNative };
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
|
|
3
|
+
export interface NativeEnvironmentEntry {
|
|
4
|
+
key: string
|
|
5
|
+
value: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Configuration snapshot for one embedded coordinator, fixed at construction.
|
|
10
|
+
* `fsMode` is the storage mode every session on this coordinator starts in;
|
|
11
|
+
* `isolation` picks how commands run. Neither can be changed later, because the
|
|
12
|
+
* coordinator and its active filesystem state live for the whole process.
|
|
13
|
+
*/
|
|
14
|
+
export interface NativeDeltaboxOptions {
|
|
15
|
+
stateDir?: string
|
|
16
|
+
runtimeDir?: string
|
|
17
|
+
fsMode?: 'cbcow-through' | 'cbcow-private' | 'copy-private'
|
|
18
|
+
/**
|
|
19
|
+
* `deltabox` keeps the session's own sandbox and deny set. `none` lets
|
|
20
|
+
* commands share the Node process ambient environment, so a host has to name
|
|
21
|
+
* it explicitly; the native transport is the only one that can offer it.
|
|
22
|
+
*/
|
|
23
|
+
isolation?: 'deltabox' | 'none'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface NativeSessionInfo {
|
|
27
|
+
session_id: string
|
|
28
|
+
project: string
|
|
29
|
+
started_at_ms: number
|
|
30
|
+
status: 'running' | 'stopped'
|
|
31
|
+
checkpoint_count: number
|
|
32
|
+
pending_changes: number
|
|
33
|
+
requested_fs_mode: 'cbcow-through' | 'cbcow-private' | 'copy-private'
|
|
34
|
+
resolved_fs_mode: 'cbcow-through' | 'cbcow-private' | 'copy-private'
|
|
35
|
+
host_visibility: 'immediate' | 'on-commit'
|
|
36
|
+
durability: string
|
|
37
|
+
group_commit_ms?: number
|
|
38
|
+
isolation: 'deltabox' | 'none'
|
|
39
|
+
/** Resolved OS mechanism behind `deltabox` isolation, absent under `none`. */
|
|
40
|
+
isolation_provider: string | null
|
|
41
|
+
state_provider: string | null
|
|
42
|
+
fallback_reason: string | null
|
|
43
|
+
rollback_guarantee: string
|
|
44
|
+
tainted: boolean
|
|
45
|
+
mountpoint?: string
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface NativeExecResult {
|
|
49
|
+
exit_code: number | null
|
|
50
|
+
stdout: string
|
|
51
|
+
stderr: string
|
|
52
|
+
duration_ms: number
|
|
53
|
+
truncated: boolean
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Filesystem breadth for one command. `workspace-write` (the default) keeps
|
|
58
|
+
* writes inside the session workspace; `read-write` additionally reaches the
|
|
59
|
+
* rest of the host filesystem while the workspace stays Deltabox-managed and
|
|
60
|
+
* the backing project stays denied.
|
|
61
|
+
*/
|
|
62
|
+
export type NativeExecutionProfile = 'workspace-write' | 'read-write'
|
|
63
|
+
|
|
64
|
+
export interface NativeCheckpointInfo {
|
|
65
|
+
id: string
|
|
66
|
+
label: string | null
|
|
67
|
+
created_at_ms: number
|
|
68
|
+
change_count: number
|
|
69
|
+
committed: boolean
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface NativeActiveReview {
|
|
73
|
+
checkpoint_id: string
|
|
74
|
+
kind: 'task' | 'tool' | 'risky'
|
|
75
|
+
label: string | null
|
|
76
|
+
started_at_ms: number
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface NativeChange {
|
|
80
|
+
path: string
|
|
81
|
+
kind: 'added' | 'modified' | 'deleted'
|
|
82
|
+
old_size: number | null
|
|
83
|
+
new_size: number | null
|
|
84
|
+
is_binary: boolean
|
|
85
|
+
added_lines: number
|
|
86
|
+
removed_lines: number
|
|
87
|
+
text_diff?: string
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface NativeDiffResult {
|
|
91
|
+
from: string | null
|
|
92
|
+
to: string | null
|
|
93
|
+
pending_changes: number
|
|
94
|
+
changes: NativeChange[]
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface NativeCommitResult {
|
|
98
|
+
checkpoint_id: string
|
|
99
|
+
applied: number
|
|
100
|
+
/**
|
|
101
|
+
* How many sibling publications this commit's baseline was fast-forwarded
|
|
102
|
+
* over; absent when zero. When set, the host moved since this session's
|
|
103
|
+
* baseline and the orchestrator should re-verify (build, test) after
|
|
104
|
+
* integration.
|
|
105
|
+
*/
|
|
106
|
+
folded_publications?: number
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export interface NativeAbortResult {
|
|
110
|
+
checkpoint_id: string
|
|
111
|
+
restored: number
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface NativeDeltaboxInstance {
|
|
115
|
+
startSession(
|
|
116
|
+
policy?: string,
|
|
117
|
+
durability?: 'fast' | 'strict',
|
|
118
|
+
groupCommitMs?: number,
|
|
119
|
+
filesystemMode?: 'auto' | 'cbcow-through' | 'cbcow-private' | 'copy-private',
|
|
120
|
+
requireFilesystemMode?: boolean,
|
|
121
|
+
): Promise<NativeSessionInfo>
|
|
122
|
+
stopSession(sessionId: string): Promise<NativeSessionInfo>
|
|
123
|
+
sessionStatus(sessionId: string): Promise<NativeSessionInfo>
|
|
124
|
+
exec(
|
|
125
|
+
sessionId: string,
|
|
126
|
+
argv: string[],
|
|
127
|
+
cwd?: string,
|
|
128
|
+
environment?: NativeEnvironmentEntry[],
|
|
129
|
+
label?: string,
|
|
130
|
+
executionProfile?: NativeExecutionProfile,
|
|
131
|
+
): Promise<NativeExecResult>
|
|
132
|
+
readFile(sessionId: string, path: string): Promise<Buffer>
|
|
133
|
+
writeFile(sessionId: string, path: string, content: Buffer): Promise<void>
|
|
134
|
+
recordFileChanges(sessionId: string, paths: string[]): Promise<void>
|
|
135
|
+
checkpoint(sessionId: string, label?: string): Promise<NativeCheckpointInfo>
|
|
136
|
+
diff(sessionId: string, from?: string, to?: string): Promise<NativeDiffResult>
|
|
137
|
+
commit(sessionId: string, checkpoint?: string): Promise<NativeCommitResult>
|
|
138
|
+
abort(sessionId: string, checkpoint?: string): Promise<NativeAbortResult>
|
|
139
|
+
beginReview(sessionId: string, kind: 'task' | 'tool' | 'risky', label?: string): Promise<NativeActiveReview>
|
|
140
|
+
reviewStatus(sessionId: string): Promise<NativeActiveReview | null>
|
|
141
|
+
reviewDiff(sessionId: string): Promise<NativeDiffResult>
|
|
142
|
+
reviewCommit(sessionId: string): Promise<NativeCommitResult>
|
|
143
|
+
reviewAbort(sessionId: string): Promise<NativeAbortResult>
|
|
144
|
+
reviewSkip(sessionId: string): Promise<NativeActiveReview>
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export interface NativeDeltaboxConstructor {
|
|
148
|
+
new(
|
|
149
|
+
projectRoot: string,
|
|
150
|
+
helperBinary: string,
|
|
151
|
+
options?: NativeDeltaboxOptions,
|
|
152
|
+
): NativeDeltaboxInstance
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export interface DeltaboxNativeBinding {
|
|
156
|
+
NativeDeltabox: NativeDeltaboxConstructor
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function binaryPath(): string
|
|
160
|
+
export function nativePath(): string
|
|
161
|
+
export function loadNative(): DeltaboxNativeBinding
|
package/package.json
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deltabox-lite",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"license": "Apache-2.0",
|
|
5
|
+
"description": "Native sandbox runtime with diff, commit, and abort for AI coding agents",
|
|
6
|
+
"repository": "https://github.com/delta-box/deltabox-lite",
|
|
7
|
+
"main": "index.cjs",
|
|
8
|
+
"types": "index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"deltabox": "bin/deltabox.js"
|
|
11
|
+
},
|
|
12
|
+
"os": [
|
|
13
|
+
"darwin",
|
|
14
|
+
"linux"
|
|
15
|
+
],
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=18"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"index.cjs",
|
|
21
|
+
"index.d.ts",
|
|
22
|
+
"bin/deltabox.js",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"optionalDependencies": {
|
|
26
|
+
"deltabox-lite-darwin-arm64": "0.1.0",
|
|
27
|
+
"deltabox-lite-darwin-x64": "0.1.0",
|
|
28
|
+
"deltabox-lite-linux-arm64": "0.1.0",
|
|
29
|
+
"deltabox-lite-linux-x64": "0.1.0"
|
|
30
|
+
}
|
|
31
|
+
}
|