poe-code 8.0.0 → 9.0.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/dist/cli/commands/harness.js +12 -3
- package/dist/cli/commands/harness.js.map +1 -1
- package/dist/index.js +1515 -712
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/package.json +15 -2
- package/packages/safejs/dist/chunks/chunk-4YIDX44G.js +40 -0
- package/packages/safejs/dist/chunks/chunk-4YIDX44G.js.map +7 -0
- package/packages/safejs/dist/chunks/chunk-55ZK3CR7.js +7802 -0
- package/packages/safejs/dist/chunks/chunk-55ZK3CR7.js.map +7 -0
- package/packages/safejs/dist/chunks/chunk-GQBEEFVQ.js +28798 -0
- package/packages/safejs/dist/chunks/chunk-GQBEEFVQ.js.map +7 -0
- package/packages/safejs/dist/chunks/chunk-NI4WFFTL.js +5701 -0
- package/packages/safejs/dist/chunks/chunk-NI4WFFTL.js.map +7 -0
- package/packages/safejs/dist/chunks/inMemory-RLZ4QGDZ.js +48 -0
- package/packages/safejs/dist/chunks/inMemory-RLZ4QGDZ.js.map +7 -0
- package/packages/safejs/dist/chunks/server-3SNT3RE2.js +12518 -0
- package/packages/safejs/dist/chunks/server-3SNT3RE2.js.map +7 -0
- package/packages/safejs/dist/chunks/types-BTF37PZ6.js +348 -0
- package/packages/safejs/dist/chunks/types-BTF37PZ6.js.map +7 -0
- package/packages/safejs/dist/cli.d.ts +2 -0
- package/packages/safejs/dist/cli.js +550 -491
- package/packages/safejs/dist/cli.js.map +7 -0
- package/packages/safejs/dist/core.js +14 -4
- package/packages/safejs/dist/core.js.map +7 -0
- package/packages/safejs/dist/index.d.ts +3 -0
- package/packages/safejs/dist/index.js +791 -30
- package/packages/safejs/dist/index.js.map +7 -0
- package/packages/safejs/dist/interp/host-bridge.d.ts +2 -0
- package/packages/safejs/dist/interp/host-bridge.js +20 -9
- package/packages/safejs/dist/interp/host-call.d.ts +5 -0
- package/packages/safejs/dist/interp/host-call.js +48 -3
- package/packages/safejs/dist/interp/resources.d.ts +7 -0
- package/packages/safejs/dist/interp/resources.js +36 -0
- package/packages/safejs/dist/modules/mcp-transport.d.ts +26 -0
- package/packages/safejs/dist/modules/mcp-transport.js +259 -0
- package/packages/safejs/dist/modules/mcp.d.ts +15 -1
- package/packages/safejs/dist/modules/mcp.js +107 -0
- package/packages/safejs/dist/run.js +6 -3
- package/packages/safejs/dist/snapshot/dump-format.d.ts +1 -1
- package/packages/safejs/dist/snapshot/dump-format.js +1 -1
- package/packages/safejs/dist/snapshot/replay-data.d.ts +1 -0
- package/packages/safejs/dist/snapshot/replay-data.js +3 -1
- package/packages/safejs/dist/snapshot/replay-inputs.d.ts +2 -2
- package/packages/safejs/dist/snapshot/replay-inputs.js +2 -1
|
@@ -1,569 +1,628 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
countLineBreaks,
|
|
4
|
+
createBrokenPipeState,
|
|
5
|
+
createLintModulesFromRuntimeRegistry,
|
|
6
|
+
createSafeOutputStream,
|
|
7
|
+
extractBlock,
|
|
8
|
+
formatInterpreterError,
|
|
9
|
+
makeAgentModule,
|
|
10
|
+
makeFailModule,
|
|
11
|
+
makeFsModule,
|
|
12
|
+
makeHarnessModule,
|
|
13
|
+
makeLogModule,
|
|
14
|
+
makeMcpModule,
|
|
15
|
+
makeMetricModule,
|
|
16
|
+
parseMcpConfig,
|
|
17
|
+
splitFrontmatter,
|
|
18
|
+
withBrokenPipeGuard
|
|
19
|
+
} from "./chunks/chunk-55ZK3CR7.js";
|
|
20
|
+
import {
|
|
21
|
+
Budget,
|
|
22
|
+
SandboxError,
|
|
23
|
+
dump,
|
|
24
|
+
dumpCurrent,
|
|
25
|
+
hasOwnErrorCode,
|
|
26
|
+
lint,
|
|
27
|
+
parseModule,
|
|
28
|
+
replaceErrorStack,
|
|
29
|
+
restore,
|
|
30
|
+
run
|
|
31
|
+
} from "./chunks/chunk-GQBEEFVQ.js";
|
|
32
|
+
import "./chunks/chunk-4YIDX44G.js";
|
|
33
|
+
|
|
34
|
+
// packages/safejs/src/cli.ts
|
|
2
35
|
import { mkdir, readFile, realpath, stat, writeFile } from "node:fs/promises";
|
|
3
36
|
import path, { dirname, extname } from "node:path";
|
|
4
37
|
import { formatWithOptions } from "node:util";
|
|
5
38
|
import { fileURLToPath } from "node:url";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
import { run } from "./run.js";
|
|
24
|
-
import { dump, dumpCurrent } from "./snapshot/dump.js";
|
|
25
|
-
const EXIT_RUNTIME = 1;
|
|
26
|
-
const EXIT_PARSE = 2;
|
|
27
|
-
const EXIT_BUDGET = 3;
|
|
28
|
-
const EXIT_SIGINT = 130;
|
|
29
|
-
export async function runCli(argv, options = {}) {
|
|
30
|
-
const brokenPipe = createBrokenPipeState();
|
|
31
|
-
const stdout = createSafeOutputStream(options.stdout ?? process.stdout, brokenPipe);
|
|
32
|
-
const stderr = createSafeOutputStream(options.stderr ?? process.stderr, brokenPipe);
|
|
33
|
-
return withBrokenPipeGuard([options.stdout ?? process.stdout, options.stderr ?? process.stderr], brokenPipe, async () => {
|
|
34
|
-
try {
|
|
35
|
-
if (argv.includes("--help") || argv.includes("-h")) {
|
|
36
|
-
stdout.write(`${createUsage()}\n`);
|
|
37
|
-
return 0;
|
|
38
|
-
}
|
|
39
|
-
const parsed = parseArgs(argv);
|
|
40
|
-
if (parsed.filepath === undefined) {
|
|
41
|
-
stderr.write(`${createUsage()}\n`);
|
|
42
|
-
return brokenPipe.closed ? 0 : EXIT_RUNTIME;
|
|
43
|
-
}
|
|
44
|
-
const cwd = options.cwd ?? readCurrentWorkingDirectory();
|
|
45
|
-
const filepath = path.resolve(cwd, parsed.filepath);
|
|
46
|
-
await assertHarnessFile({
|
|
47
|
-
displayPath: parsed.filepath,
|
|
48
|
-
filepath,
|
|
49
|
-
statFile: options.stat ?? stat
|
|
50
|
-
});
|
|
51
|
-
return await runScriptFile(filepath, parsed, {
|
|
52
|
-
cwd,
|
|
53
|
-
modulesFor: options.modulesFor,
|
|
54
|
-
process: options.process ?? process,
|
|
55
|
-
readFile: options.readFile ?? readFile,
|
|
56
|
-
brokenPipe,
|
|
57
|
-
stderr,
|
|
58
|
-
stdout,
|
|
59
|
-
writeFile: options.writeFile ?? writeFile
|
|
60
|
-
});
|
|
39
|
+
var EXIT_RUNTIME = 1;
|
|
40
|
+
var EXIT_PARSE = 2;
|
|
41
|
+
var EXIT_BUDGET = 3;
|
|
42
|
+
var EXIT_SIGINT = 130;
|
|
43
|
+
async function runCli(argv, options = {}) {
|
|
44
|
+
const brokenPipe = createBrokenPipeState();
|
|
45
|
+
const stdout = createSafeOutputStream(options.stdout ?? process.stdout, brokenPipe);
|
|
46
|
+
const stderr = createSafeOutputStream(options.stderr ?? process.stderr, brokenPipe);
|
|
47
|
+
return withBrokenPipeGuard(
|
|
48
|
+
[options.stdout ?? process.stdout, options.stderr ?? process.stderr],
|
|
49
|
+
brokenPipe,
|
|
50
|
+
async () => {
|
|
51
|
+
try {
|
|
52
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
53
|
+
stdout.write(`${createUsage()}
|
|
54
|
+
`);
|
|
55
|
+
return 0;
|
|
61
56
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return brokenPipe.closed
|
|
68
|
-
? 0
|
|
69
|
-
: error instanceof CliExitError
|
|
70
|
-
? error.exitCode
|
|
71
|
-
: exitCodeForError(error);
|
|
57
|
+
const parsed = parseArgs(argv);
|
|
58
|
+
if (parsed.filepath === void 0) {
|
|
59
|
+
stderr.write(`${createUsage()}
|
|
60
|
+
`);
|
|
61
|
+
return brokenPipe.closed ? 0 : EXIT_RUNTIME;
|
|
72
62
|
}
|
|
73
|
-
|
|
63
|
+
const cwd = options.cwd ?? readCurrentWorkingDirectory();
|
|
64
|
+
const filepath = path.resolve(cwd, parsed.filepath);
|
|
65
|
+
await assertHarnessFile({
|
|
66
|
+
displayPath: parsed.filepath,
|
|
67
|
+
filepath,
|
|
68
|
+
statFile: options.stat ?? stat
|
|
69
|
+
});
|
|
70
|
+
return await runScriptFile(filepath, parsed, {
|
|
71
|
+
cwd,
|
|
72
|
+
mcp: options.mcp,
|
|
73
|
+
modulesFor: options.modulesFor,
|
|
74
|
+
process: options.process ?? process,
|
|
75
|
+
readFile: options.readFile ?? readFile,
|
|
76
|
+
brokenPipe,
|
|
77
|
+
stderr,
|
|
78
|
+
stdout,
|
|
79
|
+
writeFile: options.writeFile ?? writeFile
|
|
80
|
+
});
|
|
81
|
+
} catch (error) {
|
|
82
|
+
if (brokenPipe.closed) {
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
stderr.write(`${readErrorMessage(error)}
|
|
86
|
+
`);
|
|
87
|
+
return brokenPipe.closed ? 0 : error instanceof CliExitError ? error.exitCode : exitCodeForError(error);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
);
|
|
74
91
|
}
|
|
75
92
|
function readCurrentWorkingDirectory() {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
93
|
+
try {
|
|
94
|
+
return process.cwd();
|
|
95
|
+
} catch (error) {
|
|
96
|
+
throw new Error(`Unable to resolve current working directory: ${readErrorMessage(error)}`);
|
|
97
|
+
}
|
|
82
98
|
}
|
|
83
99
|
function parseArgs(argv) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
|
|
100
|
+
const parsed = {
|
|
101
|
+
fix: false,
|
|
102
|
+
fs: false
|
|
103
|
+
};
|
|
104
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
105
|
+
const arg = argv[index];
|
|
106
|
+
if (arg === "--fix") {
|
|
107
|
+
parsed.fix = true;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (arg === "--fs") {
|
|
111
|
+
parsed.fs = true;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (arg === "--fs-root") {
|
|
115
|
+
parsed.fsRoot = readFlagValue(argv, index, arg);
|
|
116
|
+
index += 1;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (arg === "--mcp-config") {
|
|
120
|
+
parsed.mcpConfig = readFlagValue(argv, index, arg);
|
|
121
|
+
index += 1;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (arg === "--snapshot") {
|
|
125
|
+
parsed.snapshotPath = readFlagValue(argv, index, arg);
|
|
126
|
+
index += 1;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (arg === "--restore") {
|
|
130
|
+
parsed.restorePath = readFlagValue(argv, index, arg);
|
|
131
|
+
index += 1;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (arg === "--max-steps") {
|
|
135
|
+
parsed.maxSteps = readPositiveInteger(readFlagValue(argv, index, arg), arg);
|
|
136
|
+
index += 1;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (arg === "--data-size") {
|
|
140
|
+
parsed.dataSize = readPositiveInteger(readFlagValue(argv, index, arg), arg);
|
|
141
|
+
index += 1;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (arg.startsWith("-")) {
|
|
145
|
+
throw new CliExitError(`Unknown flag: ${arg}`, EXIT_RUNTIME);
|
|
146
|
+
}
|
|
147
|
+
if (parsed.filepath !== void 0) {
|
|
148
|
+
throw new CliExitError(`Unexpected argument: ${arg}`, EXIT_RUNTIME);
|
|
149
|
+
}
|
|
150
|
+
parsed.filepath = arg;
|
|
151
|
+
}
|
|
152
|
+
if (!parsed.fs && parsed.fsRoot !== void 0) {
|
|
153
|
+
throw new CliExitError(
|
|
154
|
+
"--fs-root requires --fs. Pass --fs to give the script a filesystem confined to that root, or drop --fs-root.",
|
|
155
|
+
EXIT_RUNTIME
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
return parsed;
|
|
135
159
|
}
|
|
136
160
|
function readFlagValue(argv, index, flag) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
161
|
+
const value = argv[index + 1];
|
|
162
|
+
if (value === void 0 || value.length === 0) {
|
|
163
|
+
throw new CliExitError(`Missing value for ${flag}`, EXIT_RUNTIME);
|
|
164
|
+
}
|
|
165
|
+
return value;
|
|
142
166
|
}
|
|
143
167
|
function readPositiveInteger(value, flag) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
168
|
+
const parsed = Number(value);
|
|
169
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
170
|
+
throw new CliExitError(`${flag} must be a positive integer`, EXIT_RUNTIME);
|
|
171
|
+
}
|
|
172
|
+
return parsed;
|
|
149
173
|
}
|
|
150
174
|
async function assertHarnessFile(input) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
175
|
+
let stats;
|
|
176
|
+
try {
|
|
177
|
+
stats = await input.statFile(input.filepath);
|
|
178
|
+
} catch (error) {
|
|
179
|
+
if (hasErrorCode(error, "ENOENT")) {
|
|
180
|
+
throw new CliExitError(`File not found: ${input.displayPath}`, EXIT_RUNTIME);
|
|
181
|
+
}
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
if (!stats.isFile()) {
|
|
185
|
+
throw new CliExitError(`Harness path must point to a file: ${input.displayPath}`, EXIT_RUNTIME);
|
|
186
|
+
}
|
|
164
187
|
}
|
|
165
188
|
async function runScriptFile(filepath, parsed, options) {
|
|
166
|
-
|
|
167
|
-
|
|
189
|
+
const loaded = loadExecutableSource(filepath, await options.readFile(filepath, "utf8"));
|
|
190
|
+
const meta = {
|
|
191
|
+
filepath,
|
|
192
|
+
kind: loaded.frontmatter.kind,
|
|
193
|
+
version: loaded.frontmatter.version
|
|
194
|
+
};
|
|
195
|
+
const runtime = createRuntime(loaded.frontmatter, meta, {
|
|
196
|
+
fs: parsed.fs ? { root: path.resolve(options.cwd, parsed.fsRoot ?? dirname(filepath)) } : void 0,
|
|
197
|
+
modulesFor: options.modulesFor,
|
|
198
|
+
stderr: options.stderr,
|
|
199
|
+
stdout: options.stdout
|
|
200
|
+
});
|
|
201
|
+
let mcp = options.mcp;
|
|
202
|
+
if (parsed.mcpConfig !== void 0) {
|
|
203
|
+
if (mcp !== void 0) throw new TypeError("Pass MCP options or --mcp-config, not both.");
|
|
204
|
+
const configPath = path.resolve(options.cwd, parsed.mcpConfig);
|
|
205
|
+
mcp = parseMcpConfig(await options.readFile(configPath, "utf8"), dirname(configPath));
|
|
206
|
+
}
|
|
207
|
+
if (mcp !== void 0) {
|
|
208
|
+
const registry = new Map(
|
|
209
|
+
runtime.registry instanceof Map ? runtime.registry : Object.entries(runtime.registry)
|
|
210
|
+
);
|
|
211
|
+
if (registry.has("mcp")) throw new TypeError("MCP is already registered by modulesFor.");
|
|
212
|
+
registry.set("mcp", makeMcpModule(mcp));
|
|
213
|
+
runtime.registry = registry;
|
|
214
|
+
}
|
|
215
|
+
const modules = excludeHarnessModule(runtime.registry, loaded.isRawScript);
|
|
216
|
+
let executableSource = loaded.executableSource;
|
|
217
|
+
const lintResult = parsed.fix ? lint(executableSource, {
|
|
218
|
+
allowedExportNames: ["schema"],
|
|
219
|
+
filename: filepath,
|
|
220
|
+
fix: true,
|
|
221
|
+
fixRanges: loaded.fixRanges,
|
|
222
|
+
frontmatterFields: Object.keys(loaded.frontmatter),
|
|
223
|
+
modules: createLintModulesFromRuntimeRegistry(modules)
|
|
224
|
+
}) : lint(executableSource, {
|
|
225
|
+
allowedExportNames: ["schema"],
|
|
226
|
+
filename: filepath,
|
|
227
|
+
frontmatterFields: Object.keys(loaded.frontmatter),
|
|
228
|
+
modules: createLintModulesFromRuntimeRegistry(modules)
|
|
229
|
+
});
|
|
230
|
+
const diagnostics = Array.isArray(lintResult) ? lintResult : lintResult.diagnostics;
|
|
231
|
+
if (!Array.isArray(lintResult)) {
|
|
232
|
+
executableSource = lintResult.fixed;
|
|
233
|
+
if (lintResult.fixed !== loaded.executableSource) {
|
|
234
|
+
await options.writeFile(
|
|
168
235
|
filepath,
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const runtime = createRuntime(loaded.frontmatter, meta, {
|
|
173
|
-
fs: parsed.fs
|
|
174
|
-
? { root: path.resolve(options.cwd, parsed.fsRoot ?? dirname(filepath)) }
|
|
175
|
-
: undefined,
|
|
176
|
-
modulesFor: options.modulesFor,
|
|
177
|
-
stderr: options.stderr,
|
|
178
|
-
stdout: options.stdout
|
|
179
|
-
});
|
|
180
|
-
const modules = excludeHarnessModule(runtime.registry, loaded.isRawScript);
|
|
181
|
-
let executableSource = loaded.executableSource;
|
|
182
|
-
const lintResult = parsed.fix
|
|
183
|
-
? lint(executableSource, {
|
|
184
|
-
allowedExportNames: ["schema"],
|
|
185
|
-
filename: filepath,
|
|
186
|
-
fix: true,
|
|
187
|
-
fixRanges: loaded.fixRanges,
|
|
188
|
-
frontmatterFields: Object.keys(loaded.frontmatter),
|
|
189
|
-
modules: createLintModulesFromRuntimeRegistry(modules)
|
|
190
|
-
})
|
|
191
|
-
: lint(executableSource, {
|
|
192
|
-
allowedExportNames: ["schema"],
|
|
193
|
-
filename: filepath,
|
|
194
|
-
frontmatterFields: Object.keys(loaded.frontmatter),
|
|
195
|
-
modules: createLintModulesFromRuntimeRegistry(modules)
|
|
196
|
-
});
|
|
197
|
-
const diagnostics = Array.isArray(lintResult) ? lintResult : lintResult.diagnostics;
|
|
198
|
-
if (!Array.isArray(lintResult)) {
|
|
199
|
-
executableSource = lintResult.fixed;
|
|
200
|
-
if (lintResult.fixed !== loaded.executableSource) {
|
|
201
|
-
await options.writeFile(filepath, replaceExecutableSource(loaded.rawSource, loaded, lintResult.fixes), {
|
|
202
|
-
encoding: "utf8"
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
const lintErrors = diagnostics.filter((diagnostic) => diagnostic.severity === "error");
|
|
207
|
-
if (lintErrors.length > 0) {
|
|
208
|
-
options.stderr.write(`Lint failed:\n${formatDiagnostics(lintErrors)}\n`);
|
|
209
|
-
if (options.brokenPipe.closed) {
|
|
210
|
-
return 0;
|
|
211
|
-
}
|
|
212
|
-
return lintErrors.some((diagnostic) => diagnostic.code === "AS001") ? EXIT_PARSE : EXIT_RUNTIME;
|
|
213
|
-
}
|
|
214
|
-
const lintWarnings = diagnostics.filter((diagnostic) => diagnostic.severity === "warning");
|
|
215
|
-
if (lintWarnings.length > 0) {
|
|
216
|
-
options.stderr.write(`Lint warnings:\n${formatDiagnostics(lintWarnings)}\n`);
|
|
217
|
-
if (options.brokenPipe.closed) {
|
|
218
|
-
return 0;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
const snapshot = await readRestoreSnapshot(parsed.restorePath, options);
|
|
222
|
-
if (snapshot !== undefined) {
|
|
223
|
-
restore(snapshot, { source: executableSource });
|
|
224
|
-
}
|
|
225
|
-
const abortController = new AbortController();
|
|
226
|
-
let interrupted = false;
|
|
227
|
-
let runPromise;
|
|
228
|
-
let signalSnapshotWrite;
|
|
229
|
-
const onSigint = () => {
|
|
230
|
-
interrupted = true;
|
|
231
|
-
abortController.abort(createAbortError());
|
|
232
|
-
options.stderr.write("Interrupted by SIGINT\n");
|
|
233
|
-
if (parsed.snapshotPath !== undefined && runPromise !== undefined) {
|
|
234
|
-
signalSnapshotWrite = writeCurrentSnapshot(runPromise, parsed.snapshotPath, options);
|
|
235
|
-
}
|
|
236
|
-
};
|
|
237
|
-
options.process.on("SIGINT", onSigint);
|
|
238
|
-
try {
|
|
239
|
-
runPromise = run(executableSource, {
|
|
240
|
-
budget: parsed.maxSteps === undefined && parsed.dataSize === undefined
|
|
241
|
-
? undefined
|
|
242
|
-
: new Budget({ dataSize: parsed.dataSize, maxSteps: parsed.maxSteps }),
|
|
243
|
-
entryPointArgs: hasDefaultExport(executableSource, filepath) ? [] : undefined,
|
|
244
|
-
filename: filepath,
|
|
245
|
-
modules,
|
|
246
|
-
signal: abortController.signal,
|
|
247
|
-
sink: createConsoleSink(options.stdout, options.stderr),
|
|
248
|
-
snapshot
|
|
249
|
-
});
|
|
250
|
-
const result = await runPromise;
|
|
251
|
-
await signalSnapshotWrite;
|
|
252
|
-
if (options.brokenPipe.closed) {
|
|
253
|
-
return 0;
|
|
254
|
-
}
|
|
255
|
-
if (parsed.snapshotPath !== undefined) {
|
|
256
|
-
await writeSnapshot(parsed.snapshotPath, await dump(result), options);
|
|
257
|
-
}
|
|
258
|
-
if (!result.ok) {
|
|
259
|
-
options.stderr.write(`${formatInterpreterError(result.error, {
|
|
260
|
-
filename: filepath,
|
|
261
|
-
source: executableSource
|
|
262
|
-
})}\n`);
|
|
263
|
-
if (options.brokenPipe.closed) {
|
|
264
|
-
return 0;
|
|
265
|
-
}
|
|
266
|
-
return interrupted ? EXIT_SIGINT : exitCodeForError(result.error);
|
|
267
|
-
}
|
|
268
|
-
options.stdout.write(`${JSON.stringify({ ok: true, returnValue: result.returnValue })}\n`);
|
|
269
|
-
return options.brokenPipe.closed ? 0 : interrupted ? EXIT_SIGINT : 0;
|
|
270
|
-
}
|
|
271
|
-
catch (error) {
|
|
272
|
-
await signalSnapshotWrite;
|
|
273
|
-
if (options.brokenPipe.closed) {
|
|
274
|
-
return 0;
|
|
236
|
+
replaceExecutableSource(loaded.rawSource, loaded, lintResult.fixes),
|
|
237
|
+
{
|
|
238
|
+
encoding: "utf8"
|
|
275
239
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
const lintErrors = diagnostics.filter((diagnostic) => diagnostic.severity === "error");
|
|
244
|
+
if (lintErrors.length > 0) {
|
|
245
|
+
options.stderr.write(`Lint failed:
|
|
246
|
+
${formatDiagnostics(lintErrors)}
|
|
247
|
+
`);
|
|
248
|
+
if (options.brokenPipe.closed) {
|
|
249
|
+
return 0;
|
|
250
|
+
}
|
|
251
|
+
return lintErrors.some((diagnostic) => diagnostic.code === "AS001") ? EXIT_PARSE : EXIT_RUNTIME;
|
|
252
|
+
}
|
|
253
|
+
const lintWarnings = diagnostics.filter((diagnostic) => diagnostic.severity === "warning");
|
|
254
|
+
if (lintWarnings.length > 0) {
|
|
255
|
+
options.stderr.write(`Lint warnings:
|
|
256
|
+
${formatDiagnostics(lintWarnings)}
|
|
257
|
+
`);
|
|
258
|
+
if (options.brokenPipe.closed) {
|
|
259
|
+
return 0;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
const snapshot = await readRestoreSnapshot(parsed.restorePath, options);
|
|
263
|
+
if (snapshot !== void 0) {
|
|
264
|
+
restore(snapshot, { source: executableSource });
|
|
265
|
+
}
|
|
266
|
+
const abortController = new AbortController();
|
|
267
|
+
let interrupted = false;
|
|
268
|
+
let runPromise;
|
|
269
|
+
let signalSnapshotWrite;
|
|
270
|
+
const onSigint = () => {
|
|
271
|
+
interrupted = true;
|
|
272
|
+
abortController.abort(createAbortError());
|
|
273
|
+
options.stderr.write("Interrupted by SIGINT\n");
|
|
274
|
+
if (parsed.snapshotPath !== void 0 && runPromise !== void 0) {
|
|
275
|
+
signalSnapshotWrite = writeCurrentSnapshot(runPromise, parsed.snapshotPath, options);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
options.process.on("SIGINT", onSigint);
|
|
279
|
+
try {
|
|
280
|
+
runPromise = run(executableSource, {
|
|
281
|
+
budget: parsed.maxSteps === void 0 && parsed.dataSize === void 0 ? void 0 : new Budget({ dataSize: parsed.dataSize, maxSteps: parsed.maxSteps }),
|
|
282
|
+
entryPointArgs: hasDefaultExport(executableSource, filepath) ? [] : void 0,
|
|
283
|
+
filename: filepath,
|
|
284
|
+
modules,
|
|
285
|
+
signal: abortController.signal,
|
|
286
|
+
sink: createConsoleSink(options.stdout, options.stderr),
|
|
287
|
+
snapshot
|
|
288
|
+
});
|
|
289
|
+
const result = await runPromise;
|
|
290
|
+
await signalSnapshotWrite;
|
|
291
|
+
if (options.brokenPipe.closed) {
|
|
292
|
+
return 0;
|
|
293
|
+
}
|
|
294
|
+
if (parsed.snapshotPath !== void 0) {
|
|
295
|
+
await writeSnapshot(parsed.snapshotPath, await dump(result), options);
|
|
296
|
+
}
|
|
297
|
+
if (!result.ok) {
|
|
298
|
+
options.stderr.write(
|
|
299
|
+
`${formatInterpreterError(result.error, {
|
|
300
|
+
filename: filepath,
|
|
301
|
+
source: executableSource
|
|
302
|
+
})}
|
|
303
|
+
`
|
|
304
|
+
);
|
|
305
|
+
if (options.brokenPipe.closed) {
|
|
306
|
+
return 0;
|
|
307
|
+
}
|
|
308
|
+
return interrupted ? EXIT_SIGINT : exitCodeForError(result.error);
|
|
309
|
+
}
|
|
310
|
+
options.stdout.write(`${JSON.stringify({ ok: true, returnValue: result.returnValue })}
|
|
311
|
+
`);
|
|
312
|
+
return options.brokenPipe.closed ? 0 : interrupted ? EXIT_SIGINT : 0;
|
|
313
|
+
} catch (error) {
|
|
314
|
+
await signalSnapshotWrite;
|
|
315
|
+
if (options.brokenPipe.closed) {
|
|
316
|
+
return 0;
|
|
317
|
+
}
|
|
318
|
+
options.stderr.write(
|
|
319
|
+
`${formatInterpreterError(error, {
|
|
320
|
+
filename: filepath,
|
|
321
|
+
source: executableSource
|
|
322
|
+
})}
|
|
323
|
+
`
|
|
324
|
+
);
|
|
325
|
+
return options.brokenPipe.closed ? 0 : interrupted ? EXIT_SIGINT : exitCodeForError(error);
|
|
326
|
+
} finally {
|
|
327
|
+
options.process.off("SIGINT", onSigint);
|
|
328
|
+
}
|
|
285
329
|
}
|
|
286
330
|
function loadExecutableSource(filepath, rawSource) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
return {
|
|
291
|
-
sourceOffset: byteOrderMarkLength,
|
|
292
|
-
executableSource: source,
|
|
293
|
-
frontmatter: {},
|
|
294
|
-
isRawScript: true,
|
|
295
|
-
rawSource
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
const { frontmatter, body } = splitFrontmatter(source);
|
|
299
|
-
const bodyStartOffset = source.length - body.length;
|
|
300
|
-
const executableBlock = extractBlock(body, countLineBreaks(source, 0, bodyStartOffset) + 1);
|
|
301
|
-
const lineOffset = countLineBreaks(source, 0, bodyStartOffset + executableBlock.startOffset);
|
|
331
|
+
const source = stripByteOrderMark(rawSource);
|
|
332
|
+
const byteOrderMarkLength = rawSource.length - source.length;
|
|
333
|
+
if (isRawScriptExtension(extname(filepath))) {
|
|
302
334
|
return {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
executableSource: createLineOffsetSource(executableBlock.source, lineOffset),
|
|
309
|
-
frontmatter,
|
|
310
|
-
isRawScript: false,
|
|
311
|
-
rawSource
|
|
335
|
+
sourceOffset: byteOrderMarkLength,
|
|
336
|
+
executableSource: source,
|
|
337
|
+
frontmatter: {},
|
|
338
|
+
isRawScript: true,
|
|
339
|
+
rawSource
|
|
312
340
|
};
|
|
341
|
+
}
|
|
342
|
+
const { frontmatter, body } = splitFrontmatter(source);
|
|
343
|
+
const bodyStartOffset = source.length - body.length;
|
|
344
|
+
const executableBlock = extractBlock(body, countLineBreaks(source, 0, bodyStartOffset) + 1);
|
|
345
|
+
const lineOffset = countLineBreaks(source, 0, bodyStartOffset + executableBlock.startOffset);
|
|
346
|
+
return {
|
|
347
|
+
sourceOffset: byteOrderMarkLength + bodyStartOffset + executableBlock.startOffset - lineOffset,
|
|
348
|
+
fixRanges: executableBlock.ranges.map(([start, end]) => [
|
|
349
|
+
start - executableBlock.startOffset + lineOffset,
|
|
350
|
+
end - executableBlock.startOffset + lineOffset
|
|
351
|
+
]),
|
|
352
|
+
executableSource: createLineOffsetSource(executableBlock.source, lineOffset),
|
|
353
|
+
frontmatter,
|
|
354
|
+
isRawScript: false,
|
|
355
|
+
rawSource
|
|
356
|
+
};
|
|
313
357
|
}
|
|
314
358
|
function isRawScriptExtension(extension) {
|
|
315
|
-
|
|
359
|
+
return extension === ".safejs" || extension === ".ajs";
|
|
316
360
|
}
|
|
317
361
|
function replaceExecutableSource(source, loaded, fixes) {
|
|
318
|
-
|
|
362
|
+
return fixes.reduce(
|
|
363
|
+
(result, fix) => `${result.slice(0, loaded.sourceOffset + fix.range[0])}${fix.replacement}${result.slice(loaded.sourceOffset + fix.range[1])}`,
|
|
364
|
+
source
|
|
365
|
+
);
|
|
319
366
|
}
|
|
320
367
|
function createRuntime(frontmatter, meta, options) {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
const state = {
|
|
330
|
-
checkpointCount: 0,
|
|
331
|
-
commitCount: 0,
|
|
332
|
-
metricCalls: new Map(),
|
|
333
|
-
spawnCount: 0
|
|
334
|
-
};
|
|
335
|
-
const harness = makeHarnessModule(frontmatter, meta);
|
|
336
|
-
const agent = makeAgentModule(async (input) => {
|
|
337
|
-
state.spawnCount += 1;
|
|
338
|
-
return {
|
|
339
|
-
exitCode: 0,
|
|
340
|
-
stdout: "",
|
|
341
|
-
stderr: "",
|
|
342
|
-
summary: `${input.agent} handled ${summarizePrompt(input.prompt)}`,
|
|
343
|
-
durationMs: 25 * state.spawnCount
|
|
344
|
-
};
|
|
345
|
-
});
|
|
346
|
-
const git = {
|
|
347
|
-
async checkpoint() {
|
|
348
|
-
state.checkpointCount += 1;
|
|
349
|
-
return {
|
|
350
|
-
head: `head-${state.checkpointCount}`,
|
|
351
|
-
stashRef: `savepoint-${state.checkpointCount}`
|
|
352
|
-
};
|
|
353
|
-
},
|
|
354
|
-
async commit() {
|
|
355
|
-
state.commitCount += 1;
|
|
356
|
-
return `commit-${state.commitCount}`;
|
|
357
|
-
},
|
|
358
|
-
async revert() {
|
|
359
|
-
return undefined;
|
|
360
|
-
}
|
|
368
|
+
if (options.modulesFor !== void 0) {
|
|
369
|
+
return {
|
|
370
|
+
registry: options.modulesFor(frontmatter, meta, {
|
|
371
|
+
stderr: options.stderr,
|
|
372
|
+
stdout: options.stdout
|
|
373
|
+
})
|
|
361
374
|
};
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
375
|
+
}
|
|
376
|
+
const state = {
|
|
377
|
+
checkpointCount: 0,
|
|
378
|
+
commitCount: 0,
|
|
379
|
+
metricCalls: /* @__PURE__ */ new Map(),
|
|
380
|
+
spawnCount: 0
|
|
381
|
+
};
|
|
382
|
+
const harness = makeHarnessModule(frontmatter, meta);
|
|
383
|
+
const agent = makeAgentModule(async (input) => {
|
|
384
|
+
state.spawnCount += 1;
|
|
368
385
|
return {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
git: toModuleExports(new Map([
|
|
375
|
-
["checkpoint", git.checkpoint],
|
|
376
|
-
["commit", git.commit],
|
|
377
|
-
["revert", git.revert]
|
|
378
|
-
])),
|
|
379
|
-
harness: toModuleExports(harness),
|
|
380
|
-
log: toModuleExports(log),
|
|
381
|
-
metric: toModuleExports(metric)
|
|
382
|
-
}
|
|
386
|
+
exitCode: 0,
|
|
387
|
+
stdout: "",
|
|
388
|
+
stderr: "",
|
|
389
|
+
summary: `${input.agent} handled ${summarizePrompt(input.prompt)}`,
|
|
390
|
+
durationMs: 25 * state.spawnCount
|
|
383
391
|
};
|
|
392
|
+
});
|
|
393
|
+
const git = {
|
|
394
|
+
async checkpoint() {
|
|
395
|
+
state.checkpointCount += 1;
|
|
396
|
+
return {
|
|
397
|
+
head: `head-${state.checkpointCount}`,
|
|
398
|
+
stashRef: `savepoint-${state.checkpointCount}`
|
|
399
|
+
};
|
|
400
|
+
},
|
|
401
|
+
async commit() {
|
|
402
|
+
state.commitCount += 1;
|
|
403
|
+
return `commit-${state.commitCount}`;
|
|
404
|
+
},
|
|
405
|
+
async revert() {
|
|
406
|
+
return void 0;
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
const log = makeLogModule((entry) => {
|
|
410
|
+
const normalized = normalizeLogEntry(entry);
|
|
411
|
+
const stream = normalized.type === "error" ? options.stderr : options.stdout;
|
|
412
|
+
stream.write(`${JSON.stringify(normalized)}
|
|
413
|
+
`);
|
|
414
|
+
});
|
|
415
|
+
const metric = makeMetricModule(async (scriptName) => `${readMetricScore(scriptName, state)}
|
|
416
|
+
`);
|
|
417
|
+
return {
|
|
418
|
+
registry: {
|
|
419
|
+
agent: toModuleExports(agent),
|
|
420
|
+
fail: toModuleExports(/* @__PURE__ */ new Map([["default", makeFailModule().default]])),
|
|
421
|
+
// The one module here that is not a stub, so it is registered only when asked for.
|
|
422
|
+
...options.fs === void 0 ? {} : { fs: toModuleExports(makeFsModule(options.fs)) },
|
|
423
|
+
git: toModuleExports(
|
|
424
|
+
/* @__PURE__ */ new Map([
|
|
425
|
+
["checkpoint", git.checkpoint],
|
|
426
|
+
["commit", git.commit],
|
|
427
|
+
["revert", git.revert]
|
|
428
|
+
])
|
|
429
|
+
),
|
|
430
|
+
harness: toModuleExports(harness),
|
|
431
|
+
log: toModuleExports(log),
|
|
432
|
+
metric: toModuleExports(metric)
|
|
433
|
+
}
|
|
434
|
+
};
|
|
384
435
|
}
|
|
385
436
|
async function readRestoreSnapshot(restorePath, options) {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
throw new Error(`Failed to parse snapshot at ${restorePath}: ${readErrorMessage(error)}`);
|
|
405
|
-
}
|
|
437
|
+
if (restorePath === void 0) {
|
|
438
|
+
return void 0;
|
|
439
|
+
}
|
|
440
|
+
const snapshotPath = path.resolve(options.cwd, restorePath);
|
|
441
|
+
let rawSnapshot;
|
|
442
|
+
try {
|
|
443
|
+
rawSnapshot = await options.readFile(snapshotPath, "utf8");
|
|
444
|
+
} catch (error) {
|
|
445
|
+
if (hasErrorCode(error, "ENOENT")) {
|
|
446
|
+
throw new CliExitError(`Snapshot not found: ${restorePath}`, EXIT_RUNTIME);
|
|
447
|
+
}
|
|
448
|
+
throw error;
|
|
449
|
+
}
|
|
450
|
+
try {
|
|
451
|
+
return JSON.parse(rawSnapshot);
|
|
452
|
+
} catch (error) {
|
|
453
|
+
throw new Error(`Failed to parse snapshot at ${restorePath}: ${readErrorMessage(error)}`);
|
|
454
|
+
}
|
|
406
455
|
}
|
|
407
456
|
async function writeCurrentSnapshot(result, snapshotPath, options) {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
457
|
+
try {
|
|
458
|
+
await writeSnapshot(snapshotPath, await dumpCurrent(result), options);
|
|
459
|
+
} catch (error) {
|
|
460
|
+
options.stderr.write(
|
|
461
|
+
`Failed to write snapshot at ${snapshotPath}: ${readErrorMessage(error)}
|
|
462
|
+
`
|
|
463
|
+
);
|
|
464
|
+
}
|
|
414
465
|
}
|
|
415
466
|
async function writeSnapshot(snapshotPath, content, options) {
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
467
|
+
const resolvedPath = path.resolve(options.cwd, snapshotPath);
|
|
468
|
+
await mkdir(dirname(resolvedPath), { recursive: true });
|
|
469
|
+
await options.writeFile(resolvedPath, content, { encoding: "utf8" });
|
|
419
470
|
}
|
|
420
471
|
function createConsoleSink(stdout, stderr) {
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
472
|
+
return {
|
|
473
|
+
error(...args) {
|
|
474
|
+
stderr.write(`${formatConsoleArgs(args)}
|
|
475
|
+
`);
|
|
476
|
+
},
|
|
477
|
+
log(...args) {
|
|
478
|
+
stdout.write(`${formatConsoleArgs(args)}
|
|
479
|
+
`);
|
|
480
|
+
}
|
|
481
|
+
};
|
|
429
482
|
}
|
|
430
483
|
function formatConsoleArgs(args) {
|
|
431
|
-
|
|
484
|
+
return formatWithOptions({ colors: false, depth: 4 }, ...args);
|
|
432
485
|
}
|
|
433
486
|
function createUsage() {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
487
|
+
return [
|
|
488
|
+
"Usage: poe-safejs [options] <script.md|script.safejs|script.ajs>",
|
|
489
|
+
"",
|
|
490
|
+
"Options:",
|
|
491
|
+
" --fix apply lint fixes before running",
|
|
492
|
+
" --fs register the fs module: a real filesystem, unlike the agent,",
|
|
493
|
+
" git, and metric stubs this runner bundles",
|
|
494
|
+
" --fs-root <path> directory --fs confines the script to (default: the script's",
|
|
495
|
+
" directory)",
|
|
496
|
+
" --mcp-config <path> register named MCP servers from an explicit JSON config",
|
|
497
|
+
" --snapshot <path> write the final snapshot, and best-effort snapshot on SIGINT",
|
|
498
|
+
" --restore <path> restore from a snapshot before running",
|
|
499
|
+
" --max-steps <n> cap interpreter step budget",
|
|
500
|
+
" --data-size <n> cap retained sandbox data units",
|
|
501
|
+
" -h, --help print this help",
|
|
502
|
+
"",
|
|
503
|
+
"Exit codes:",
|
|
504
|
+
" 0 success",
|
|
505
|
+
" 1 runtime, usage, file, or restore error",
|
|
506
|
+
" 2 parse error",
|
|
507
|
+
" 3 budget exceeded",
|
|
508
|
+
" 130 interrupted by SIGINT"
|
|
509
|
+
].join("\n");
|
|
456
510
|
}
|
|
457
511
|
function formatDiagnostics(diagnostics) {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
512
|
+
return diagnostics.map(
|
|
513
|
+
(diagnostic) => `${diagnostic.filename}:${diagnostic.line}:${diagnostic.column} ${diagnostic.code} ${diagnostic.message}`
|
|
514
|
+
).join("\n");
|
|
461
515
|
}
|
|
462
516
|
function exitCodeForError(error) {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
517
|
+
if (error instanceof SandboxError && error.code === "budgetExceeded") {
|
|
518
|
+
return EXIT_BUDGET;
|
|
519
|
+
}
|
|
520
|
+
if (isParseError(error)) {
|
|
521
|
+
return EXIT_PARSE;
|
|
522
|
+
}
|
|
523
|
+
return EXIT_RUNTIME;
|
|
470
524
|
}
|
|
471
525
|
function isParseError(error) {
|
|
472
|
-
|
|
526
|
+
return error instanceof Error && error.name === "ParseError";
|
|
473
527
|
}
|
|
474
528
|
function hasDefaultExport(source, filename) {
|
|
475
|
-
|
|
529
|
+
return parseModule(source, filename).body.some(
|
|
530
|
+
(statement) => statement.type === "ExportDefaultDeclaration"
|
|
531
|
+
);
|
|
476
532
|
}
|
|
477
533
|
function excludeHarnessModule(modules, isRawScript) {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
534
|
+
if (!isRawScript) {
|
|
535
|
+
return modules;
|
|
536
|
+
}
|
|
537
|
+
if (modules instanceof Map) {
|
|
538
|
+
const rawModules2 = new Map(modules);
|
|
539
|
+
rawModules2.delete("harness");
|
|
540
|
+
return rawModules2;
|
|
541
|
+
}
|
|
542
|
+
const rawModules = /* @__PURE__ */ Object.create(null);
|
|
543
|
+
for (const [moduleName, moduleExports] of Object.entries(modules)) {
|
|
544
|
+
if (moduleName !== "harness") {
|
|
545
|
+
rawModules[moduleName] = moduleExports;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
return rawModules;
|
|
493
549
|
}
|
|
494
550
|
function stripByteOrderMark(source) {
|
|
495
|
-
|
|
551
|
+
return source.startsWith("\uFEFF") ? source.slice(1) : source;
|
|
496
552
|
}
|
|
497
553
|
function createLineOffsetSource(source, lineOffset) {
|
|
498
|
-
|
|
554
|
+
return `${"\n".repeat(Math.max(lineOffset, 0))}${source}`;
|
|
499
555
|
}
|
|
500
556
|
function normalizeLogEntry(entry) {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
557
|
+
return {
|
|
558
|
+
...entry,
|
|
559
|
+
ts: "2026-04-29T00:00:00.000Z"
|
|
560
|
+
};
|
|
505
561
|
}
|
|
506
562
|
function summarizePrompt(prompt) {
|
|
507
|
-
|
|
508
|
-
|
|
563
|
+
const normalizedPrompt = prompt.trim().replaceAll("\n", " ");
|
|
564
|
+
return normalizedPrompt.length <= 48 ? normalizedPrompt : `${normalizedPrompt.slice(0, 45)}...`;
|
|
509
565
|
}
|
|
510
566
|
function readMetricScore(scriptName, state) {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
567
|
+
const callCount = (state.metricCalls.get(scriptName) ?? 0) + 1;
|
|
568
|
+
state.metricCalls.set(scriptName, callCount);
|
|
569
|
+
if (scriptName === "tests" && callCount === 1) {
|
|
570
|
+
return 10;
|
|
571
|
+
}
|
|
572
|
+
if (scriptName === "tests" && callCount === 2) {
|
|
573
|
+
return 9;
|
|
574
|
+
}
|
|
575
|
+
return 9 + callCount;
|
|
520
576
|
}
|
|
521
577
|
function toModuleExports(value) {
|
|
522
|
-
|
|
578
|
+
return value;
|
|
523
579
|
}
|
|
524
580
|
function createAbortError() {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
581
|
+
if (typeof DOMException === "function") {
|
|
582
|
+
const error2 = new DOMException("This operation was aborted", "AbortError");
|
|
583
|
+
replaceErrorStack(error2);
|
|
584
|
+
return error2;
|
|
585
|
+
}
|
|
586
|
+
const error = new Error("This operation was aborted");
|
|
587
|
+
error.name = "AbortError";
|
|
588
|
+
replaceErrorStack(error);
|
|
589
|
+
return error;
|
|
534
590
|
}
|
|
535
591
|
function hasErrorCode(error, code) {
|
|
536
|
-
|
|
592
|
+
return hasOwnErrorCode(error, code);
|
|
537
593
|
}
|
|
538
594
|
function readErrorMessage(error) {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
}
|
|
595
|
+
if (error instanceof Error) {
|
|
596
|
+
return error.message;
|
|
597
|
+
}
|
|
598
|
+
return String(error);
|
|
599
|
+
}
|
|
600
|
+
var CliExitError = class extends Error {
|
|
601
|
+
exitCode;
|
|
602
|
+
constructor(message, exitCode) {
|
|
603
|
+
super(message);
|
|
604
|
+
this.name = "CliExitError";
|
|
605
|
+
this.exitCode = exitCode;
|
|
606
|
+
}
|
|
607
|
+
};
|
|
552
608
|
async function isDirectExecution(entryPoint) {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
}
|
|
609
|
+
if (typeof entryPoint !== "string" || entryPoint.length === 0) {
|
|
610
|
+
return false;
|
|
611
|
+
}
|
|
612
|
+
try {
|
|
613
|
+
const [resolvedEntryPoint, resolvedModule] = await Promise.all([
|
|
614
|
+
realpath(path.resolve(entryPoint)),
|
|
615
|
+
realpath(fileURLToPath(import.meta.url))
|
|
616
|
+
]);
|
|
617
|
+
return resolvedEntryPoint === resolvedModule;
|
|
618
|
+
} catch {
|
|
619
|
+
return false;
|
|
620
|
+
}
|
|
566
621
|
}
|
|
567
622
|
if (await isDirectExecution(process.argv[1])) {
|
|
568
|
-
|
|
623
|
+
process.exitCode = await runCli(process.argv.slice(2));
|
|
569
624
|
}
|
|
625
|
+
export {
|
|
626
|
+
runCli
|
|
627
|
+
};
|
|
628
|
+
//# sourceMappingURL=cli.js.map
|