poe-code 3.0.203 → 3.0.204

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 (110) hide show
  1. package/dist/cli/commands/braintrust.d.ts +3 -0
  2. package/dist/cli/commands/braintrust.js +77 -0
  3. package/dist/cli/commands/braintrust.js.map +1 -0
  4. package/dist/cli/commands/configure.d.ts +1 -0
  5. package/dist/cli/commands/configure.js +197 -0
  6. package/dist/cli/commands/configure.js.map +1 -1
  7. package/dist/cli/commands/experiment.js +42 -5
  8. package/dist/cli/commands/experiment.js.map +1 -1
  9. package/dist/cli/commands/harness.d.ts +3 -0
  10. package/dist/cli/commands/harness.js +260 -0
  11. package/dist/cli/commands/harness.js.map +1 -0
  12. package/dist/cli/commands/pipeline.js +58 -24
  13. package/dist/cli/commands/pipeline.js.map +1 -1
  14. package/dist/cli/commands/ralph.js +8 -3
  15. package/dist/cli/commands/ralph.js.map +1 -1
  16. package/dist/cli/commands/runtime/build.d.ts +7 -0
  17. package/dist/cli/commands/runtime/build.js +128 -0
  18. package/dist/cli/commands/runtime/build.js.map +1 -0
  19. package/dist/cli/commands/runtime/index.d.ts +3 -0
  20. package/dist/cli/commands/runtime/index.js +14 -0
  21. package/dist/cli/commands/runtime/index.js.map +1 -0
  22. package/dist/cli/commands/runtime/init.d.ts +7 -0
  23. package/dist/cli/commands/runtime/init.js +39 -0
  24. package/dist/cli/commands/runtime/init.js.map +1 -0
  25. package/dist/cli/commands/runtime/jobs/attach.d.ts +3 -0
  26. package/dist/cli/commands/runtime/jobs/attach.js +35 -0
  27. package/dist/cli/commands/runtime/jobs/attach.js.map +1 -0
  28. package/dist/cli/commands/runtime/jobs/index.d.ts +3 -0
  29. package/dist/cli/commands/runtime/jobs/index.js +16 -0
  30. package/dist/cli/commands/runtime/jobs/index.js.map +1 -0
  31. package/dist/cli/commands/runtime/jobs/logs.d.ts +3 -0
  32. package/dist/cli/commands/runtime/jobs/logs.js +27 -0
  33. package/dist/cli/commands/runtime/jobs/logs.js.map +1 -0
  34. package/dist/cli/commands/runtime/jobs/ls.d.ts +3 -0
  35. package/dist/cli/commands/runtime/jobs/ls.js +60 -0
  36. package/dist/cli/commands/runtime/jobs/ls.js.map +1 -0
  37. package/dist/cli/commands/runtime/jobs/sandbox.d.ts +3 -0
  38. package/dist/cli/commands/runtime/jobs/sandbox.js +15 -0
  39. package/dist/cli/commands/runtime/jobs/sandbox.js.map +1 -0
  40. package/dist/cli/commands/runtime/jobs/shared.d.ts +22 -0
  41. package/dist/cli/commands/runtime/jobs/shared.js +124 -0
  42. package/dist/cli/commands/runtime/jobs/shared.js.map +1 -0
  43. package/dist/cli/commands/runtime/jobs/stop.d.ts +3 -0
  44. package/dist/cli/commands/runtime/jobs/stop.js +31 -0
  45. package/dist/cli/commands/runtime/jobs/stop.js.map +1 -0
  46. package/dist/cli/commands/runtime/jobs/sync.d.ts +3 -0
  47. package/dist/cli/commands/runtime/jobs/sync.js +25 -0
  48. package/dist/cli/commands/runtime/jobs/sync.js.map +1 -0
  49. package/dist/cli/commands/runtime/shared.d.ts +20 -0
  50. package/dist/cli/commands/runtime/shared.js +69 -0
  51. package/dist/cli/commands/runtime/shared.js.map +1 -0
  52. package/dist/cli/commands/runtime/templates/clear.d.ts +3 -0
  53. package/dist/cli/commands/runtime/templates/clear.js +53 -0
  54. package/dist/cli/commands/runtime/templates/clear.js.map +1 -0
  55. package/dist/cli/commands/runtime/templates/index.d.ts +3 -0
  56. package/dist/cli/commands/runtime/templates/index.js +10 -0
  57. package/dist/cli/commands/runtime/templates/index.js.map +1 -0
  58. package/dist/cli/commands/runtime/templates/ls.d.ts +3 -0
  59. package/dist/cli/commands/runtime/templates/ls.js +52 -0
  60. package/dist/cli/commands/runtime/templates/ls.js.map +1 -0
  61. package/dist/cli/commands/runtime-options.d.ts +1 -0
  62. package/dist/cli/commands/runtime-options.js +5 -2
  63. package/dist/cli/commands/runtime-options.js.map +1 -1
  64. package/dist/cli/commands/spawn.js +27 -4
  65. package/dist/cli/commands/spawn.js.map +1 -1
  66. package/dist/cli/program.js +17 -1
  67. package/dist/cli/program.js.map +1 -1
  68. package/dist/index.js +24192 -2429
  69. package/dist/index.js.map +4 -4
  70. package/dist/providers/claude-code.js +1692 -93
  71. package/dist/providers/claude-code.js.map +4 -4
  72. package/dist/providers/codex.js +1692 -93
  73. package/dist/providers/codex.js.map +4 -4
  74. package/dist/providers/goose.js +1687 -88
  75. package/dist/providers/goose.js.map +4 -4
  76. package/dist/providers/kimi.js +1692 -93
  77. package/dist/providers/kimi.js.map +4 -4
  78. package/dist/providers/opencode.js +1692 -93
  79. package/dist/providers/opencode.js.map +4 -4
  80. package/dist/providers/poe-agent.js +1580 -308
  81. package/dist/providers/poe-agent.js.map +4 -4
  82. package/dist/providers/spawn-options.d.ts +4 -1
  83. package/dist/sdk/experiment.js +1 -0
  84. package/dist/sdk/experiment.js.map +1 -1
  85. package/dist/sdk/ralph.js +108 -16
  86. package/dist/sdk/ralph.js.map +1 -1
  87. package/dist/sdk/spawn.js +11 -4
  88. package/dist/sdk/spawn.js.map +1 -1
  89. package/dist/sdk/types.d.ts +12 -1
  90. package/dist/utils/command-checks.js +2 -29
  91. package/dist/utils/command-checks.js.map +1 -1
  92. package/package.json +12 -7
  93. package/packages/design-system/dist/components/help-formatter-plain.d.ts +4 -0
  94. package/packages/design-system/dist/components/help-formatter-plain.js +132 -0
  95. package/packages/design-system/dist/components/help-formatter.d.ts +13 -0
  96. package/packages/design-system/dist/components/help-formatter.js +116 -7
  97. package/packages/design-system/dist/components/index.d.ts +2 -2
  98. package/packages/design-system/dist/components/index.js +1 -1
  99. package/packages/design-system/dist/components/text.d.ts +1 -0
  100. package/packages/design-system/dist/components/text.js +8 -0
  101. package/packages/design-system/dist/index.d.ts +3 -2
  102. package/packages/design-system/dist/index.js +2 -1
  103. package/packages/memory/dist/index.js +1201 -115
  104. package/packages/memory/dist/index.js.map +4 -4
  105. package/packages/superintendent/dist/commands/run.d.ts +10 -0
  106. package/packages/superintendent/dist/commands/run.js +96 -49
  107. package/packages/superintendent/dist/commands/superintendent-group.d.ts +6 -0
  108. package/packages/superintendent/dist/runtime/agent-runner.d.ts +1 -0
  109. package/packages/superintendent/dist/runtime/agent-runner.js +4 -2
  110. package/packages/superintendent/dist/runtime/loop.d.ts +1 -0
@@ -94,6 +94,11 @@ var runtimeConfigScope = {
94
94
  default: "",
95
95
  doc: "Path to the Docker build context"
96
96
  },
97
+ workspace_dir: {
98
+ type: "string",
99
+ default: "/workspace",
100
+ doc: "Sandbox-local workspace directory for E2B runtime upload, execution, and download"
101
+ },
97
102
  engine: {
98
103
  type: "string",
99
104
  default: "",
@@ -115,6 +120,11 @@ var runtimeConfigScope = {
115
120
  default: "",
116
121
  doc: "Prebuilt E2B template id"
117
122
  },
123
+ from_template: {
124
+ type: "string",
125
+ default: "",
126
+ doc: "Existing E2B template alias to extend instead of using the Dockerfile FROM image"
127
+ },
118
128
  cpu: {
119
129
  type: "json",
120
130
  default: void 0,
@@ -138,11 +148,6 @@ var runtimeConfigScope = {
138
148
  default: void 0,
139
149
  parse: parseOptionalNumber,
140
150
  doc: "Hours to keep an E2B sandbox alive after job exit"
141
- },
142
- api_key_env: {
143
- type: "string",
144
- default: "",
145
- doc: "Environment variable name containing the E2B API key"
146
151
  }
147
152
  }
148
153
  };
@@ -162,6 +167,7 @@ function parseRunner(raw) {
162
167
  detach: parseOptionalBoolean(record.detach, "runner.detach") ?? false,
163
168
  upload_max_file_mb: uploadMaxFileMb,
164
169
  download_conflict: parseDownloadConflict(record.download_conflict),
170
+ sync: parseRunnerSync(record.sync),
165
171
  workspace: parseRunnerWorkspace(record.workspace)
166
172
  });
167
173
  }
@@ -200,13 +206,14 @@ function parseRuntime(raw) {
200
206
  ...shared,
201
207
  type,
202
208
  template_id: parseOptionalString(record.template_id),
209
+ from_template: parseOptionalString(record.from_template),
203
210
  dockerfile: parseOptionalString(record.dockerfile),
204
211
  build_context: parseOptionalString(record.build_context),
212
+ workspace_dir: parseWorkspaceDir(record.workspace_dir),
205
213
  cpu: parseOptionalNumber(record.cpu),
206
214
  memory_mb: parseOptionalNumber(record.memory_mb),
207
215
  timeout_minutes: parseOptionalNumber(record.timeout_minutes),
208
- preserve_after_exit_hours: preserveAfterExitHours,
209
- api_key_env: parseOptionalString(record.api_key_env) ?? "E2B_API_KEY"
216
+ preserve_after_exit_hours: preserveAfterExitHours
210
217
  });
211
218
  }
212
219
  return {
@@ -295,11 +302,23 @@ function parseRuntimeType(value) {
295
302
  }
296
303
  throw new Error('type: expected "host", "docker", or "e2b".');
297
304
  }
