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.
Files changed (45) hide show
  1. package/dist/cli/commands/harness.js +12 -3
  2. package/dist/cli/commands/harness.js.map +1 -1
  3. package/dist/index.js +1515 -712
  4. package/dist/index.js.map +4 -4
  5. package/dist/metafile.json +1 -1
  6. package/package.json +15 -2
  7. package/packages/safejs/dist/chunks/chunk-4YIDX44G.js +40 -0
  8. package/packages/safejs/dist/chunks/chunk-4YIDX44G.js.map +7 -0
  9. package/packages/safejs/dist/chunks/chunk-55ZK3CR7.js +7802 -0
  10. package/packages/safejs/dist/chunks/chunk-55ZK3CR7.js.map +7 -0
  11. package/packages/safejs/dist/chunks/chunk-GQBEEFVQ.js +28798 -0
  12. package/packages/safejs/dist/chunks/chunk-GQBEEFVQ.js.map +7 -0
  13. package/packages/safejs/dist/chunks/chunk-NI4WFFTL.js +5701 -0
  14. package/packages/safejs/dist/chunks/chunk-NI4WFFTL.js.map +7 -0
  15. package/packages/safejs/dist/chunks/inMemory-RLZ4QGDZ.js +48 -0
  16. package/packages/safejs/dist/chunks/inMemory-RLZ4QGDZ.js.map +7 -0
  17. package/packages/safejs/dist/chunks/server-3SNT3RE2.js +12518 -0
  18. package/packages/safejs/dist/chunks/server-3SNT3RE2.js.map +7 -0
  19. package/packages/safejs/dist/chunks/types-BTF37PZ6.js +348 -0
  20. package/packages/safejs/dist/chunks/types-BTF37PZ6.js.map +7 -0
  21. package/packages/safejs/dist/cli.d.ts +2 -0
  22. package/packages/safejs/dist/cli.js +550 -491
  23. package/packages/safejs/dist/cli.js.map +7 -0
  24. package/packages/safejs/dist/core.js +14 -4
  25. package/packages/safejs/dist/core.js.map +7 -0
  26. package/packages/safejs/dist/index.d.ts +3 -0
  27. package/packages/safejs/dist/index.js +791 -30
  28. package/packages/safejs/dist/index.js.map +7 -0
  29. package/packages/safejs/dist/interp/host-bridge.d.ts +2 -0
  30. package/packages/safejs/dist/interp/host-bridge.js +20 -9
  31. package/packages/safejs/dist/interp/host-call.d.ts +5 -0
  32. package/packages/safejs/dist/interp/host-call.js +48 -3
  33. package/packages/safejs/dist/interp/resources.d.ts +7 -0
  34. package/packages/safejs/dist/interp/resources.js +36 -0
  35. package/packages/safejs/dist/modules/mcp-transport.d.ts +26 -0
  36. package/packages/safejs/dist/modules/mcp-transport.js +259 -0
  37. package/packages/safejs/dist/modules/mcp.d.ts +15 -1
  38. package/packages/safejs/dist/modules/mcp.js +107 -0
  39. package/packages/safejs/dist/run.js +6 -3
  40. package/packages/safejs/dist/snapshot/dump-format.d.ts +1 -1
  41. package/packages/safejs/dist/snapshot/dump-format.js +1 -1
  42. package/packages/safejs/dist/snapshot/replay-data.d.ts +1 -0
  43. package/packages/safejs/dist/snapshot/replay-data.js +3 -1
  44. package/packages/safejs/dist/snapshot/replay-inputs.d.ts +2 -2
  45. package/packages/safejs/dist/snapshot/replay-inputs.js +2 -1
