@geminixiang/mikan 1.3.0 → 1.4.0-beta.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/CHANGELOG.md +37 -0
- package/README.md +7 -8
- package/dist/adapters/commands/login.js +1 -1
- package/dist/adapters/commands/login.js.map +1 -1
- package/dist/adapters/commands/sandbox.js +2 -2
- package/dist/adapters/commands/sandbox.js.map +1 -1
- package/dist/cli/boot.js +1 -1
- package/dist/cli/boot.js.map +1 -1
- package/dist/cli/migrate.d.ts.map +1 -1
- package/dist/cli/migrate.js +3 -2
- package/dist/cli/migrate.js.map +1 -1
- package/dist/cli/onboard.d.ts.map +1 -1
- package/dist/cli/onboard.js +15 -13
- package/dist/cli/onboard.js.map +1 -1
- package/dist/cli/pm2-ecosystem.d.ts +1 -2
- package/dist/cli/pm2-ecosystem.d.ts.map +1 -1
- package/dist/cli/pm2-ecosystem.js +2 -3
- package/dist/cli/pm2-ecosystem.js.map +1 -1
- package/dist/env-manifest.d.ts.map +1 -1
- package/dist/env-manifest.js +11 -0
- package/dist/env-manifest.js.map +1 -1
- package/dist/harness/execution-resolver.d.ts +3 -2
- package/dist/harness/execution-resolver.d.ts.map +1 -1
- package/dist/harness/execution-resolver.js +12 -10
- package/dist/harness/execution-resolver.js.map +1 -1
- package/dist/harness/prompt.d.ts.map +1 -1
- package/dist/harness/prompt.js +3 -2
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +37 -62
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/session.js +1 -1
- package/dist/harness/session.js.map +1 -1
- package/dist/harness/tools/attach.d.ts +3 -2
- package/dist/harness/tools/attach.d.ts.map +1 -1
- package/dist/harness/tools/attach.js +9 -2
- package/dist/harness/tools/attach.js.map +1 -1
- package/dist/harness/tools/index.d.ts +3 -2
- package/dist/harness/tools/index.d.ts.map +1 -1
- package/dist/harness/tools/index.js +6 -4
- package/dist/harness/tools/index.js.map +1 -1
- package/dist/harness/tools/jev-browser.d.ts +2 -2
- package/dist/harness/tools/jev-browser.d.ts.map +1 -1
- package/dist/harness/tools/jev-browser.js +41 -33
- package/dist/harness/tools/jev-browser.js.map +1 -1
- package/dist/harness/tools/sandbox.js +2 -2
- package/dist/harness/tools/sandbox.js.map +1 -1
- package/dist/harness/tools/types.d.ts +4 -0
- package/dist/harness/tools/types.d.ts.map +1 -1
- package/dist/harness/tools/types.js.map +1 -1
- package/dist/harness/tools/web-fetch.d.ts +6 -0
- package/dist/harness/tools/web-fetch.d.ts.map +1 -0
- package/dist/harness/tools/web-fetch.js +136 -0
- package/dist/harness/tools/web-fetch.js.map +1 -0
- package/dist/harness/types.d.ts +4 -3
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/main.js +10 -24
- package/dist/main.js.map +1 -1
- package/dist/migrations/index.js +2 -2
- package/dist/migrations/index.js.map +1 -1
- package/dist/package-version.d.ts +2 -0
- package/dist/package-version.d.ts.map +1 -0
- package/dist/package-version.js +19 -0
- package/dist/package-version.js.map +1 -0
- package/dist/sandbox/container.d.ts +3 -17
- package/dist/sandbox/container.d.ts.map +1 -1
- package/dist/sandbox/container.js +108 -129
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sandbox/engine.d.ts +4 -0
- package/dist/sandbox/engine.d.ts.map +1 -0
- package/dist/sandbox/engine.js +30 -0
- package/dist/sandbox/engine.js.map +1 -0
- package/dist/sandbox/host.d.ts +1 -10
- package/dist/sandbox/host.d.ts.map +1 -1
- package/dist/sandbox/host.js +2 -79
- package/dist/sandbox/host.js.map +1 -1
- package/dist/sandbox/provisioner.d.ts +15 -1
- package/dist/sandbox/provisioner.d.ts.map +1 -1
- package/dist/sandbox/provisioner.js +159 -111
- package/dist/sandbox/provisioner.js.map +1 -1
- package/dist/sandbox/published-image.d.ts +3 -0
- package/dist/sandbox/published-image.d.ts.map +1 -0
- package/dist/sandbox/published-image.js +9 -0
- package/dist/sandbox/published-image.js.map +1 -0
- package/dist/sandbox/registry.d.ts +5 -3
- package/dist/sandbox/registry.d.ts.map +1 -1
- package/dist/sandbox/registry.js +36 -27
- package/dist/sandbox/registry.js.map +1 -1
- package/dist/sandbox/types.d.ts +14 -22
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/sandbox/utils.d.ts +0 -15
- package/dist/sandbox/utils.d.ts.map +1 -1
- package/dist/sandbox/utils.js +0 -72
- package/dist/sandbox/utils.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vault/index.js +1 -1
- package/dist/vault/index.js.map +1 -1
- package/package.json +3 -1
- package/dist/harness/execution-env.d.ts +0 -4
- package/dist/harness/execution-env.d.ts.map +0 -1
- package/dist/harness/execution-env.js +0 -322
- package/dist/harness/execution-env.js.map +0 -1
|
@@ -1,322 +0,0 @@
|
|
|
1
|
-
import { randomBytes } from "node:crypto";
|
|
2
|
-
import { posix } from "node:path";
|
|
3
|
-
import { ExecutionError, FileError, LineScanner, err, ok, } from "@earendil-works/pi-durable/env";
|
|
4
|
-
import { NodeExecutionEnv } from "@earendil-works/pi-durable/env/node";
|
|
5
|
-
import { execAppendFile, execWriteFile, shellEscape } from "../sandbox/utils.js";
|
|
6
|
-
import { errorMessage } from "../unknown-values.js";
|
|
7
|
-
const SPILL_DIR = ".mikan/bash-output";
|
|
8
|
-
const READ_REGULAR_FILE = [
|
|
9
|
-
'if [ "$2" = 1 ] && [ -L "$1" ]; then echo link;',
|
|
10
|
-
'elif [ -d "$1" ]; then echo directory;',
|
|
11
|
-
'elif [ -f "$1" ]; then echo "file $(date -r "$1" +%s)"; base64 < "$1";',
|
|
12
|
-
'elif [ -e "$1" ]; then echo other; else echo missing; fi',
|
|
13
|
-
].join(" ");
|
|
14
|
-
export function createSandboxExecutionEnv(executor, sandboxType, runtimeWorkspaceRoot) {
|
|
15
|
-
if (sandboxType === "host") {
|
|
16
|
-
return new NodeExecutionEnv({ cwd: runtimeWorkspaceRoot });
|
|
17
|
-
}
|
|
18
|
-
return new ShellExecutionEnv(executor, runtimeWorkspaceRoot);
|
|
19
|
-
}
|
|
20
|
-
class ShellExecutionEnv {
|
|
21
|
-
constructor(executor, runtimeWorkspaceRoot) {
|
|
22
|
-
this.executor = executor;
|
|
23
|
-
this.id = `mikan-sandbox:${randomBytes(8).toString("hex")}`;
|
|
24
|
-
this.cwd = runtimeWorkspaceRoot;
|
|
25
|
-
}
|
|
26
|
-
async absolutePath(path, _context) {
|
|
27
|
-
return ok(posix.isAbsolute(path) ? posix.normalize(path) : posix.resolve(this.cwd, path));
|
|
28
|
-
}
|
|
29
|
-
async joinPath(parts, _context) {
|
|
30
|
-
return ok(posix.join(...parts));
|
|
31
|
-
}
|
|
32
|
-
readTextFile(path, context) {
|
|
33
|
-
return this.fileOp(() => this.executor.readFile(path, this.execOptions(context)));
|
|
34
|
-
}
|
|
35
|
-
openTextLineReader(path, context) {
|
|
36
|
-
return this.fileOp(async () => {
|
|
37
|
-
const content = await this.executor.readFile(path, this.execOptions(context));
|
|
38
|
-
return new ShellTextLineReader(content);
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
async readBinaryFile(path, context) {
|
|
42
|
-
return this.fileOp(async () => Buffer.from(await this.executor.readFileBase64(path, this.execOptions(context)), "base64"));
|
|
43
|
-
}
|
|
44
|
-
readTextLines(path, options, context) {
|
|
45
|
-
return this.fileOp(async () => {
|
|
46
|
-
const max = options?.maxLines;
|
|
47
|
-
const command = max === undefined
|
|
48
|
-
? `cat ${shellEscape(path)}`
|
|
49
|
-
: `head -n ${Math.max(0, Math.floor(max))} ${shellEscape(path)}`;
|
|
50
|
-
const { stdout } = await this.run(command, context);
|
|
51
|
-
const lines = stdout.split("\n");
|
|
52
|
-
if (lines.at(-1) === "")
|
|
53
|
-
lines.pop();
|
|
54
|
-
return lines;
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
writeFile(path, content, context) {
|
|
58
|
-
return this.fileOp(() => execWriteFile(this.executor, path, content, this.execOptions(context)));
|
|
59
|
-
}
|
|
60
|
-
appendFile(path, content, context) {
|
|
61
|
-
return this.fileOp(() => execAppendFile(this.executor, path, content, this.execOptions(context)));
|
|
62
|
-
}
|
|
63
|
-
truncateFile(path, size, context) {
|
|
64
|
-
return this.fileOp(async () => {
|
|
65
|
-
await this.run(`truncate -s ${Math.max(0, Math.floor(size))} ${shellEscape(path)}`, context);
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
flushFile(path, context) {
|
|
69
|
-
return this.fileOp(async () => {
|
|
70
|
-
await this.run(`sync ${shellEscape(path)}`, context);
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
renameFile(sourcePath, destinationPath, context) {
|
|
74
|
-
return this.fileOp(async () => {
|
|
75
|
-
await this.run(`mv -f ${shellEscape(sourcePath)} ${shellEscape(destinationPath)}`, context);
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
fileInfo(path, context) {
|
|
79
|
-
return this.fileOp(async () => {
|
|
80
|
-
const escaped = shellEscape(path);
|
|
81
|
-
const probe = await this.executor.exec(`if [ -L ${escaped} ]; then printf 'symlink'; elif [ -d ${escaped} ]; then printf 'directory'; ` +
|
|
82
|
-
`elif [ -f ${escaped} ]; then printf 'file'; else exit 1; fi`, this.execOptions(context));
|
|
83
|
-
if (probe.code !== 0)
|
|
84
|
-
throw new Error(`No such file or directory: ${path}`);
|
|
85
|
-
const kind = probe.stdout.trim();
|
|
86
|
-
let size = 0;
|
|
87
|
-
if (kind === "file") {
|
|
88
|
-
const stat = await this.executor.exec(`wc -c < ${escaped}`, this.execOptions(context));
|
|
89
|
-
if (stat.code === 0)
|
|
90
|
-
size = Number.parseInt(stat.stdout.trim(), 10) || 0;
|
|
91
|
-
}
|
|
92
|
-
let mtimeMs = 0;
|
|
93
|
-
const mtime = await this.executor.exec(`date -r ${escaped} +%s`, this.execOptions(context));
|
|
94
|
-
if (mtime.code === 0)
|
|
95
|
-
mtimeMs = (Number.parseInt(mtime.stdout.trim(), 10) || 0) * 1000;
|
|
96
|
-
return { name: posix.basename(path), path, kind, size, mtimeMs };
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
async openBinaryReader(path, options, context) {
|
|
100
|
-
return this.fileOp(async () => {
|
|
101
|
-
const { stdout } = await this.run(`sh -c ${shellEscape(READ_REGULAR_FILE)} _ ${shellEscape(path)} ${options?.noFollow ? 1 : 0}`, context);
|
|
102
|
-
const headerEnd = stdout.indexOf("\n");
|
|
103
|
-
const [kind, mtime] = stdout.slice(0, headerEnd).split(" ");
|
|
104
|
-
if (kind === "missing")
|
|
105
|
-
throw new FileError("not_found", `No such file: ${path}`, path);
|
|
106
|
-
if (kind === "directory")
|
|
107
|
-
throw new FileError("is_directory", `Is a directory: ${path}`, path);
|
|
108
|
-
if (kind !== "file")
|
|
109
|
-
throw new FileError("invalid", `Not a regular file: ${path}`, path);
|
|
110
|
-
const bytes = Buffer.from(stdout.slice(headerEnd + 1).replace(/\s+/g, ""), "base64");
|
|
111
|
-
return new SnapshotBinaryReader(bytes, {
|
|
112
|
-
name: posix.basename(path),
|
|
113
|
-
path,
|
|
114
|
-
kind: "file",
|
|
115
|
-
size: bytes.length,
|
|
116
|
-
mtimeMs: (Number.parseInt(mtime ?? "", 10) || 0) * 1000,
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
openDirReader(path, context) {
|
|
121
|
-
return this.fileOp(async () => {
|
|
122
|
-
const listed = await this.listDir(path, context);
|
|
123
|
-
if (!listed.ok)
|
|
124
|
-
throw listed.error;
|
|
125
|
-
return new SnapshotDirReader(listed.value);
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
async watch() {
|
|
129
|
-
return err(new FileError("not_supported", "The sandbox does not report file changes"));
|
|
130
|
-
}
|
|
131
|
-
async listDir(path, context) {
|
|
132
|
-
return this.fileOp(async () => {
|
|
133
|
-
const { stdout } = await this.run(`ls -A ${shellEscape(path)}`, context);
|
|
134
|
-
const names = stdout.split("\n").filter(Boolean).toSorted();
|
|
135
|
-
const entries = [];
|
|
136
|
-
for (const name of names) {
|
|
137
|
-
const child = posix.join(path, name);
|
|
138
|
-
const info = await this.fileInfo(child, context);
|
|
139
|
-
if (info.ok)
|
|
140
|
-
entries.push(info.value);
|
|
141
|
-
}
|
|
142
|
-
return entries;
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
canonicalPath(path, context) {
|
|
146
|
-
return this.fileOp(async () => (await this.run(`realpath ${shellEscape(path)}`, context)).stdout.trim());
|
|
147
|
-
}
|
|
148
|
-
async exists(path, context) {
|
|
149
|
-
try {
|
|
150
|
-
const result = await this.executor.exec(`test -e ${shellEscape(path)}`, this.execOptions(context));
|
|
151
|
-
return ok(result.code === 0);
|
|
152
|
-
}
|
|
153
|
-
catch (error) {
|
|
154
|
-
return err(toFileError(error));
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
createDir(path, options, context) {
|
|
158
|
-
return this.fileOp(async () => {
|
|
159
|
-
const flag = options?.recursive === false ? "" : "-p ";
|
|
160
|
-
await this.run(`mkdir ${flag}${shellEscape(path)}`, context);
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
remove(path, options, context) {
|
|
164
|
-
return this.fileOp(async () => {
|
|
165
|
-
const recursive = options?.recursive ? "-r" : "";
|
|
166
|
-
const force = options?.force ? "-f" : "";
|
|
167
|
-
await this.run(`rm ${recursive} ${force} ${shellEscape(path)}`, context);
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
createTempDir(prefix, context) {
|
|
171
|
-
return this.fileOp(async () => {
|
|
172
|
-
const template = prefix === undefined ? "" : shellEscape(`${prefix}XXXXXX`);
|
|
173
|
-
const { stdout } = await this.run(`mktemp -d ${template}`.trim(), context);
|
|
174
|
-
return stdout.trim();
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
createTempFile(options, context) {
|
|
178
|
-
return this.fileOp(async () => {
|
|
179
|
-
const template = options?.prefix === undefined && options?.suffix === undefined
|
|
180
|
-
? ""
|
|
181
|
-
: shellEscape(`${options?.prefix ?? ""}XXXXXX${options?.suffix ?? ""}`);
|
|
182
|
-
const { stdout } = await this.run(`mktemp ${template}`.trim(), context);
|
|
183
|
-
return stdout.trim();
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
async cleanup(_context) { }
|
|
187
|
-
async exec(command, options, context) {
|
|
188
|
-
try {
|
|
189
|
-
const shellCommand = typeof command === "string" ? command : command.map(shellEscape).join(" ");
|
|
190
|
-
const result = await this.executor.exec(shellCommand, {
|
|
191
|
-
cwd: options?.cwd || undefined,
|
|
192
|
-
timeout: options?.timeout || undefined,
|
|
193
|
-
signal: context.abortSignal,
|
|
194
|
-
});
|
|
195
|
-
const stdout = result.stdout.length > 0 && result.stderr.length > 0 ? `${result.stdout}\n` : result.stdout;
|
|
196
|
-
if (stdout.length > 0)
|
|
197
|
-
options?.onOutput?.(stdout, context, { stream: "stdout" });
|
|
198
|
-
if (result.stderr.length > 0) {
|
|
199
|
-
options?.onOutput?.(result.stderr, context, { stream: "stderr" });
|
|
200
|
-
}
|
|
201
|
-
const combined = `${stdout}${result.stderr}`;
|
|
202
|
-
return ok({ exitCode: result.code, spillPath: await this.spill(combined, options, context) });
|
|
203
|
-
}
|
|
204
|
-
catch (error) {
|
|
205
|
-
return err(toExecutionError(error, context));
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
async spill(output, options, context) {
|
|
209
|
-
const limits = options?.spill;
|
|
210
|
-
if (!limits)
|
|
211
|
-
return undefined;
|
|
212
|
-
const lines = output.split("\n").length;
|
|
213
|
-
if (Buffer.byteLength(output, "utf8") <= limits.afterBytes && lines <= limits.afterLines)
|
|
214
|
-
return undefined;
|
|
215
|
-
try {
|
|
216
|
-
const spillPath = posix.join(this.cwd, SPILL_DIR, `${randomBytes(8).toString("hex")}.log`);
|
|
217
|
-
await this.executor.writeFile(spillPath, output, this.execOptions(context));
|
|
218
|
-
return spillPath;
|
|
219
|
-
}
|
|
220
|
-
catch {
|
|
221
|
-
return undefined;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
execOptions(context) {
|
|
225
|
-
return { signal: context.abortSignal };
|
|
226
|
-
}
|
|
227
|
-
async run(command, context) {
|
|
228
|
-
const result = await this.executor.exec(command, this.execOptions(context));
|
|
229
|
-
if (result.code !== 0) {
|
|
230
|
-
throw new Error(result.stderr.trim() || `Command failed (${result.code}): ${command}`);
|
|
231
|
-
}
|
|
232
|
-
return result;
|
|
233
|
-
}
|
|
234
|
-
async fileOp(op) {
|
|
235
|
-
try {
|
|
236
|
-
return ok(await op());
|
|
237
|
-
}
|
|
238
|
-
catch (error) {
|
|
239
|
-
return err(toFileError(error));
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
class SnapshotBinaryReader {
|
|
244
|
-
constructor(bytes, metadata) {
|
|
245
|
-
this.bytes = bytes;
|
|
246
|
-
this.metadata = metadata;
|
|
247
|
-
}
|
|
248
|
-
async info(_context) {
|
|
249
|
-
return ok(this.metadata);
|
|
250
|
-
}
|
|
251
|
-
async read(offset, length, _context) {
|
|
252
|
-
return ok(this.bytes.subarray(offset, offset + length));
|
|
253
|
-
}
|
|
254
|
-
async scanLines(options, _context) {
|
|
255
|
-
const scanner = new LineScanner(options.startLine, options.endLine);
|
|
256
|
-
scanner.push(this.bytes);
|
|
257
|
-
return ok(scanner.finish());
|
|
258
|
-
}
|
|
259
|
-
async close(_context) { }
|
|
260
|
-
}
|
|
261
|
-
class SnapshotDirReader {
|
|
262
|
-
constructor(entries) {
|
|
263
|
-
this.entries = entries;
|
|
264
|
-
this.offset = 0;
|
|
265
|
-
}
|
|
266
|
-
async next(maxEntries, _context) {
|
|
267
|
-
const page = this.entries.slice(this.offset, this.offset + Math.max(1, maxEntries));
|
|
268
|
-
this.offset += page.length;
|
|
269
|
-
return ok({ entries: page, done: this.offset >= this.entries.length });
|
|
270
|
-
}
|
|
271
|
-
async close(_context) {
|
|
272
|
-
this.offset = this.entries.length;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
class ShellTextLineReader {
|
|
276
|
-
constructor(content) {
|
|
277
|
-
this.content = content;
|
|
278
|
-
this.offset = 0;
|
|
279
|
-
}
|
|
280
|
-
async readLine(_context) {
|
|
281
|
-
if (this.offset >= this.content.length)
|
|
282
|
-
return ok(undefined);
|
|
283
|
-
const newline = this.content.indexOf("\n", this.offset);
|
|
284
|
-
if (newline === -1) {
|
|
285
|
-
const text = this.content.slice(this.offset);
|
|
286
|
-
this.offset = this.content.length;
|
|
287
|
-
return ok({ text, terminated: false });
|
|
288
|
-
}
|
|
289
|
-
const text = this.content.slice(this.offset, newline);
|
|
290
|
-
this.offset = newline + 1;
|
|
291
|
-
return ok({ text, terminated: true });
|
|
292
|
-
}
|
|
293
|
-
async close(_context) {
|
|
294
|
-
this.offset = this.content.length;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
function toFileError(error) {
|
|
298
|
-
if (error instanceof FileError)
|
|
299
|
-
return error;
|
|
300
|
-
const message = errorMessage(error);
|
|
301
|
-
if (/aborted/i.test(message))
|
|
302
|
-
return new FileError("aborted", message);
|
|
303
|
-
if (/no such file|not found/i.test(message))
|
|
304
|
-
return new FileError("not_found", message);
|
|
305
|
-
if (/permission denied/i.test(message))
|
|
306
|
-
return new FileError("permission_denied", message);
|
|
307
|
-
if (/not a directory/i.test(message))
|
|
308
|
-
return new FileError("not_directory", message);
|
|
309
|
-
if (/is a directory/i.test(message))
|
|
310
|
-
return new FileError("is_directory", message);
|
|
311
|
-
return new FileError("unknown", message, undefined, error instanceof Error ? error : undefined);
|
|
312
|
-
}
|
|
313
|
-
function toExecutionError(error, context) {
|
|
314
|
-
const message = errorMessage(error);
|
|
315
|
-
if (context.abortSignal?.aborted || /aborted/i.test(message)) {
|
|
316
|
-
return new ExecutionError("aborted", message);
|
|
317
|
-
}
|
|
318
|
-
if (/timed out/i.test(message))
|
|
319
|
-
return new ExecutionError("timeout", message);
|
|
320
|
-
return new ExecutionError("unknown", message, error instanceof Error ? error : undefined);
|
|
321
|
-
}
|
|
322
|
-
//# sourceMappingURL=execution-env.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"execution-env.js","sourceRoot":"","sources":["../../src/harness/execution-env.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { posix } from \"node:path\";\nimport type { Context } from \"@earendil-works/chord\";\nimport {\n ExecutionError,\n FileError,\n LineScanner,\n err,\n ok,\n type BinaryReader,\n type DirReader,\n type ExecutionEnv,\n type FileInfo,\n type FileKind,\n type FileWatcher,\n type LineScan,\n type Result,\n type ShellExecOptions,\n type ShellExecResult,\n type TextLine,\n type TextLineReader,\n} from \"@earendil-works/pi-durable/env\";\nimport { NodeExecutionEnv } from \"@earendil-works/pi-durable/env/node\";\nimport type { Executor, SandboxConfig } from \"../sandbox/types.js\";\nimport { execAppendFile, execWriteFile, shellEscape } from \"../sandbox/utils.js\";\nimport { errorMessage } from \"../unknown-values.js\";\n\nconst SPILL_DIR = \".mikan/bash-output\";\n\nconst READ_REGULAR_FILE = [\n 'if [ \"$2\" = 1 ] && [ -L \"$1\" ]; then echo link;',\n 'elif [ -d \"$1\" ]; then echo directory;',\n 'elif [ -f \"$1\" ]; then echo \"file $(date -r \"$1\" +%s)\"; base64 < \"$1\";',\n 'elif [ -e \"$1\" ]; then echo other; else echo missing; fi',\n].join(\" \");\n\nexport function createSandboxExecutionEnv(\n executor: Executor,\n sandboxType: SandboxConfig[\"type\"],\n runtimeWorkspaceRoot: string,\n): ExecutionEnv {\n if (sandboxType === \"host\") {\n return new NodeExecutionEnv({ cwd: runtimeWorkspaceRoot });\n }\n return new ShellExecutionEnv(executor, runtimeWorkspaceRoot);\n}\n\nclass ShellExecutionEnv implements ExecutionEnv {\n readonly id: string;\n readonly cwd: string;\n\n constructor(\n private readonly executor: Executor,\n runtimeWorkspaceRoot: string,\n ) {\n this.id = `mikan-sandbox:${randomBytes(8).toString(\"hex\")}`;\n this.cwd = runtimeWorkspaceRoot;\n }\n\n async absolutePath(path: string, _context: Context): Promise<Result<string, FileError>> {\n return ok(posix.isAbsolute(path) ? posix.normalize(path) : posix.resolve(this.cwd, path));\n }\n\n async joinPath(parts: string[], _context: Context): Promise<Result<string, FileError>> {\n return ok(posix.join(...parts));\n }\n\n readTextFile(path: string, context: Context): Promise<Result<string, FileError>> {\n return this.fileOp(() => this.executor.readFile(path, this.execOptions(context)));\n }\n\n openTextLineReader(path: string, context: Context): Promise<Result<TextLineReader, FileError>> {\n return this.fileOp(async () => {\n const content = await this.executor.readFile(path, this.execOptions(context));\n return new ShellTextLineReader(content);\n });\n }\n\n async readBinaryFile(path: string, context: Context): Promise<Result<Uint8Array, FileError>> {\n return this.fileOp(async () =>\n Buffer.from(await this.executor.readFileBase64(path, this.execOptions(context)), \"base64\"),\n );\n }\n\n readTextLines(\n path: string,\n options: { maxLines?: number } | undefined,\n context: Context,\n ): Promise<Result<string[], FileError>> {\n return this.fileOp(async () => {\n const max = options?.maxLines;\n const command =\n max === undefined\n ? `cat ${shellEscape(path)}`\n : `head -n ${Math.max(0, Math.floor(max))} ${shellEscape(path)}`;\n const { stdout } = await this.run(command, context);\n const lines = stdout.split(\"\\n\");\n if (lines.at(-1) === \"\") lines.pop();\n return lines;\n });\n }\n\n writeFile(\n path: string,\n content: string | Uint8Array,\n context: Context,\n ): Promise<Result<void, FileError>> {\n return this.fileOp(() =>\n execWriteFile(this.executor, path, content, this.execOptions(context)),\n );\n }\n\n appendFile(\n path: string,\n content: string | Uint8Array,\n context: Context,\n ): Promise<Result<void, FileError>> {\n return this.fileOp(() =>\n execAppendFile(this.executor, path, content, this.execOptions(context)),\n );\n }\n\n truncateFile(path: string, size: number, context: Context): Promise<Result<void, FileError>> {\n return this.fileOp(async () => {\n await this.run(`truncate -s ${Math.max(0, Math.floor(size))} ${shellEscape(path)}`, context);\n });\n }\n\n flushFile(path: string, context: Context): Promise<Result<void, FileError>> {\n return this.fileOp(async () => {\n await this.run(`sync ${shellEscape(path)}`, context);\n });\n }\n\n renameFile(\n sourcePath: string,\n destinationPath: string,\n context: Context,\n ): Promise<Result<void, FileError>> {\n return this.fileOp(async () => {\n await this.run(`mv -f ${shellEscape(sourcePath)} ${shellEscape(destinationPath)}`, context);\n });\n }\n\n fileInfo(path: string, context: Context): Promise<Result<FileInfo, FileError>> {\n return this.fileOp(async () => {\n const escaped = shellEscape(path);\n const probe = await this.executor.exec(\n `if [ -L ${escaped} ]; then printf 'symlink'; elif [ -d ${escaped} ]; then printf 'directory'; ` +\n `elif [ -f ${escaped} ]; then printf 'file'; else exit 1; fi`,\n this.execOptions(context),\n );\n if (probe.code !== 0) throw new Error(`No such file or directory: ${path}`);\n const kind = probe.stdout.trim() as FileKind;\n let size = 0;\n if (kind === \"file\") {\n const stat = await this.executor.exec(`wc -c < ${escaped}`, this.execOptions(context));\n if (stat.code === 0) size = Number.parseInt(stat.stdout.trim(), 10) || 0;\n }\n let mtimeMs = 0;\n const mtime = await this.executor.exec(`date -r ${escaped} +%s`, this.execOptions(context));\n if (mtime.code === 0) mtimeMs = (Number.parseInt(mtime.stdout.trim(), 10) || 0) * 1000;\n return { name: posix.basename(path), path, kind, size, mtimeMs };\n });\n }\n\n async openBinaryReader(\n path: string,\n options: { noFollow?: boolean } | undefined,\n context: Context,\n ): Promise<Result<BinaryReader, FileError>> {\n return this.fileOp(async () => {\n const { stdout } = await this.run(\n `sh -c ${shellEscape(READ_REGULAR_FILE)} _ ${shellEscape(path)} ${options?.noFollow ? 1 : 0}`,\n context,\n );\n const headerEnd = stdout.indexOf(\"\\n\");\n const [kind, mtime] = stdout.slice(0, headerEnd).split(\" \");\n if (kind === \"missing\") throw new FileError(\"not_found\", `No such file: ${path}`, path);\n if (kind === \"directory\")\n throw new FileError(\"is_directory\", `Is a directory: ${path}`, path);\n if (kind !== \"file\") throw new FileError(\"invalid\", `Not a regular file: ${path}`, path);\n const bytes = Buffer.from(stdout.slice(headerEnd + 1).replace(/\\s+/g, \"\"), \"base64\");\n return new SnapshotBinaryReader(bytes, {\n name: posix.basename(path),\n path,\n kind: \"file\",\n size: bytes.length,\n mtimeMs: (Number.parseInt(mtime ?? \"\", 10) || 0) * 1000,\n });\n });\n }\n\n openDirReader(path: string, context: Context): Promise<Result<DirReader, FileError>> {\n return this.fileOp(async () => {\n const listed = await this.listDir(path, context);\n if (!listed.ok) throw listed.error;\n return new SnapshotDirReader(listed.value);\n });\n }\n\n async watch(): Promise<Result<FileWatcher, FileError>> {\n return err(new FileError(\"not_supported\", \"The sandbox does not report file changes\"));\n }\n\n async listDir(path: string, context: Context): Promise<Result<FileInfo[], FileError>> {\n return this.fileOp(async () => {\n const { stdout } = await this.run(`ls -A ${shellEscape(path)}`, context);\n const names = stdout.split(\"\\n\").filter(Boolean).toSorted();\n const entries: FileInfo[] = [];\n for (const name of names) {\n const child = posix.join(path, name);\n const info = await this.fileInfo(child, context);\n if (info.ok) entries.push(info.value);\n }\n return entries;\n });\n }\n\n canonicalPath(path: string, context: Context): Promise<Result<string, FileError>> {\n return this.fileOp(async () =>\n (await this.run(`realpath ${shellEscape(path)}`, context)).stdout.trim(),\n );\n }\n\n async exists(path: string, context: Context): Promise<Result<boolean, FileError>> {\n try {\n const result = await this.executor.exec(\n `test -e ${shellEscape(path)}`,\n this.execOptions(context),\n );\n return ok(result.code === 0);\n } catch (error) {\n return err(toFileError(error));\n }\n }\n\n createDir(\n path: string,\n options: { recursive?: boolean } | undefined,\n context: Context,\n ): Promise<Result<void, FileError>> {\n return this.fileOp(async () => {\n const flag = options?.recursive === false ? \"\" : \"-p \";\n await this.run(`mkdir ${flag}${shellEscape(path)}`, context);\n });\n }\n\n remove(\n path: string,\n options: { recursive?: boolean; force?: boolean } | undefined,\n context: Context,\n ): Promise<Result<void, FileError>> {\n return this.fileOp(async () => {\n const recursive = options?.recursive ? \"-r\" : \"\";\n const force = options?.force ? \"-f\" : \"\";\n await this.run(`rm ${recursive} ${force} ${shellEscape(path)}`, context);\n });\n }\n\n createTempDir(prefix: string | undefined, context: Context): Promise<Result<string, FileError>> {\n return this.fileOp(async () => {\n const template = prefix === undefined ? \"\" : shellEscape(`${prefix}XXXXXX`);\n const { stdout } = await this.run(`mktemp -d ${template}`.trim(), context);\n return stdout.trim();\n });\n }\n\n createTempFile(\n options: { prefix?: string; suffix?: string } | undefined,\n context: Context,\n ): Promise<Result<string, FileError>> {\n return this.fileOp(async () => {\n const template =\n options?.prefix === undefined && options?.suffix === undefined\n ? \"\"\n : shellEscape(`${options?.prefix ?? \"\"}XXXXXX${options?.suffix ?? \"\"}`);\n const { stdout } = await this.run(`mktemp ${template}`.trim(), context);\n return stdout.trim();\n });\n }\n\n async cleanup(_context: Context): Promise<void> {}\n\n async exec(\n command: string | readonly string[],\n options: ShellExecOptions | undefined,\n context: Context,\n ): Promise<Result<ShellExecResult, ExecutionError>> {\n try {\n const shellCommand =\n typeof command === \"string\" ? command : command.map(shellEscape).join(\" \");\n const result = await this.executor.exec(shellCommand, {\n cwd: options?.cwd || undefined,\n timeout: options?.timeout || undefined,\n signal: context.abortSignal,\n });\n const stdout =\n result.stdout.length > 0 && result.stderr.length > 0 ? `${result.stdout}\\n` : result.stdout;\n if (stdout.length > 0) options?.onOutput?.(stdout, context, { stream: \"stdout\" });\n if (result.stderr.length > 0) {\n options?.onOutput?.(result.stderr, context, { stream: \"stderr\" });\n }\n const combined = `${stdout}${result.stderr}`;\n return ok({ exitCode: result.code, spillPath: await this.spill(combined, options, context) });\n } catch (error) {\n return err(toExecutionError(error, context));\n }\n }\n\n private async spill(\n output: string,\n options: ShellExecOptions | undefined,\n context: Context,\n ): Promise<string | undefined> {\n const limits = options?.spill;\n if (!limits) return undefined;\n const lines = output.split(\"\\n\").length;\n if (Buffer.byteLength(output, \"utf8\") <= limits.afterBytes && lines <= limits.afterLines)\n return undefined;\n try {\n const spillPath = posix.join(this.cwd, SPILL_DIR, `${randomBytes(8).toString(\"hex\")}.log`);\n await this.executor.writeFile(spillPath, output, this.execOptions(context));\n return spillPath;\n } catch {\n return undefined;\n }\n }\n\n private execOptions(context: Context): { signal: AbortSignal | undefined } {\n return { signal: context.abortSignal };\n }\n\n private async run(\n command: string,\n context: Context,\n ): Promise<{ stdout: string; stderr: string }> {\n const result = await this.executor.exec(command, this.execOptions(context));\n if (result.code !== 0) {\n throw new Error(result.stderr.trim() || `Command failed (${result.code}): ${command}`);\n }\n return result;\n }\n\n private async fileOp<T>(op: () => Promise<T>): Promise<Result<T, FileError>> {\n try {\n return ok(await op());\n } catch (error) {\n return err(toFileError(error));\n }\n }\n}\n\nclass SnapshotBinaryReader implements BinaryReader {\n constructor(\n private readonly bytes: Uint8Array,\n private readonly metadata: FileInfo,\n ) {}\n\n async info(_context: Context): Promise<Result<FileInfo, FileError>> {\n return ok(this.metadata);\n }\n\n async read(\n offset: number,\n length: number,\n _context: Context,\n ): Promise<Result<Uint8Array, FileError>> {\n return ok(this.bytes.subarray(offset, offset + length));\n }\n\n async scanLines(\n options: { startLine: number; endLine?: number },\n _context: Context,\n ): Promise<Result<LineScan, FileError>> {\n const scanner = new LineScanner(options.startLine, options.endLine);\n scanner.push(this.bytes);\n return ok(scanner.finish());\n }\n\n async close(_context: Context): Promise<void> {}\n}\n\nclass SnapshotDirReader implements DirReader {\n private offset = 0;\n\n constructor(private readonly entries: FileInfo[]) {}\n\n async next(\n maxEntries: number,\n _context: Context,\n ): Promise<Result<{ entries: FileInfo[]; done: boolean }, FileError>> {\n const page = this.entries.slice(this.offset, this.offset + Math.max(1, maxEntries));\n this.offset += page.length;\n return ok({ entries: page, done: this.offset >= this.entries.length });\n }\n\n async close(_context: Context): Promise<void> {\n this.offset = this.entries.length;\n }\n}\n\nclass ShellTextLineReader implements TextLineReader {\n private offset = 0;\n\n constructor(private readonly content: string) {}\n\n async readLine(_context: Context): Promise<Result<TextLine | undefined, FileError>> {\n if (this.offset >= this.content.length) return ok(undefined);\n const newline = this.content.indexOf(\"\\n\", this.offset);\n if (newline === -1) {\n const text = this.content.slice(this.offset);\n this.offset = this.content.length;\n return ok({ text, terminated: false });\n }\n const text = this.content.slice(this.offset, newline);\n this.offset = newline + 1;\n return ok({ text, terminated: true });\n }\n\n async close(_context: Context): Promise<void> {\n this.offset = this.content.length;\n }\n}\n\nfunction toFileError(error: unknown): FileError {\n if (error instanceof FileError) return error;\n const message = errorMessage(error);\n if (/aborted/i.test(message)) return new FileError(\"aborted\", message);\n if (/no such file|not found/i.test(message)) return new FileError(\"not_found\", message);\n if (/permission denied/i.test(message)) return new FileError(\"permission_denied\", message);\n if (/not a directory/i.test(message)) return new FileError(\"not_directory\", message);\n if (/is a directory/i.test(message)) return new FileError(\"is_directory\", message);\n return new FileError(\"unknown\", message, undefined, error instanceof Error ? error : undefined);\n}\n\nfunction toExecutionError(error: unknown, context: Context): ExecutionError {\n const message = errorMessage(error);\n if (context.abortSignal?.aborted || /aborted/i.test(message)) {\n return new ExecutionError(\"aborted\", message);\n }\n if (/timed out/i.test(message)) return new ExecutionError(\"timeout\", message);\n return new ExecutionError(\"unknown\", message, error instanceof Error ? error : undefined);\n}\n"]}
|