305
+ function parseWorkspaceDir(value) {
306
+ const workspaceDir = parseOptionalString(value) ?? "/workspace";
307
+ if (!path2.posix.isAbsolute(workspaceDir)) {
308
+ throw new Error("workspace_dir: expected an absolute sandbox path.");
309
+ }
310
+ let normalized = path2.posix.normalize(workspaceDir);
311
+ while (normalized.length > 1 && normalized.endsWith("/")) {
312
+ normalized = normalized.slice(0, -1);
313
+ }
314
+ return normalized;
315
+ }
298
316
  function createDefaultRunnerScope() {
299
317
  return {
300
318
  detach: false,
301
319
  upload_max_file_mb: 100,
302
320
  download_conflict: "refuse",
321
+ sync: "both",
303
322
  workspace: {
304
323
  exclude: [...defaultWorkspaceExclude]
305
324
  }
@@ -330,6 +349,15 @@ function parseDownloadConflict(value) {
330
349
  }
331
350
  throw new Error('runner.download_conflict: expected "refuse" or "overwrite".');
332
351
  }
352
+ function parseRunnerSync(value) {
353
+ if (value === void 0) {
354
+ return "both";
355
+ }
356
+ if (value === "both" || value === "upload" || value === "none") {
357
+ return value;
358
+ }
359
+ throw new Error('runner.sync: expected "both", "upload", or "none".');
360
+ }
333
361
  function parseBuildArgs(value) {
334
362
  if (value === void 0) {
335
363
  return {};
@@ -442,6 +470,43 @@ function defineScope(scope, schema) {
442
470
  schema
443
471
  };
444
472
  }
473
+ var integrationsConfigScope = defineScope("integrations", {
474
+ braintrust: {
475
+ type: "json",
476
+ default: {
477
+ enabled: false
478
+ },
479
+ parse: parseBraintrustIntegrationConfig,
480
+ doc: "Braintrust integration configuration"
481
+ }
482
+ });
483
+ function parseBraintrustIntegrationConfig(value) {
484
+ if (!isRecord(value)) {
485
+ throw new Error("expected an object");
486
+ }
487
+ const enabled = value.enabled === void 0 ? false : value.enabled;
488
+ if (typeof enabled !== "boolean") {
489
+ throw new Error("enabled must be a boolean");
490
+ }
491
+ return {
492
+ enabled,
493
+ ...optionalStringEntry("apiKey", value.apiKey),
494
+ ...optionalStringEntry("apiUrl", value.apiUrl),
495
+ ...optionalStringEntry("project", value.project)
496
+ };
497
+ }
498
+ function optionalStringEntry(key, value) {
499
+ if (value === void 0) {
500
+ return {};
501
+ }
502
+ if (typeof value !== "string") {
503
+ throw new Error(`${key} must be a string`);
504
+ }
505
+ return { [key]: value };
506
+ }
507
+ function isRecord(value) {
508
+ return typeof value === "object" && value !== null && !Array.isArray(value);
509
+ }
445
510
 
446
511
  // packages/poe-code-config/src/plan-scope.ts
447
512
  var planConfigScope = defineScope("plan", {
@@ -546,11 +611,11 @@ function stripBom(content) {
546
611
  function mergeLayers(layers) {
547
612
  return mergeObjectLayers(layers, []);
548
613
  }
549
- function mergeObjectLayers(layers, path38) {
614
+ function mergeObjectLayers(layers, path42) {
550
615
  const data = {};
551
616
  const sources = {};
552
617
  for (const key of collectKeys(layers)) {
553
- const resolved = resolveKey(layers, key, path38);
618
+ const resolved = resolveKey(layers, key, path42);
554
619
  if (resolved === void 0) {
555
620
  continue;
556
621
  }
@@ -568,7 +633,7 @@ function collectKeys(layers) {
568
633
  }
569
634
  return [...keys];
570
635
  }
571
- function resolveKey(layers, key, path38) {
636
+ function resolveKey(layers, key, path42) {
572
637
  let winningSource;
573
638
  let winningValue;
574
639
  const objectLayers = [];
@@ -598,9 +663,9 @@ function resolveKey(layers, key, path38) {
598
663
  if (winningSource === void 0) {
599
664
  return void 0;
600
665
  }
601
- const fullPath = buildPath(path38, key);
666
+ const fullPath = buildPath(path42, key);
602
667
  if (isPlainObject(winningValue)) {
603
- const merged = mergeObjectLayers(objectLayers, [...path38, key]);
668
+ const merged = mergeObjectLayers(objectLayers, [...path42, key]);
604
669
  return {
605
670
  value: merged.data,
606
671
  sources: {
@@ -625,8 +690,8 @@ function isWinningCandidate(key, value) {
625
690
  }
626
691
  return true;
627
692
  }
628
- function buildPath(path38, key) {
629
- return [...path38, key].join(".");
693
+ function buildPath(path42, key) {
694
+ return [...path42, key].join(".");
630
695
  }
631
696
  function isPlainObject(value) {
632
697
  if (value === null || Array.isArray(value) || typeof value !== "object") {
@@ -1260,16 +1325,16 @@ function getConfigFormat(pathOrFormat) {
1260
1325
  }
1261
1326
  return formatRegistry[formatName];
1262
1327
  }
1263
- function detectFormat2(path38) {
1264
- const ext = getExtension(path38);
1328
+ function detectFormat2(path42) {
1329
+ const ext = getExtension(path42);
1265
1330
  return extensionMap[ext];
1266
1331
  }
1267
- function getExtension(path38) {
1268
- const lastDot = path38.lastIndexOf(".");
1332
+ function getExtension(path42) {
1333
+ const lastDot = path42.lastIndexOf(".");
1269
1334
  if (lastDot === -1) {
1270
1335
  return "";
1271
1336
  }
1272
- return path38.slice(lastDot).toLowerCase();
1337
+ return path42.slice(lastDot).toLowerCase();
1273
1338
  }
1274
1339
 
1275
1340
  // packages/config-mutations/src/execution/path-utils.ts
@@ -1977,7 +2042,7 @@ async function parseStoredDocument(fs14, filePath, raw) {
1977
2042
  }
1978
2043
  }
1979
2044
  function normalizeDocument(value) {
1980
- if (!isRecord(value)) {
2045
+ if (!isRecord2(value)) {
1981
2046
  return {};
1982
2047
  }
1983
2048
  const document = {};
@@ -1990,7 +2055,7 @@ function normalizeDocument(value) {
1990
2055
  return document;
1991
2056
  }
1992
2057
  function normalizeScopeValues(value) {
1993
- if (!isRecord(value)) {
2058
+ if (!isRecord2(value)) {
1994
2059
  return {};
1995
2060
  }
1996
2061
  const normalized = {};
@@ -2022,7 +2087,7 @@ function createInvalidBackupPath(filePath) {
2022
2087
  const baseName = path7.basename(filePath);
2023
2088
  return path7.join(directory, `${baseName}.invalid-${createTimestamp()}.json`);
2024
2089
  }
2025
- function isRecord(value) {
2090
+ function isRecord2(value) {
2026
2091
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
2027
2092
  }
2028
2093
  function resolveConfigPath(homeDir) {
@@ -2139,7 +2204,7 @@ function mergeScope(scope, baseScope, overrideScope) {
2139
2204
  ...Object.fromEntries(scopeEntries)
2140
2205
  };
2141
2206
  }
2142
- function mergeRuntimeScope(baseScope, overrideScope, path38 = []) {
2207
+ function mergeRuntimeScope(baseScope, overrideScope, path42 = []) {
2143
2208
  const merged = {};
2144
2209
  const keys = /* @__PURE__ */ new Set([...Object.keys(baseScope), ...Object.keys(overrideScope)]);
2145
2210
  for (const key of keys) {
@@ -2151,22 +2216,22 @@ function mergeRuntimeScope(baseScope, overrideScope, path38 = []) {
2151
2216
  }
2152
2217
  continue;
2153
2218
  }
2154
- if (isRuntimeConcatenativeArray([...path38, key]) && Array.isArray(baseValue) && Array.isArray(overrideValue)) {
2219
+ if (isRuntimeConcatenativeArray([...path42, key]) && Array.isArray(baseValue) && Array.isArray(overrideValue)) {
2155
2220
  merged[key] = [...baseValue, ...overrideValue];
2156
2221
  continue;
2157
2222
  }
2158
- if (isRecord2(baseValue) && isRecord2(overrideValue)) {
2159
- merged[key] = mergeRuntimeScope(baseValue, overrideValue, [...path38, key]);
2223
+ if (isRecord3(baseValue) && isRecord3(overrideValue)) {
2224
+ merged[key] = mergeRuntimeScope(baseValue, overrideValue, [...path42, key]);
2160
2225
  continue;
2161
2226
  }
2162
2227
  merged[key] = overrideValue;
2163
2228
  }
2164
2229
  return merged;
2165
2230
  }
2166
- function isRuntimeConcatenativeArray(path38) {
2167
- return path38.join(".") === "mounts" || path38.join(".") === "runner.workspace.exclude";
2231
+ function isRuntimeConcatenativeArray(path42) {
2232
+ return path42.join(".") === "mounts" || path42.join(".") === "runner.workspace.exclude";
2168
2233
  }
2169
- function isRecord2(value) {
2234
+ function isRecord3(value) {
2170
2235
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
2171
2236
  }
2172
2237
 
@@ -2285,8 +2350,8 @@ function isPidRunning(pid) {
2285
2350
  }
2286
2351
  function createDefaultFs() {
2287
2352
  return {
2288
- open: (path38, flags) => fsPromises.open(path38, flags),
2289
- readFile: (path38, encoding) => fsPromises.readFile(path38, encoding),
2353
+ open: (path42, flags) => fsPromises.open(path42, flags),
2354
+ readFile: (path42, encoding) => fsPromises.readFile(path42, encoding),
2290
2355
  stat: fsPromises.stat,
2291
2356
  unlink: fsPromises.unlink
2292
2357
  };
@@ -2579,12 +2644,12 @@ function parseJobEntry(content) {
2579
2644
  return parsed;
2580
2645
  }
2581
2646
  function isJobEntry(value) {
2582
- return isRecord3(value) && typeof value.id === "string" && typeof value.env_id === "string" && typeof value.env_kind === "string" && typeof value.tool === "string" && Array.isArray(value.argv) && value.argv.every((arg) => typeof arg === "string") && typeof value.cwd === "string" && typeof value.started_at === "string" && isJobStatus(value.status) && (value.exit_code === void 0 || typeof value.exit_code === "number") && (value.exited_at === void 0 || typeof value.exited_at === "string") && (value.log_file === void 0 || typeof value.log_file === "string");
2647
+ return isRecord4(value) && typeof value.id === "string" && typeof value.env_id === "string" && typeof value.env_kind === "string" && typeof value.tool === "string" && Array.isArray(value.argv) && value.argv.every((arg) => typeof arg === "string") && typeof value.cwd === "string" && typeof value.started_at === "string" && isJobStatus(value.status) && (value.exit_code === void 0 || typeof value.exit_code === "number") && (value.exited_at === void 0 || typeof value.exited_at === "string") && (value.log_file === void 0 || typeof value.log_file === "string");
2583
2648
  }
2584
2649
  function isJobStatus(value) {
2585
2650
  return value === "pending" || value === "running" || value === "exited" || value === "killed" || value === "lost";
2586
2651
  }
2587
- function isRecord3(value) {
2652
+ function isRecord4(value) {
2588
2653
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
2589
2654
  }
2590
2655
 
@@ -2653,7 +2718,7 @@ function createEmptyState() {
2653
2718
  };
2654
2719
  }
2655
2720
  function normalizeTemplateState(value) {
2656
- if (!isRecord4(value)) {
2721
+ if (!isRecord5(value)) {
2657
2722
  return createEmptyState();
2658
2723
  }
2659
2724
  return {
@@ -2662,7 +2727,7 @@ function normalizeTemplateState(value) {
2662
2727
  };
2663
2728
  }
2664
2729
  function normalizeTemplateEntries(value) {
2665
- if (!isRecord4(value)) {
2730
+ if (!isRecord5(value)) {
2666
2731
  return {};
2667
2732
  }
2668
2733
  const entries = {};
@@ -2674,9 +2739,9 @@ function normalizeTemplateEntries(value) {
2674
2739
  return entries;
2675
2740
  }
2676
2741
  function isTemplateEntry(value) {
2677
- return isRecord4(value) && typeof value.hash === "string" && typeof value.runtime_type === "string" && typeof value.dockerfile_path === "string" && typeof value.built_at === "string" && (value.template_id === void 0 || typeof value.template_id === "string") && (value.image === void 0 || typeof value.image === "string");
2742
+ return isRecord5(value) && typeof value.hash === "string" && typeof value.runtime_type === "string" && typeof value.dockerfile_path === "string" && typeof value.built_at === "string" && (value.template_id === void 0 || typeof value.template_id === "string") && (value.image === void 0 || typeof value.image === "string");
2678
2743
  }
2679
- function isRecord4(value) {
2744
+ function isRecord5(value) {
2680
2745
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
2681
2746
  }
2682
2747
 
@@ -2878,7 +2943,7 @@ function parseYamlFrontmatter(yamlBlock) {
2878
2943
  if (parsed === null) {
2879
2944
  return {};
2880
2945
  }
2881
- if (!isRecord5(parsed)) {
2946
+ if (!isRecord6(parsed)) {
2882
2947
  throw new Error("YAML frontmatter must parse to an object.");
2883
2948
  }
2884
2949
  return parsed;
@@ -2909,13 +2974,13 @@ function parseSources(value) {
2909
2974
  if (typeof item === "string") {
2910
2975
  return parseSourceRef(item);
2911
2976
  }
2912
- if (!isRecord5(item)) {
2977
+ if (!isRecord6(item)) {
2913
2978
  throw new Error('Invalid "sources" frontmatter. Expected each source to be a string or object.');
2914
2979
  }
2915
- const path38 = readRequiredString(item.path, "sources[].path");
2980
+ const path42 = readRequiredString(item.path, "sources[].path");
2916
2981
  const startLine = readOptionalPositiveInteger(item.startLine, "sources[].startLine");
2917
2982
  const endLine = readOptionalPositiveInteger(item.endLine, "sources[].endLine");
2918
- return parseSourceRef(serializeSourceRef({ path: path38, ...startLine === void 0 ? {} : { startLine }, ...endLine === void 0 ? {} : { endLine } }));
2983
+ return parseSourceRef(serializeSourceRef({ path: path42, ...startLine === void 0 ? {} : { startLine }, ...endLine === void 0 ? {} : { endLine } }));
2919
2984
  });
2920
2985
  }
2921
2986
  function readOptionalString(value, field) {
@@ -2948,7 +3013,7 @@ function assertValidLineNumber(line, value) {
2948
3013
  throw new Error(`Invalid source ref "${value}": line numbers must be positive integers.`);
2949
3014
  }
2950
3015
  }
2951
- function isRecord5(value) {
3016
+ function isRecord6(value) {
2952
3017
  return typeof value === "object" && value !== null && !Array.isArray(value);
2953
3018
  }
2954
3019
 
@@ -3971,7 +4036,7 @@ function parseOlderThan(value) {
3971
4036
 
3972
4037
  // packages/memory/src/ingest.ts
3973
4038
  import * as fs11 from "node:fs/promises";
3974
- import path31 from "node:path";
4039
+ import path35 from "node:path";
3975
4040
 
3976
4041
  // packages/agent-spawn/src/register-factories.ts
3977
4042
  import { spawn as spawnChildProcess2 } from "node:child_process";
@@ -4145,6 +4210,38 @@ function wrapForLogTee(argv, jobId) {
4145
4210
  ].join(" && ");
4146
4211
  return ["sh", "-c", script];
4147
4212
  }
4213
+ async function* streamLogFile(env, jobId, opts) {
4214
+ const fs14 = env.fs ?? nodeFs2;
4215
+ const file = jobLogPath(jobId);
4216
+ let byteOffset = opts.sinceByte ?? 0;
4217
+ while (true) {
4218
+ if (opts.since !== void 0 && !await wasModifiedSince(fs14, file, opts.since)) {
4219
+ await waitForLogChange(fs14, file);
4220
+ continue;
4221
+ }
4222
+ const result = await readLogChunk(fs14, file, byteOffset);
4223
+ if (result !== null) {
4224
+ byteOffset = result.nextByteOffset;
4225
+ yield result.chunk;
4226
+ continue;
4227
+ }
4228
+ await waitForLogChange(fs14, file);
4229
+ }
4230
+ }
4231
+ async function wasModifiedSince(fs14, file, since) {
4232
+ if (fs14.promises.stat === void 0) {
4233
+ return true;
4234
+ }
4235
+ try {
4236
+ const stat7 = await fs14.promises.stat(file);
4237
+ return stat7.mtimeMs >= since.getTime();
4238
+ } catch (error2) {
4239
+ if (isNodeError(error2) && error2.code === "ENOENT") {
4240
+ return false;
4241
+ }
4242
+ throw error2;
4243
+ }
4244
+ }
4148
4245
  async function waitForExit(env, jobId, opts = {}) {
4149
4246
  const fs14 = env.fs ?? nodeFs2;
4150
4247
  const file = jobExitPath(jobId);
@@ -4168,6 +4265,19 @@ function jobLogPath(jobId) {
4168
4265
  function jobExitPath(jobId) {
4169
4266
  return `${JOB_DIR}/${jobId}.exit`;
4170
4267
  }
4268
+ async function readLogChunk(fs14, file, byteOffset) {
4269
+ const contents = await readFileIfExists2(fs14, file);
4270
+ if (contents === null || byteOffset >= contents.byteLength) {
4271
+ return null;
4272
+ }
4273
+ return {
4274
+ chunk: {
4275
+ byteOffset,
4276
+ data: contents.subarray(byteOffset).toString("utf8")
4277
+ },
4278
+ nextByteOffset: contents.byteLength
4279
+ };
4280
+ }
4171
4281
  async function readTextFileIfExists(fs14, file) {
4172
4282
  const contents = await readFileIfExists2(fs14, file);
4173
4283
  return contents?.toString("utf8") ?? null;
@@ -4183,6 +4293,27 @@ async function readFileIfExists2(fs14, file) {
4183
4293
  throw error2;
4184
4294
  }
4185
4295
  }
4296
+ async function waitForLogChange(fs14, file) {
4297
+ const watch = fs14.watch;
4298
+ if (typeof watch !== "function") {
4299
+ await sleep3(POLL_INTERVAL_MS);
4300
+ return;
4301
+ }
4302
+ await new Promise((resolve2) => {
4303
+ let watcher = null;
4304
+ const timer = setTimeout(done, POLL_INTERVAL_MS);
4305
+ function done() {
4306
+ clearTimeout(timer);
4307
+ watcher?.close();
4308
+ resolve2();
4309
+ }
4310
+ try {
4311
+ watcher = watch(file, done);
4312
+ } catch {
4313
+ done();
4314
+ }
4315
+ });
4316
+ }
4186
4317
  function sleep3(ms, signal) {
4187
4318
  return new Promise((resolve2, reject) => {
4188
4319
  let timer = null;
@@ -4217,6 +4348,35 @@ function isNodeError(error2) {
4217
4348
 
4218
4349
  // packages/agent-harness-tools/src/run-poe-command.ts
4219
4350
  import { randomBytes } from "node:crypto";
4351
+
4352
+ // packages/agent-harness-tools/src/binary-exists.ts
4353
+ function createBinaryExistsDetectors(binaryName) {
4354
+ const commonPaths = [
4355
+ `/usr/local/bin/${binaryName}`,
4356
+ `/usr/bin/${binaryName}`,
4357
+ `$HOME/.local/bin/${binaryName}`,
4358
+ `$HOME/.claude/local/bin/${binaryName}`
4359
+ ];
4360
+ return [
4361
+ {
4362
+ command: "which",
4363
+ args: [binaryName],
4364
+ validate: (result) => result.exitCode === 0
4365
+ },
4366
+ {
4367
+ command: "where",
4368
+ args: [binaryName],
4369
+ validate: (result) => result.exitCode === 0 && result.stdout.trim().length > 0
4370
+ },
4371
+ {
4372
+ command: "sh",
4373
+ args: ["-c", commonPaths.map((p) => `test -f "${p}"`).join(" || ")],
4374
+ validate: (result) => result.exitCode === 0
4375
+ }
4376
+ ];
4377
+ }
4378
+
4379
+ // packages/agent-harness-tools/src/run-poe-command.ts
4220
4380
  var ULID_ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
4221
4381
  async function runPoeCommand(opts) {
4222
4382
  const jobId = createUlid();
@@ -4237,12 +4397,18 @@ async function runPoeCommand(opts) {
4237
4397
  let shouldClose = true;
4238
4398
  try {
4239
4399
  const upload = env.uploadWorkspace();
4400
+ await Promise.all([pendingJob, upload]);
4401
+ await configureE2bSpawnAgentIfAvailable({
4402
+ env,
4403
+ openSpec: opts.openSpec,
4404
+ factoryType: opts.factory.type
4405
+ });
4240
4406
  const argv = wrapCommand ? wrapForLogTee(opts.openSpec.jobLabel.argv, jobId) : opts.openSpec.jobLabel.argv;
4241
4407
  const handle = execution?.tty ? env.shell() : env.exec({
4242
4408
  command: argv[0],
4243
4409
  args: argv.slice(1),
4244
4410
  cwd: opts.openSpec.cwd,
4245
- env: execution && "env" in execution ? execution.env : opts.openSpec.env,
4411
+ env: resolveExecutionEnv(opts.openSpec),
4246
4412
  stdin: execution?.stdin ?? "inherit",
4247
4413
  stdout: execution?.stdout ?? "pipe",
4248
4414
  stderr: execution?.stderr ?? "pipe",
@@ -4252,15 +4418,19 @@ async function runPoeCommand(opts) {
4252
4418
  handle.stdin?.setDefaultEncoding("utf8");
4253
4419
  handle.stdin?.end(execution.input);
4254
4420
  }
4255
- const runningJob = Promise.all([pendingJob, upload]).then(
4256
- () => opts.state.jobs.update(jobId, {
4257
- status: "running",
4258
- env_id: env.id,
4259
- started_at: (/* @__PURE__ */ new Date()).toISOString()
4260
- })
4261
- );
4421
+ const runningJob = opts.state.jobs.update(jobId, {
4422
+ status: "running",
4423
+ env_id: env.id,
4424
+ started_at: (/* @__PURE__ */ new Date()).toISOString()
4425
+ });
4262
4426
  if (opts.detach) {
4263
4427
  await runningJob;
4428
+ setDetachedJobContext(env, {
4429
+ id: jobId,
4430
+ tool: opts.openSpec.jobLabel.tool,
4431
+ argv: opts.openSpec.jobLabel.argv
4432
+ });
4433
+ await env.detach();
4264
4434
  shouldClose = false;
4265
4435
  return { kind: "detached", jobId, envId: env.id };
4266
4436
  }
@@ -4292,6 +4462,97 @@ async function runPoeCommand(opts) {
4292
4462
  }
4293
4463
  }
4294
4464
  }
4465
+ async function configureE2bSpawnAgentIfAvailable(opts) {
4466
+ if (opts.factoryType !== "e2b") {
4467
+ return;
4468
+ }
4469
+ const agentId = resolveAgentId(opts.openSpec.jobLabel.tool);
4470
+ const agent = allAgents.find((candidate) => candidate.id === agentId);
4471
+ const binaryName = agent?.binaryName;
4472
+ if (!agentId || !binaryName) {
4473
+ return;
4474
+ }
4475
+ const commandEnv = resolveExecutionEnv(opts.openSpec);
4476
+ const exists = await binaryExists(opts.env, {
4477
+ binaryName,
4478
+ cwd: opts.openSpec.cwd,
4479
+ env: commandEnv
4480
+ });
4481
+ if (!exists) {
4482
+ return;
4483
+ }
4484
+ const result = await runProbeCommand(opts.env, {
4485
+ command: "poe-code",
4486
+ args: ["configure", "--yes", "--provider", "poe", agentId],
4487
+ cwd: opts.openSpec.cwd,
4488
+ env: commandEnv
4489
+ });
4490
+ if (result.exitCode !== 0) {
4491
+ throw new Error(
4492
+ `Failed to configure ${agentId} for Poe inside E2B sandbox.
4493
+ ${formatProbeResult(result)}`
4494
+ );
4495
+ }
4496
+ }
4497
+ async function binaryExists(env, opts) {
4498
+ for (const detector of createBinaryExistsDetectors(opts.binaryName)) {
4499
+ const result = await runProbeCommand(env, {
4500
+ ...detector,
4501
+ cwd: opts.cwd,
4502
+ env: opts.env
4503
+ });
4504
+ if (detector.validate(result)) {
4505
+ return true;
4506
+ }
4507
+ }
4508
+ return false;
4509
+ }
4510
+ function resolveExecutionEnv(openSpec) {
4511
+ const execution = openSpec.execution;
4512
+ return execution?.env ?? openSpec.env;
4513
+ }
4514
+ async function runProbeCommand(env, spec) {
4515
+ const handle = env.exec({
4516
+ command: spec.command,
4517
+ args: spec.args,
4518
+ cwd: spec.cwd,
4519
+ env: spec.env,
4520
+ stdin: "ignore",
4521
+ stdout: "pipe",
4522
+ stderr: "pipe"
4523
+ });
4524
+ const stdout = readStream(handle.stdout);
4525
+ const stderr = readStream(handle.stderr);
4526
+ const result = await handle.result;
4527
+ return {
4528
+ exitCode: result.exitCode,
4529
+ stdout: await stdout,
4530
+ stderr: await stderr
4531
+ };
4532
+ }
4533
+ function readStream(stream) {
4534
+ if (!stream) {
4535
+ return Promise.resolve("");
4536
+ }
4537
+ return new Promise((resolve2, reject) => {
4538
+ let output = "";
4539
+ stream.setEncoding("utf8");
4540
+ stream.on("data", (chunk) => {
4541
+ output += chunk.toString();
4542
+ });
4543
+ stream.on("error", reject);
4544
+ stream.on("end", () => resolve2(output));
4545
+ });
4546
+ }
4547
+ function formatProbeResult(result) {
4548
+ return [
4549
+ `Exit code: ${result.exitCode}`,
4550
+ result.stdout.trim() ? `stdout:
4551
+ ${result.stdout.trim()}` : "",
4552
+ result.stderr.trim() ? `stderr:
4553
+ ${result.stderr.trim()}` : ""
4554
+ ].filter(Boolean).join("\n");
4555
+ }
4295
4556
  async function runSync(opts) {
4296
4557
  const execution = opts.openSpec.execution;
4297
4558
  const capture = execution?.captureOutput === true;
@@ -4303,7 +4564,9 @@ async function runSync(opts) {
4303
4564
  const download = await opts.env.downloadWorkspace({
4304
4565
  conflictPolicy: opts.openSpec.runner?.download_conflict ?? "refuse"
4305
4566
  });
4306
- await opts.env.close();
4567
+ if (opts.closeAfterDownload !== false) {
4568
+ await opts.env.close();
4569
+ }
4307
4570
  return {
4308
4571
  exitCode,
4309
4572
  download,
@@ -4459,6 +4722,10 @@ function toLogStreamEnv(env) {
4459
4722
  const candidate = env;
4460
4723
  return candidate.fs === void 0 ? {} : { fs: candidate.fs };
4461
4724
  }
4725
+ function setDetachedJobContext(env, context) {
4726
+ const candidate = env;
4727
+ candidate.setDetachedJobContext?.(context);
4728
+ }
4462
4729
  function isPromiseLike(value) {
4463
4730
  return typeof value.then === "function";
4464
4731
  }
@@ -4501,10 +4768,13 @@ function registerExecutionEnvFactory(factory) {
4501
4768
  executionEnvFactories.set(factory.type, factory);
4502
4769
  }
4503
4770
  function selectExecutionEnv(runtime) {
4504
- const factory = executionEnvFactories.get(runtime.type);
4771
+ return selectExecutionEnvFactory(runtime.type);
4772
+ }
4773
+ function selectExecutionEnvFactory(type) {
4774
+ const factory = executionEnvFactories.get(type);
4505
4775
  if (factory === void 0) {
4506
4776
  throw new Error(
4507
- `No execution environment factory registered for runtime type "${runtime.type}".`
4777
+ `No execution environment factory registered for runtime type "${type}".`
4508
4778
  );
4509
4779
  }
4510
4780
  return factory;
@@ -4513,8 +4783,10 @@ function selectExecutionEnv(runtime) {
4513
4783
  // packages/agent-harness-tools/src/poe-command-execution.ts
4514
4784
  function resolvePoeCommandExecution(input) {
4515
4785
  const homeDir = input.context?.homeDir ?? os3.homedir();
4516
- const config = applyRuntimeOverrides(loadRuntimeConfig(input.cwd, homeDir), input.runtime, input.cwd);
4517
- const resolved = resolveRuntime({ cwd: input.cwd, config });
4786
+ const runtimeConfigCwd = input.runtimeConfigCwd ?? input.cwd;
4787
+ const loaded = loadRuntimeConfig(runtimeConfigCwd, homeDir);
4788
+ const config = applyRuntimeOverrides(loaded, input.runtime, runtimeConfigCwd);
4789
+ const resolved = resolveRuntime({ cwd: runtimeConfigCwd, config });
4518
4790
  const factory = selectExecutionEnv(resolved.runtime);
4519
4791
  const state = input.context?.state ?? loadState(homeDir);
4520
4792
  return {
@@ -4523,6 +4795,7 @@ function resolvePoeCommandExecution(input) {
4523
4795
  state,
4524
4796
  openSpec: {
4525
4797
  cwd: input.cwd,
4798
+ runtimeCwd: runtimeConfigCwd,
4526
4799
  runtime: resolved.runtime,
4527
4800
  runner: config.runner,
4528
4801
  state,
@@ -4538,10 +4811,11 @@ function resolvePoeCommandExecution(input) {
4538
4811
  }
4539
4812
  function applyRuntimeOverrides(config, overrides, cwd = process.cwd()) {
4540
4813
  if (!overrides) {
4541
- return config;
4814
+ return { runtime: config.runtime, runner: config.runner };
4542
4815
  }
4816
+ const base = "rawScope" in config && config.rawScope ? { ...config.rawScope } : { ...config.runtime };
4543
4817
  const runtime = parseRuntime({
4544
- ...config.runtime,
4818
+ ...base,
4545
4819
  ...overrides.runtime !== void 0 ? { type: overrides.runtime } : {},
4546
4820
  ...overrides.runtimeImage !== void 0 ? { image: overrides.runtimeImage } : {},
4547
4821
  ...overrides.runtimeTemplate !== void 0 ? { template_id: overrides.runtimeTemplate } : {},
@@ -4551,7 +4825,8 @@ function applyRuntimeOverrides(config, overrides, cwd = process.cwd()) {
4551
4825
  runtime,
4552
4826
  runner: {
4553
4827
  ...config.runner,
4554
- ...overrides.detach === true ? { detach: true } : {}
4828
+ ...overrides.detach === true ? { detach: true } : {},
4829
+ ...overrides.runnerSync !== void 0 ? { sync: overrides.runnerSync } : {}
4555
4830
  }
4556
4831
  };
4557
4832
  }
@@ -4569,6 +4844,7 @@ function loadRuntimeConfig(cwd, homeDir) {
4569
4844
  );
4570
4845
  const runtimeScope = resolveScope(runtimeConfigScope.schema, document.runtime, process.env);
4571
4846
  return {
4847
+ rawScope: { ...runtimeScope },
4572
4848
  runtime: parseRuntime(runtimeScope),
4573
4849
  runner: runtimeScope.runner
4574
4850
  };
@@ -4865,14 +5141,15 @@ var dockerExecutionEnvFactory = {
4865
5141
  context
4866
5142
  });
4867
5143
  },
4868
- async attach(envId) {
5144
+ async attach(envId, context) {
4869
5145
  const engine = detectEngine();
4870
5146
  return createDockerEnv({
4871
5147
  id: envId,
4872
- spec: createAttachedSpec(),
5148
+ spec: createAttachedSpec(context?.cwd),
4873
5149
  runner: createHostRunner(),
4874
5150
  engine,
4875
- context: detectContext()
5151
+ context: detectContext(),
5152
+ attachedJobId: context?.jobId
4876
5153
  });
4877
5154
  }
4878
5155
  };
@@ -4880,7 +5157,7 @@ function createDockerEnv(input) {
4880
5157
  const containerRef = input.id;
4881
5158
  return {
4882
5159
  id: containerRef,
4883
- job: null,
5160
+ job: input.attachedJobId === void 0 ? null : createContainerJob(containerRef, input.runner, input.engine, input.context, input.attachedJobId),
4884
5161
  async uploadWorkspace() {
4885
5162
  const tempDir = mkdtempSync(path26.join(tmpdir(), "poe-docker-upload-"));
4886
5163
  const archivePath = path26.join(tempDir, "workspace.tar");
@@ -5015,35 +5292,57 @@ async function resolveImage(input) {
5015
5292
  if (input.runtime.image !== void 0) {
5016
5293
  return input.runtime.image;
5017
5294
  }
5295
+ const result = await buildDockerRuntimeTemplate({
5296
+ cwd: input.spec.cwd,
5297
+ runtime: input.runtime,
5298
+ state: input.spec.state,
5299
+ runner: input.runner
5300
+ });
5301
+ return result.image;
5302
+ }
5303
+ async function buildDockerRuntimeTemplate(input) {
5304
+ const runner = input.runner ?? createHostRunner();
5305
+ const engine = input.runtime.engine ?? detectEngine();
5306
+ const context = detectContext();
5018
5307
  const dockerfilePath = path26.resolve(
5019
- input.spec.cwd,
5308
+ input.cwd,
5020
5309
  input.runtime.dockerfile ?? path26.join(".poe-code", "Dockerfile")
5021
5310
  );
5022
- const buildContext = path26.resolve(input.spec.cwd, input.runtime.build_context ?? ".");
5311
+ const buildContext = path26.resolve(input.cwd, input.runtime.build_context ?? ".");
5023
5312
  const dockerfileBytes = await readFile10(dockerfilePath);
5024
5313
  const hash = hashDockerTemplate(dockerfileBytes, input.runtime.build_args ?? {});
5025
- const cached2 = await input.spec.state?.templates.get("docker", hash);
5314
+ const cached2 = input.force ? null : await input.state?.templates.get("docker", hash);
5026
5315
  if (cached2?.image !== void 0) {
5027
- return cached2.image;
5316
+ return {
5317
+ backend: "docker",
5318
+ hash,
5319
+ image: cached2.image,
5320
+ cached: true
5321
+ };
5028
5322
  }
5029
5323
  const image = `poe-code/local:${hash}`;
5030
5324
  await buildImage({
5031
- runner: input.runner,
5032
- engine: input.engine,
5033
- context: input.context,
5325
+ runner,
5326
+ engine,
5327
+ context,
5034
5328
  image,
5035
5329
  dockerfilePath,
5036
5330
  buildContext,
5037
5331
  buildArgs: input.runtime.build_args ?? {}
5038
5332
  });
5039
- await input.spec.state?.templates.put("docker", {
5333
+ await input.state?.templates.put("docker", {
5040
5334
  hash,
5041
5335
  image,
5042
5336
  runtime_type: "docker",
5043
5337
  dockerfile_path: dockerfilePath,
5044
5338
  built_at: (/* @__PURE__ */ new Date()).toISOString()
5045
5339
  });
5046
- return image;
5340
+ return {
5341
+ backend: "docker",
5342
+ hash,
5343
+ image,
5344
+ cached: false
5345
+ };
5047
5346
  }
5048
5347
  function hashDockerTemplate(dockerfileBytes, buildArgs) {
5049
5348
  const hash = createHash4("sha256");
@@ -5089,8 +5388,8 @@ function parseDockerRuntime(runtime) {
5089
5388
  }
5090
5389
  async function runAndRead(runner, spec) {
5091
5390
  const handle = runner.exec(spec);
5092
- const stdout = readStream(handle.stdout);
5093
- const stderr = readStream(handle.stderr);
5391
+ const stdout = readStream2(handle.stdout);
5392
+ const stderr = readStream2(handle.stderr);
5094
5393
  const result = await handle.result;
5095
5394
  const output = await stdout;
5096
5395
  if (result.exitCode !== 0) {
@@ -5105,7 +5404,7 @@ ${errorOutput}` : ""}`
5105
5404
  async function runOrThrow(runner, spec) {
5106
5405
  await runAndRead(runner, spec);
5107
5406
  }
5108
- async function readStream(stream) {
5407
+ async function readStream2(stream) {
5109
5408
  if (stream === null) {
5110
5409
  return "";
5111
5410
  }
@@ -5128,9 +5427,9 @@ function buildEnvArgs(env) {
5128
5427
  function createContainerName() {
5129
5428
  return `poe-env-${randomBytes3(6).toString("hex")}`;
5130
5429
  }
5131
- async function createContainerJob(containerId, runner, engine, context) {
5430
+ function createContainerJob(containerId, runner, engine, context, jobId = containerId) {
5132
5431
  return {
5133
- id: containerId,
5432
+ id: jobId,
5134
5433
  envId: containerId,
5135
5434
  tool: "docker",
5136
5435
  argv: ["attach", containerId],
@@ -5147,14 +5446,32 @@ async function createContainerJob(containerId, runner, engine, context) {
5147
5446
  stdout: "pipe",
5148
5447
  stderr: "pipe"
5149
5448
  });
5150
- const stdout = await readStream(handle.stdout);
5449
+ const stdout = await readStream2(handle.stdout);
5151
5450
  const result = await handle.result;
5152
5451
  if (result.exitCode !== 0) {
5153
5452
  return "lost";
5154
5453
  }
5155
5454
  return stdout.trim() === "running" ? "running" : "exited";
5156
5455
  },
5157
- async *stream() {
5456
+ async *stream(opts) {
5457
+ const handle = runner.exec({
5458
+ command: engine,
5459
+ args: [
5460
+ ...buildContextArgs(engine, context),
5461
+ "exec",
5462
+ containerId,
5463
+ "sh",
5464
+ "-c",
5465
+ `test -f ${shellQuote2(`/tmp/poe-jobs/${jobId}.log`)} && tail -c +${(opts?.sinceByte ?? 0) + 1} ${shellQuote2(`/tmp/poe-jobs/${jobId}.log`)} || true`
5466
+ ],
5467
+ stdout: "pipe",
5468
+ stderr: "pipe"
5469
+ });
5470
+ const stdout = await readStream2(handle.stdout);
5471
+ await handle.result;
5472
+ if (stdout.length > 0) {
5473
+ yield { byteOffset: opts?.sinceByte ?? 0, data: stdout };
5474
+ }
5158
5475
  },
5159
5476
  async wait() {
5160
5477
  const handle = runner.exec({
@@ -5163,7 +5480,7 @@ async function createContainerJob(containerId, runner, engine, context) {
5163
5480
  stdout: "pipe",
5164
5481
  stderr: "pipe"
5165
5482
  });
5166
- const stdout = await readStream(handle.stdout);
5483
+ const stdout = await readStream2(handle.stdout);
5167
5484
  const result = await handle.result;
5168
5485
  return { exitCode: Number.parseInt(stdout.trim(), 10) || result.exitCode };
5169
5486
  },
@@ -5178,9 +5495,9 @@ async function createContainerJob(containerId, runner, engine, context) {
5178
5495
  }
5179
5496
  };
5180
5497
  }
5181
- function createAttachedSpec() {
5498
+ function createAttachedSpec(cwd = "/workspace") {
5182
5499
  return {
5183
- cwd: "/workspace",
5500
+ cwd,
5184
5501
  runtime: {
5185
5502
  type: "docker",
5186
5503
  image: "attached",
@@ -5252,12 +5569,778 @@ var hostExecutionEnvFactory = {
5252
5569
  // packages/process-runner/src/testing/mock-runner.ts
5253
5570
  import { Readable, Writable } from "node:stream";
5254
5571
 
5572
+ // packages/runner-e2b/src/factory.ts
5573
+ import path30 from "node:path";
5574
+
5575
+ // packages/runner-e2b/src/sdk.ts
5576
+ import { Template, Sandbox } from "e2b";
5577
+ async function createSandbox(opts) {
5578
+ return Sandbox.create(opts.templateId, {
5579
+ apiKey: opts.apiKey,
5580
+ envs: opts.env,
5581
+ ...opts.timeoutMinutes === void 0 ? {} : { timeoutMs: opts.timeoutMinutes * 6e4 }
5582
+ });
5583
+ }
5584
+ async function connectSandbox(id, apiKey) {
5585
+ return Sandbox.connect(id, apiKey === void 0 ? void 0 : { apiKey });
5586
+ }
5587
+ async function buildTemplate(opts) {
5588
+ const template = Template({ fileContextPath: opts.buildContext }).fromDockerfile(
5589
+ opts.dockerfilePath
5590
+ );
5591
+ if (opts.fromTemplate !== void 0 && opts.fromTemplate.length > 0) {
5592
+ template.fromTemplate(opts.fromTemplate);
5593
+ }
5594
+ const result = await Template.build(template, opts.name, {
5595
+ apiKey: opts.apiKey,
5596
+ ...opts.cpu === void 0 ? {} : { cpuCount: opts.cpu },
5597
+ ...opts.memoryMb === void 0 ? {} : { memoryMB: opts.memoryMb },
5598
+ ...opts.onLog ? { onBuildLogs: opts.onLog } : {}
5599
+ });
5600
+ return { templateId: result.templateId };
5601
+ }
5602
+ function toArrayBuffer(buffer) {
5603
+ const output = new ArrayBuffer(buffer.byteLength);
5604
+ new Uint8Array(output).set(buffer);
5605
+ return output;
5606
+ }
5607
+ async function readableToString(stream) {
5608
+ if (stream === null) {
5609
+ return "";
5610
+ }
5611
+ stream.setEncoding("utf8");
5612
+ const chunks = [];
5613
+ for await (const chunk of stream) {
5614
+ chunks.push(String(chunk));
5615
+ }
5616
+ return chunks.join("");
5617
+ }
5618
+
5619
+ // packages/runner-e2b/src/template-build.ts
5620
+ import { createHash as createHash5 } from "node:crypto";
5621
+ import { readdir as readdir4, readFile as readFile11 } from "node:fs/promises";
5622
+ import path27 from "node:path";
5623
+ var BUILD_LOG_TAIL_SIZE = 30;
5624
+ async function buildE2bRuntimeTemplate(input) {
5625
+ const dockerfileBytes = await readFile11(input.dockerfilePath);
5626
+ const buildContextFiles = await readBuildContextFiles(input.buildContext);
5627
+ const hash = hashTemplate(dockerfileBytes, buildContextFiles, input.runtime.build_args);
5628
+ const cached2 = input.force === true ? null : await input.state?.templates.get("e2b", hash);
5629
+ if (cached2?.template_id !== void 0) {
5630
+ return { backend: "e2b", hash, templateId: cached2.template_id, cached: true };
5631
+ }
5632
+ const tail = [];
5633
+ const onLog = (entry) => {
5634
+ tail.push(entry.message);
5635
+ if (tail.length > BUILD_LOG_TAIL_SIZE) {
5636
+ tail.shift();
5637
+ }
5638
+ input.onLog?.(entry);
5639
+ };
5640
+ let built;
5641
+ try {
5642
+ built = await buildTemplate({
5643
+ apiKey: input.apiKey,
5644
+ name: `poe-code-${hash.slice(0, 32)}`,
5645
+ dockerfilePath: input.dockerfilePath,
5646
+ buildContext: input.buildContext,
5647
+ cpu: input.runtime.cpu,
5648
+ memoryMb: input.runtime.memory_mb,
5649
+ fromTemplate: input.runtime.from_template,
5650
+ onLog
5651
+ });
5652
+ } catch (error2) {
5653
+ throw decorateBuildError(error2, tail);
5654
+ }
5655
+ await input.state?.templates.put("e2b", {
5656
+ hash,
5657
+ template_id: built.templateId,
5658
+ runtime_type: "e2b",
5659
+ dockerfile_path: input.dockerfilePath,
5660
+ built_at: (/* @__PURE__ */ new Date()).toISOString()
5661
+ });
5662
+ return { backend: "e2b", hash, templateId: built.templateId, cached: false };
5663
+ }
5664
+ function decorateBuildError(error2, tail) {
5665
+ const original = error2 instanceof Error ? error2 : new Error(String(error2));
5666
+ if (tail.length === 0) {
5667
+ return original;
5668
+ }
5669
+ const decorated = new Error(`${original.message}
5670
+
5671
+ Last build output:
5672
+ ${tail.join("\n")}`);
5673
+ decorated.stack = original.stack;
5674
+ decorated.cause = original;
5675
+ return decorated;
5676
+ }
5677
+ function hashTemplate(dockerfileBytes, buildContextFiles, buildArgs) {
5678
+ const hash = createHash5("sha256");
5679
+ hash.update(dockerfileBytes);
5680
+ hash.update("\0");
5681
+ for (const file of buildContextFiles) {
5682
+ hash.update(file.relativePath);
5683
+ hash.update("\0");
5684
+ hash.update(file.bytes);
5685
+ hash.update("\0");
5686
+ }
5687
+ for (const [key, value] of Object.entries(buildArgs).sort(
5688
+ ([left], [right]) => left.localeCompare(right)
5689
+ )) {
5690
+ hash.update(key);
5691
+ hash.update("=");
5692
+ hash.update(value);
5693
+ hash.update("\0");
5694
+ }
5695
+ return hash.digest("hex");
5696
+ }
5697
+ async function readBuildContextFiles(buildContext) {
5698
+ const files = [];
5699
+ await collectBuildContextFiles(buildContext, "", files);
5700
+ return files.sort((left, right) => left.relativePath.localeCompare(right.relativePath));
5701
+ }
5702
+ async function collectBuildContextFiles(buildContext, relativeDir, files) {
5703
+ const absoluteDir = path27.join(buildContext, relativeDir);
5704
+ const entries = await readdir4(absoluteDir, { withFileTypes: true });
5705
+ for (const entry of entries) {
5706
+ const relativePath = path27.join(relativeDir, entry.name);
5707
+ if (entry.isDirectory()) {
5708
+ await collectBuildContextFiles(buildContext, relativePath, files);
5709
+ continue;
5710
+ }
5711
+ if (!entry.isFile()) {
5712
+ continue;
5713
+ }
5714
+ files.push({
5715
+ relativePath: relativePath.split(path27.sep).join("/"),
5716
+ bytes: await readFile11(path27.join(buildContext, relativePath))
5717
+ });
5718
+ }
5719
+ }
5720
+
5721
+ // packages/runner-e2b/src/opened-env.ts
5722
+ import { mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "node:fs";
5723
+ import { readFile as readFile12, writeFile as writeFile7 } from "node:fs/promises";
5724
+ import { tmpdir as tmpdir2 } from "node:os";
5725
+ import path29 from "node:path";
5726
+ import { PassThrough, Writable as Writable2 } from "node:stream";
5727
+
5728
+ // packages/runner-e2b/src/job-handle.ts
5729
+ import path28 from "node:path";
5730
+ var JOB_DIR2 = "/tmp/poe-jobs";
5731
+ function createE2bJobHandle(input) {
5732
+ const fs14 = createE2bLogStreamFs(input.sandbox);
5733
+ return {
5734
+ id: input.jobId,
5735
+ envId: input.envId,
5736
+ tool: input.tool,
5737
+ argv: input.argv,
5738
+ async status() {
5739
+ const exit = await readExitCode(input.sandbox, input.jobId);
5740
+ if (exit !== null) {
5741
+ return "exited";
5742
+ }
5743
+ const processes = await input.sandbox.commands.list();
5744
+ const isRunning = input.pid === void 0 ? processes.some((process2) => processMentionsJob(process2, input.jobId)) : processes.some((process2) => process2.pid === input.pid);
5745
+ return isRunning ? "running" : "lost";
5746
+ },
5747
+ stream(opts = {}) {
5748
+ return streamLogFile({ fs: fs14 }, input.jobId, opts);
5749
+ },
5750
+ async wait() {
5751
+ const result = await waitForExit({ fs: fs14 }, input.jobId);
5752
+ const preserveMs = input.preserveAfterExitHours * 60 * 60 * 1e3;
5753
+ if (preserveMs > 0) {
5754
+ await input.sandbox.setTimeout(preserveMs);
5755
+ }
5756
+ return result;
5757
+ },
5758
+ async kill() {
5759
+ const pids = input.pid === void 0 ? (await input.sandbox.commands.list()).filter((process2) => processMentionsJob(process2, input.jobId)).map((process2) => process2.pid) : [input.pid];
5760
+ await Promise.all(pids.map((pid) => input.sandbox.commands.kill(pid)));
5761
+ }
5762
+ };
5763
+ }
5764
+ function createE2bLogStreamFs(sandbox) {
5765
+ return {
5766
+ promises: {
5767
+ async readFile(filePath) {
5768
+ return Buffer.from(await sandbox.files.read(filePath, { format: "bytes" }));
5769
+ },
5770
+ async stat(filePath) {
5771
+ const result = await sandbox.commands.run(
5772
+ `stat -c %Y ${shellQuote3(filePath)} 2>/dev/null || stat -f %m ${shellQuote3(filePath)}`
5773
+ );
5774
+ if (!("stdout" in result)) {
5775
+ throw new Error(`Unable to stat ${filePath}`);
5776
+ }
5777
+ const seconds = Number(result.stdout?.trim());
5778
+ if (!Number.isFinite(seconds)) {
5779
+ throw new Error(`Unable to stat ${filePath}`);
5780
+ }
5781
+ return { mtimeMs: seconds * 1e3 };
5782
+ }
5783
+ },
5784
+ watch(filePath, listener) {
5785
+ let closed = false;
5786
+ let stop = null;
5787
+ void sandbox.files.watchDir(path28.dirname(filePath), listener, { recursive: false }).then((handle) => {
5788
+ if (closed) {
5789
+ void handle.stop();
5790
+ return;
5791
+ }
5792
+ stop = () => {
5793
+ void handle.stop();
5794
+ };
5795
+ });
5796
+ return {
5797
+ close() {
5798
+ closed = true;
5799
+ stop?.();
5800
+ }
5801
+ };
5802
+ }
5803
+ };
5804
+ }
5805
+ function processMentionsJob(process2, jobId) {
5806
+ const needle = `/tmp/poe-jobs/${jobId}`;
5807
+ return process2.cmd.includes(needle) || process2.args.some((arg) => arg.includes(needle));
5808
+ }
5809
+ function shellQuote3(value) {
5810
+ return `'${value.replaceAll("'", "'\\''")}'`;
5811
+ }
5812
+ async function readExitCode(sandbox, jobId) {
5813
+ try {
5814
+ const contents = await sandbox.files.read(`${JOB_DIR2}/${jobId}.exit`);
5815
+ const exitCode = Number(contents.trim());
5816
+ return Number.isInteger(exitCode) ? exitCode : null;
5817
+ } catch {
5818
+ return null;
5819
+ }
5820
+ }
5821
+
5822
+ // packages/runner-e2b/src/opened-env.ts
5823
+ var REMOTE_COMMAND_STDERR_TAIL_SIZE = 30;
5824
+ function createOpenedE2bEnv(input) {
5825
+ const hostRunner = input.spec.hostRunner ?? createHostRunner();
5826
+ const hostWorkspaceDir = path29.resolve(input.spec.cwd);
5827
+ const sandboxWorkspaceDir = normalizeSandboxWorkspaceDir(input.runtime.workspace_dir);
5828
+ let lastProcess = null;
5829
+ let detachedJobContext = null;
5830
+ const mapWorkspaceCwd = (cwd) => {
5831
+ if (cwd === void 0) {
5832
+ return void 0;
5833
+ }
5834
+ if (path29.isAbsolute(cwd) && path29.resolve(cwd) === hostWorkspaceDir) {
5835
+ return sandboxWorkspaceDir;
5836
+ }
5837
+ return cwd;
5838
+ };
5839
+ const attachedJobId = input.spec.detachedJobId;
5840
+ const env = {
5841
+ id: input.sandbox.sandboxId,
5842
+ job: attachedJobId ? createE2bJobHandle({
5843
+ sandbox: input.sandbox,
5844
+ envId: input.sandbox.sandboxId,
5845
+ jobId: attachedJobId,
5846
+ tool: input.spec.jobLabel.tool,
5847
+ argv: input.spec.jobLabel.argv,
5848
+ preserveAfterExitHours: input.runtime.preserve_after_exit_hours ?? 24
5849
+ }) : null,
5850
+ fs: createE2bLogStreamFs(input.sandbox),
5851
+ setDetachedJobContext(context) {
5852
+ detachedJobContext = context;
5853
+ },
5854
+ async uploadWorkspace() {
5855
+ if (input.spec.runner?.sync === "none") {
5856
+ return { files: 0, bytes: 0, skipped: [] };
5857
+ }
5858
+ const tempDir = mkdtempSync2(path29.join(tmpdir2(), "poe-e2b-upload-"));
5859
+ const archivePath = path29.join(tempDir, "workspace.tar");
5860
+ try {
5861
+ await runOrThrow2(hostRunner, {
5862
+ command: "tar",
5863
+ args: [
5864
+ ...input.spec.uploadIgnoreFiles.flatMap((ignored) => ["--exclude", ignored]),
5865
+ "-cf",
5866
+ archivePath,
5867
+ "-C",
5868
+ input.spec.cwd,
5869
+ "."
5870
+ ],
5871
+ stdout: "pipe",
5872
+ stderr: "pipe"
5873
+ });
5874
+ await input.sandbox.files.write(
5875
+ "/tmp/poe-workspace-upload.tar",
5876
+ toArrayBuffer(await readFile12(archivePath))
5877
+ );
5878
+ await runRemoteOrThrow(
5879
+ input.sandbox,
5880
+ createUploadWorkspaceCommand(sandboxWorkspaceDir)
5881
+ );
5882
+ return { files: 0, bytes: 0, skipped: [] };
5883
+ } finally {
5884
+ rmSync2(tempDir, { recursive: true, force: true });
5885
+ }
5886
+ },
5887
+ async downloadWorkspace(opts) {
5888
+ if (input.spec.runner?.sync === "upload" || input.spec.runner?.sync === "none") {
5889
+ return { files: 0, bytes: 0, conflicts: [] };
5890
+ }
5891
+ const tempDir = mkdtempSync2(path29.join(tmpdir2(), "poe-e2b-download-"));
5892
+ const archivePath = path29.join(tempDir, "workspace.tar");
5893
+ try {
5894
+ await runRemoteOrThrow(
5895
+ input.sandbox,
5896
+ `tar -cf /tmp/poe-workspace-download.tar -C ${shellQuote4(sandboxWorkspaceDir)} .`
5897
+ );
5898
+ const archive = await input.sandbox.files.read("/tmp/poe-workspace-download.tar", {
5899
+ format: "bytes"
5900
+ });
5901
+ await writeFile7(archivePath, Buffer.from(archive));
5902
+ await runOrThrow2(hostRunner, {
5903
+ command: "tar",
5904
+ args: [
5905
+ opts.conflictPolicy === "refuse" ? "-xkf" : "-xf",
5906
+ archivePath,
5907
+ "-C",
5908
+ input.spec.cwd
5909
+ ],
5910
+ stdout: "pipe",
5911
+ stderr: "pipe"
5912
+ });
5913
+ return { files: 0, bytes: archive.byteLength, conflicts: [] };
5914
+ } finally {
5915
+ rmSync2(tempDir, { recursive: true, force: true });
5916
+ }
5917
+ },
5918
+ exec(spec) {
5919
+ const handle = runE2bCommand(input.sandbox, {
5920
+ ...spec,
5921
+ cwd: mapWorkspaceCwd(spec.cwd),
5922
+ env: resolveSandboxCommandEnv(spec.env)
5923
+ });
5924
+ lastProcess = { started: handle.started };
5925
+ return handle;
5926
+ },
5927
+ async detach() {
5928
+ if (detachedJobContext === null) {
5929
+ throw new Error("Cannot detach E2B environment before a job context is registered.");
5930
+ }
5931
+ if (lastProcess === null) {
5932
+ throw new Error("Cannot detach E2B environment before a command is running.");
5933
+ }
5934
+ const command = await lastProcess.started;
5935
+ const preserveAfterExitHours = input.runtime.preserve_after_exit_hours ?? 24;
5936
+ const preserveMs = preserveAfterExitHours * 60 * 60 * 1e3;
5937
+ if (preserveMs > 0) {
5938
+ await input.sandbox.setTimeout(preserveMs);
5939
+ }
5940
+ return createE2bJobHandle({
5941
+ sandbox: input.sandbox,
5942
+ envId: input.sandbox.sandboxId,
5943
+ jobId: detachedJobContext.id,
5944
+ tool: detachedJobContext.tool,
5945
+ argv: detachedJobContext.argv,
5946
+ pid: command.pid,
5947
+ preserveAfterExitHours
5948
+ });
5949
+ },
5950
+ shell() {
5951
+ const shellSpec = input.spec.shellSpec;
5952
+ const command = shellSpec?.command ?? input.spec.env.SHELL ?? "sh";
5953
+ return runE2bPty(input.sandbox, {
5954
+ command,
5955
+ ...shellSpec?.args ? { args: shellSpec.args } : {},
5956
+ cwd: mapWorkspaceCwd(shellSpec?.cwd ?? input.spec.cwd),
5957
+ env: resolveSandboxCommandEnv(
5958
+ shellSpec && "env" in shellSpec ? shellSpec.env : input.spec.env
5959
+ ),
5960
+ stdin: "inherit",
5961
+ stdout: "inherit",
5962
+ stderr: "inherit",
5963
+ tty: true
5964
+ });
5965
+ },
5966
+ async close() {
5967
+ await input.sandbox.kill();
5968
+ }
5969
+ };
5970
+ return env;
5971
+ }
5972
+ function runE2bCommand(sandbox, spec) {
5973
+ const stdout = spec.stdout === "inherit" ? null : new PassThrough();
5974
+ const stderr = spec.stderr === "inherit" ? null : new PassThrough();
5975
+ let e2bHandle = null;
5976
+ const command = shellCommand([spec.command, ...spec.args ?? []]);
5977
+ const started = sandbox.commands.run(command, {
5978
+ background: true,
5979
+ cwd: spec.cwd,
5980
+ envs: spec.env,
5981
+ stdin: spec.stdin === "pipe",
5982
+ onStdout(data) {
5983
+ stdout?.write(data);
5984
+ if (spec.stdout === "inherit") {
5985
+ process.stdout.write(data);
5986
+ }
5987
+ },
5988
+ onStderr(data) {
5989
+ stderr?.write(data);
5990
+ if (spec.stderr === "inherit") {
5991
+ process.stderr.write(data);
5992
+ }
5993
+ }
5994
+ });
5995
+ const stdin = spec.stdin === "pipe" ? new Writable2({
5996
+ write(chunk, _encoding, callback) {
5997
+ started.then(
5998
+ (handle) => sandbox.commands.sendStdin(
5999
+ handle.pid,
6000
+ Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))
6001
+ )
6002
+ ).then(() => callback(), callback);
6003
+ },
6004
+ final(callback) {
6005
+ if (sandbox.commands.closeStdin === void 0) {
6006
+ callback();
6007
+ return;
6008
+ }
6009
+ started.then((handle) => sandbox.commands.closeStdin(handle.pid)).then(() => callback(), callback);
6010
+ }
6011
+ }) : null;
6012
+ const result = started.then((handle) => {
6013
+ e2bHandle = handle;
6014
+ return handle.wait();
6015
+ }).then(
6016
+ (result2) => {
6017
+ stdout?.end();
6018
+ stderr?.end();
6019
+ return { exitCode: result2.exitCode ?? 0 };
6020
+ },
6021
+ (error2) => {
6022
+ stdout?.end();
6023
+ stderr?.end();
6024
+ if (isExitError(error2)) {
6025
+ return { exitCode: error2.exitCode };
6026
+ }
6027
+ return { exitCode: 1 };
6028
+ }
6029
+ );
6030
+ return {
6031
+ get pid() {
6032
+ return e2bHandle?.pid ?? null;
6033
+ },
6034
+ stdin,
6035
+ stdout,
6036
+ stderr,
6037
+ result,
6038
+ kill() {
6039
+ void e2bHandle?.kill();
6040
+ },
6041
+ get e2bHandle() {
6042
+ return e2bHandle;
6043
+ },
6044
+ started
6045
+ };
6046
+ }
6047
+ function runE2bPty(sandbox, spec) {
6048
+ const stdout = new PassThrough();
6049
+ let handleRef = null;
6050
+ const stdin = new Writable2({
6051
+ write(chunk, _encoding, callback) {
6052
+ if (handleRef === null) {
6053
+ callback(new Error("E2B PTY stdin is not ready."));
6054
+ return;
6055
+ }
6056
+ sandbox.pty.sendInput(handleRef.pid, Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))).then(() => callback(), callback);
6057
+ }
6058
+ });
6059
+ const started = sandbox.pty.create({
6060
+ cols: process.stdout.columns || 80,
6061
+ rows: process.stdout.rows || 24,
6062
+ cwd: spec.cwd,
6063
+ envs: spec.env,
6064
+ onData(data) {
6065
+ stdout.write(Buffer.from(data));
6066
+ if (spec.stdout === "inherit") {
6067
+ process.stdout.write(Buffer.from(data));
6068
+ }
6069
+ }
6070
+ });
6071
+ const result = started.then((handle) => {
6072
+ handleRef = handle;
6073
+ return handle.wait();
6074
+ }).then(
6075
+ (result2) => {
6076
+ stdout.end();
6077
+ return { exitCode: result2.exitCode ?? 0 };
6078
+ },
6079
+ () => {
6080
+ stdout.end();
6081
+ return { exitCode: 1 };
6082
+ }
6083
+ );
6084
+ return {
6085
+ get pid() {
6086
+ return handleRef?.pid ?? null;
6087
+ },
6088
+ stdin: spec.stdin === "inherit" ? process.stdin : stdin,
6089
+ stdout: spec.stdout === "inherit" ? null : stdout,
6090
+ stderr: null,
6091
+ result,
6092
+ kill() {
6093
+ void (handleRef === null ? void 0 : sandbox.pty.kill(handleRef.pid));
6094
+ }
6095
+ };
6096
+ }
6097
+ async function runRemoteOrThrow(sandbox, command) {
6098
+ const stdoutTail = createLineTail(REMOTE_COMMAND_STDERR_TAIL_SIZE);
6099
+ const stderrTail = createLineTail(REMOTE_COMMAND_STDERR_TAIL_SIZE);
6100
+ let result;
6101
+ try {
6102
+ result = await sandbox.commands.run(command, {
6103
+ onStdout(data) {
6104
+ stdoutTail.push(data);
6105
+ },
6106
+ onStderr(data) {
6107
+ stderrTail.push(data);
6108
+ }
6109
+ });
6110
+ } catch (error2) {
6111
+ appendRemoteCommandOutput(error2, stdoutTail, stderrTail);
6112
+ if (isCommandExitError(error2)) {
6113
+ throw decorateRemoteCommandError(error2, command, stderrTail.values());
6114
+ }
6115
+ throw error2;
6116
+ }
6117
+ appendRemoteCommandOutput(result, stdoutTail, stderrTail);
6118
+ if ("exitCode" in result && result.exitCode !== 0) {
6119
+ throw decorateRemoteCommandError(
6120
+ new Error(`E2B command failed with exit code ${result.exitCode}`),
6121
+ command,
6122
+ stderrTail.values()
6123
+ );
6124
+ }
6125
+ }
6126
+ function appendRemoteCommandOutput(source, stdoutTail, stderrTail) {
6127
+ if (!source || typeof source !== "object") {
6128
+ return;
6129
+ }
6130
+ const output = source;
6131
+ if (typeof output.stdout === "string") {
6132
+ stdoutTail.push(output.stdout);
6133
+ }
6134
+ if (typeof output.stderr === "string") {
6135
+ stderrTail.push(output.stderr);
6136
+ }
6137
+ }
6138
+ function decorateRemoteCommandError(error2, command, stderrTail) {
6139
+ const original = error2 instanceof Error ? error2 : new Error(String(error2));
6140
+ const tail = stderrTail.length === 0 ? "" : `
6141
+
6142
+ Last stderr output:
6143
+ ${stderrTail.join("\n")}`;
6144
+ const decorated = new Error(`E2B command failed: ${command}
6145
+ ${original.message}${tail}`);
6146
+ decorated.stack = original.stack;
6147
+ decorated.cause = original;
6148
+ return decorated;
6149
+ }
6150
+ function createLineTail(maxLines) {
6151
+ const lines = [];
6152
+ let pending = "";
6153
+ const appendLine = (line) => {
6154
+ lines.push(trimTrailingCarriageReturn(line));
6155
+ while (lines.length > maxLines) {
6156
+ lines.shift();
6157
+ }
6158
+ };
6159
+ return {
6160
+ push(chunk) {
6161
+ pending += chunk;
6162
+ const parts = pending.split("\n");
6163
+ pending = parts.pop() ?? "";
6164
+ for (const line of parts) {
6165
+ appendLine(line);
6166
+ }
6167
+ },
6168
+ values() {
6169
+ const output = [...lines];
6170
+ if (pending.length > 0) {
6171
+ output.push(trimTrailingCarriageReturn(pending));
6172
+ }
6173
+ return output.slice(-maxLines);
6174
+ }
6175
+ };
6176
+ }
6177
+ function trimTrailingCarriageReturn(value) {
6178
+ return value.endsWith("\r") ? value.slice(0, -1) : value;
6179
+ }
6180
+ async function runOrThrow2(runner, spec) {
6181
+ const handle = runner.exec(spec);
6182
+ const stderr = readableToString(handle.stderr);
6183
+ const result = await handle.result;
6184
+ if (result.exitCode !== 0) {
6185
+ throw new Error(
6186
+ `Command failed with exit code ${result.exitCode}: ${spec.command} ${(spec.args ?? []).join(" ")}
6187
+ ${await stderr}`
6188
+ );
6189
+ }
6190
+ }
6191
+ function shellCommand(argv) {
6192
+ return argv.map(shellQuote4).join(" ");
6193
+ }
6194
+ function shellQuote4(value) {
6195
+ return `'${value.replaceAll("'", "'\\''")}'`;
6196
+ }
6197
+ function createUploadWorkspaceCommand(sandboxWorkspaceDir) {
6198
+ const quotedWorkspaceDir = shellQuote4(sandboxWorkspaceDir);
6199
+ return [
6200
+ `mkdir -p ${quotedWorkspaceDir} || { command -v sudo >/dev/null 2>&1 && sudo mkdir -p ${quotedWorkspaceDir} && sudo chown "$(id -u):$(id -g)" ${quotedWorkspaceDir}; }`,
6201
+ `test -w ${quotedWorkspaceDir} && tar -xf /tmp/poe-workspace-upload.tar -C ${quotedWorkspaceDir}`
6202
+ ].join("\n");
6203
+ }
6204
+ function resolveSandboxCommandEnv(env) {
6205
+ if (env === void 0) {
6206
+ return void 0;
6207
+ }
6208
+ return {
6209
+ ...env,
6210
+ HOME: "/home/user"
6211
+ };
6212
+ }
6213
+ function normalizeSandboxWorkspaceDir(workspaceDir) {
6214
+ const resolvedWorkspaceDir = workspaceDir ?? "/workspace";
6215
+ if (!path29.posix.isAbsolute(resolvedWorkspaceDir)) {
6216
+ throw new Error("E2B runtime workspace_dir must be an absolute sandbox path.");
6217
+ }
6218
+ let normalized = path29.posix.normalize(resolvedWorkspaceDir);
6219
+ while (normalized.length > 1 && normalized.endsWith("/")) {
6220
+ normalized = normalized.slice(0, -1);
6221
+ }
6222
+ return normalized;
6223
+ }
6224
+ function isExitError(error2) {
6225
+ return Boolean(
6226
+ error2 && typeof error2 === "object" && typeof error2.exitCode === "number"
6227
+ );
6228
+ }
6229
+ function isCommandExitError(error2) {
6230
+ return isExitError(error2) || Boolean(
6231
+ error2 && typeof error2 === "object" && error2.name === "CommandExitError"
6232
+ );
6233
+ }
6234
+
6235
+ // packages/runner-e2b/src/auth-scope.ts
6236
+ import os4 from "node:os";
6237
+ import { promises as nodeFs4 } from "node:fs";
6238
+ var e2bAuthScope = defineScope("e2b", {
6239
+ api_key: {
6240
+ type: "string",
6241
+ default: "",
6242
+ doc: "E2B API key",
6243
+ env: "E2B_API_KEY"
6244
+ }
6245
+ });
6246
+ async function resolveE2bApiKey(input) {
6247
+ const homeDir = input.homeDir ?? os4.homedir();
6248
+ const fs14 = input.fs ?? nodeFs4;
6249
+ const env = input.env ?? process.env;
6250
+ const document = await readMergedDocument(
6251
+ fs14,
6252
+ resolveConfigPath(homeDir),
6253
+ resolveProjectConfigPath(input.cwd)
6254
+ );
6255
+ const resolved = resolveScope(e2bAuthScope.schema, document.e2b, env);
6256
+ if (resolved.api_key.length === 0) {
6257
+ throw new Error(
6258
+ "No E2B API key. Set E2B_API_KEY or e2b.api_key in ~/.poe-code/config.json."
6259
+ );
6260
+ }
6261
+ return resolved.api_key;
6262
+ }
6263
+
6264
+ // packages/runner-e2b/src/factory.ts
6265
+ var e2bExecutionEnvFactory = {
6266
+ type: "e2b",
6267
+ supportsDetach: true,
6268
+ async open(spec) {
6269
+ const runtime = parseE2bRuntime(spec.runtime);
6270
+ const runtimeCwd = spec.runtimeCwd ?? spec.cwd;
6271
+ const apiKey = await resolveE2bApiKey({ cwd: runtimeCwd });
6272
+ const templateId = runtime.template_id ?? (await buildE2bRuntimeTemplate({
6273
+ runtime,
6274
+ dockerfilePath: path30.resolve(
6275
+ runtimeCwd,
6276
+ runtime.dockerfile ?? path30.join(".poe-code", "Dockerfile")
6277
+ ),
6278
+ buildContext: path30.resolve(runtimeCwd, runtime.build_context ?? "."),
6279
+ state: spec.state,
6280
+ apiKey
6281
+ })).templateId;
6282
+ const sandbox = await createSandbox({
6283
+ apiKey,
6284
+ templateId,
6285
+ env: spec.env,
6286
+ timeoutMinutes: runtime.timeout_minutes
6287
+ });
6288
+ return createOpenedE2bEnv({ sandbox, spec, runtime });
6289
+ },
6290
+ async attach(envId, context) {
6291
+ const cwd = context?.cwd ?? process.cwd();
6292
+ const apiKey = await resolveE2bApiKey({ cwd });
6293
+ const sandbox = await connectSandbox(envId, apiKey);
6294
+ return createOpenedE2bEnv({
6295
+ sandbox,
6296
+ spec: {
6297
+ cwd: context?.cwd ?? "/workspace",
6298
+ runtime: {
6299
+ type: "e2b",
6300
+ build_args: {},
6301
+ mounts: [],
6302
+ workspace_dir: "/workspace",
6303
+ preserve_after_exit_hours: 24
6304
+ },
6305
+ env: {},
6306
+ uploadIgnoreFiles: [],
6307
+ jobLabel: { tool: context?.tool ?? "e2b", argv: context?.argv ?? [] },
6308
+ ...context?.jobId ? { detachedJobId: context.jobId } : {}
6309
+ },
6310
+ runtime: {
6311
+ type: "e2b",
6312
+ build_args: {},
6313
+ mounts: [],
6314
+ workspace_dir: "/workspace",
6315
+ preserve_after_exit_hours: 24
6316
+ }
6317
+ });
6318
+ }
6319
+ };
6320
+ function parseE2bRuntime(runtime) {
6321
+ if (!runtime || typeof runtime !== "object" || Array.isArray(runtime)) {
6322
+ throw new Error("e2b runtime must be an object");
6323
+ }
6324
+ const record = runtime;
6325
+ if (record.type !== "e2b") {
6326
+ throw new Error('e2b runtime type must be "e2b"');
6327
+ }
6328
+ return record;
6329
+ }
6330
+
6331
+ // packages/runner-e2b/src/index.ts
6332
+ var e2bExecutionEnvFactory2 = e2bExecutionEnvFactory;
6333
+
5255
6334
  // packages/agent-spawn/src/register-factories.ts
5256
6335
  registerExecutionEnvFactory(hostExecutionEnvFactory);
5257
6336
  registerExecutionEnvFactory(dockerExecutionEnvFactory);
5258
- if (process.env.VITEST === "true") {
6337
+ registerExecutionEnvFactory(e2bExecutionEnvFactory2);
6338
+ if (isVitest()) {
5259
6339
  registerExecutionEnvFactory(createTestHostExecutionEnvFactory());
5260
6340
  }
6341
+ function isVitest() {
6342
+ return process.env.VITEST !== void 0 || process.env.VITEST_POOL_ID !== void 0;
6343
+ }
5261
6344
  function createTestHostExecutionEnvFactory() {
5262
6345
  return {
5263
6346
  type: "host",
@@ -5619,7 +6702,7 @@ function listMcpSupportedAgents() {
5619
6702
 
5620
6703
  // packages/agent-spawn/src/spawn.ts
5621
6704
  import { mkdirSync, openSync, writeSync, closeSync } from "node:fs";
5622
- import path27 from "node:path";
6705
+ import path31 from "node:path";
5623
6706
 
5624
6707
  // packages/agent-spawn/src/configs/resolve-config.ts
5625
6708
  function resolveConfig(agentId) {
@@ -5759,6 +6842,7 @@ async function spawn3(agentId, options, context) {
5759
6842
  const argv = [binaryName, ...spawnArgs];
5760
6843
  const execution = resolvePoeCommandExecution({
5761
6844
  cwd: options.cwd ?? process.cwd(),
6845
+ runtimeConfigCwd: options.runtimeConfigCwd,
5762
6846
  env: processEnv ?? process.env,
5763
6847
  argv,
5764
6848
  tool: resolvedId,
@@ -5767,7 +6851,8 @@ async function spawn3(agentId, options, context) {
5767
6851
  runtimeImage: options.runtimeImage,
5768
6852
  runtimeTemplate: options.runtimeTemplate,
5769
6853
  detach: options.detach,
5770
- mountPoeCode: options.mountPoeCode
6854
+ mountPoeCode: options.mountPoeCode,
6855
+ runnerSync: options.runnerSync
5771
6856
  },
5772
6857
  context,
5773
6858
  openSpec: {
@@ -5804,6 +6889,7 @@ async function spawn3(agentId, options, context) {
5804
6889
  stdout: "",
5805
6890
  stderr: "",
5806
6891
  exitCode: 0,
6892
+ detached: { jobId: result.jobId, envId: result.envId },
5807
6893
  ...logFilePath ? { logFile: logFilePath } : {}
5808
6894
  };
5809
6895
  }
@@ -5825,11 +6911,11 @@ function resolveSpawnLogPath(options) {
5825
6911
  if (!options.logDir || !options.logFileName) {
5826
6912
  return void 0;
5827
6913
  }
5828
- return path27.join(options.logDir, options.logFileName);
6914
+ return path31.join(options.logDir, options.logFileName);
5829
6915
  }
5830
6916
  function openSpawnLog(filePath) {
5831
6917
  try {
5832
- mkdirSync(path27.dirname(filePath), { recursive: true });
6918
+ mkdirSync(path31.dirname(filePath), { recursive: true });
5833
6919
  return openSync(filePath, "a");
5834
6920
  } catch {
5835
6921
  return void 0;
@@ -6225,7 +7311,7 @@ import chalk8 from "chalk";
6225
7311
 
6226
7312
  // packages/design-system/src/dashboard/terminal.ts
6227
7313
  import readline from "node:readline";
6228
- import { PassThrough } from "node:stream";
7314
+ import { PassThrough as PassThrough2 } from "node:stream";
6229
7315
 
6230
7316
  // packages/design-system/src/prompts/index.ts
6231
7317
  import chalk15 from "chalk";
@@ -6257,9 +7343,9 @@ import chalk16 from "chalk";
6257
7343
  var DEFAULT_ACTIVITY_TIMEOUT_MS = 10 * 60 * 1e3;
6258
7344
 
6259
7345
  // packages/agent-spawn/src/acp/replay.ts
6260
- import path28 from "node:path";
7346
+ import path32 from "node:path";
6261
7347
  import { homedir as homedir2 } from "node:os";
6262
- import { open as open2, readdir as readdir4 } from "node:fs/promises";
7348
+ import { open as open2, readdir as readdir5 } from "node:fs/promises";
6263
7349
  import { createInterface } from "node:readline";
6264
7350
 
6265
7351
  // packages/poe-acp-client/src/acp-client.ts
@@ -6276,13 +7362,13 @@ import { homedir } from "node:os";
6276
7362
  import { join } from "node:path";
6277
7363
 
6278
7364
  // packages/agent-spawn/src/acp/middlewares/spawn-log.ts
6279
- import path29 from "node:path";
7365
+ import path33 from "node:path";
6280
7366
  import { homedir as homedir3 } from "node:os";
6281
7367
  import { mkdir as mkdir5, open as open3 } from "node:fs/promises";
6282
7368
 
6283
7369
  // packages/memory/src/tokens.ts
6284
7370
  import * as fs10 from "node:fs/promises";
6285
- import path30 from "node:path";
7371
+ import path34 from "node:path";
6286
7372
 
6287
7373
  // packages/tokenfill/dist/tokenizer.js
6288
7374
  import { get_encoding } from "tiktoken";
@@ -6366,11 +7452,11 @@ async function computeTokenStats(root) {
6366
7452
  }
6367
7453
  }
6368
7454
  }
6369
- const repoRoot = path30.resolve(root, "..", "..");
7455
+ const repoRoot = path34.resolve(root, "..", "..");
6370
7456
  let sourceTokens = 0;
6371
7457
  const missingSources = [];
6372
7458
  for (const sourcePath of sourcePaths) {
6373
- const absPath = path30.isAbsolute(sourcePath) ? sourcePath : path30.resolve(repoRoot, sourcePath);
7459
+ const absPath = path34.isAbsolute(sourcePath) ? sourcePath : path34.resolve(repoRoot, sourcePath);
6374
7460
  try {
6375
7461
  const content = await fs10.readFile(absPath, "utf8");
6376
7462
  sourceTokens += countTokens(content);
@@ -6421,10 +7507,10 @@ function resolveRunners(overrides) {
6421
7507
  async function ingest(root, opts, runners) {
6422
7508
  const resolved = resolveRunners(runners);
6423
7509
  const source = await materializeSource(opts.source);
6424
- const indexMdBytes = await fs11.readFile(path31.join(root, MEMORY_INDEX_RELPATH));
7510
+ const indexMdBytes = await fs11.readFile(path35.join(root, MEMORY_INDEX_RELPATH));
6425
7511
  const configOptions = {
6426
7512
  fs: fs11,
6427
- filePath: path31.join(inferRepoRoot(root), "poe-code.json")
7513
+ filePath: path35.join(inferRepoRoot(root), "poe-code.json")
6428
7514
  };
6429
7515
  const agentId = await resolveAgent(configOptions, opts.agent ?? null) ?? opts.agent ?? "claude-code";
6430
7516
  const key = resolved.computeIngestKey({
@@ -6514,7 +7600,7 @@ async function materializeSource(source) {
6514
7600
  throw new Error("URL ingest not implemented yet.");
6515
7601
  }
6516
7602
  function inferRepoRoot(root) {
6517
- return path31.resolve(root, "..", "..");
7603
+ return path35.resolve(root, "..", "..");
6518
7604
  }
6519
7605
  async function runWithTimeout(promise, timeoutMs) {
6520
7606
  return await new Promise((resolve2, reject) => {
@@ -7272,8 +8358,8 @@ function printMcpConfig() {
7272
8358
  }
7273
8359
 
7274
8360
  // packages/agent-skill-config/src/configs.ts
7275
- import os4 from "node:os";
7276
- import path32 from "node:path";
8361
+ import os5 from "node:os";
8362
+ import path36 from "node:path";
7277
8363
  var agentSkillConfigs = {
7278
8364
  "claude-code": {
7279
8365
  globalSkillDir: "~/.claude/skills",
@@ -7306,8 +8392,8 @@ function resolveAgentSupport(input, registry = agentSkillConfigs) {
7306
8392
  }
7307
8393
 
7308
8394
  // packages/agent-skill-config/src/templates.ts
7309
- import { readFile as readFile13, stat as stat6 } from "node:fs/promises";
7310
- import path33 from "node:path";
8395
+ import { readFile as readFile15, stat as stat6 } from "node:fs/promises";
8396
+ import path37 from "node:path";
7311
8397
  import { fileURLToPath as fileURLToPath2 } from "node:url";
7312
8398
 
7313
8399
  // packages/agent-skill-config/src/apply.ts
@@ -7440,7 +8526,7 @@ function resolveConfigPath2(config, platform) {
7440
8526
  }
7441
8527
 
7442
8528
  // packages/agent-mcp-config/src/apply.ts
7443
- import path34 from "node:path";
8529
+ import path38 from "node:path";
7444
8530
  import { parse as parseYaml3, stringify as stringifyYaml2 } from "yaml";
7445
8531
 
7446
8532
  // packages/agent-mcp-config/src/shapes.ts
@@ -7532,7 +8618,7 @@ function getShapeTransformer(shape) {
7532
8618
 
7533
8619
  // packages/agent-mcp-config/src/apply.ts
7534
8620
  function getConfigDirectory(configPath) {
7535
- return path34.dirname(configPath);
8621
+ return path38.dirname(configPath);
7536
8622
  }
7537
8623
  var UnsupportedAgentError2 = class extends Error {
7538
8624
  constructor(agentId) {
@@ -7558,9 +8644,9 @@ function expandHomePath(configPath, homeDir) {
7558
8644
  return homeDir;
7559
8645
  }
7560
8646
  if (configPath.startsWith("~/")) {
7561
- return path34.join(homeDir, configPath.slice(2));
8647
+ return path38.join(homeDir, configPath.slice(2));
7562
8648
  }
7563
- return path34.join(homeDir, configPath.slice(1));
8649
+ return path38.join(homeDir, configPath.slice(1));
7564
8650
  }
7565
8651
  function parseYamlDocument(content) {
7566
8652
  if (content.trim() === "") {
@@ -7593,7 +8679,7 @@ async function writeYamlConfig(configPath, document, options) {
7593
8679
  return;
7594
8680
  }
7595
8681
  const absolutePath = expandHomePath(configPath, options.homeDir);
7596
- const configDir = path34.dirname(absolutePath);
8682
+ const configDir = path38.dirname(absolutePath);
7597
8683
  await options.fs.mkdir(configDir, { recursive: true });
7598
8684
  await options.fs.writeFile(absolutePath, serializeYamlDocument(document), {
7599
8685
  encoding: "utf8"
@@ -7771,7 +8857,7 @@ async function installMemory(options) {
7771
8857
 
7772
8858
  // packages/memory/src/query.ts
7773
8859
  import * as fs12 from "node:fs/promises";
7774
- import path35 from "node:path";
8860
+ import path39 from "node:path";
7775
8861
  async function queryMemory(root, options) {
7776
8862
  const pages = await listPages(root);
7777
8863
  if (pages.length === 0) {
@@ -7785,7 +8871,7 @@ async function queryMemory(root, options) {
7785
8871
  }
7786
8872
  const configOptions = {
7787
8873
  fs: fs12,
7788
- filePath: path35.join(inferRepoRoot2(root), "poe-code.json")
8874
+ filePath: path39.join(inferRepoRoot2(root), "poe-code.json")
7789
8875
  };
7790
8876
  const agentId = await resolveAgent(configOptions, options.agent ?? null) ?? options.agent ?? "claude-code";
7791
8877
  const context = await selectQueryContext(root, options.question, options.budget);
@@ -7800,7 +8886,7 @@ async function queryMemory(root, options) {
7800
8886
  }
7801
8887
  async function selectQueryContext(root, question, budget) {
7802
8888
  const [indexText, pages] = await Promise.all([
7803
- fs12.readFile(path35.join(root, MEMORY_INDEX_RELPATH), "utf8"),
8889
+ fs12.readFile(path39.join(root, MEMORY_INDEX_RELPATH), "utf8"),
7804
8890
  listPages(root)
7805
8891
  ]);
7806
8892
  const indexTokens = countTokens(indexText);
@@ -7879,12 +8965,12 @@ function tokenize(text4) {
7879
8965
  return text4.toLowerCase().split(/[^a-z0-9]+/).filter((token) => token.length > 0);
7880
8966
  }
7881
8967
  function inferRepoRoot2(root) {
7882
- return path35.resolve(root, "..", "..");
8968
+ return path39.resolve(root, "..", "..");
7883
8969
  }
7884
8970
 
7885
8971
  // packages/memory/src/explain.ts
7886
8972
  import * as fs13 from "node:fs/promises";
7887
- import path36 from "node:path";
8973
+ import path40 from "node:path";
7888
8974
  async function explainPage(root, options) {
7889
8975
  const targetPage = await readPageIfPresent(root, options.relPath);
7890
8976
  if (targetPage === void 0) {
@@ -7907,7 +8993,7 @@ async function explainPage(root, options) {
7907
8993
  }
7908
8994
  const configOptions = {
7909
8995
  fs: fs13,
7910
- filePath: path36.join(inferRepoRoot3(root), "poe-code.json")
8996
+ filePath: path40.join(inferRepoRoot3(root), "poe-code.json")
7911
8997
  };
7912
8998
  const agentId = await resolveAgent(configOptions, options.agent ?? null) ?? options.agent ?? "claude-code";
7913
8999
  const response = await spawn3(agentId, { prompt });
@@ -7956,7 +9042,7 @@ async function readPageIfPresent(root, relPath) {
7956
9042
  }
7957
9043
  }
7958
9044
  function inferRepoRoot3(root) {
7959
- return path36.resolve(root, "..", "..");
9045
+ return path40.resolve(root, "..", "..");
7960
9046
  }
7961
9047
 
7962
9048
  // packages/memory/src/explain.cli.ts
@@ -7969,9 +9055,9 @@ async function runMemoryExplain(input) {
7969
9055
  }
7970
9056
 
7971
9057
  // packages/memory/src/handle.ts
7972
- import path37 from "node:path";
9058
+ import path41 from "node:path";
7973
9059
  function openMemory(opts) {
7974
- if (!path37.isAbsolute(opts.root)) {
9060
+ if (!path41.isAbsolute(opts.root)) {
7975
9061
  throw new Error(`openMemory: root must be absolute, got ${opts.root}`);
7976
9062
  }
7977
9063
  const root = opts.root;