@@ -1,30 +1,791 @@
1
- export { parse } from "./parse.js";
2
- export { parseModule } from "./parse/parser.js";
3
- export { lint } from "./lint.js";
4
- export { run } from "./run.js";
5
- export { createReplayableRandom } from "./random.js";
6
- export { noopOtelSink } from "./observability/otel.js";
7
- export { FileSnapshotBackend } from "./snapshot/backend.js";
8
- export { declareHostOperation } from "./interp/host-bridge.js";
9
- export { HostCallResumabilityError } from "./interp/host-call.js";
10
- export { HostOperationResumePolicyError, registerPendingHostCallPolicy } from "./snapshot/policy.js";
11
- export { dump } from "./dump.js";
12
- export { restore } from "./restore.js";
13
- export { SnapshotValidationError } from "./snapshot/validation.js";
14
- export { Budget, SandboxError } from "./interp/budget.js";
15
- export { formatInterpreterError } from "./error/format.js";
16
- export { deepCopyFromSandbox, deepCopyToSandbox } from "./interp/values.js";
17
- export { runHarness, runHarnessPair } from "./runner/run-harness.js";
18
- export { extractBlock } from "./loader/extract-block.js";
19
- export { findExportedConstInitializer } from "./loader/find-exported.js";
20
- export { splitFrontmatter } from "./loader/frontmatter.js";
21
- export { AgentSpawnError, createSpawnUsageAccumulator, makeAgentModule, runWithSpawnUsageAccumulator } from "./modules/agent.js";
22
- export { makeEnvModule } from "./modules/env.js";
23
- export { makeFailModule } from "./modules/fail.js";
24
- export { makeFsModule } from "./modules/fs.js";
25
- export { makeGitModule } from "./modules/git.js";
26
- export { makeHarnessModule } from "./modules/harness.js";
27
- export { makeLogModule } from "./modules/log.js";
28
- export { makeMetricModule } from "./modules/metric.js";
29
- export { makeMcpModule } from "./modules/mcp.js";
30
- export { makeTimeModule } from "./modules/time.js";
1
+ import {
2
+ AgentSpawnError,
3
+ SPAWN_MODES,
4
+ containsPath,
5
+ countLineBreaks,
6
+ createLintModulesFromRuntimeRegistry,
7
+ createSpawnUsageAccumulator,
8
+ extractBlock,
9
+ formatInterpreterError,
10
+ isSamePath,
11
+ makeAgentModule,
12
+ makeFailModule,
13
+ makeFsModule,
14
+ makeHarnessModule,
15
+ makeLogModule,
16
+ makeMcpModule,
17
+ makeMetricModule,
18
+ parseMcpConfig,
19
+ resolveCanonicalPath,
20
+ runWithSpawnUsageAccumulator,
21
+ splitFrontmatter,
22
+ supportsSpawnMode
23
+ } from "./chunks/chunk-55ZK3CR7.js";
24
+ import {
25
+ Budget,
26
+ FileSnapshotBackend,
27
+ HostCallResumabilityError,
28
+ HostOperationResumePolicyError,
29
+ SandboxError,
30
+ SnapshotValidationError,
31
+ createReplayableRandom,
32
+ createSeededRandom,
33
+ declareHostOperation,
34
+ deepCopyFromSandbox,
35
+ deepCopyToSandbox,
36
+ dump,
37
+ hasOwnErrorCode,
38
+ lint,
39
+ noopOtelSink,
40
+ parse,
41
+ parseModule,
42
+ registerPendingHostCallPolicy,
43
+ restore,
44
+ run
45
+ } from "./chunks/chunk-GQBEEFVQ.js";
46
+ import "./chunks/chunk-4YIDX44G.js";
47
+
48
+ // packages/safejs/src/runner/run-harness.ts
49
+ import { readFile, stat } from "node:fs/promises";
50
+ import { extname } from "node:path";
51
+ function getOwnEntry(record, key) {
52
+ return Object.prototype.hasOwnProperty.call(record, key) ? record[key] : void 0;
53
+ }
54
+ function createHarnessMeta(filepath, frontmatter) {
55
+ return {
56
+ filepath,
57
+ kind: getOwnEntry(frontmatter, "kind"),
58
+ version: getOwnEntry(frontmatter, "version")
59
+ };
60
+ }
61
+ function assertFrontmatterAgentModes(frontmatter) {
62
+ const agents = getOwnEntry(frontmatter, "agents");
63
+ if (typeof agents !== "object" || agents === null || Array.isArray(agents)) {
64
+ return;
65
+ }
66
+ for (const [name, definition] of Object.entries(agents)) {
67
+ if (typeof definition !== "object" || definition === null || Array.isArray(definition)) {
68
+ continue;
69
+ }
70
+ const record = definition;
71
+ const agent = getOwnEntry(record, "agent");
72
+ const mode = getOwnEntry(record, "mode");
73
+ if (typeof agent !== "string" || typeof mode !== "string") {
74
+ continue;
75
+ }
76
+ if (!SPAWN_MODES.includes(mode)) {
77
+ continue;
78
+ }
79
+ if (!supportsSpawnMode(agent, mode)) {
80
+ throw new Error(`Harness agent "${name}": agent "${agent}" does not support mode "${mode}".`);
81
+ }
82
+ }
83
+ }
84
+ var LintError = class extends Error {
85
+ diagnostics;
86
+ constructor(diagnostics) {
87
+ super(formatLintErrorMessage(diagnostics));
88
+ this.name = "LintError";
89
+ this.diagnostics = diagnostics;
90
+ }
91
+ };
92
+ async function runHarness(filepath, options) {
93
+ const rawSource = stripByteOrderMark(await readHarnessFile(filepath));
94
+ const { executableSource, frontmatter, isRawScript } = loadExecutableSource(filepath, rawSource);
95
+ assertFrontmatterAgentModes(frontmatter);
96
+ const meta = createHarnessMeta(filepath, frontmatter);
97
+ const modules = excludeHarnessModule(options.modulesFor(frontmatter, meta), isRawScript);
98
+ const diagnostics = lint(executableSource, {
99
+ filename: filepath,
100
+ modules: createLintModulesFromRuntimeRegistry(modules)
101
+ });
102
+ const lintErrors = diagnostics.filter((diagnostic) => diagnostic.severity === "error");
103
+ if (lintErrors.length > 0) {
104
+ throw new LintError(lintErrors);
105
+ }
106
+ return runHarnessSource(executableSource, {
107
+ entryPointArgs: hasDefaultExport(executableSource, filepath) ? [] : void 0,
108
+ filename: filepath,
109
+ modules,
110
+ otelSink: options.otelSink,
111
+ signal: options.signal,
112
+ snapshotBackend: options.snapshotBackend,
113
+ snapshotIntervalMs: options.snapshotIntervalMs,
114
+ snapshotPath: options.snapshotPath
115
+ });
116
+ }
117
+ async function runHarnessPair(filepath, options) {
118
+ const pair = resolveHarnessPair(filepath);
119
+ const [rawMarkdown, rawScript] = await Promise.all([
120
+ readHarnessFile(pair.markdownPath),
121
+ readHarnessFile(pair.scriptPath)
122
+ ]);
123
+ const { frontmatter, body } = splitFrontmatter(stripByteOrderMark(rawMarkdown));
124
+ assertFrontmatterAgentModes(frontmatter);
125
+ const executableSource = stripByteOrderMark(rawScript);
126
+ const meta = createHarnessMeta(pair.markdownPath, frontmatter);
127
+ const modules = options.modulesFor(frontmatter, meta);
128
+ const diagnostics = lint(executableSource, {
129
+ allowedExportNames: ["schema"],
130
+ defaultExport: {
131
+ parameters: ["frontmatter"],
132
+ required: true
133
+ },
134
+ filename: pair.scriptPath,
135
+ frontmatterFields: Object.keys(frontmatter),
136
+ modules: createLintModulesFromRuntimeRegistry(modules)
137
+ });
138
+ const lintErrors = diagnostics.filter((diagnostic) => diagnostic.severity === "error");
139
+ if (lintErrors.length > 0) {
140
+ throw new LintError(lintErrors);
141
+ }
142
+ return runHarnessSource(executableSource, {
143
+ entryPointArgs: [frontmatter],
144
+ filename: pair.scriptPath,
145
+ importMeta: {
146
+ body,
147
+ filepath: pair.markdownPath,
148
+ kind: meta.kind,
149
+ version: meta.version
150
+ },
151
+ modules,
152
+ otelSink: options.otelSink,
153
+ signal: options.signal,
154
+ snapshotBackend: options.snapshotBackend,
155
+ snapshotIntervalMs: options.snapshotIntervalMs,
156
+ snapshotPath: options.snapshotPath
157
+ });
158
+ }
159
+ async function readHarnessFile(filepath) {
160
+ try {
161
+ const stats = await stat(filepath);
162
+ if (!stats.isFile()) {
163
+ throw new Error(`Harness path must point to a file: ${filepath}`);
164
+ }
165
+ return await readFile(filepath, "utf8");
166
+ } catch (error) {
167
+ if (hasOwnErrorCode(error, "ENOENT") || hasOwnErrorCode(error, "ENOTDIR")) {
168
+ throw new Error(`Harness file not found: ${filepath}`);
169
+ }
170
+ throw error;
171
+ }
172
+ }
173
+ function loadExecutableSource(filepath, source) {
174
+ if (isRawScriptPath(filepath)) {
175
+ if (source.length === 0) {
176
+ throw new Error(`No code block found in empty harness file: ${filepath}`);
177
+ }
178
+ return {
179
+ executableSource: source,
180
+ frontmatter: {},
181
+ isRawScript: true
182
+ };
183
+ }
184
+ const { frontmatter, body } = splitFrontmatter(source);
185
+ if (source.length === 0 || body.trim().length === 0) {
186
+ throw new Error(`No code block found in empty harness file: ${filepath}`);
187
+ }
188
+ const bodyStartOffset = source.length - body.length;
189
+ const { source: executableBlock, startOffset } = extractBlock(
190
+ body,
191
+ countLineBreaks(source, 0, bodyStartOffset) + 1
192
+ );
193
+ const absoluteLineOffset = countLineBreaks(source, 0, bodyStartOffset + startOffset);
194
+ return {
195
+ executableSource: createLineOffsetSource(stripHashbang(executableBlock), absoluteLineOffset),
196
+ frontmatter,
197
+ isRawScript: false
198
+ };
199
+ }
200
+ function resolveHarnessPair(filepath) {
201
+ const extension = extname(filepath);
202
+ const basename = extension.length === 0 ? filepath : filepath.slice(0, -extension.length);
203
+ if (isRawScriptExtension(extension)) {
204
+ return {
205
+ markdownPath: `${basename}.md`,
206
+ scriptPath: filepath
207
+ };
208
+ }
209
+ return {
210
+ markdownPath: filepath,
211
+ scriptPath: `${basename}.ajs`
212
+ };
213
+ }
214
+ function isRawScriptPath(filepath) {
215
+ return isRawScriptExtension(extname(filepath));
216
+ }
217
+ function isRawScriptExtension(extension) {
218
+ return extension === ".safejs" || extension === ".ajs";
219
+ }
220
+ async function runHarnessSource(executableSource, options) {
221
+ try {
222
+ return await run(executableSource, options);
223
+ } catch (error) {
224
+ if (isSetupError(error)) {
225
+ throw error;
226
+ }
227
+ return {
228
+ ...isAbortError(error) ? { aborted: true } : {},
229
+ error,
230
+ ok: false
231
+ };
232
+ }
233
+ }
234
+ function isSetupError(error) {
235
+ return error instanceof Error && error.name === "ParseError";
236
+ }
237
+ function isAbortError(error) {
238
+ if (error instanceof Error) {
239
+ return error.name === "AbortError";
240
+ }
241
+ return typeof error === "object" && error !== null && Object.prototype.hasOwnProperty.call(error, "name") && error.name === "AbortError";
242
+ }
243
+ function hasDefaultExport(source, filename) {
244
+ return parseModule(source, filename).body.some(
245
+ (statement) => statement.type === "ExportDefaultDeclaration"
246
+ );
247
+ }
248
+ function excludeHarnessModule(modules, isRawScript) {
249
+ if (!isRawScript) {
250
+ return modules;
251
+ }
252
+ if (modules instanceof Map) {
253
+ const rawModules2 = new Map(modules);
254
+ rawModules2.delete("harness");
255
+ return rawModules2;
256
+ }
257
+ const rawModules = {};
258
+ for (const [moduleName, moduleExports] of Object.entries(modules)) {
259
+ if (moduleName !== "harness") {
260
+ rawModules[moduleName] = moduleExports;
261
+ }
262
+ }
263
+ return rawModules;
264
+ }
265
+ function stripByteOrderMark(source) {
266
+ return source.startsWith("\uFEFF") ? source.slice(1) : source;
267
+ }
268
+ function stripHashbang(source) {
269
+ if (!source.startsWith("#!")) {
270
+ return source;
271
+ }
272
+ let end = 2;
273
+ while (end < source.length && source[end] !== "\n" && source[end] !== "\r") end += 1;
274
+ return `${" ".repeat(end)}${source.slice(end)}`;
275
+ }
276
+ function createLineOffsetSource(source, lineOffset) {
277
+ return `${"\n".repeat(Math.max(lineOffset, 0))}${source}`;
278
+ }
279
+ function formatLintErrorMessage(diagnostics) {
280
+ if (diagnostics.length === 0) {
281
+ return "Script lint failed.";
282
+ }
283
+ return diagnostics.map(
284
+ (diagnostic) => `${diagnostic.filename}:${diagnostic.line}:${diagnostic.column} ${diagnostic.code} ${diagnostic.message}`
285
+ ).join("\n");
286
+ }
287
+
288
+ // packages/safejs/src/loader/find-exported.ts
289
+ function findExportedConstInitializer(module, name) {
290
+ for (const statement of module.body) {
291
+ if (statement.type === "ExportDefaultDeclaration") {
292
+ if (name === "default") {
293
+ return statement.declaration;
294
+ }
295
+ continue;
296
+ }
297
+ if (statement.type !== "ExportNamedDeclaration") {
298
+ continue;
299
+ }
300
+ const declaration = statement.declaration;
301
+ if (declaration.kind !== "const") {
302
+ throw new Error(`Exported '${name}' must be declared with const.`);
303
+ }
304
+ if (declaration.declarations.length !== 1) {
305
+ throw new Error("Exported const declarations must contain exactly one declarator.");
306
+ }
307
+ const declarator = declaration.declarations[0];
308
+ if (declarator.id.type !== "Identifier") {
309
+ throw new Error("Destructured exported const bindings are not supported.");
310
+ }
311
+ if (declarator.id.name !== name) {
312
+ continue;
313
+ }
314
+ if (declarator.init === void 0) {
315
+ throw new Error(`Exported const '${name}' must have an initializer.`);
316
+ }
317
+ return declarator.init;
318
+ }
319
+ return void 0;
320
+ }
321
+
322
+ // packages/safejs/src/modules/env.ts
323
+ function makeEnvModule(allowList) {
324
+ const allowedNames = normalizeAllowList(allowList);
325
+ return {
326
+ get(name) {
327
+ const normalizedName = readNonEmptyString(name, "Environment variable name");
328
+ if (!allowedNames.has(normalizedName)) {
329
+ return void 0;
330
+ }
331
+ return process.env[normalizedName];
332
+ }
333
+ };
334
+ }
335
+ function normalizeAllowList(allowList) {
336
+ if (!Array.isArray(allowList)) {
337
+ throw new Error("Environment allow list must be an array of non-empty strings.");
338
+ }
339
+ return new Set(
340
+ allowList.map((entry, index) => readNonEmptyString(entry, `Environment allow list[${index}]`))
341
+ );
342
+ }
343
+ function readNonEmptyString(value, label) {
344
+ if (typeof value !== "string") {
345
+ throw new Error(`${label} must be a non-empty string.`);
346
+ }
347
+ const normalizedValue = value.trim();
348
+ if (normalizedValue.length === 0) {
349
+ throw new Error(`${label} must be a non-empty string.`);
350
+ }
351
+ return normalizedValue;
352
+ }
353
+
354
+ // packages/safejs/src/modules/git.ts
355
+ import { execFile } from "node:child_process";
356
+ import { mkdir, readlink, realpath, rm, stat as stat2 } from "node:fs/promises";
357
+ import { dirname, isAbsolute, resolve } from "node:path";
358
+ var GIT_EXEC_MAX_BUFFER = 10 * 1024 * 1024;
359
+ var SAVEPOINT_REF_PREFIX = "refs/poe-code/checkpoints/";
360
+ function makeGitModule(cwd) {
361
+ const normalizedCwd = readNonEmptyString2(cwd, "Git module cwd");
362
+ return {
363
+ async head() {
364
+ return runGitAndTrim(normalizedCwd, ["rev-parse", "HEAD"]);
365
+ },
366
+ async checkpoint() {
367
+ const currentHead = await runGitAndTrim(normalizedCwd, ["rev-parse", "HEAD"]);
368
+ const status = await runGitAndTrim(normalizedCwd, ["status", "--porcelain"]);
369
+ if (status.length === 0) {
370
+ return {
371
+ head: currentHead
372
+ };
373
+ }
374
+ const stashRef = createSavepointRef();
375
+ const stashMessage = `poe-code checkpoint ${stashRef}`;
376
+ await runGit(normalizedCwd, [
377
+ "stash",
378
+ "push",
379
+ "--include-untracked",
380
+ "--message",
381
+ stashMessage
382
+ ]);
383
+ try {
384
+ const stashOid = await runGitAndTrim(normalizedCwd, ["rev-parse", "stash@{0}"]);
385
+ await runGit(normalizedCwd, ["update-ref", stashRef, stashOid]);
386
+ await runGit(normalizedCwd, ["stash", "apply", "--index", stashRef]);
387
+ await runGit(normalizedCwd, ["stash", "drop", "stash@{0}"]);
388
+ return {
389
+ head: currentHead,
390
+ stashRef
391
+ };
392
+ } catch (error) {
393
+ await cleanupFailedCheckpoint(normalizedCwd, stashRef);
394
+ throw error;
395
+ }
396
+ },
397
+ async commit(options) {
398
+ const normalizedOptions = normalizeCommitOptions(options);
399
+ if (normalizedOptions.files === void 0) {
400
+ await runGit(normalizedCwd, ["add", "--all"]);
401
+ await runGit(normalizedCwd, ["commit", "--message", normalizedOptions.message]);
402
+ } else {
403
+ await runGit(normalizedCwd, ["add", "--", ...normalizedOptions.files]);
404
+ await runGit(normalizedCwd, [
405
+ "commit",
406
+ "--message",
407
+ normalizedOptions.message,
408
+ "--",
409
+ ...normalizedOptions.files
410
+ ]);
411
+ }
412
+ return runGitAndTrim(normalizedCwd, ["rev-parse", "HEAD"]);
413
+ },
414
+ async revert(savepoint) {
415
+ const normalizedSavepoint = normalizeSavepoint(savepoint);
416
+ try {
417
+ await runGit(normalizedCwd, ["reset", "--hard", normalizedSavepoint.head]);
418
+ await runGit(normalizedCwd, ["clean", "--force", "-d"]);
419
+ if (normalizedSavepoint.stashRef !== void 0) {
420
+ await runGit(normalizedCwd, ["stash", "apply", "--index", normalizedSavepoint.stashRef]);
421
+ }
422
+ } finally {
423
+ if (normalizedSavepoint.stashRef !== void 0) {
424
+ await deleteSavepointRef(normalizedCwd, normalizedSavepoint.stashRef);
425
+ }
426
+ }
427
+ },
428
+ async diff() {
429
+ const { stdout } = await runGit(normalizedCwd, ["diff", "HEAD", "--"]);
430
+ return stdout;
431
+ },
432
+ async worktreeCreate(branch, options) {
433
+ const normalizedBranch = readNonEmptyString2(branch, "Git worktree branch");
434
+ const normalizedOptions = normalizeWorktreeCreateOptions(options);
435
+ const repoRoot = await getRepoRoot(normalizedCwd);
436
+ const worktreePath = await resolveWorktreePath(
437
+ repoRoot,
438
+ normalizedOptions.path ?? createDefaultWorktreePath(repoRoot, normalizedBranch),
439
+ "Git worktree path"
440
+ );
441
+ if (await gitRefExists(normalizedCwd, `refs/heads/${normalizedBranch}`)) {
442
+ throw new Error(`Git worktree branch '${normalizedBranch}' already exists.`);
443
+ }
444
+ await mkdir(dirname(worktreePath), { recursive: true });
445
+ try {
446
+ await runGit(normalizedCwd, [
447
+ "worktree",
448
+ "add",
449
+ "-b",
450
+ normalizedBranch,
451
+ worktreePath,
452
+ normalizedOptions.base
453
+ ]);
454
+ } catch (error) {
455
+ if (isBranchAlreadyExistsError(error, normalizedBranch)) {
456
+ throw new Error(`Git worktree branch '${normalizedBranch}' already exists.`);
457
+ }
458
+ throw error;
459
+ }
460
+ return {
461
+ path: worktreePath,
462
+ branch: normalizedBranch
463
+ };
464
+ },
465
+ async worktreeRemove(path) {
466
+ const repoRoot = await getRepoRoot(normalizedCwd);
467
+ const worktreePath = await resolveWorktreePath(repoRoot, path, "Git worktree path");
468
+ const worktrees = await listWorktrees(normalizedCwd);
469
+ if (!worktrees.some((worktree) => resolve(worktree.path) === worktreePath)) {
470
+ return;
471
+ }
472
+ await runGit(normalizedCwd, ["worktree", "remove", "--force", worktreePath]);
473
+ await rm(worktreePath, { recursive: true, force: true });
474
+ },
475
+ async worktreeList() {
476
+ return listWorktrees(normalizedCwd);
477
+ }
478
+ };
479
+ }
480
+ function normalizeCommitOptions(options) {
481
+ if (!isRecord(options)) {
482
+ throw new Error("Git commit options must be an object.");
483
+ }
484
+ const files = getOwnProperty(options, "files");
485
+ return {
486
+ message: readNonEmptyString2(getOwnProperty(options, "message"), "Git commit options message"),
487
+ files: files === void 0 ? void 0 : readNonEmptyStringArray(files, "Git commit options files")
488
+ };
489
+ }
490
+ function normalizeSavepoint(savepoint) {
491
+ if (!isRecord(savepoint)) {
492
+ throw new Error("Git savepoint must be an object.");
493
+ }
494
+ const stashRefValue = getOwnProperty(savepoint, "stashRef");
495
+ const stashRef = stashRefValue === void 0 ? void 0 : readNonEmptyString2(stashRefValue, "Git savepoint stashRef");
496
+ if (stashRef !== void 0 && !stashRef.startsWith(SAVEPOINT_REF_PREFIX)) {
497
+ throw new Error("Git savepoint stashRef must be a Poe checkpoint ref.");
498
+ }
499
+ return {
500
+ head: readNonEmptyString2(getOwnProperty(savepoint, "head"), "Git savepoint head"),
501
+ stashRef
502
+ };
503
+ }
504
+ function normalizeWorktreeCreateOptions(options) {
505
+ if (options === void 0) {
506
+ return {
507
+ base: "HEAD"
508
+ };
509
+ }
510
+ if (!isRecord(options)) {
511
+ throw new Error("Git worktree create options must be an object.");
512
+ }
513
+ const base = getOwnProperty(options, "base");
514
+ const path = getOwnProperty(options, "path");
515
+ return {
516
+ base: base === void 0 ? "HEAD" : readNonEmptyString2(base, "Git worktree create options base"),
517
+ path: path === void 0 ? void 0 : readNonEmptyString2(path, "Git worktree create options path")
518
+ };
519
+ }
520
+ function createSavepointRef() {
521
+ return `${SAVEPOINT_REF_PREFIX}${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
522
+ }
523
+ function createDefaultWorktreePath(repoRoot, branch) {
524
+ return resolve(repoRoot, ".poe-code", "worktrees", createSafeBranchDirectoryName(branch));
525
+ }
526
+ function createSafeBranchDirectoryName(branch) {
527
+ return encodeURIComponent(branch);
528
+ }
529
+ async function getRepoRoot(cwd) {
530
+ return runGitAndTrim(cwd, ["rev-parse", "--show-toplevel"]);
531
+ }
532
+ async function gitRefExists(cwd, ref) {
533
+ try {
534
+ await runGit(cwd, ["show-ref", "--verify", "--quiet", ref]);
535
+ return true;
536
+ } catch (error) {
537
+ void error;
538
+ return false;
539
+ }
540
+ }
541
+ async function listWorktrees(cwd) {
542
+ const { stdout } = await runGit(cwd, ["worktree", "list", "--porcelain"]);
543
+ return parseWorktreeList(stdout);
544
+ }
545
+ function parseWorktreeList(output) {
546
+ const worktrees = [];
547
+ let current = {};
548
+ const finishCurrent = () => {
549
+ if (current.path !== void 0 && current.branch !== void 0) {
550
+ worktrees.push({
551
+ path: current.path,
552
+ branch: current.branch
553
+ });
554
+ }
555
+ current = {};
556
+ };
557
+ for (const line of output.split("\n")) {
558
+ if (line.length === 0) {
559
+ finishCurrent();
560
+ continue;
561
+ }
562
+ if (line.startsWith("worktree ")) {
563
+ current.path = line.slice("worktree ".length);
564
+ continue;
565
+ }
566
+ if (line.startsWith("branch ")) {
567
+ current.branch = parseBranchRef(line.slice("branch ".length));
568
+ }
569
+ }
570
+ finishCurrent();
571
+ return worktrees;
572
+ }
573
+ function parseBranchRef(ref) {
574
+ const branchPrefix = "refs/heads/";
575
+ return ref.startsWith(branchPrefix) ? ref.slice(branchPrefix.length) : ref;
576
+ }
577
+ async function resolveWorktreePath(repoRoot, path, label) {
578
+ const resolvedRoot = resolve(repoRoot);
579
+ const resolvedPath = isAbsolute(path) ? resolve(path) : resolve(resolvedRoot, path);
580
+ const canonicalRoot = await realpath(resolvedRoot);
581
+ const canonicalPath = await resolveCanonicalPath({ realpath, readlink }, resolvedPath);
582
+ const [inside, isRootItself] = await Promise.all([
583
+ containsPath(stat2, canonicalRoot, canonicalPath),
584
+ isSamePath(stat2, canonicalPath, canonicalRoot)
585
+ ]);
586
+ if (!inside || isRootItself) {
587
+ throw new Error(`${label} must be inside the git repository.`);
588
+ }
589
+ return canonicalPath;
590
+ }
591
+ function isBranchAlreadyExistsError(error, branch) {
592
+ return error instanceof Error && error.message.includes(branch) && error.message.includes("already exists");
593
+ }
594
+ async function runGitAndTrim(cwd, args) {
595
+ const { stdout } = await runGit(cwd, args);
596
+ return stdout.trim();
597
+ }
598
+ async function runGit(cwd, args) {
599
+ return new Promise((resolve2, reject) => {
600
+ execFile(
601
+ "git",
602
+ args,
603
+ {
604
+ cwd,
605
+ encoding: "utf8",
606
+ maxBuffer: GIT_EXEC_MAX_BUFFER
607
+ },
608
+ (error, stdout, stderr) => {
609
+ if (error) {
610
+ reject(
611
+ new Error(
612
+ `${formatGitCommand(args)} failed: ${pickGitFailureMessage(stdout, stderr, error)}`
613
+ )
614
+ );
615
+ return;
616
+ }
617
+ resolve2({
618
+ stdout,
619
+ stderr
620
+ });
621
+ }
622
+ );
623
+ });
624
+ }
625
+ async function cleanupFailedCheckpoint(cwd, stashRef) {
626
+ await deleteSavepointRef(cwd, stashRef);
627
+ const restored = await tryRunGit(cwd, ["stash", "apply", "--index", "stash@{0}"]);
628
+ if (restored) {
629
+ await tryRunGit(cwd, ["stash", "drop", "stash@{0}"]);
630
+ }
631
+ }
632
+ async function deleteSavepointRef(cwd, stashRef) {
633
+ await tryRunGit(cwd, ["update-ref", "--delete", stashRef]);
634
+ }
635
+ async function tryRunGit(cwd, args) {
636
+ try {
637
+ await runGit(cwd, args);
638
+ return true;
639
+ } catch (error) {
640
+ void error;
641
+ return false;
642
+ }
643
+ }
644
+ function formatGitCommand(args) {
645
+ return ["git", ...args].join(" ");
646
+ }
647
+ function pickGitFailureMessage(stdout, stderr, error) {
648
+ const stderrText = stderr.trim();
649
+ if (stderrText.length > 0) {
650
+ return stderrText;
651
+ }
652
+ const stdoutText = stdout.trim();
653
+ if (stdoutText.length > 0) {
654
+ return stdoutText;
655
+ }
656
+ return error.message;
657
+ }
658
+ function readNonEmptyString2(value, label) {
659
+ if (typeof value !== "string" || value.trim().length === 0) {
660
+ throw new Error(`${label} must be a non-empty string.`);
661
+ }
662
+ return value;
663
+ }
664
+ function readNonEmptyStringArray(value, label) {
665
+ if (!Array.isArray(value) || value.length === 0) {
666
+ throw new Error(`${label} must be a non-empty array of strings.`);
667
+ }
668
+ const entries = value.map((entry, index) => readNonEmptyString2(entry, `${label}[${index}]`));
669
+ return [...entries];
670
+ }
671
+ function isRecord(value) {
672
+ return typeof value === "object" && value !== null;
673
+ }
674
+ function getOwnProperty(value, name) {
675
+ return hasOwnProperty(value, name) ? value[name] : void 0;
676
+ }
677
+ function hasOwnProperty(value, name) {
678
+ return Object.prototype.hasOwnProperty.call(value, name);
679
+ }
680
+
681
+ // packages/safejs/src/modules/time.ts
682
+ function makeTimeModule(options = {}) {
683
+ const hasDeterministicRandom = options.random !== void 0 || options.seed !== void 0;
684
+ const random = options.random ?? (options.seed === void 0 ? () => Math.random() : createSeededRandom(options.seed).next);
685
+ const now = options.now ?? (() => Date.now());
686
+ const signal = options.signal;
687
+ async function sleep(ms) {
688
+ assertSleepDelay(ms);
689
+ return await new Promise((resolve2, reject) => {
690
+ if (signal?.aborted === true) {
691
+ reject(createSleepAbortError());
692
+ return;
693
+ }
694
+ const start = performance.now();
695
+ let timeout = setTimeout(resolveSleep, ms);
696
+ function cleanup() {
697
+ clearTimeout(timeout);
698
+ signal?.removeEventListener("abort", rejectSleep);
699
+ }
700
+ function resolveSleep() {
701
+ const remainingMs = ms - (performance.now() - start);
702
+ if (remainingMs > 0) {
703
+ timeout = setTimeout(resolveSleep, remainingMs);
704
+ return;
705
+ }
706
+ cleanup();
707
+ resolve2();
708
+ }
709
+ function rejectSleep() {
710
+ cleanup();
711
+ reject(createSleepAbortError());
712
+ }
713
+ signal?.addEventListener("abort", rejectSleep, { once: true });
714
+ });
715
+ }
716
+ return {
717
+ random,
718
+ now,
719
+ sleep,
720
+ uuid: hasDeterministicRandom ? () => createRandomUuid(random) : () => crypto.randomUUID()
721
+ };
722
+ }
723
+ function createRandomUuid(random) {
724
+ const bytes = Array.from({ length: 16 }, () => Math.floor(readRandomUnit(random()) * 256));
725
+ bytes[6] = bytes[6] & 15 | 64;
726
+ bytes[8] = bytes[8] & 63 | 128;
727
+ const hex = bytes.map((byte) => byte.toString(16).padStart(2, "0")).join("");
728
+ return [
729
+ hex.slice(0, 8),
730
+ hex.slice(8, 12),
731
+ hex.slice(12, 16),
732
+ hex.slice(16, 20),
733
+ hex.slice(20)
734
+ ].join("-");
735
+ }
736
+ function readRandomUnit(value) {
737
+ if (Number.isFinite(value) && value >= 0 && value < 1) {
738
+ return value;
739
+ }
740
+ throw new RangeError("time.uuid() random source must return a number in [0, 1).");
741
+ }
742
+ function assertSleepDelay(ms) {
743
+ if (Number.isFinite(ms) && ms >= 0) {
744
+ return;
745
+ }
746
+ throw new RangeError("time.sleep(ms) requires a non-negative finite millisecond delay.");
747
+ }
748
+ function createSleepAbortError() {
749
+ return new Error("time.sleep aborted.");
750
+ }
751
+ export {
752
+ AgentSpawnError,
753
+ Budget,
754
+ FileSnapshotBackend,
755
+ HostCallResumabilityError,
756
+ HostOperationResumePolicyError,
757
+ SandboxError,
758
+ SnapshotValidationError,
759
+ createReplayableRandom,
760
+ createSpawnUsageAccumulator,
761
+ declareHostOperation,
762
+ deepCopyFromSandbox,
763
+ deepCopyToSandbox,
764
+ dump,
765
+ extractBlock,
766
+ findExportedConstInitializer,
767
+ formatInterpreterError,
768
+ lint,
769
+ makeAgentModule,
770
+ makeEnvModule,
771
+ makeFailModule,
772
+ makeFsModule,
773
+ makeGitModule,
774
+ makeHarnessModule,
775
+ makeLogModule,
776
+ makeMcpModule,
777
+ makeMetricModule,
778
+ makeTimeModule,
779
+ noopOtelSink,
780
+ parse,
781
+ parseMcpConfig,
782
+ parseModule,
783
+ registerPendingHostCallPolicy,
784
+ restore,
785
+ run,
786
+ runHarness,
787
+ runHarnessPair,
788
+ runWithSpawnUsageAccumulator,
789
+ splitFrontmatter
790
+ };
791
+ //# sourceMappingURL=index.js.map