poe-code 3.0.131 → 3.0.133

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 (36) hide show
  1. package/README.md +33 -3
  2. package/dist/cli/commands/spawn.js +154 -150
  3. package/dist/cli/commands/spawn.js.map +1 -1
  4. package/dist/cli/poe-agent-main.js +10 -9
  5. package/dist/cli/poe-agent-main.js.map +1 -1
  6. package/dist/cli/program.js +0 -2
  7. package/dist/cli/program.js.map +1 -1
  8. package/dist/index.js +1113 -1087
  9. package/dist/index.js.map +4 -4
  10. package/dist/prompts/github-issue-opened.md +20 -1
  11. package/dist/providers/claude-code.js +29 -23
  12. package/dist/providers/claude-code.js.map +4 -4
  13. package/dist/providers/codex.js +29 -23
  14. package/dist/providers/codex.js.map +4 -4
  15. package/dist/providers/kimi.js +29 -23
  16. package/dist/providers/kimi.js.map +4 -4
  17. package/dist/providers/opencode.js +29 -23
  18. package/dist/providers/opencode.js.map +4 -4
  19. package/dist/sdk/launch.js +17 -1
  20. package/dist/sdk/launch.js.map +1 -1
  21. package/dist/sdk/spawn-core.d.ts +1 -1
  22. package/dist/sdk/spawn-core.js +54 -57
  23. package/dist/sdk/spawn-core.js.map +1 -1
  24. package/dist/sdk/spawn.js +31 -12
  25. package/dist/sdk/spawn.js.map +1 -1
  26. package/dist/sdk/types.d.ts +3 -3
  27. package/dist/workspace/resolve-spawn-workspace.d.ts +15 -0
  28. package/dist/workspace/resolve-spawn-workspace.js +28 -0
  29. package/dist/workspace/resolve-spawn-workspace.js.map +1 -0
  30. package/package.json +2 -1
  31. package/dist/cli/commands/research.d.ts +0 -13
  32. package/dist/cli/commands/research.js +0 -158
  33. package/dist/cli/commands/research.js.map +0 -1
  34. package/dist/sdk/research.d.ts +0 -62
  35. package/dist/sdk/research.js +0 -343
  36. package/dist/sdk/research.js.map +0 -1
package/dist/index.js CHANGED
@@ -1265,8 +1265,8 @@ async function applyChmod(mutation, context, options) {
1265
1265
  };
1266
1266
  }
1267
1267
  try {
1268
- const stat11 = await context.fs.stat(targetPath);
1269
- const currentMode = typeof stat11.mode === "number" ? stat11.mode & 511 : null;
1268
+ const stat13 = await context.fs.stat(targetPath);
1269
+ const currentMode = typeof stat13.mode === "number" ? stat13.mode & 511 : null;
1270
1270
  if (currentMode === mutation.mode) {
1271
1271
  return {
1272
1272
  outcome: { changed: false, effect: "none", detail: "noop" },
@@ -2756,7 +2756,7 @@ function toTomlInlineTable(values) {
2756
2756
  return `{${parts.join(", ")}}`;
2757
2757
  }
2758
2758
  function serializeJsonMcpArgs(servers) {
2759
- return ["--mcp-config", JSON.stringify({ mcpServers: toJsonMcpServers(servers) })];
2759
+ return ["--mcp-servers", JSON.stringify({ mcpServers: toJsonMcpServers(servers) })];
2760
2760
  }
2761
2761
  function serializeOpenCodeMcpEnv(servers) {
2762
2762
  const mcp = {};
@@ -3925,10 +3925,10 @@ function renderTableTerminal(options) {
3925
3925
  }
3926
3926
  function renderTableMarkdown(options) {
3927
3927
  const { columns, rows } = options;
3928
- const header = `| ${columns.map((c) => c.title).join(" | ")} |`;
3929
- const separator = `| ${columns.map((c) => c.alignment === "right" ? "---:" : ":---").join(" | ")} |`;
3928
+ const header = `| ${columns.map((c2) => c2.title).join(" | ")} |`;
3929
+ const separator = `| ${columns.map((c2) => c2.alignment === "right" ? "---:" : ":---").join(" | ")} |`;
3930
3930
  const dataRows = rows.map(
3931
- (row) => `| ${columns.map((c) => stripAnsi2(row[c.name] ?? "").replace(/\|/g, "\\|")).join(" | ")} |`
3931
+ (row) => `| ${columns.map((c2) => stripAnsi2(row[c2.name] ?? "").replace(/\|/g, "\\|")).join(" | ")} |`
3932
3932
  );
3933
3933
  return [header, separator, ...dataRows].join("\n");
3934
3934
  }
@@ -4105,6 +4105,42 @@ var init_acp = __esm({
4105
4105
  }
4106
4106
  });
4107
4107
 
4108
+ // node_modules/fast-string-truncated-width/dist/utils.js
4109
+ var init_utils = __esm({
4110
+ "node_modules/fast-string-truncated-width/dist/utils.js"() {
4111
+ }
4112
+ });
4113
+
4114
+ // node_modules/fast-string-truncated-width/dist/index.js
4115
+ var EMOJI_RE, MODIFIER_RE;
4116
+ var init_dist = __esm({
4117
+ "node_modules/fast-string-truncated-width/dist/index.js"() {
4118
+ init_utils();
4119
+ EMOJI_RE = new RegExp("[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*", "yu");
4120
+ MODIFIER_RE = new RegExp("\\p{M}+", "gu");
4121
+ }
4122
+ });
4123
+
4124
+ // node_modules/fast-string-width/dist/index.js
4125
+ var init_dist2 = __esm({
4126
+ "node_modules/fast-string-width/dist/index.js"() {
4127
+ init_dist();
4128
+ }
4129
+ });
4130
+
4131
+ // node_modules/fast-wrap-ansi/lib/main.js
4132
+ var ANSI_ESCAPE_BELL, ANSI_CSI, ANSI_OSC, ANSI_ESCAPE_LINK, GROUP_REGEX;
4133
+ var init_main = __esm({
4134
+ "node_modules/fast-wrap-ansi/lib/main.js"() {
4135
+ init_dist2();
4136
+ ANSI_ESCAPE_BELL = "\x07";
4137
+ ANSI_CSI = "[";
4138
+ ANSI_OSC = "]";
4139
+ ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
4140
+ GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
4141
+ }
4142
+ });
4143
+
4108
4144
  // node_modules/sisteransi/src/index.js
4109
4145
  var require_src = __commonJS({
4110
4146
  "node_modules/sisteransi/src/index.js"(exports, module) {
@@ -4113,16 +4149,16 @@ var require_src = __commonJS({
4113
4149
  var CSI = `${ESC}[`;
4114
4150
  var beep = "\x07";
4115
4151
  var cursor = {
4116
- to(x, y) {
4117
- if (!y) return `${CSI}${x + 1}G`;
4118
- return `${CSI}${y + 1};${x + 1}H`;
4152
+ to(x, y2) {
4153
+ if (!y2) return `${CSI}${x + 1}G`;
4154
+ return `${CSI}${y2 + 1};${x + 1}H`;
4119
4155
  },
4120
- move(x, y) {
4156
+ move(x, y2) {
4121
4157
  let ret = "";
4122
4158
  if (x < 0) ret += `${CSI}${-x}D`;
4123
4159
  else if (x > 0) ret += `${CSI}${x}C`;
4124
- if (y < 0) ret += `${CSI}${-y}A`;
4125
- else if (y > 0) ret += `${CSI}${y}B`;
4160
+ if (y2 < 0) ret += `${CSI}${-y2}A`;
4161
+ else if (y2 > 0) ret += `${CSI}${y2}B`;
4126
4162
  return ret;
4127
4163
  },
4128
4164
  up: (count = 1) => `${CSI}${count}A`,
@@ -4162,30 +4198,24 @@ var require_src = __commonJS({
4162
4198
  });
4163
4199
 
4164
4200
  // node_modules/@clack/core/dist/index.mjs
4165
- import { stdout as R, stdin as q } from "node:process";
4166
- import * as k from "node:readline";
4167
- import ot from "node:readline";
4168
- import { ReadStream as J } from "node:tty";
4169
- function Ct(t) {
4170
- return t === z;
4171
- }
4172
- var import_sisteransi, P, ct, pt, ft, j, Q, dt, U, et, At, _, bt, z;
4173
- var init_dist = __esm({
4201
+ import { styleText as y } from "node:util";
4202
+ import { stdout as S, stdin as $ } from "node:process";
4203
+ import * as _ from "node:readline";
4204
+ import P from "node:readline";
4205
+ import { ReadStream as D } from "node:tty";
4206
+ function q(r) {
4207
+ return r === C;
4208
+ }
4209
+ var import_sisteransi, E, G, u, Y, C;
4210
+ var init_dist3 = __esm({
4174
4211
  "node_modules/@clack/core/dist/index.mjs"() {
4212
+ init_main();
4175
4213
  import_sisteransi = __toESM(require_src(), 1);
4176
- P = new RegExp("[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*", "yu");
4177
- ct = new RegExp("\\p{M}+", "gu");
4178
- pt = { limit: 1 / 0, ellipsis: "" };
4179
- ft = { limit: 1 / 0, ellipsis: "", ellipsisWidth: 0 };
4180
- j = "\x07";
4181
- Q = "[";
4182
- dt = "]";
4183
- U = `${dt}8;;`;
4184
- et = new RegExp(`(?:\\${Q}(?<code>\\d+)m|\\${U}(?<uri>.*)${j})`, "y");
4185
- At = ["up", "down", "left", "right", "space", "enter", "cancel"];
4186
- _ = { actions: new Set(At), aliases: /* @__PURE__ */ new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["", "cancel"], ["escape", "cancel"]]), messages: { cancel: "Canceled", error: "Something went wrong" }, withGuide: true };
4187
- bt = globalThis.process.platform.startsWith("win");
4188
- z = /* @__PURE__ */ Symbol("clack:cancel");
4214
+ E = ["up", "down", "left", "right", "space", "enter", "cancel"];
4215
+ G = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
4216
+ u = { actions: new Set(E), aliases: /* @__PURE__ */ new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["", "cancel"], ["escape", "cancel"]]), messages: { cancel: "Canceled", error: "Something went wrong" }, withGuide: true, date: { monthNames: [...G], messages: { required: "Please enter a valid date", invalidMonth: "There are only 12 months in a year", invalidDay: (r, t) => `There are only ${r} days in ${t}`, afterMin: (r) => `Date must be on or after ${r.toISOString().slice(0, 10)}`, beforeMax: (r) => `Date must be on or before ${r.toISOString().slice(0, 10)}` } } };
4217
+ Y = globalThis.process.platform.startsWith("win");
4218
+ C = /* @__PURE__ */ Symbol("clack:cancel");
4189
4219
  }
4190
4220
  });
4191
4221
 
@@ -4202,7 +4232,7 @@ function cancel(msg = "") {
4202
4232
  var init_cancel = __esm({
4203
4233
  "packages/design-system/src/prompts/primitives/cancel.ts"() {
4204
4234
  "use strict";
4205
- init_dist();
4235
+ init_dist3();
4206
4236
  init_output_format();
4207
4237
  }
4208
4238
  });
@@ -4688,7 +4718,7 @@ function extractThreadId(value) {
4688
4718
  const maybeThreadId = isNonEmptyString(obj.thread_id) && obj.thread_id || isNonEmptyString(obj.threadId) && obj.threadId || isNonEmptyString(obj.threadID) && obj.threadID || isNonEmptyString(obj.session_id) && obj.session_id || isNonEmptyString(obj.sessionId) && obj.sessionId || isNonEmptyString(obj.sessionID) && obj.sessionID;
4689
4719
  return maybeThreadId || void 0;
4690
4720
  }
4691
- var init_utils = __esm({
4721
+ var init_utils2 = __esm({
4692
4722
  "packages/agent-spawn/src/adapters/utils.ts"() {
4693
4723
  "use strict";
4694
4724
  }
@@ -4805,7 +4835,7 @@ var TOOL_KIND_MAP, TITLE_KEYS;
4805
4835
  var init_claude = __esm({
4806
4836
  "packages/agent-spawn/src/adapters/claude.ts"() {
4807
4837
  "use strict";
4808
- init_utils();
4838
+ init_utils2();
4809
4839
  TOOL_KIND_MAP = {
4810
4840
  Read: "read",
4811
4841
  Write: "edit",
@@ -4928,7 +4958,7 @@ async function* adaptCodex(lines) {
4928
4958
  var init_codex3 = __esm({
4929
4959
  "packages/agent-spawn/src/adapters/codex.ts"() {
4930
4960
  "use strict";
4931
- init_utils();
4961
+ init_utils2();
4932
4962
  }
4933
4963
  });
4934
4964
 
@@ -4968,7 +4998,7 @@ async function* adaptKimi(lines) {
4968
4998
  var init_kimi3 = __esm({
4969
4999
  "packages/agent-spawn/src/adapters/kimi.ts"() {
4970
5000
  "use strict";
4971
- init_utils();
5001
+ init_utils2();
4972
5002
  }
4973
5003
  });
4974
5004
 
@@ -5003,7 +5033,7 @@ async function* adaptNative(lines) {
5003
5033
  var init_native = __esm({
5004
5034
  "packages/agent-spawn/src/adapters/native.ts"() {
5005
5035
  "use strict";
5006
- init_utils();
5036
+ init_utils2();
5007
5037
  }
5008
5038
  });
5009
5039
 
@@ -5119,7 +5149,7 @@ async function* adaptOpenCode(lines) {
5119
5149
  var init_opencode3 = __esm({
5120
5150
  "packages/agent-spawn/src/adapters/opencode.ts"() {
5121
5151
  "use strict";
5122
- init_utils();
5152
+ init_utils2();
5123
5153
  }
5124
5154
  });
5125
5155
 
@@ -7415,8 +7445,357 @@ var init_shared = __esm({
7415
7445
  }
7416
7446
  });
7417
7447
 
7418
- // src/sdk/spawn-core.ts
7448
+ // packages/workspace-resolver/src/parse.ts
7449
+ function parseLocator(input) {
7450
+ const value = input.trim();
7451
+ if (value.length === 0 || looksLikeWindowsDrivePath(value)) {
7452
+ return { scheme: "local", path: value };
7453
+ }
7454
+ const schemeSeparator = value.indexOf("://");
7455
+ if (schemeSeparator === -1) {
7456
+ return { scheme: "local", path: value };
7457
+ }
7458
+ const scheme = value.slice(0, schemeSeparator).toLowerCase();
7459
+ const rest = value.slice(schemeSeparator + 3);
7460
+ if (scheme === "github") {
7461
+ return parseGithubLocator(rest);
7462
+ }
7463
+ if (scheme === "ssh") {
7464
+ return parseSshLocator(value);
7465
+ }
7466
+ if (scheme === "docker") {
7467
+ return parseDockerLocator(rest);
7468
+ }
7469
+ throw new Error(`Unsupported workspace locator scheme "${scheme}".`);
7470
+ }
7471
+ function parseGithubLocator(input) {
7472
+ const { head, tail } = splitOnce(input, "#");
7473
+ const segments = splitPathSegments(head);
7474
+ const owner = segments[0];
7475
+ const repo = segments[1];
7476
+ if (!owner || !repo) {
7477
+ throw new Error(`Invalid github workspace locator "${input}".`);
7478
+ }
7479
+ const pathSubdir = joinPathSegments(segments.slice(2));
7480
+ let ref;
7481
+ let fragmentSubdir;
7482
+ if (tail !== void 0 && tail.length > 0) {
7483
+ const refParts = splitOnce(tail, ":");
7484
+ ref = refParts.head || void 0;
7485
+ fragmentSubdir = refParts.tail || void 0;
7486
+ }
7487
+ if (pathSubdir && fragmentSubdir) {
7488
+ throw new Error(`Invalid github workspace locator "${input}".`);
7489
+ }
7490
+ return {
7491
+ scheme: "github",
7492
+ owner,
7493
+ repo,
7494
+ ...ref ? { ref } : {},
7495
+ ...pathSubdir || fragmentSubdir ? { subdir: pathSubdir || fragmentSubdir } : {}
7496
+ };
7497
+ }
7498
+ function parseSshLocator(input) {
7499
+ const url = new URL(input);
7500
+ const host = url.hostname;
7501
+ const pathname = url.pathname;
7502
+ if (!host || pathname.length === 0) {
7503
+ throw new Error(`Invalid ssh workspace locator "${input}".`);
7504
+ }
7505
+ const port = url.port.length > 0 ? Number.parseInt(url.port, 10) : void 0;
7506
+ return {
7507
+ scheme: "ssh",
7508
+ ...url.username ? { user: decodeURIComponent(url.username) } : {},
7509
+ host,
7510
+ ...port !== void 0 ? { port } : {},
7511
+ path: pathname
7512
+ };
7513
+ }
7514
+ function parseDockerLocator(input) {
7515
+ const slashIndex = input.indexOf("/");
7516
+ if (slashIndex === -1) {
7517
+ throw new Error(`Invalid docker workspace locator "${input}".`);
7518
+ }
7519
+ const container = input.slice(0, slashIndex);
7520
+ const path42 = input.slice(slashIndex);
7521
+ if (container.length === 0 || path42.length === 0) {
7522
+ throw new Error(`Invalid docker workspace locator "${input}".`);
7523
+ }
7524
+ return {
7525
+ scheme: "docker",
7526
+ container,
7527
+ path: path42
7528
+ };
7529
+ }
7530
+ function splitOnce(input, separator) {
7531
+ const index = input.indexOf(separator);
7532
+ if (index === -1) {
7533
+ return { head: input };
7534
+ }
7535
+ return {
7536
+ head: input.slice(0, index),
7537
+ tail: input.slice(index + separator.length)
7538
+ };
7539
+ }
7540
+ function splitPathSegments(input) {
7541
+ const segments = [];
7542
+ let current = "";
7543
+ for (let index = 0; index < input.length; index += 1) {
7544
+ const char = input[index];
7545
+ if (char === "/") {
7546
+ if (current.length > 0) {
7547
+ segments.push(current);
7548
+ }
7549
+ current = "";
7550
+ continue;
7551
+ }
7552
+ current += char;
7553
+ }
7554
+ if (current.length > 0) {
7555
+ segments.push(current);
7556
+ }
7557
+ return segments;
7558
+ }
7559
+ function joinPathSegments(segments) {
7560
+ if (segments.length === 0) {
7561
+ return void 0;
7562
+ }
7563
+ let output = segments[0] ?? "";
7564
+ for (let index = 1; index < segments.length; index += 1) {
7565
+ output += `/${segments[index]}`;
7566
+ }
7567
+ return output;
7568
+ }
7569
+ function looksLikeWindowsDrivePath(input) {
7570
+ if (input.length < 3 || input[1] !== ":") {
7571
+ return false;
7572
+ }
7573
+ const drive = input.charCodeAt(0);
7574
+ const isLetter = drive >= 65 && drive <= 90 || drive >= 97 && drive <= 122;
7575
+ if (!isLetter) {
7576
+ return false;
7577
+ }
7578
+ const separator = input[2];
7579
+ return separator === "\\" || separator === "/";
7580
+ }
7581
+ var init_parse = __esm({
7582
+ "packages/workspace-resolver/src/parse.ts"() {
7583
+ "use strict";
7584
+ }
7585
+ });
7586
+
7587
+ // packages/workspace-resolver/src/github/clone.ts
7419
7588
  import path8 from "node:path";
7589
+ function buildCachePath(homeDir, locator) {
7590
+ return path8.join(
7591
+ homeDir,
7592
+ ".poe-code",
7593
+ "workspaces",
7594
+ "github",
7595
+ `${locator.owner}-${locator.repo}`
7596
+ );
7597
+ }
7598
+ function buildCloneUrl(locator) {
7599
+ return `https://github.com/${locator.owner}/${locator.repo}.git`;
7600
+ }
7601
+ async function cloneOrUpdate(locator, options) {
7602
+ const cacheDir = buildCachePath(options.homeDir, locator);
7603
+ const exists = await pathExists2(options.fs, cacheDir);
7604
+ if (!exists) {
7605
+ await options.fs.mkdir(path8.dirname(cacheDir), { recursive: true });
7606
+ await assertExecSuccess(
7607
+ await options.exec("git", ["clone", "--depth", "1", buildCloneUrl(locator), cacheDir]),
7608
+ "git clone failed"
7609
+ );
7610
+ await options.fs.mkdir(cacheDir, { recursive: true });
7611
+ } else {
7612
+ const statusResult = await options.exec("git", ["status", "--porcelain"], { cwd: cacheDir });
7613
+ if (statusResult.exitCode === 0 && statusResult.stdout.trim().length === 0) {
7614
+ await options.exec("git", ["pull", "--ff-only"], { cwd: cacheDir });
7615
+ }
7616
+ }
7617
+ if (locator.ref) {
7618
+ await assertExecSuccess(
7619
+ await options.exec("git", ["fetch", "origin"], { cwd: cacheDir }),
7620
+ "git fetch failed"
7621
+ );
7622
+ await assertExecSuccess(
7623
+ await options.exec("git", ["checkout", locator.ref], { cwd: cacheDir }),
7624
+ "git checkout failed"
7625
+ );
7626
+ }
7627
+ return cacheDir;
7628
+ }
7629
+ async function pathExists2(fs3, target) {
7630
+ try {
7631
+ await fs3.stat(target);
7632
+ return true;
7633
+ } catch {
7634
+ return false;
7635
+ }
7636
+ }
7637
+ function assertExecSuccess(result, fallback) {
7638
+ if (result.exitCode === 0) {
7639
+ return;
7640
+ }
7641
+ const detail = result.stderr.trim() || result.stdout.trim() || fallback;
7642
+ throw new Error(detail);
7643
+ }
7644
+ var init_clone = __esm({
7645
+ "packages/workspace-resolver/src/github/clone.ts"() {
7646
+ "use strict";
7647
+ }
7648
+ });
7649
+
7650
+ // packages/workspace-resolver/src/github/isolation.ts
7651
+ import path9 from "node:path";
7652
+ async function createWritableCheckout(locator, sourceCwd, options) {
7653
+ const cwd = path9.join(
7654
+ options.homeDir,
7655
+ ".poe-code",
7656
+ "workspaces",
7657
+ "checkouts",
7658
+ `${locator.owner}-${locator.repo}`,
7659
+ createCheckoutId()
7660
+ );
7661
+ const revision = locator.ref ?? "HEAD";
7662
+ await options.fs.mkdir(path9.dirname(cwd), { recursive: true });
7663
+ await assertExecSuccess2(
7664
+ await options.exec("git", ["worktree", "add", "--detach", cwd, revision], {
7665
+ cwd: sourceCwd
7666
+ }),
7667
+ "git worktree add failed"
7668
+ );
7669
+ await options.fs.mkdir(cwd, { recursive: true });
7670
+ return {
7671
+ cwd,
7672
+ cleanup: async () => {
7673
+ const result = await options.exec("git", ["worktree", "remove", "--force", cwd], {
7674
+ cwd: sourceCwd
7675
+ });
7676
+ if (result.exitCode === 0) {
7677
+ return;
7678
+ }
7679
+ if (options.fs.rm) {
7680
+ await options.fs.rm(cwd, { recursive: true, force: true });
7681
+ }
7682
+ }
7683
+ };
7684
+ }
7685
+ function createCheckoutId() {
7686
+ return `${Date.now().toString(36)}-${process.pid.toString(36)}`;
7687
+ }
7688
+ function assertExecSuccess2(result, fallback) {
7689
+ if (result.exitCode === 0) {
7690
+ return;
7691
+ }
7692
+ const detail = result.stderr.trim() || result.stdout.trim() || fallback;
7693
+ throw new Error(detail);
7694
+ }
7695
+ var init_isolation = __esm({
7696
+ "packages/workspace-resolver/src/github/isolation.ts"() {
7697
+ "use strict";
7698
+ }
7699
+ });
7700
+
7701
+ // packages/workspace-resolver/src/resolve.ts
7702
+ import path10 from "node:path";
7703
+ async function resolveWorkspace(input, options) {
7704
+ const locator = parseLocator(input);
7705
+ if (locator.scheme === "local") {
7706
+ return {
7707
+ cwd: path10.isAbsolute(locator.path) ? locator.path : path10.resolve(options.baseDir, locator.path),
7708
+ locator
7709
+ };
7710
+ }
7711
+ if (locator.scheme === "ssh" || locator.scheme === "docker") {
7712
+ throw new Error(`Unsupported workspace locator scheme "${locator.scheme}".`);
7713
+ }
7714
+ const mode = options.mode ?? "read";
7715
+ const cacheDir = await cloneOrUpdate(locator, options);
7716
+ let writable;
7717
+ try {
7718
+ writable = mode === "read" ? void 0 : await createWritableCheckout(locator, cacheDir, options);
7719
+ const workspaceRoot = writable?.cwd ?? cacheDir;
7720
+ const cwd = locator.subdir ? path10.join(workspaceRoot, locator.subdir) : workspaceRoot;
7721
+ await assertPathExists(options.fs, cwd, locator);
7722
+ return {
7723
+ cwd,
7724
+ ...writable ? { cleanup: writable.cleanup } : {},
7725
+ locator
7726
+ };
7727
+ } catch (error2) {
7728
+ await writable?.cleanup?.();
7729
+ throw error2;
7730
+ }
7731
+ }
7732
+ async function assertPathExists(fs3, target, locator) {
7733
+ try {
7734
+ await fs3.stat(target);
7735
+ } catch {
7736
+ if (locator.scheme === "github" && locator.subdir) {
7737
+ throw new Error(
7738
+ `Workspace subdirectory "${locator.subdir}" does not exist in github://${locator.owner}/${locator.repo}.`
7739
+ );
7740
+ }
7741
+ throw new Error(`Workspace path "${target}" does not exist.`);
7742
+ }
7743
+ }
7744
+ var init_resolve2 = __esm({
7745
+ "packages/workspace-resolver/src/resolve.ts"() {
7746
+ "use strict";
7747
+ init_clone();
7748
+ init_isolation();
7749
+ init_parse();
7750
+ }
7751
+ });
7752
+
7753
+ // packages/workspace-resolver/src/index.ts
7754
+ var init_src8 = __esm({
7755
+ "packages/workspace-resolver/src/index.ts"() {
7756
+ "use strict";
7757
+ init_parse();
7758
+ init_resolve2();
7759
+ init_clone();
7760
+ init_isolation();
7761
+ }
7762
+ });
7763
+
7764
+ // src/workspace/resolve-spawn-workspace.ts
7765
+ async function resolveSpawnWorkspace(candidate, options) {
7766
+ if (!candidate || candidate.trim().length === 0) {
7767
+ return {};
7768
+ }
7769
+ const locator = parseLocator(candidate);
7770
+ if (locator.scheme !== "local" && options.resolveRemoteLocators === false) {
7771
+ return {
7772
+ cwd: candidate
7773
+ };
7774
+ }
7775
+ const resolved = await resolveWorkspace(candidate, {
7776
+ baseDir: options.baseDir,
7777
+ homeDir: options.homeDir,
7778
+ mode: options.mode,
7779
+ fs: {
7780
+ mkdir: options.fs.mkdir,
7781
+ stat: options.fs.stat,
7782
+ ...options.fs.rm ? { rm: options.fs.rm } : {}
7783
+ },
7784
+ exec: async (command, args, execOptions) => await options.exec(command, args, execOptions ? { cwd: execOptions.cwd } : void 0)
7785
+ });
7786
+ return {
7787
+ cwd: resolved.cwd,
7788
+ cleanup: resolved.cleanup
7789
+ };
7790
+ }
7791
+ var init_resolve_spawn_workspace = __esm({
7792
+ "src/workspace/resolve-spawn-workspace.ts"() {
7793
+ "use strict";
7794
+ init_src8();
7795
+ }
7796
+ });
7797
+
7798
+ // src/sdk/spawn-core.ts
7420
7799
  import chalk17 from "chalk";
7421
7800
  async function spawnCore(container, service, options, flags = { dryRun: false, verbose: false }) {
7422
7801
  const adapter = container.registry.get(service);
@@ -7424,66 +7803,75 @@ async function spawnCore(container, service, options, flags = { dryRun: false, v
7424
7803
  throw new Error(`Unknown service "${service}".`);
7425
7804
  }
7426
7805
  const model = await resolveConfiguredModel(container, service, options.model);
7427
- const cwdOverride = resolveSpawnWorkingDirectory(
7428
- container.env.cwd,
7429
- options.cwd
7430
- );
7431
- const spawnOptions = {
7432
- prompt: options.prompt,
7433
- args: options.args,
7434
- model,
7806
+ const workspace = await resolveSpawnWorkspace(options.cwd, {
7807
+ baseDir: container.env.cwd,
7808
+ homeDir: container.env.homeDir,
7435
7809
  mode: options.mode,
7436
- mcpServers: options.mcpServers,
7437
- cwd: cwdOverride,
7438
- useStdin: options.useStdin ?? false
7439
- };
7440
- const commandFlags = { dryRun: flags.dryRun, assumeYes: true, verbose: flags.verbose };
7441
- const resources = createExecutionResources(
7442
- container,
7443
- commandFlags,
7444
- `spawn:${service}`
7445
- );
7446
- if (flags.dryRun) {
7447
- const summary = formatSpawnDryRunMessage(adapter.label, spawnOptions);
7448
- resources.logger.dryRun(summary);
7449
- return {
7450
- stdout: "",
7451
- stderr: "",
7452
- exitCode: 0
7810
+ resolveRemoteLocators: !flags.dryRun,
7811
+ fs: container.fs,
7812
+ exec: container.commandRunner
7813
+ });
7814
+ const cwdOverride = workspace.cwd;
7815
+ try {
7816
+ const spawnOptions = {
7817
+ prompt: options.prompt,
7818
+ args: options.args,
7819
+ model,
7820
+ mode: options.mode,
7821
+ mcpServers: options.mcpServers,
7822
+ cwd: cwdOverride,
7823
+ useStdin: options.useStdin ?? false
7453
7824
  };
7454
- }
7455
- if (typeof adapter.spawn !== "function") {
7456
- throw new Error(`${adapter.label} does not support spawn.`);
7457
- }
7458
- if (spawnOptions.useStdin && !adapter.supportsStdinPrompt) {
7459
- throw new Error(
7460
- `${adapter.label} does not support stdin prompts. Use a different service (e.g. "codex") or pass the prompt as an argument.`
7825
+ const commandFlags = { dryRun: flags.dryRun, assumeYes: true, verbose: flags.verbose };
7826
+ const resources = createExecutionResources(
7827
+ container,
7828
+ commandFlags,
7829
+ `spawn:${service}`
7461
7830
  );
7462
- }
7463
- const providerContext = buildProviderContext(container, adapter, resources);
7464
- const result = await container.registry.invoke(
7465
- adapter.name,
7466
- "spawn",
7467
- async (entry) => {
7468
- if (!entry.spawn) {
7469
- throw new Error(`${adapter.label} does not support spawn.`);
7831
+ if (flags.dryRun) {
7832
+ const summary = formatSpawnDryRunMessage(adapter.label, spawnOptions);
7833
+ resources.logger.dryRun(summary);
7834
+ return {
7835
+ stdout: "",
7836
+ stderr: "",
7837
+ exitCode: 0
7838
+ };
7839
+ }
7840
+ if (typeof adapter.spawn !== "function") {
7841
+ throw new Error(`${adapter.label} does not support spawn.`);
7842
+ }
7843
+ if (spawnOptions.useStdin && !adapter.supportsStdinPrompt) {
7844
+ throw new Error(
7845
+ `${adapter.label} does not support stdin prompts. Use a different service (e.g. "codex") or pass the prompt as an argument.`
7846
+ );
7847
+ }
7848
+ const providerContext = buildProviderContext(container, adapter, resources);
7849
+ const result = await container.registry.invoke(
7850
+ adapter.name,
7851
+ "spawn",
7852
+ async (entry) => {
7853
+ if (!entry.spawn) {
7854
+ throw new Error(`${adapter.label} does not support spawn.`);
7855
+ }
7856
+ const output = await entry.spawn(providerContext, spawnOptions);
7857
+ return output;
7470
7858
  }
7471
- const output = await entry.spawn(providerContext, spawnOptions);
7472
- return output;
7859
+ );
7860
+ if (!result) {
7861
+ return {
7862
+ stdout: "",
7863
+ stderr: "",
7864
+ exitCode: 0
7865
+ };
7473
7866
  }
7474
- );
7475
- if (!result) {
7476
7867
  return {
7477
- stdout: "",
7478
- stderr: "",
7479
- exitCode: 0
7868
+ stdout: result.stdout,
7869
+ stderr: result.stderr,
7870
+ exitCode: result.exitCode
7480
7871
  };
7872
+ } finally {
7873
+ await workspace.cleanup?.();
7481
7874
  }
7482
- return {
7483
- stdout: result.stdout,
7484
- stderr: result.stderr,
7485
- exitCode: result.exitCode
7486
- };
7487
7875
  }
7488
7876
  async function resolveConfiguredModel(container, service, model) {
7489
7877
  if (model != null) {
@@ -7531,26 +7919,18 @@ function formatSpawnArg(arg) {
7531
7919
  function formatQuoted(value) {
7532
7920
  return JSON.stringify(value);
7533
7921
  }
7534
- function resolveSpawnWorkingDirectory(baseDir, candidate) {
7535
- if (!candidate || candidate.trim().length === 0) {
7536
- return void 0;
7537
- }
7538
- if (path8.isAbsolute(candidate)) {
7539
- return candidate;
7540
- }
7541
- return path8.resolve(baseDir, candidate);
7542
- }
7543
7922
  var init_spawn_core = __esm({
7544
7923
  "src/sdk/spawn-core.ts"() {
7545
7924
  "use strict";
7546
7925
  init_src2();
7547
7926
  init_src4();
7548
7927
  init_shared();
7928
+ init_resolve_spawn_workspace();
7549
7929
  }
7550
7930
  });
7551
7931
 
7552
7932
  // src/cli/environment.ts
7553
- import path9 from "node:path";
7933
+ import path11 from "node:path";
7554
7934
  function createCliEnvironment(init) {
7555
7935
  const platform = init.platform ?? process.platform;
7556
7936
  const variables = init.variables ?? process.env;
@@ -7558,7 +7938,7 @@ function createCliEnvironment(init) {
7558
7938
  const projectConfigPath = resolveProjectConfigPath(init.cwd);
7559
7939
  const logDir = resolveLogDir(init.homeDir);
7560
7940
  const { poeApiBaseUrl, poeBaseUrl } = resolvePoeBaseUrls(variables);
7561
- const resolveHomePath = (...segments) => path9.join(init.homeDir, ...segments);
7941
+ const resolveHomePath = (...segments) => path11.join(init.homeDir, ...segments);
7562
7942
  const getVariable = (name) => variables[name];
7563
7943
  return {
7564
7944
  cwd: init.cwd,
@@ -7575,7 +7955,7 @@ function createCliEnvironment(init) {
7575
7955
  };
7576
7956
  }
7577
7957
  function resolveLogDir(homeDir) {
7578
- return path9.join(homeDir, ".poe-code", "logs");
7958
+ return path11.join(homeDir, ".poe-code", "logs");
7579
7959
  }
7580
7960
  function resolvePoeBaseUrls(variables) {
7581
7961
  const raw = variables.POE_BASE_URL;
@@ -8031,7 +8411,7 @@ var init_oauth_client = __esm({
8031
8411
  });
8032
8412
 
8033
8413
  // packages/poe-oauth/src/index.ts
8034
- var init_src8 = __esm({
8414
+ var init_src9 = __esm({
8035
8415
  "packages/poe-oauth/src/index.ts"() {
8036
8416
  "use strict";
8037
8417
  init_check_auth();
@@ -8471,7 +8851,7 @@ var init_logger2 = __esm({
8471
8851
  });
8472
8852
 
8473
8853
  // src/cli/error-logger.ts
8474
- import path10 from "node:path";
8854
+ import path12 from "node:path";
8475
8855
  var DEFAULT_MAX_SIZE, DEFAULT_MAX_BACKUPS, ErrorLogger;
8476
8856
  var init_error_logger = __esm({
8477
8857
  "src/cli/error-logger.ts"() {
@@ -8488,7 +8868,7 @@ var init_error_logger = __esm({
8488
8868
  fileLoggingAvailable;
8489
8869
  constructor(options) {
8490
8870
  this.fs = options.fs;
8491
- this.logFilePath = path10.join(options.logDir, "errors.log");
8871
+ this.logFilePath = path12.join(options.logDir, "errors.log");
8492
8872
  this.logToStderr = options.logToStderr ?? true;
8493
8873
  this.maxSize = options.maxSize ?? DEFAULT_MAX_SIZE;
8494
8874
  this.maxBackups = options.maxBackups ?? DEFAULT_MAX_BACKUPS;
@@ -8609,7 +8989,7 @@ ${entry.stack}`);
8609
8989
  return `${this.logFilePath}.${index}`;
8610
8990
  }
8611
8991
  ensureLogDirectory() {
8612
- const directory = path10.dirname(this.logFilePath);
8992
+ const directory = path12.dirname(this.logFilePath);
8613
8993
  try {
8614
8994
  if (!this.fs.existsSync(directory)) {
8615
8995
  this.fs.mkdirSync(directory, { recursive: true });
@@ -8627,7 +9007,7 @@ ${entry.stack}`);
8627
9007
  });
8628
9008
 
8629
9009
  // src/providers/index.ts
8630
- import path11 from "node:path";
9010
+ import path13 from "node:path";
8631
9011
  import { readdir } from "node:fs/promises";
8632
9012
  import { fileURLToPath, pathToFileURL } from "node:url";
8633
9013
  function isProviderModule(filename) {
@@ -8654,7 +9034,7 @@ async function loadProviders() {
8654
9034
  for (const entry of entries) {
8655
9035
  if (!entry.isFile()) continue;
8656
9036
  if (!isProviderModule(entry.name)) continue;
8657
- const moduleUrl = pathToFileURL(path11.join(currentDir, entry.name)).href;
9037
+ const moduleUrl = pathToFileURL(path13.join(currentDir, entry.name)).href;
8658
9038
  const moduleExports = await import(moduleUrl);
8659
9039
  if (!moduleExports.provider) {
8660
9040
  throw new Error(`Provider module "${entry.name}" must export "provider".`);
@@ -8670,8 +9050,8 @@ var moduleDir, currentDir, defaultProviders;
8670
9050
  var init_providers = __esm({
8671
9051
  async "src/providers/index.ts"() {
8672
9052
  "use strict";
8673
- moduleDir = path11.dirname(fileURLToPath(import.meta.url));
8674
- currentDir = path11.basename(moduleDir) === "providers" ? moduleDir : path11.join(moduleDir, "providers");
9053
+ moduleDir = path13.dirname(fileURLToPath(import.meta.url));
9054
+ currentDir = path13.basename(moduleDir) === "providers" ? moduleDir : path13.join(moduleDir, "providers");
8675
9055
  defaultProviders = await loadProviders();
8676
9056
  }
8677
9057
  });
@@ -9129,7 +9509,7 @@ var init_container = __esm({
9129
9509
  init_service_registry();
9130
9510
  init_context();
9131
9511
  init_prompts2();
9132
- init_src8();
9512
+ init_src9();
9133
9513
  init_options();
9134
9514
  init_logger2();
9135
9515
  init_error_logger();
@@ -9141,9 +9521,11 @@ var init_container = __esm({
9141
9521
  });
9142
9522
 
9143
9523
  // src/sdk/spawn.ts
9524
+ import * as nodeFs from "node:fs/promises";
9525
+ import os2 from "node:os";
9144
9526
  function spawn4(service, promptOrOptions, maybeOptions) {
9145
9527
  const options = typeof promptOrOptions === "string" ? { ...maybeOptions, prompt: promptOrOptions } : promptOrOptions;
9146
- const mcpConfig = options.mcpConfig ?? options.mcpServers;
9528
+ const resolvedMcpServers = options.mcpServers ?? options.mcpConfig;
9147
9529
  const emptyEvents = (async function* () {
9148
9530
  })();
9149
9531
  let resolveEvents;
@@ -9162,11 +9544,24 @@ function spawn4(service, promptOrOptions, maybeOptions) {
9162
9544
  }
9163
9545
  })();
9164
9546
  const result = (async () => {
9547
+ let workspace;
9165
9548
  try {
9549
+ workspace = await resolveSpawnWorkspace(options.cwd, {
9550
+ baseDir: process.cwd(),
9551
+ homeDir: os2.homedir(),
9552
+ mode: options.mode,
9553
+ fs: {
9554
+ mkdir: async (target, resolveOptions) => await nodeFs.mkdir(target, resolveOptions).then(() => void 0),
9555
+ stat: async (target) => await nodeFs.stat(target),
9556
+ rm: async (target, resolveOptions) => await nodeFs.rm(target, resolveOptions)
9557
+ },
9558
+ exec: runCommand
9559
+ });
9560
+ const cwd = workspace.cwd;
9166
9561
  await getPoeApiKey();
9167
9562
  let container;
9168
9563
  const getContainer = () => {
9169
- container ??= createSdkContainer({ cwd: options.cwd });
9564
+ container ??= createSdkContainer({ cwd });
9170
9565
  return container;
9171
9566
  };
9172
9567
  const resolveModel3 = async () => options.model ?? await resolveConfiguredModel(getContainer(), service);
@@ -9175,12 +9570,12 @@ function spawn4(service, promptOrOptions, maybeOptions) {
9175
9570
  const model2 = await resolveModel3();
9176
9571
  const interactiveResult = await spawnInteractive(service, {
9177
9572
  prompt: options.prompt,
9178
- cwd: options.cwd,
9573
+ cwd,
9179
9574
  model: model2,
9180
9575
  mode: options.mode,
9181
9576
  signal: options.signal,
9182
9577
  args: options.args,
9183
- ...mcpConfig ? { mcpServers: mcpConfig } : {}
9578
+ ...resolvedMcpServers ? { mcpServers: resolvedMcpServers } : {}
9184
9579
  });
9185
9580
  return {
9186
9581
  stdout: interactiveResult.stdout,
@@ -9238,12 +9633,12 @@ function spawn4(service, promptOrOptions, maybeOptions) {
9238
9633
  const { events: rawEvents, done } = spawnStreaming({
9239
9634
  agentId: service,
9240
9635
  prompt: options.prompt,
9241
- cwd: options.cwd,
9636
+ cwd,
9242
9637
  model: model2,
9243
9638
  mode: options.mode,
9244
9639
  args: options.args,
9245
9640
  signal: options.signal,
9246
- ...mcpConfig ? { mcpServers: mcpConfig } : {},
9641
+ ...resolvedMcpServers ? { mcpServers: resolvedMcpServers } : {},
9247
9642
  ...options.activityTimeoutMs !== void 0 ? { activityTimeoutMs: options.activityTimeoutMs } : {},
9248
9643
  useStdin: false
9249
9644
  });
@@ -9260,7 +9655,7 @@ function spawn4(service, promptOrOptions, maybeOptions) {
9260
9655
  prompt: options.prompt,
9261
9656
  model: model2,
9262
9657
  mode: options.mode,
9263
- cwd: options.cwd,
9658
+ cwd,
9264
9659
  startedAt: /* @__PURE__ */ new Date()
9265
9660
  };
9266
9661
  await applyMiddlewares([sessionCapture, usageCapture, spawnLog], middlewareContext);
@@ -9283,12 +9678,12 @@ function spawn4(service, promptOrOptions, maybeOptions) {
9283
9678
  const model2 = await resolveModel3();
9284
9679
  return spawn3(service, {
9285
9680
  prompt: options.prompt,
9286
- cwd: options.cwd,
9681
+ cwd,
9287
9682
  model: model2,
9288
9683
  mode: options.mode,
9289
9684
  args: options.args,
9290
9685
  signal: options.signal,
9291
- ...mcpConfig ? { mcpServers: mcpConfig } : {},
9686
+ ...resolvedMcpServers ? { mcpServers: resolvedMcpServers } : {},
9292
9687
  ...options.activityTimeoutMs !== void 0 ? { activityTimeoutMs: options.activityTimeoutMs } : {},
9293
9688
  useStdin: false
9294
9689
  });
@@ -9297,16 +9692,18 @@ function spawn4(service, promptOrOptions, maybeOptions) {
9297
9692
  const model = await resolveModel3();
9298
9693
  return spawnCore(getContainer(), service, {
9299
9694
  prompt: options.prompt,
9300
- cwd: options.cwd,
9695
+ cwd,
9301
9696
  model,
9302
9697
  mode: options.mode,
9303
9698
  args: options.args,
9304
- ...mcpConfig ? { mcpServers: mcpConfig } : {},
9699
+ ...resolvedMcpServers ? { mcpServers: resolvedMcpServers } : {},
9305
9700
  useStdin: false
9306
9701
  });
9307
9702
  } catch (error2) {
9308
9703
  resolveEventsOnce(emptyEvents);
9309
9704
  throw error2;
9705
+ } finally {
9706
+ await workspace?.cleanup?.();
9310
9707
  }
9311
9708
  })();
9312
9709
  return { events, result };
@@ -9330,6 +9727,7 @@ var init_spawn3 = __esm({
9330
9727
  init_spawn_core();
9331
9728
  await init_container();
9332
9729
  init_src7();
9730
+ init_resolve_spawn_workspace();
9333
9731
  spawn4.pretty = async function pretty(service, promptOrOptions, maybeOptions) {
9334
9732
  const { events, result } = spawn4(service, promptOrOptions, maybeOptions);
9335
9733
  await renderAcpStream(events);
@@ -9366,14 +9764,14 @@ function createAbortError4() {
9366
9764
  error2.name = "AbortError";
9367
9765
  return error2;
9368
9766
  }
9369
- var init_utils2 = __esm({
9767
+ var init_utils3 = __esm({
9370
9768
  "packages/pipeline/src/utils.ts"() {
9371
9769
  "use strict";
9372
9770
  }
9373
9771
  });
9374
9772
 
9375
9773
  // packages/pipeline/src/config/loader.ts
9376
- import path12 from "node:path";
9774
+ import path14 from "node:path";
9377
9775
  import { parse as parse4 } from "yaml";
9378
9776
  function asStepMode(value) {
9379
9777
  if (value === void 0 || value === null) {
@@ -9465,8 +9863,8 @@ async function loadStepsFile(fs3, filePath) {
9465
9863
  return parseStepConfigDocument(filePath, content);
9466
9864
  }
9467
9865
  async function loadPipelineConfig(options) {
9468
- const globalPath = path12.join(options.homeDir, ".poe-code", "pipeline", "config.yaml");
9469
- const projectPath = path12.join(options.cwd, ".poe-code", "pipeline", "config.yaml");
9866
+ const globalPath = path14.join(options.homeDir, ".poe-code", "pipeline", "config.yaml");
9867
+ const projectPath = path14.join(options.cwd, ".poe-code", "pipeline", "config.yaml");
9470
9868
  const [globalConfig, projectConfig] = await Promise.all([
9471
9869
  loadConfigFile(options.fs, globalPath),
9472
9870
  loadConfigFile(options.fs, projectPath)
@@ -9477,8 +9875,8 @@ async function loadPipelineConfig(options) {
9477
9875
  };
9478
9876
  }
9479
9877
  async function loadResolvedSteps(options) {
9480
- const globalPath = path12.join(options.homeDir, ".poe-code", "pipeline", "steps.yaml");
9481
- const projectPath = path12.join(options.cwd, ".poe-code", "pipeline", "steps.yaml");
9878
+ const globalPath = path14.join(options.homeDir, ".poe-code", "pipeline", "steps.yaml");
9879
+ const projectPath = path14.join(options.cwd, ".poe-code", "pipeline", "steps.yaml");
9482
9880
  const [globalConfig, projectConfig] = await Promise.all([
9483
9881
  loadStepsFile(options.fs, globalPath),
9484
9882
  loadStepsFile(options.fs, projectPath)
@@ -9492,7 +9890,7 @@ async function loadResolvedSteps(options) {
9492
9890
  var init_loader = __esm({
9493
9891
  "packages/pipeline/src/config/loader.ts"() {
9494
9892
  "use strict";
9495
- init_utils2();
9893
+ init_utils3();
9496
9894
  }
9497
9895
  });
9498
9896
 
@@ -9638,23 +10036,23 @@ function parsePlan(yamlContent, options = {}) {
9638
10036
  var init_parser = __esm({
9639
10037
  "packages/pipeline/src/plan/parser.ts"() {
9640
10038
  "use strict";
9641
- init_utils2();
10039
+ init_utils3();
9642
10040
  }
9643
10041
  });
9644
10042
 
9645
10043
  // packages/pipeline/src/plan/discovery.ts
9646
- import path13 from "node:path";
10044
+ import path15 from "node:path";
9647
10045
  import * as fsPromises2 from "node:fs/promises";
9648
10046
  function createDefaultFs() {
9649
10047
  return {
9650
10048
  readFile: fsPromises2.readFile,
9651
10049
  readdir: fsPromises2.readdir,
9652
10050
  stat: async (filePath) => {
9653
- const stat11 = await fsPromises2.stat(filePath);
10051
+ const stat13 = await fsPromises2.stat(filePath);
9654
10052
  return {
9655
- isFile: () => stat11.isFile(),
9656
- isDirectory: () => stat11.isDirectory(),
9657
- mtimeMs: stat11.mtimeMs
10053
+ isFile: () => stat13.isFile(),
10054
+ isDirectory: () => stat13.isDirectory(),
10055
+ mtimeMs: stat13.mtimeMs
9658
10056
  };
9659
10057
  }
9660
10058
  };
@@ -9679,10 +10077,10 @@ function countCompletedTasks(planPath, content) {
9679
10077
  };
9680
10078
  }
9681
10079
  async function ensurePlanExists(fs3, cwd, planPath) {
9682
- const absolutePath = path13.isAbsolute(planPath) ? planPath : path13.resolve(cwd, planPath);
10080
+ const absolutePath = path15.isAbsolute(planPath) ? planPath : path15.resolve(cwd, planPath);
9683
10081
  try {
9684
- const stat11 = await fs3.stat(absolutePath);
9685
- if (!stat11.isFile()) {
10082
+ const stat13 = await fs3.stat(absolutePath);
10083
+ if (!stat13.isFile()) {
9686
10084
  throw new Error(`Plan not found at "${planPath}".`);
9687
10085
  }
9688
10086
  } catch (error2) {
@@ -9707,12 +10105,12 @@ async function scanPlansDir(fs3, plansDir, displayPrefix) {
9707
10105
  if (!isPlanCandidateFile(entry)) {
9708
10106
  continue;
9709
10107
  }
9710
- const absolutePath = path13.join(plansDir, entry);
9711
- const stat11 = await fs3.stat(absolutePath);
9712
- if (!stat11.isFile()) {
10108
+ const absolutePath = path15.join(plansDir, entry);
10109
+ const stat13 = await fs3.stat(absolutePath);
10110
+ if (!stat13.isFile()) {
9713
10111
  continue;
9714
10112
  }
9715
- const displayPath = path13.join(displayPrefix, entry);
10113
+ const displayPath = path15.join(displayPrefix, entry);
9716
10114
  const content = await fs3.readFile(absolutePath, "utf8");
9717
10115
  candidates.push(countCompletedTasks(displayPath, content));
9718
10116
  }
@@ -9729,8 +10127,8 @@ async function scanCustomPlanDir(fs3, planDirectory, cwd, homeDir) {
9729
10127
  return scanPlansDir(fs3, absoluteDir, planDirectory);
9730
10128
  }
9731
10129
  async function scanDefaultPlanDirs(fs3, cwd, homeDir) {
9732
- const projectDir = path13.join(cwd, ".poe-code", "pipeline", "plans");
9733
- const globalDir = path13.join(homeDir, ".poe-code", "pipeline", "plans");
10130
+ const projectDir = path15.join(cwd, ".poe-code", "pipeline", "plans");
10131
+ const globalDir = path15.join(homeDir, ".poe-code", "pipeline", "plans");
9734
10132
  const [projectCandidates, globalCandidates] = await Promise.all([
9735
10133
  scanPlansDir(fs3, projectDir, ".poe-code/pipeline/plans"),
9736
10134
  scanPlansDir(fs3, globalDir, "~/.poe-code/pipeline/plans")
@@ -9739,9 +10137,9 @@ async function scanDefaultPlanDirs(fs3, cwd, homeDir) {
9739
10137
  }
9740
10138
  function resolveAbsoluteDirectory(dir, cwd, homeDir) {
9741
10139
  if (dir.startsWith("~/")) {
9742
- return path13.join(homeDir, dir.slice(2));
10140
+ return path15.join(homeDir, dir.slice(2));
9743
10141
  }
9744
- return path13.isAbsolute(dir) ? dir : path13.resolve(cwd, dir);
10142
+ return path15.isAbsolute(dir) ? dir : path15.resolve(cwd, dir);
9745
10143
  }
9746
10144
  async function resolvePlanDirectory(options) {
9747
10145
  const customDir = options.planDirectory?.trim();
@@ -9749,21 +10147,21 @@ async function resolvePlanDirectory(options) {
9749
10147
  return resolveAbsoluteDirectory(customDir, options.cwd, options.homeDir);
9750
10148
  }
9751
10149
  const fs3 = options.fs ?? createDefaultFs();
9752
- const projectDir = path13.join(options.cwd, ".poe-code");
10150
+ const projectDir = path15.join(options.cwd, ".poe-code");
9753
10151
  try {
9754
- const stat11 = await fs3.stat(projectDir);
9755
- if (stat11.isDirectory()) {
9756
- return path13.join(options.cwd, ".poe-code", "pipeline", "plans");
10152
+ const stat13 = await fs3.stat(projectDir);
10153
+ if (stat13.isDirectory()) {
10154
+ return path15.join(options.cwd, ".poe-code", "pipeline", "plans");
9757
10155
  }
9758
10156
  } catch {
9759
10157
  }
9760
- return path13.join(options.homeDir, ".poe-code", "pipeline", "plans");
10158
+ return path15.join(options.homeDir, ".poe-code", "pipeline", "plans");
9761
10159
  }
9762
10160
  function resolveAbsolutePlanPath(planPath, cwd, homeDir) {
9763
10161
  if (planPath.startsWith("~/")) {
9764
- return path13.join(homeDir, planPath.slice(2));
10162
+ return path15.join(homeDir, planPath.slice(2));
9765
10163
  }
9766
- return path13.isAbsolute(planPath) ? planPath : path13.resolve(cwd, planPath);
10164
+ return path15.isAbsolute(planPath) ? planPath : path15.resolve(cwd, planPath);
9767
10165
  }
9768
10166
  async function resolvePlanPath(options) {
9769
10167
  const fs3 = options.fs ?? createDefaultFs();
@@ -9815,7 +10213,7 @@ var init_discovery = __esm({
9815
10213
  "use strict";
9816
10214
  init_loader();
9817
10215
  init_parser();
9818
- init_utils2();
10216
+ init_utils3();
9819
10217
  }
9820
10218
  });
9821
10219
 
@@ -9867,7 +10265,7 @@ var init_writer = __esm({
9867
10265
  });
9868
10266
 
9869
10267
  // packages/pipeline/src/run/runner.ts
9870
- import path14 from "node:path";
10268
+ import path16 from "node:path";
9871
10269
  function getFailedStepName(status) {
9872
10270
  return Object.entries(status).find(([, value]) => value === "failed")?.[0];
9873
10271
  }
@@ -9921,7 +10319,7 @@ async function resolveFileIncludes(template, cwd, readFile15) {
9921
10319
  }
9922
10320
  let result = template;
9923
10321
  for (const match of matches) {
9924
- const absolutePath = path14.resolve(cwd, match[1]);
10322
+ const absolutePath = path16.resolve(cwd, match[1]);
9925
10323
  const content = await readFile15(absolutePath, "utf8");
9926
10324
  result = result.replace(match[0], content);
9927
10325
  }
@@ -9967,11 +10365,11 @@ function createDefaultFs2() {
9967
10365
  },
9968
10366
  rmdir: fsPromises3.rmdir,
9969
10367
  stat: async (filePath) => {
9970
- const stat11 = await fsPromises3.stat(filePath);
10368
+ const stat13 = await fsPromises3.stat(filePath);
9971
10369
  return {
9972
- isFile: () => stat11.isFile(),
9973
- isDirectory: () => stat11.isDirectory(),
9974
- mtimeMs: stat11.mtimeMs
10370
+ isFile: () => stat13.isFile(),
10371
+ isDirectory: () => stat13.isDirectory(),
10372
+ mtimeMs: stat13.mtimeMs
9975
10373
  };
9976
10374
  }
9977
10375
  };
@@ -10004,8 +10402,8 @@ async function lockFile(filePath, options = {}) {
10004
10402
  if (!error2 || typeof error2 !== "object" || !("code" in error2) || error2.code !== "EEXIST") {
10005
10403
  throw error2;
10006
10404
  }
10007
- const stat11 = await fs3.stat(lockPath);
10008
- if (Date.now() - stat11.mtimeMs > staleMs) {
10405
+ const stat13 = await fs3.stat(lockPath);
10406
+ if (Date.now() - stat13.mtimeMs > staleMs) {
10009
10407
  await fs3.rmdir(lockPath);
10010
10408
  continue;
10011
10409
  }
@@ -10023,7 +10421,7 @@ var init_lock = __esm({
10023
10421
  });
10024
10422
 
10025
10423
  // packages/pipeline/src/run/pipeline.ts
10026
- import path15 from "node:path";
10424
+ import path17 from "node:path";
10027
10425
  import * as fsPromises4 from "node:fs/promises";
10028
10426
  function createDefaultFs3() {
10029
10427
  return {
@@ -10031,11 +10429,11 @@ function createDefaultFs3() {
10031
10429
  writeFile: fsPromises4.writeFile,
10032
10430
  readdir: fsPromises4.readdir,
10033
10431
  stat: async (filePath) => {
10034
- const stat11 = await fsPromises4.stat(filePath);
10432
+ const stat13 = await fsPromises4.stat(filePath);
10035
10433
  return {
10036
- isFile: () => stat11.isFile(),
10037
- isDirectory: () => stat11.isDirectory(),
10038
- mtimeMs: stat11.mtimeMs
10434
+ isFile: () => stat13.isFile(),
10435
+ isDirectory: () => stat13.isDirectory(),
10436
+ mtimeMs: stat13.mtimeMs
10039
10437
  };
10040
10438
  },
10041
10439
  mkdir: async (filePath, options) => {
@@ -10066,9 +10464,9 @@ function resolveMode(stepName, steps) {
10066
10464
  return step.mode;
10067
10465
  }
10068
10466
  async function archivePlan(fs3, absolutePlanPath) {
10069
- const dir = path15.dirname(absolutePlanPath);
10070
- const archiveDir = path15.join(dir, "archive");
10071
- const archivePath = path15.join(archiveDir, path15.basename(absolutePlanPath));
10467
+ const dir = path17.dirname(absolutePlanPath);
10468
+ const archiveDir = path17.join(dir, "archive");
10469
+ const archivePath = path17.join(archiveDir, path17.basename(absolutePlanPath));
10072
10470
  await fs3.mkdir(archiveDir, { recursive: true });
10073
10471
  await fs3.rename(absolutePlanPath, archivePath);
10074
10472
  }
@@ -10396,12 +10794,12 @@ var init_pipeline = __esm({
10396
10794
  init_parser();
10397
10795
  init_writer();
10398
10796
  init_runner();
10399
- init_utils2();
10797
+ init_utils3();
10400
10798
  }
10401
10799
  });
10402
10800
 
10403
10801
  // packages/pipeline/src/index.ts
10404
- var init_src9 = __esm({
10802
+ var init_src10 = __esm({
10405
10803
  "packages/pipeline/src/index.ts"() {
10406
10804
  "use strict";
10407
10805
  init_loader();
@@ -10446,18 +10844,18 @@ var AUTONOMOUS_ACTIVITY_TIMEOUT_MS, MAX_TIMEOUT_RETRIES;
10446
10844
  var init_pipeline2 = __esm({
10447
10845
  async "src/sdk/pipeline.ts"() {
10448
10846
  "use strict";
10449
- init_src9();
10847
+ init_src10();
10450
10848
  init_src7();
10451
10849
  await init_spawn3();
10452
- init_src9();
10850
+ init_src10();
10453
10851
  AUTONOMOUS_ACTIVITY_TIMEOUT_MS = 10 * 60 * 1e3;
10454
10852
  MAX_TIMEOUT_RETRIES = 3;
10455
10853
  }
10456
10854
  });
10457
10855
 
10458
10856
  // packages/process-launcher/src/state/state-store.ts
10459
- import path16 from "node:path";
10460
- import * as nodeFs from "node:fs/promises";
10857
+ import path18 from "node:path";
10858
+ import * as nodeFs2 from "node:fs/promises";
10461
10859
  function isNotFoundError2(error2) {
10462
10860
  return error2 instanceof Error && "code" in error2 && error2.code === "ENOENT";
10463
10861
  }
@@ -10472,9 +10870,9 @@ async function removeDirectory2(fs3, directoryPath) {
10472
10870
  throw error2;
10473
10871
  }
10474
10872
  for (const entry of entries) {
10475
- const entryPath = path16.join(directoryPath, entry);
10476
- const stat11 = await fs3.stat(entryPath);
10477
- if (stat11.isFile()) {
10873
+ const entryPath = path18.join(directoryPath, entry);
10874
+ const stat13 = await fs3.stat(entryPath);
10875
+ if (stat13.isFile()) {
10478
10876
  await fs3.rm(entryPath, { force: true });
10479
10877
  continue;
10480
10878
  }
@@ -10487,9 +10885,9 @@ async function removeDirectory2(fs3, directoryPath) {
10487
10885
  }
10488
10886
  await fs3.rm(directoryPath, { force: true });
10489
10887
  }
10490
- function createStateStore(stateDir, fs3 = nodeFs) {
10888
+ function createStateStore(stateDir, fs3 = nodeFs2) {
10491
10889
  async function read(id) {
10492
- const statePath = path16.join(stateDir, id, "state.json");
10890
+ const statePath = path18.join(stateDir, id, "state.json");
10493
10891
  try {
10494
10892
  const content = await fs3.readFile(statePath, "utf8");
10495
10893
  return JSON.parse(content);
@@ -10501,9 +10899,9 @@ function createStateStore(stateDir, fs3 = nodeFs) {
10501
10899
  }
10502
10900
  }
10503
10901
  async function write2(id, state) {
10504
- const processDir = path16.join(stateDir, id);
10902
+ const processDir = path18.join(stateDir, id);
10505
10903
  await fs3.mkdir(processDir, { recursive: true });
10506
- await fs3.writeFile(path16.join(processDir, "state.json"), `${JSON.stringify(state, null, 2)}
10904
+ await fs3.writeFile(path18.join(processDir, "state.json"), `${JSON.stringify(state, null, 2)}
10507
10905
  `);
10508
10906
  }
10509
10907
  async function list() {
@@ -10518,10 +10916,10 @@ function createStateStore(stateDir, fs3 = nodeFs) {
10518
10916
  }
10519
10917
  const states = [];
10520
10918
  for (const entry of [...entries].sort()) {
10521
- const entryPath = path16.join(stateDir, entry);
10919
+ const entryPath = path18.join(stateDir, entry);
10522
10920
  try {
10523
- const stat11 = await fs3.stat(entryPath);
10524
- if (stat11.isFile()) {
10921
+ const stat13 = await fs3.stat(entryPath);
10922
+ if (stat13.isFile()) {
10525
10923
  continue;
10526
10924
  }
10527
10925
  } catch (error2) {
@@ -10538,7 +10936,7 @@ function createStateStore(stateDir, fs3 = nodeFs) {
10538
10936
  return states;
10539
10937
  }
10540
10938
  async function remove2(id) {
10541
- await removeDirectory2(fs3, path16.join(stateDir, id));
10939
+ await removeDirectory2(fs3, path18.join(stateDir, id));
10542
10940
  }
10543
10941
  return { read, write: write2, list, remove: remove2 };
10544
10942
  }
@@ -10549,16 +10947,16 @@ var init_state_store = __esm({
10549
10947
  });
10550
10948
 
10551
10949
  // packages/process-launcher/src/logs/log-writer.ts
10552
- import path17 from "node:path";
10553
- import * as nodeFs2 from "node:fs/promises";
10950
+ import path19 from "node:path";
10951
+ import * as nodeFs3 from "node:fs/promises";
10554
10952
  function isNotFoundError3(error2) {
10555
10953
  return error2 instanceof Error && "code" in error2 && error2.code === "ENOENT";
10556
10954
  }
10557
10955
  function getCurrentLogPath(logDir, stream) {
10558
- return path17.join(logDir, `${stream}.log`);
10956
+ return path19.join(logDir, `${stream}.log`);
10559
10957
  }
10560
10958
  function getRotatedLogPath(logDir, stream, index) {
10561
- return path17.join(logDir, `${stream}.${index}.log`);
10959
+ return path19.join(logDir, `${stream}.${index}.log`);
10562
10960
  }
10563
10961
  async function isFile(fs3, filePath) {
10564
10962
  try {
@@ -10605,7 +11003,7 @@ async function removeAllStreamLogs(fs3, logDir, stream) {
10605
11003
  if (getRotatedLogIndex(fileName, stream) === null) {
10606
11004
  continue;
10607
11005
  }
10608
- await fs3.rm(path17.join(logDir, fileName), { force: true });
11006
+ await fs3.rm(path19.join(logDir, fileName), { force: true });
10609
11007
  }
10610
11008
  } catch (error2) {
10611
11009
  if (isNotFoundError3(error2)) {
@@ -10624,7 +11022,7 @@ function getLines(content) {
10624
11022
  }
10625
11023
  return lines;
10626
11024
  }
10627
- function createLogWriter(logDir, retainCount, fs3 = nodeFs2) {
11025
+ function createLogWriter(logDir, retainCount, fs3 = nodeFs3) {
10628
11026
  const maxRetainedRuns = Math.max(0, Math.trunc(retainCount));
10629
11027
  async function write2(line, stream) {
10630
11028
  await fs3.mkdir(logDir, { recursive: true });
@@ -10865,7 +11263,7 @@ var init_engine = __esm({
10865
11263
  });
10866
11264
 
10867
11265
  // packages/process-runner/src/docker/args.ts
10868
- import path18 from "node:path";
11266
+ import path20 from "node:path";
10869
11267
  function buildDockerRunArgs(input) {
10870
11268
  const args = [input.engine];
10871
11269
  if (input.engine === "docker" && input.context) {
@@ -10892,7 +11290,7 @@ function buildDockerRunArgs(input) {
10892
11290
  args.push("-e", `${key}=${value}`);
10893
11291
  }
10894
11292
  for (const mount of input.mounts) {
10895
- const volume = `${path18.resolve(mount.source)}:${mount.target}${mount.readonly ? ":ro" : ""}`;
11293
+ const volume = `${path20.resolve(mount.source)}:${mount.target}${mount.readonly ? ":ro" : ""}`;
10896
11294
  args.push("-v", volume);
10897
11295
  }
10898
11296
  for (const port of input.ports) {
@@ -11134,7 +11532,7 @@ var init_testing = __esm({
11134
11532
  });
11135
11533
 
11136
11534
  // packages/process-runner/src/index.ts
11137
- var init_src10 = __esm({
11535
+ var init_src11 = __esm({
11138
11536
  "packages/process-runner/src/index.ts"() {
11139
11537
  "use strict";
11140
11538
  init_context2();
@@ -11146,13 +11544,16 @@ var init_src10 = __esm({
11146
11544
  });
11147
11545
 
11148
11546
  // packages/process-launcher/src/supervisor/supervisor.ts
11149
- import path19 from "node:path";
11547
+ import { spawnSync } from "node:child_process";
11548
+ import * as nodeFs4 from "node:fs/promises";
11549
+ import os3 from "node:os";
11550
+ import path21 from "node:path";
11150
11551
  function createSupervisor(options) {
11151
11552
  const { spec } = options;
11152
11553
  const runner = resolveRunner(options);
11153
11554
  const stateStore = createStateStore(options.stateDir, options.fs);
11154
11555
  const logWriter = createLogWriter(
11155
- path19.join(options.stateDir, spec.id, "logs"),
11556
+ path21.join(options.stateDir, spec.id, "logs"),
11156
11557
  spec.logRetainCount ?? 5,
11157
11558
  options.fs
11158
11559
  );
@@ -11165,6 +11566,8 @@ function createSupervisor(options) {
11165
11566
  let activeReadyController = null;
11166
11567
  let stableTimer = null;
11167
11568
  let stopRequested = false;
11569
+ let workspacePromise = null;
11570
+ let workspaceCleanupPromise = null;
11168
11571
  const onAbort = () => {
11169
11572
  void stop();
11170
11573
  };
@@ -11204,6 +11607,7 @@ function createSupervisor(options) {
11204
11607
  state.pid = null;
11205
11608
  state.lastStoppedAt = (/* @__PURE__ */ new Date()).toISOString();
11206
11609
  await transitionTo("stopped");
11610
+ await cleanupWorkspace();
11207
11611
  }
11208
11612
  async function restart() {
11209
11613
  await stop();
@@ -11218,7 +11622,14 @@ function createSupervisor(options) {
11218
11622
  async function launch(isRestart) {
11219
11623
  const nextRunId = runId + 1;
11220
11624
  runId = nextRunId;
11221
- const nextHandle = runner.exec(createRunSpec(spec));
11625
+ const workspace = await ensureWorkspace();
11626
+ let nextHandle;
11627
+ try {
11628
+ nextHandle = runner.exec(createRunSpec(spec, workspace.cwd));
11629
+ } catch (error2) {
11630
+ await cleanupWorkspace();
11631
+ throw error2;
11632
+ }
11222
11633
  handle = nextHandle;
11223
11634
  state.pid = nextHandle.pid;
11224
11635
  state.lastExitCode = null;
@@ -11265,15 +11676,18 @@ function createSupervisor(options) {
11265
11676
  state.lastStoppedAt = (/* @__PURE__ */ new Date()).toISOString();
11266
11677
  if (stopRequested || options.signal?.aborted) {
11267
11678
  await transitionTo("stopped");
11679
+ await cleanupWorkspace();
11268
11680
  return;
11269
11681
  }
11270
11682
  if (!shouldRestart(result.exitCode, spec.restart)) {
11271
11683
  await transitionTo("stopped");
11684
+ await cleanupWorkspace();
11272
11685
  return;
11273
11686
  }
11274
11687
  const maxRestarts = spec.maxRestarts ?? 5;
11275
11688
  if (maxRestarts > 0 && state.restartCount >= maxRestarts) {
11276
11689
  await transitionTo("crashed");
11690
+ await cleanupWorkspace();
11277
11691
  return;
11278
11692
  }
11279
11693
  const backoffMs = getBackoffDelay(
@@ -11321,6 +11735,36 @@ function createSupervisor(options) {
11321
11735
  stableTimer = null;
11322
11736
  }
11323
11737
  }
11738
+ async function ensureWorkspace() {
11739
+ if (workspacePromise !== null) {
11740
+ return await workspacePromise;
11741
+ }
11742
+ workspacePromise = resolveProcessWorkspace(spec.cwd, options.stateDir);
11743
+ try {
11744
+ return await workspacePromise;
11745
+ } catch (error2) {
11746
+ workspacePromise = null;
11747
+ throw error2;
11748
+ }
11749
+ }
11750
+ async function cleanupWorkspace() {
11751
+ if (workspacePromise === null) {
11752
+ return;
11753
+ }
11754
+ const workspace = await workspacePromise;
11755
+ if (!workspace.cleanup) {
11756
+ return;
11757
+ }
11758
+ if (workspaceCleanupPromise !== null) {
11759
+ await workspaceCleanupPromise;
11760
+ return;
11761
+ }
11762
+ workspaceCleanupPromise = workspace.cleanup().finally(() => {
11763
+ workspaceCleanupPromise = null;
11764
+ workspacePromise = null;
11765
+ });
11766
+ await workspaceCleanupPromise;
11767
+ }
11324
11768
  return {
11325
11769
  start,
11326
11770
  stop,
@@ -11351,11 +11795,11 @@ function createInitialState(spec, runner) {
11351
11795
  args: [...spec.args ?? []]
11352
11796
  };
11353
11797
  }
11354
- function createRunSpec(spec) {
11798
+ function createRunSpec(spec, cwdOverride) {
11355
11799
  return {
11356
11800
  command: spec.command,
11357
11801
  args: spec.args,
11358
- cwd: spec.cwd,
11802
+ cwd: cwdOverride ?? spec.cwd,
11359
11803
  env: spec.env,
11360
11804
  stderr: "pipe",
11361
11805
  stdout: "pipe"
@@ -11452,6 +11896,54 @@ function pipeOutput(stream, output, write2, onLog) {
11452
11896
  stream.once("error", reject);
11453
11897
  });
11454
11898
  }
11899
+ async function resolveProcessWorkspace(cwd, stateDir) {
11900
+ if (!cwd) {
11901
+ return {};
11902
+ }
11903
+ const resolved = await resolveWorkspace(cwd, {
11904
+ baseDir: process.cwd(),
11905
+ homeDir: resolveWorkspaceHomeDir(stateDir),
11906
+ mode: "edit",
11907
+ exec: async (command, args, options) => execWorkspaceCommand(command, args, options?.cwd),
11908
+ fs: {
11909
+ mkdir: async (target, options) => {
11910
+ await nodeFs4.mkdir(target, options);
11911
+ },
11912
+ stat: async (target) => await nodeFs4.stat(target),
11913
+ rm: async (target, options) => {
11914
+ await nodeFs4.rm(target, options);
11915
+ }
11916
+ }
11917
+ });
11918
+ return {
11919
+ cwd: resolved.cwd,
11920
+ cleanup: resolved.cleanup
11921
+ };
11922
+ }
11923
+ function resolveWorkspaceHomeDir(stateDir) {
11924
+ if (path21.basename(stateDir) === "launch" && path21.basename(path21.dirname(stateDir)) === ".poe-code") {
11925
+ return path21.dirname(path21.dirname(stateDir));
11926
+ }
11927
+ return os3.homedir();
11928
+ }
11929
+ function execWorkspaceCommand(command, args, cwd) {
11930
+ const result = spawnSync(command, args, {
11931
+ cwd,
11932
+ encoding: "utf8"
11933
+ });
11934
+ if (result.error) {
11935
+ return {
11936
+ stdout: result.stdout ?? "",
11937
+ stderr: result.error.message,
11938
+ exitCode: typeof result.status === "number" ? result.status : 1
11939
+ };
11940
+ }
11941
+ return {
11942
+ stdout: result.stdout ?? "",
11943
+ stderr: result.stderr ?? "",
11944
+ exitCode: result.status ?? 0
11945
+ };
11946
+ }
11455
11947
  function resolveReadyCheck(check, spec) {
11456
11948
  if (check.kind !== "tcp" || spec.docker === void 0) {
11457
11949
  return check;
@@ -11473,7 +11965,8 @@ function resolveReadyCheck(check, spec) {
11473
11965
  var init_supervisor = __esm({
11474
11966
  "packages/process-launcher/src/supervisor/supervisor.ts"() {
11475
11967
  "use strict";
11476
- init_src10();
11968
+ init_src11();
11969
+ init_src8();
11477
11970
  init_health_check();
11478
11971
  init_log_writer();
11479
11972
  init_state_store();
@@ -11481,8 +11974,8 @@ var init_supervisor = __esm({
11481
11974
  });
11482
11975
 
11483
11976
  // packages/process-launcher/src/launcher.ts
11484
- import path20 from "node:path";
11485
- import * as nodeFs3 from "node:fs/promises";
11977
+ import path22 from "node:path";
11978
+ import * as nodeFs5 from "node:fs/promises";
11486
11979
  async function startManagedProcess(options) {
11487
11980
  const fs3 = options.fs ?? defaultFs();
11488
11981
  const spec = normalizeSpec(options.spec);
@@ -11830,10 +12323,10 @@ async function listIds(fs3, baseDir) {
11830
12323
  const entries = await fs3.readdir(baseDir);
11831
12324
  const ids = [];
11832
12325
  for (const entry of entries) {
11833
- const entryPath = path20.join(baseDir, entry);
12326
+ const entryPath = path22.join(baseDir, entry);
11834
12327
  try {
11835
- const stat11 = await fs3.stat(entryPath);
11836
- if (!stat11.isFile()) {
12328
+ const stat13 = await fs3.stat(entryPath);
12329
+ if (!stat13.isFile()) {
11837
12330
  ids.push(entry);
11838
12331
  }
11839
12332
  } catch (error2) {
@@ -11880,30 +12373,30 @@ async function readJsonFile(fs3, filePath) {
11880
12373
  }
11881
12374
  }
11882
12375
  async function writeJsonFile(fs3, filePath, value) {
11883
- await fs3.mkdir(path20.dirname(filePath), { recursive: true });
12376
+ await fs3.mkdir(path22.dirname(filePath), { recursive: true });
11884
12377
  await fs3.writeFile(filePath, `${JSON.stringify(value, null, 2)}
11885
12378
  `);
11886
12379
  }
11887
12380
  function resolveProcessDir(baseDir, id) {
11888
- return path20.join(baseDir, id);
12381
+ return path22.join(baseDir, id);
11889
12382
  }
11890
12383
  function resolveSpecPath(baseDir, id) {
11891
- return path20.join(resolveProcessDir(baseDir, id), "spec.json");
12384
+ return path22.join(resolveProcessDir(baseDir, id), "spec.json");
11892
12385
  }
11893
12386
  function resolveStatePath(baseDir, id) {
11894
- return path20.join(resolveProcessDir(baseDir, id), "state.json");
12387
+ return path22.join(resolveProcessDir(baseDir, id), "state.json");
11895
12388
  }
11896
12389
  function resolveMetaPath(baseDir, id) {
11897
- return path20.join(resolveProcessDir(baseDir, id), "meta.json");
12390
+ return path22.join(resolveProcessDir(baseDir, id), "meta.json");
11898
12391
  }
11899
12392
  function resolveLogDir2(baseDir, id) {
11900
- return path20.join(resolveProcessDir(baseDir, id), "logs");
12393
+ return path22.join(resolveProcessDir(baseDir, id), "logs");
11901
12394
  }
11902
12395
  function isNotFoundError4(error2) {
11903
12396
  return error2 instanceof Error && "code" in error2 && error2.code === "ENOENT";
11904
12397
  }
11905
12398
  function defaultFs() {
11906
- return nodeFs3;
12399
+ return nodeFs5;
11907
12400
  }
11908
12401
  function defaultSignalProcess(pid, signal) {
11909
12402
  process.kill(pid, signal);
@@ -11941,7 +12434,7 @@ var init_launcher = __esm({
11941
12434
  });
11942
12435
 
11943
12436
  // packages/process-launcher/src/index.ts
11944
- var init_src11 = __esm({
12437
+ var init_src12 = __esm({
11945
12438
  "packages/process-launcher/src/index.ts"() {
11946
12439
  "use strict";
11947
12440
  init_state_store();
@@ -12080,16 +12573,16 @@ var init_frontmatter = __esm({
12080
12573
  });
12081
12574
 
12082
12575
  // packages/ralph/src/discovery/discovery.ts
12083
- import path21 from "node:path";
12576
+ import path23 from "node:path";
12084
12577
  import * as fsPromises5 from "node:fs/promises";
12085
12578
  function createDefaultFs4() {
12086
12579
  return {
12087
12580
  readdir: fsPromises5.readdir,
12088
12581
  stat: async (filePath) => {
12089
- const stat11 = await fsPromises5.stat(filePath);
12582
+ const stat13 = await fsPromises5.stat(filePath);
12090
12583
  return {
12091
- isFile: () => stat11.isFile(),
12092
- mtimeMs: stat11.mtimeMs
12584
+ isFile: () => stat13.isFile(),
12585
+ mtimeMs: stat13.mtimeMs
12093
12586
  };
12094
12587
  }
12095
12588
  };
@@ -12115,12 +12608,12 @@ async function scanDir(fs3, absoluteDir, displayDir) {
12115
12608
  if (!isMarkdownFile(entry)) {
12116
12609
  continue;
12117
12610
  }
12118
- const absolutePath = path21.join(absoluteDir, entry);
12119
- const stat11 = await fs3.stat(absolutePath);
12120
- if (!stat11.isFile()) {
12611
+ const absolutePath = path23.join(absoluteDir, entry);
12612
+ const stat13 = await fs3.stat(absolutePath);
12613
+ if (!stat13.isFile()) {
12121
12614
  continue;
12122
12615
  }
12123
- const displayPath = path21.join(displayDir, entry);
12616
+ const displayPath = path23.join(displayDir, entry);
12124
12617
  docs.push({
12125
12618
  path: displayPath,
12126
12619
  displayPath
@@ -12133,8 +12626,8 @@ async function discoverDocs(options) {
12133
12626
  const customDir = options.planDirectory?.trim();
12134
12627
  const docs = customDir ? await scanCustomDir(fs3, customDir, options.cwd, options.homeDir) : await scanDefaultDirs(fs3, options.cwd, options.homeDir);
12135
12628
  return docs.sort((left, right) => {
12136
- const leftName = path21.basename(left.displayPath).toLowerCase();
12137
- const rightName = path21.basename(right.displayPath).toLowerCase();
12629
+ const leftName = path23.basename(left.displayPath).toLowerCase();
12630
+ const rightName = path23.basename(right.displayPath).toLowerCase();
12138
12631
  return leftName === rightName ? left.displayPath.localeCompare(right.displayPath) : leftName.localeCompare(rightName);
12139
12632
  });
12140
12633
  }
@@ -12147,12 +12640,12 @@ async function scanDefaultDirs(fs3, cwd, homeDir) {
12147
12640
  const [localDocs, globalDocs] = await Promise.all([
12148
12641
  scanDir(
12149
12642
  fs3,
12150
- path21.join(cwd, ".poe-code", "ralph", "plans"),
12643
+ path23.join(cwd, ".poe-code", "ralph", "plans"),
12151
12644
  ".poe-code/ralph/plans"
12152
12645
  ),
12153
12646
  scanDir(
12154
12647
  fs3,
12155
- path21.join(homeDir, ".poe-code", "ralph", "plans"),
12648
+ path23.join(homeDir, ".poe-code", "ralph", "plans"),
12156
12649
  "~/.poe-code/ralph/plans"
12157
12650
  )
12158
12651
  ]);
@@ -12160,9 +12653,9 @@ async function scanDefaultDirs(fs3, cwd, homeDir) {
12160
12653
  }
12161
12654
  function resolveAbsoluteDirectory2(dir, cwd, homeDir) {
12162
12655
  if (dir.startsWith("~/")) {
12163
- return path21.join(homeDir, dir.slice(2));
12656
+ return path23.join(homeDir, dir.slice(2));
12164
12657
  }
12165
- return path21.isAbsolute(dir) ? dir : path21.resolve(cwd, dir);
12658
+ return path23.isAbsolute(dir) ? dir : path23.resolve(cwd, dir);
12166
12659
  }
12167
12660
  var init_discovery2 = __esm({
12168
12661
  "packages/ralph/src/discovery/discovery.ts"() {
@@ -12171,7 +12664,7 @@ var init_discovery2 = __esm({
12171
12664
  });
12172
12665
 
12173
12666
  // packages/ralph/src/run/ralph.ts
12174
- import path22 from "node:path";
12667
+ import path24 from "node:path";
12175
12668
  import * as fsPromises6 from "node:fs/promises";
12176
12669
  async function runRalph(options) {
12177
12670
  const fs3 = options.fs ?? createDefaultFs5();
@@ -12275,10 +12768,10 @@ function createDefaultFs5() {
12275
12768
  writeFile: (filePath, content) => fsPromises6.writeFile(filePath, content, "utf8"),
12276
12769
  readdir: fsPromises6.readdir,
12277
12770
  stat: async (filePath) => {
12278
- const stat11 = await fsPromises6.stat(filePath);
12771
+ const stat13 = await fsPromises6.stat(filePath);
12279
12772
  return {
12280
- isFile: () => stat11.isFile(),
12281
- mtimeMs: stat11.mtimeMs
12773
+ isFile: () => stat13.isFile(),
12774
+ mtimeMs: stat13.mtimeMs
12282
12775
  };
12283
12776
  },
12284
12777
  mkdir: async (filePath, options) => {
@@ -12303,9 +12796,9 @@ function normalizeAgents(agent2) {
12303
12796
  }
12304
12797
  function resolveAbsoluteDocPath(docPath, cwd, homeDir) {
12305
12798
  if (docPath.startsWith("~/")) {
12306
- return path22.join(homeDir, docPath.slice(2));
12799
+ return path24.join(homeDir, docPath.slice(2));
12307
12800
  }
12308
- return path22.isAbsolute(docPath) ? docPath : path22.resolve(cwd, docPath);
12801
+ return path24.isAbsolute(docPath) ? docPath : path24.resolve(cwd, docPath);
12309
12802
  }
12310
12803
  function assertNotAborted2(signal) {
12311
12804
  if (!signal?.aborted) {
@@ -12336,9 +12829,9 @@ async function updateFrontmatter(fs3, absoluteDocPath, body, frontmatter, state,
12336
12829
  await fs3.writeFile(absoluteDocPath, content);
12337
12830
  }
12338
12831
  async function archivePlan2(fs3, absoluteDocPath) {
12339
- const dir = path22.dirname(absoluteDocPath);
12340
- const archiveDir = path22.join(dir, "archive");
12341
- const archivePath = path22.join(archiveDir, path22.basename(absoluteDocPath));
12832
+ const dir = path24.dirname(absoluteDocPath);
12833
+ const archiveDir = path24.join(dir, "archive");
12834
+ const archivePath = path24.join(archiveDir, path24.basename(absoluteDocPath));
12342
12835
  await fs3.mkdir(archiveDir, { recursive: true });
12343
12836
  await fs3.rename(absoluteDocPath, archivePath);
12344
12837
  }
@@ -12362,7 +12855,7 @@ var init_ralph = __esm({
12362
12855
  });
12363
12856
 
12364
12857
  // packages/ralph/src/index.ts
12365
- var init_src12 = __esm({
12858
+ var init_src13 = __esm({
12366
12859
  "packages/ralph/src/index.ts"() {
12367
12860
  "use strict";
12368
12861
  init_frontmatter();
@@ -12402,7 +12895,7 @@ var AUTONOMOUS_ACTIVITY_TIMEOUT_MS2, MAX_TIMEOUT_RETRIES2;
12402
12895
  var init_ralph2 = __esm({
12403
12896
  async "src/sdk/ralph.ts"() {
12404
12897
  "use strict";
12405
- init_src12();
12898
+ init_src13();
12406
12899
  init_src7();
12407
12900
  await init_spawn3();
12408
12901
  AUTONOMOUS_ACTIVITY_TIMEOUT_MS2 = 10 * 60 * 1e3;
@@ -12566,6 +13059,8 @@ var init_journal = __esm({
12566
13059
  this.journalPath = journalPath;
12567
13060
  this.fs = fs3;
12568
13061
  }
13062
+ journalPath;
13063
+ fs;
12569
13064
  async init() {
12570
13065
  await this.fs.mkdir(dirname2(this.journalPath), { recursive: true });
12571
13066
  try {
@@ -12719,7 +13214,7 @@ var init_git = __esm({
12719
13214
  });
12720
13215
 
12721
13216
  // packages/experiment-loop/src/config/loader.ts
12722
- import path23 from "node:path";
13217
+ import path25 from "node:path";
12723
13218
  import { readFile as readFile5 } from "node:fs/promises";
12724
13219
  import { fileURLToPath as fileURLToPath2 } from "node:url";
12725
13220
  import { parse as parse7 } from "yaml";
@@ -12775,8 +13270,8 @@ async function loadInstructions() {
12775
13270
  return readBundledFile("default-instructions.md");
12776
13271
  }
12777
13272
  async function loadRunConfig(options) {
12778
- const projectPath = path23.join(options.cwd, ".poe-code", "experiments", "run.yaml");
12779
- const globalPath = path23.join(options.homeDir, ".poe-code", "experiments", "run.yaml");
13273
+ const projectPath = path25.join(options.cwd, ".poe-code", "experiments", "run.yaml");
13274
+ const globalPath = path25.join(options.homeDir, ".poe-code", "experiments", "run.yaml");
12780
13275
  const projectContent = await readOptionalFile2(options.fs, projectPath);
12781
13276
  if (projectContent != null) {
12782
13277
  const config = parseRunConfigDocument(projectPath, projectContent);
@@ -12802,17 +13297,17 @@ var init_loader2 = __esm({
12802
13297
  // packages/experiment-loop/src/run/loop.ts
12803
13298
  import { exec as execCallback } from "node:child_process";
12804
13299
  import * as fsPromises7 from "node:fs/promises";
12805
- import path24 from "node:path";
13300
+ import path26 from "node:path";
12806
13301
  function createDefaultFs6() {
12807
13302
  return {
12808
13303
  readFile: fsPromises7.readFile,
12809
13304
  writeFile: (filePath, content) => fsPromises7.writeFile(filePath, content, "utf8"),
12810
13305
  readdir: fsPromises7.readdir,
12811
13306
  stat: async (filePath) => {
12812
- const stat11 = await fsPromises7.stat(filePath);
13307
+ const stat13 = await fsPromises7.stat(filePath);
12813
13308
  return {
12814
- isFile: () => stat11.isFile(),
12815
- mtimeMs: stat11.mtimeMs
13309
+ isFile: () => stat13.isFile(),
13310
+ mtimeMs: stat13.mtimeMs
12816
13311
  };
12817
13312
  },
12818
13313
  mkdir: async (filePath, options) => {
@@ -12846,14 +13341,14 @@ function createDefaultExec() {
12846
13341
  }
12847
13342
  function resolveAbsoluteDocPath2(docPath, cwd, homeDir) {
12848
13343
  if (docPath.startsWith("~/")) {
12849
- return path24.join(homeDir, docPath.slice(2));
13344
+ return path26.join(homeDir, docPath.slice(2));
12850
13345
  }
12851
- return path24.isAbsolute(docPath) ? docPath : path24.resolve(cwd, docPath);
13346
+ return path26.isAbsolute(docPath) ? docPath : path26.resolve(cwd, docPath);
12852
13347
  }
12853
13348
  function resolveJournalPath(docPath) {
12854
- return path24.join(
12855
- path24.dirname(docPath),
12856
- `${path24.basename(docPath, path24.extname(docPath))}.journal.jsonl`
13349
+ return path26.join(
13350
+ path26.dirname(docPath),
13351
+ `${path26.basename(docPath, path26.extname(docPath))}.journal.jsonl`
12857
13352
  );
12858
13353
  }
12859
13354
  function normalizeMetrics(metric) {
@@ -13033,7 +13528,7 @@ async function runExperimentLoop(options) {
13033
13528
  experimentIndex,
13034
13529
  baseline,
13035
13530
  docPath: options.docPath,
13036
- docName: path24.basename(absoluteDocPath, path24.extname(absoluteDocPath))
13531
+ docName: path26.basename(absoluteDocPath, path26.extname(absoluteDocPath))
13037
13532
  });
13038
13533
  const currentSpecifier = agents[(experimentIndex - 1) % agents.length];
13039
13534
  const model = currentSpecifier.model;
@@ -13108,7 +13603,7 @@ var init_loop = __esm({
13108
13603
  });
13109
13604
 
13110
13605
  // packages/experiment-loop/src/index.ts
13111
- var init_src13 = __esm({
13606
+ var init_src14 = __esm({
13112
13607
  "packages/experiment-loop/src/index.ts"() {
13113
13608
  "use strict";
13114
13609
  init_types3();
@@ -13122,7 +13617,7 @@ var init_src13 = __esm({
13122
13617
  });
13123
13618
 
13124
13619
  // src/sdk/experiment.ts
13125
- import path25 from "node:path";
13620
+ import path27 from "node:path";
13126
13621
  import * as fsPromises8 from "node:fs/promises";
13127
13622
  function createDefaultFs7() {
13128
13623
  return {
@@ -13132,10 +13627,10 @@ function createDefaultFs7() {
13132
13627
  },
13133
13628
  readdir: fsPromises8.readdir,
13134
13629
  stat: async (filePath) => {
13135
- const stat11 = await fsPromises8.stat(filePath);
13630
+ const stat13 = await fsPromises8.stat(filePath);
13136
13631
  return {
13137
- isFile: () => stat11.isFile(),
13138
- mtimeMs: stat11.mtimeMs
13632
+ isFile: () => stat13.isFile(),
13633
+ mtimeMs: stat13.mtimeMs
13139
13634
  };
13140
13635
  },
13141
13636
  mkdir: async (filePath, options) => {
@@ -13148,14 +13643,14 @@ function createDefaultFs7() {
13148
13643
  }
13149
13644
  function resolveAbsoluteDocPath3(docPath, cwd, homeDir) {
13150
13645
  if (docPath.startsWith("~/")) {
13151
- return path25.join(homeDir, docPath.slice(2));
13646
+ return path27.join(homeDir, docPath.slice(2));
13152
13647
  }
13153
- return path25.isAbsolute(docPath) ? docPath : path25.resolve(cwd, docPath);
13648
+ return path27.isAbsolute(docPath) ? docPath : path27.resolve(cwd, docPath);
13154
13649
  }
13155
13650
  function resolveJournalPath2(docPath) {
13156
- return path25.join(
13157
- path25.dirname(docPath),
13158
- `${path25.basename(docPath, path25.extname(docPath))}.journal.jsonl`
13651
+ return path27.join(
13652
+ path27.dirname(docPath),
13653
+ `${path27.basename(docPath, path27.extname(docPath))}.journal.jsonl`
13159
13654
  );
13160
13655
  }
13161
13656
  async function runExperiment(options) {
@@ -13201,7 +13696,7 @@ var AUTONOMOUS_ACTIVITY_TIMEOUT_MS3, MAX_TIMEOUT_RETRIES3;
13201
13696
  var init_experiment = __esm({
13202
13697
  async "src/sdk/experiment.ts"() {
13203
13698
  "use strict";
13204
- init_src13();
13699
+ init_src14();
13205
13700
  init_src7();
13206
13701
  await init_spawn3();
13207
13702
  AUTONOMOUS_ACTIVITY_TIMEOUT_MS3 = 10 * 60 * 1e3;
@@ -13642,11 +14137,11 @@ function assertValidEnumValues(values) {
13642
14137
  throw new Error("Enum schema values must be unique");
13643
14138
  }
13644
14139
  }
13645
- var S;
13646
- var init_src14 = __esm({
14140
+ var S2;
14141
+ var init_src15 = __esm({
13647
14142
  "packages/cmdkit-schema/src/index.ts"() {
13648
14143
  "use strict";
13649
- S = {
14144
+ S2 = {
13650
14145
  String(options = {}) {
13651
14146
  return {
13652
14147
  kind: "string",
@@ -14061,10 +14556,10 @@ function getCommandSourcePath(command) {
14061
14556
  return command[commandSourcePathSymbol];
14062
14557
  }
14063
14558
  var commandConfigSymbol, groupConfigSymbol, commandSourcePathSymbol, UserError;
14064
- var init_src15 = __esm({
14559
+ var init_src16 = __esm({
14065
14560
  "packages/cmdkit/src/index.ts"() {
14066
14561
  "use strict";
14067
- init_src14();
14562
+ init_src15();
14068
14563
  commandConfigSymbol = /* @__PURE__ */ Symbol("cmdkit.command.config");
14069
14564
  groupConfigSymbol = /* @__PURE__ */ Symbol("cmdkit.group.config");
14070
14565
  commandSourcePathSymbol = /* @__PURE__ */ Symbol("cmdkit.command.sourcePath");
@@ -14097,7 +14592,7 @@ function checkUserAllow(automation, commentAuthorAssociation) {
14097
14592
  var init_check_user_allow = __esm({
14098
14593
  "packages/github-workflows/src/exec/check-user-allow.ts"() {
14099
14594
  "use strict";
14100
- init_src15();
14595
+ init_src16();
14101
14596
  }
14102
14597
  });
14103
14598
 
@@ -14121,13 +14616,13 @@ function requireCommentPrefix(automation, commentBody) {
14121
14616
  var init_require_comment_prefix = __esm({
14122
14617
  "packages/github-workflows/src/exec/require-comment-prefix.ts"() {
14123
14618
  "use strict";
14124
- init_src15();
14619
+ init_src16();
14125
14620
  }
14126
14621
  });
14127
14622
 
14128
14623
  // packages/github-workflows/src/commands.ts
14129
- import { access, mkdir as mkdir8, readFile as readFile9, unlink as unlink2, writeFile as writeFile6 } from "node:fs/promises";
14130
- import path26 from "node:path";
14624
+ import { access, mkdir as mkdir10, readFile as readFile9, unlink as unlink2, writeFile as writeFile6 } from "node:fs/promises";
14625
+ import path28 from "node:path";
14131
14626
  import { fileURLToPath as fileURLToPath4 } from "node:url";
14132
14627
  import Mustache3 from "mustache";
14133
14628
  function formatLabel(name) {
@@ -14146,7 +14641,7 @@ async function loadNamedAutomation(name, cwd) {
14146
14641
  }
14147
14642
  async function readBuiltInPromptFile(name) {
14148
14643
  try {
14149
- return await readFile9(path26.join(await resolveBuiltInPromptsDir(), `${name}.md`), "utf8");
14644
+ return await readFile9(path28.join(await resolveBuiltInPromptsDir(), `${name}.md`), "utf8");
14150
14645
  } catch (error2) {
14151
14646
  if (isMissingPathError2(error2)) {
14152
14647
  throw new UserError(`Automation "${name}" was not found.`);
@@ -14155,7 +14650,7 @@ async function readBuiltInPromptFile(name) {
14155
14650
  }
14156
14651
  }
14157
14652
  async function readBuiltInWorkflowTemplate(name, variant) {
14158
- const templatePath = path26.join(await resolveBuiltInWorkflowTemplatesDir(), `${name}.${variant}.yml`);
14653
+ const templatePath = path28.join(await resolveBuiltInWorkflowTemplatesDir(), `${name}.${variant}.yml`);
14159
14654
  try {
14160
14655
  const content = await readFile9(templatePath, "utf8");
14161
14656
  const header = variant === "ejected" ? `# Auto-generated by: poe-code github-workflows install ${name}
@@ -14185,7 +14680,7 @@ async function resolveBuiltInWorkflowTemplatesDir() {
14185
14680
  return builtInWorkflowTemplatesDirCandidates[0];
14186
14681
  }
14187
14682
  function projectPromptsDir(cwd) {
14188
- return path26.join(cwd, ".poe-code", "github-workflows");
14683
+ return path28.join(cwd, ".poe-code", "github-workflows");
14189
14684
  }
14190
14685
  async function resolveBuiltInPromptsDir() {
14191
14686
  for (const candidate of builtInPromptsDirCandidates) {
@@ -14355,7 +14850,7 @@ async function selectAutomationName(message2, automations) {
14355
14850
  message: message2,
14356
14851
  options: automations.map((a) => ({ label: a.label ?? formatLabel(a.name), value: a.name }))
14357
14852
  });
14358
- if (Ct(selected)) {
14853
+ if (q(selected)) {
14359
14854
  cancel("Operation cancelled.");
14360
14855
  throw new UserError("Operation cancelled.");
14361
14856
  }
@@ -14366,8 +14861,8 @@ var init_commands = __esm({
14366
14861
  "packages/github-workflows/src/commands.ts"() {
14367
14862
  "use strict";
14368
14863
  init_src7();
14369
- init_src14();
14370
14864
  init_src15();
14865
+ init_src16();
14371
14866
  init_src5();
14372
14867
  init_discover();
14373
14868
  init_check_user_allow();
@@ -14395,12 +14890,12 @@ var init_commands = __esm({
14395
14890
  name: "run",
14396
14891
  description: "Run a GitHub automation.",
14397
14892
  positional: ["name"],
14398
- params: S.Object({
14399
- name: S.Optional(S.String()),
14400
- agent: S.Optional(S.String()),
14401
- model: S.Optional(S.String()),
14402
- mode: S.Optional(S.Enum(["yolo", "edit", "read"])),
14403
- cwd: S.Optional(S.String())
14893
+ params: S2.Object({
14894
+ name: S2.Optional(S2.String()),
14895
+ agent: S2.Optional(S2.String()),
14896
+ model: S2.Optional(S2.String()),
14897
+ mode: S2.Optional(S2.Enum(["yolo", "edit", "read"])),
14898
+ cwd: S2.Optional(S2.String())
14404
14899
  }),
14405
14900
  secrets: {
14406
14901
  poeApiKey: { env: "POE_API_KEY" },
@@ -14480,7 +14975,7 @@ var init_commands = __esm({
14480
14975
  listCommand = defineCommand({
14481
14976
  name: "list",
14482
14977
  description: "List available automations.",
14483
- params: S.Object({}),
14978
+ params: S2.Object({}),
14484
14979
  scope: ["cli", "sdk"],
14485
14980
  handler: async () => discoverAutomations(await resolveBuiltInPromptsDir(), projectPromptsDir(resolveCwd())),
14486
14981
  render: {
@@ -14508,15 +15003,15 @@ var init_commands = __esm({
14508
15003
  name: "install",
14509
15004
  description: "Install an automation workflow into the current repo.",
14510
15005
  positional: ["name"],
14511
- params: S.Object({
14512
- name: S.Enum(installableAutomations, {
15006
+ params: S2.Object({
15007
+ name: S2.Enum(installableAutomations, {
14513
15008
  description: "Pick a GitHub workflow to install",
14514
15009
  loadOptions: async () => {
14515
15010
  const automations = await discoverAutomations(await resolveBuiltInPromptsDir());
14516
15011
  return automations.map((a) => ({ label: a.label ?? formatLabel(a.name), value: a.name }));
14517
15012
  }
14518
15013
  }),
14519
- eject: S.Optional(S.Boolean())
15014
+ eject: S2.Optional(S2.Boolean())
14520
15015
  }),
14521
15016
  scope: ["cli"],
14522
15017
  handler: async ({ params }) => {
@@ -14528,13 +15023,13 @@ var init_commands = __esm({
14528
15023
  readBuiltInPromptFile(name)
14529
15024
  ]);
14530
15025
  const cwd = resolveCwd();
14531
- const workflowPath = path26.join(cwd, ".github", "workflows", `poe-code-${name}.yml`);
14532
- await mkdir8(path26.dirname(workflowPath), { recursive: true });
15026
+ const workflowPath = path28.join(cwd, ".github", "workflows", `poe-code-${name}.yml`);
15027
+ await mkdir10(path28.dirname(workflowPath), { recursive: true });
14533
15028
  await writeFile6(workflowPath, workflowTemplate, "utf8");
14534
15029
  let promptPath;
14535
15030
  if (isEject) {
14536
- promptPath = path26.join(projectPromptsDir(cwd), `poe-code-${name}.md`);
14537
- await mkdir8(path26.dirname(promptPath), { recursive: true });
15031
+ promptPath = path28.join(projectPromptsDir(cwd), `poe-code-${name}.md`);
15032
+ await mkdir10(path28.dirname(promptPath), { recursive: true });
14538
15033
  await writeFile6(promptPath, addPromptHeader(rawPrompt, name), "utf8");
14539
15034
  }
14540
15035
  return {
@@ -14563,8 +15058,8 @@ var init_commands = __esm({
14563
15058
  name: "uninstall",
14564
15059
  description: "Remove an installed automation workflow from the current repo.",
14565
15060
  positional: ["name"],
14566
- params: S.Object({
14567
- name: S.Enum(installableAutomations, {
15061
+ params: S2.Object({
15062
+ name: S2.Enum(installableAutomations, {
14568
15063
  description: "Pick a GitHub workflow to uninstall",
14569
15064
  loadOptions: async () => {
14570
15065
  const automations = await discoverAutomations(await resolveBuiltInPromptsDir());
@@ -14575,7 +15070,7 @@ var init_commands = __esm({
14575
15070
  scope: ["cli"],
14576
15071
  handler: async ({ params }) => {
14577
15072
  const name = params.name;
14578
- const workflowPath = path26.join(resolveCwd(), ".github", "workflows", `poe-code-${name}.yml`);
15073
+ const workflowPath = path28.join(resolveCwd(), ".github", "workflows", `poe-code-${name}.yml`);
14579
15074
  try {
14580
15075
  await unlink2(workflowPath);
14581
15076
  } catch (error2) {
@@ -14598,8 +15093,8 @@ var init_commands = __esm({
14598
15093
  name: "check-user-allow",
14599
15094
  description: "Fail when COMMENT_AUTHOR_ASSOCIATION is not allowed by the automation frontmatter.",
14600
15095
  positional: ["name"],
14601
- params: S.Object({
14602
- name: S.String()
15096
+ params: S2.Object({
15097
+ name: S2.String()
14603
15098
  }),
14604
15099
  scope: ["cli"],
14605
15100
  handler: async ({ params, env }) => {
@@ -14612,8 +15107,8 @@ var init_commands = __esm({
14612
15107
  name: "require-comment-prefix",
14613
15108
  description: "Fail when COMMENT_BODY does not start with the automation prefix frontmatter.",
14614
15109
  positional: ["name"],
14615
- params: S.Object({
14616
- name: S.String()
15110
+ params: S2.Object({
15111
+ name: S2.String()
14617
15112
  }),
14618
15113
  scope: ["cli"],
14619
15114
  handler: async ({ params, env }) => {
@@ -14626,8 +15121,8 @@ var init_commands = __esm({
14626
15121
  name: "prompt-preview",
14627
15122
  description: "Preview the resolved prompt for an automation.",
14628
15123
  positional: ["name"],
14629
- params: S.Object({
14630
- name: S.String()
15124
+ params: S2.Object({
15125
+ name: S2.String()
14631
15126
  }),
14632
15127
  scope: ["cli", "sdk"],
14633
15128
  handler: async ({ params }) => {
@@ -14658,7 +15153,7 @@ var init_commands = __esm({
14658
15153
  });
14659
15154
 
14660
15155
  // packages/github-workflows/src/index.ts
14661
- var init_src16 = __esm({
15156
+ var init_src17 = __esm({
14662
15157
  "packages/github-workflows/src/index.ts"() {
14663
15158
  "use strict";
14664
15159
  init_frontmatter3();
@@ -14794,17 +15289,18 @@ var init_execution_context = __esm({
14794
15289
  });
14795
15290
 
14796
15291
  // src/sdk/launch.ts
14797
- import path27 from "node:path";
14798
- import { spawnSync } from "node:child_process";
15292
+ import path29 from "node:path";
15293
+ import { spawnSync as spawnSync2 } from "node:child_process";
14799
15294
  async function startLaunch(options) {
14800
15295
  const homeDir = resolveHomeDir(options.homeDir);
14801
15296
  const cwd = options.cwd ?? process.cwd();
14802
15297
  const variables = options.variables ?? process.env;
14803
15298
  const executionContext = getCurrentExecutionContext(import.meta.url);
14804
15299
  const runner = createHostRunner({ detached: true });
15300
+ const spec = normalizeLaunchSpec(options.spec, cwd);
14805
15301
  return await startManagedProcess({
14806
15302
  baseDir: resolveLaunchBaseDir(homeDir),
14807
- spec: options.spec,
15303
+ spec,
14808
15304
  spawnDaemon: async (id) => {
14809
15305
  const handle = runner.exec({
14810
15306
  args: [...executionContext.command.args, "launch", "__run", id],
@@ -14899,7 +15395,7 @@ async function runLaunchDaemon(options) {
14899
15395
  });
14900
15396
  }
14901
15397
  function resolveLaunchBaseDir(homeDir) {
14902
- return path27.join(homeDir, ".poe-code", "launch");
15398
+ return path29.join(homeDir, ".poe-code", "launch");
14903
15399
  }
14904
15400
  function resolveHomeDir(homeDir) {
14905
15401
  if (homeDir) {
@@ -14907,6 +15403,20 @@ function resolveHomeDir(homeDir) {
14907
15403
  }
14908
15404
  return process.env.HOME ?? process.cwd();
14909
15405
  }
15406
+ function normalizeLaunchSpec(spec, baseDir) {
15407
+ if (!spec.cwd) {
15408
+ return spec;
15409
+ }
15410
+ const locator = parseLocator(spec.cwd);
15411
+ if (locator.scheme !== "local") {
15412
+ return spec;
15413
+ }
15414
+ const cwd = path29.isAbsolute(locator.path) ? locator.path : path29.resolve(baseDir, locator.path);
15415
+ return {
15416
+ ...spec,
15417
+ cwd
15418
+ };
15419
+ }
14910
15420
  function sendSignalToManagedProcess(pid, signal) {
14911
15421
  if (process.platform === "win32") {
14912
15422
  process.kill(pid, signal);
@@ -14939,14 +15449,14 @@ async function stopDockerArtifacts(record, force) {
14939
15449
  }
14940
15450
  const engine = resolveEngine(record.spec.docker.engine);
14941
15451
  const command = force ? "kill" : "stop";
14942
- spawnSync(engine, [command, record.spec.docker.containerName], { stdio: "ignore" });
15452
+ spawnSync2(engine, [command, record.spec.docker.containerName], { stdio: "ignore" });
14943
15453
  }
14944
15454
  async function removeDockerArtifacts(record) {
14945
15455
  if (!record.spec?.docker?.containerName) {
14946
15456
  return;
14947
15457
  }
14948
15458
  const engine = resolveEngine(record.spec.docker.engine);
14949
- spawnSync(engine, ["rm", "-f", record.spec.docker.containerName], { stdio: "ignore" });
15459
+ spawnSync2(engine, ["rm", "-f", record.spec.docker.containerName], { stdio: "ignore" });
14950
15460
  }
14951
15461
  function resolveEngine(engine) {
14952
15462
  if (engine) {
@@ -14957,8 +15467,9 @@ function resolveEngine(engine) {
14957
15467
  var init_launch = __esm({
14958
15468
  "src/sdk/launch.ts"() {
14959
15469
  "use strict";
15470
+ init_src8();
15471
+ init_src12();
14960
15472
  init_src11();
14961
- init_src10();
14962
15473
  init_execution_context();
14963
15474
  }
14964
15475
  });
@@ -15977,7 +16488,7 @@ var init_acp_core = __esm({
15977
16488
  });
15978
16489
 
15979
16490
  // packages/poe-agent/src/plugins/plugin-args.ts
15980
- import path28 from "node:path";
16491
+ import path30 from "node:path";
15981
16492
  function isObjectRecord3(value) {
15982
16493
  return typeof value === "object" && value !== null && !Array.isArray(value);
15983
16494
  }
@@ -16008,13 +16519,13 @@ function getOptionalString(args, key) {
16008
16519
  return value;
16009
16520
  }
16010
16521
  function resolveAllowedPath(cwd, allowedPaths, inputPath) {
16011
- const resolvedPath = path28.resolve(cwd, inputPath);
16522
+ const resolvedPath = path30.resolve(cwd, inputPath);
16012
16523
  const isAllowed = allowedPaths.some((allowedPath) => {
16013
16524
  if (allowedPath === resolvedPath) {
16014
16525
  return true;
16015
16526
  }
16016
- const rel = path28.relative(allowedPath, resolvedPath);
16017
- return rel.length > 0 && !rel.startsWith("..") && !path28.isAbsolute(rel);
16527
+ const rel = path30.relative(allowedPath, resolvedPath);
16528
+ return rel.length > 0 && !rel.startsWith("..") && !path30.isAbsolute(rel);
16018
16529
  });
16019
16530
  if (!isAllowed) {
16020
16531
  throw new Error(`Path is outside allowed paths: ${inputPath}`);
@@ -16029,7 +16540,7 @@ var init_plugin_args = __esm({
16029
16540
 
16030
16541
  // packages/poe-agent/src/plugins/poe-agent-plugin-files.ts
16031
16542
  import fsPromises9 from "node:fs/promises";
16032
- import path29 from "node:path";
16543
+ import path31 from "node:path";
16033
16544
  async function fileExists(fs3, filePath) {
16034
16545
  try {
16035
16546
  await fs3.readFile(filePath, "utf8");
@@ -16053,9 +16564,9 @@ var init_poe_agent_plugin_files = __esm({
16053
16564
  "use strict";
16054
16565
  init_plugin_args();
16055
16566
  filesPlugin = (options = {}) => {
16056
- const cwd = path29.resolve(options.cwd ?? process.cwd());
16567
+ const cwd = path31.resolve(options.cwd ?? process.cwd());
16057
16568
  const allowedPaths = (options.allowedPaths ?? [cwd]).map(
16058
- (allowedPath) => path29.resolve(cwd, allowedPath)
16569
+ (allowedPath) => path31.resolve(cwd, allowedPath)
16059
16570
  );
16060
16571
  const fs3 = options.fs ?? fsPromises9;
16061
16572
  const readFileTool = {
@@ -16109,7 +16620,7 @@ var init_poe_agent_plugin_files = __esm({
16109
16620
  async call(args) {
16110
16621
  const command = getRequiredString(args, "command");
16111
16622
  const filePath = resolveAllowedPath(cwd, allowedPaths, getRequiredString(args, "path"));
16112
- const displayedPath = path29.relative(cwd, filePath) || path29.basename(filePath);
16623
+ const displayedPath = path31.relative(cwd, filePath) || path31.basename(filePath);
16113
16624
  if (command === "str_replace") {
16114
16625
  const oldStr = getRequiredString(args, "old_str", true);
16115
16626
  const newStr = getRequiredString(args, "new_str", true);
@@ -16129,7 +16640,7 @@ var init_poe_agent_plugin_files = __esm({
16129
16640
  if (await fileExists(fs3, filePath)) {
16130
16641
  throw new Error("File already exists \u2014 use str_replace to edit");
16131
16642
  }
16132
- await fs3.mkdir(path29.dirname(filePath), { recursive: true });
16643
+ await fs3.mkdir(path31.dirname(filePath), { recursive: true });
16133
16644
  await fs3.writeFile(filePath, fileText, "utf8");
16134
16645
  return `Created file: ${displayedPath}`;
16135
16646
  }
@@ -16170,7 +16681,7 @@ var init_poe_agent_plugin_files = __esm({
16170
16681
 
16171
16682
  // packages/poe-agent/src/plugins/poe-agent-plugin-shell.ts
16172
16683
  import { exec as execCallback2 } from "node:child_process";
16173
- import path30 from "node:path";
16684
+ import path32 from "node:path";
16174
16685
  import { promisify } from "node:util";
16175
16686
  async function defaultRunCommand(command, cwd) {
16176
16687
  try {
@@ -16203,9 +16714,9 @@ var init_poe_agent_plugin_shell = __esm({
16203
16714
  init_plugin_args();
16204
16715
  exec = promisify(execCallback2);
16205
16716
  shellPlugin = (options = {}) => {
16206
- const cwd = path30.resolve(options.cwd ?? process.cwd());
16717
+ const cwd = path32.resolve(options.cwd ?? process.cwd());
16207
16718
  const allowedPaths = (options.allowedPaths ?? [cwd]).map(
16208
- (allowedPath) => path30.resolve(cwd, allowedPath)
16719
+ (allowedPath) => path32.resolve(cwd, allowedPath)
16209
16720
  );
16210
16721
  const runCommand2 = options.runCommand ?? defaultRunCommand;
16211
16722
  const runCommandTool = {
@@ -18276,7 +18787,7 @@ var init_internal = __esm({
18276
18787
  });
18277
18788
 
18278
18789
  // packages/tiny-mcp-client/src/index.ts
18279
- var init_src17 = __esm({
18790
+ var init_src18 = __esm({
18280
18791
  "packages/tiny-mcp-client/src/index.ts"() {
18281
18792
  "use strict";
18282
18793
  init_internal();
@@ -18325,7 +18836,7 @@ var DEFAULT_MCP_CLIENT_INFO, PluginApiImpl;
18325
18836
  var init_plugin_api_impl = __esm({
18326
18837
  "packages/poe-agent/src/runtime/plugin-api-impl.ts"() {
18327
18838
  "use strict";
18328
- init_src17();
18839
+ init_src18();
18329
18840
  init_hooks();
18330
18841
  DEFAULT_MCP_CLIENT_INFO = {
18331
18842
  name: "poe-agent",
@@ -18892,7 +19403,7 @@ __export(src_exports, {
18892
19403
  agent: () => agent,
18893
19404
  createAgentSession: () => createAgentSession
18894
19405
  });
18895
- var init_src18 = __esm({
19406
+ var init_src19 = __esm({
18896
19407
  "packages/poe-agent/src/index.ts"() {
18897
19408
  "use strict";
18898
19409
  init_agent();
@@ -19230,7 +19741,7 @@ function createInMemoryAcpTransport2(options) {
19230
19741
  }
19231
19742
  if (method === "session/new") {
19232
19743
  const request = params;
19233
- const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (init_src18(), src_exports));
19744
+ const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (init_src19(), src_exports));
19234
19745
  const session = await createAgentSession2({
19235
19746
  model: options.model,
19236
19747
  cwd: request.cwd || options.cwd,
@@ -19565,14 +20076,14 @@ var init_renderer2 = __esm({
19565
20076
 
19566
20077
  // packages/cmdkit/src/cli.ts
19567
20078
  import { access as access2, readFile as readFile11, writeFile as writeFile7 } from "node:fs/promises";
19568
- import path32 from "node:path";
20079
+ import path34 from "node:path";
19569
20080
  import { Command as CommanderCommand, CommanderError, InvalidArgumentError, Option } from "commander";
19570
20081
  function inferProgramName(argv) {
19571
20082
  const entrypoint = argv[1];
19572
20083
  if (typeof entrypoint !== "string" || entrypoint.length === 0) {
19573
20084
  return "cmdkit";
19574
20085
  }
19575
- const parsed = path32.parse(entrypoint);
20086
+ const parsed = path34.parse(entrypoint);
19576
20087
  return parsed.name.length > 0 ? parsed.name : "cmdkit";
19577
20088
  }
19578
20089
  function normalizeRoots(roots, argv) {
@@ -20148,7 +20659,7 @@ async function promptForField(field) {
20148
20659
  options,
20149
20660
  initialValue: field.hasDefault ? field.defaultValue : void 0
20150
20661
  });
20151
- if (Ct(selected)) {
20662
+ if (q(selected)) {
20152
20663
  cancel("Operation cancelled.");
20153
20664
  throw new UserError("Operation cancelled.");
20154
20665
  }
@@ -20159,7 +20670,7 @@ async function promptForField(field) {
20159
20670
  message: field.displayPath,
20160
20671
  initialValue: field.hasDefault ? Boolean(field.defaultValue) : void 0
20161
20672
  });
20162
- if (Ct(selected)) {
20673
+ if (q(selected)) {
20163
20674
  cancel("Operation cancelled.");
20164
20675
  throw new UserError("Operation cancelled.");
20165
20676
  }
@@ -20169,7 +20680,7 @@ async function promptForField(field) {
20169
20680
  message: field.displayPath,
20170
20681
  initialValue: field.hasDefault && field.defaultValue !== void 0 ? formatResolvedValue(field.defaultValue) : void 0
20171
20682
  });
20172
- if (Ct(entered)) {
20683
+ if (q(entered)) {
20173
20684
  cancel("Operation cancelled.");
20174
20685
  throw new UserError("Operation cancelled.");
20175
20686
  }
@@ -20525,8 +21036,8 @@ function createFixtureService(definition) {
20525
21036
  );
20526
21037
  }
20527
21038
  function resolveFixturePath(commandPath) {
20528
- const parsed = path32.parse(commandPath);
20529
- return path32.join(parsed.dir, `${parsed.name}.fixture.json`);
21039
+ const parsed = path34.parse(commandPath);
21040
+ return path34.join(parsed.dir, `${parsed.name}.fixture.json`);
20530
21041
  }
20531
21042
  function selectFixtureScenario(scenarios, selector) {
20532
21043
  if (isNumericFixtureSelector(selector)) {
@@ -20732,7 +21243,7 @@ async function executeCommand(state, services, requirementOptions) {
20732
21243
  message: "Proceed?",
20733
21244
  initialValue: true
20734
21245
  });
20735
- if (Ct(proceed)) {
21246
+ if (q(proceed)) {
20736
21247
  cancel("Operation cancelled.");
20737
21248
  throw new UserError("Operation cancelled.");
20738
21249
  }
@@ -20816,7 +21327,7 @@ var init_cli = __esm({
20816
21327
  "packages/cmdkit/src/cli.ts"() {
20817
21328
  "use strict";
20818
21329
  init_src5();
20819
- init_src15();
21330
+ init_src16();
20820
21331
  init_renderer2();
20821
21332
  RESERVED_SERVICE_NAMES = /* @__PURE__ */ new Set(["params", "secrets", "fetch", "fs", "env", "progress"]);
20822
21333
  HELP_FLAGS = /* @__PURE__ */ new Set(["--help", "-h"]);
@@ -20868,7 +21379,7 @@ function openInBrowser(url) {
20868
21379
  var init_oauth_login = __esm({
20869
21380
  "src/cli/oauth-login.ts"() {
20870
21381
  "use strict";
20871
- init_src8();
21382
+ init_src9();
20872
21383
  init_src5();
20873
21384
  }
20874
21385
  });
@@ -20941,7 +21452,7 @@ function createCliContainer(dependencies) {
20941
21452
  checkAuth: async (apiKey) => await checkAuth({ apiKey }) !== null,
20942
21453
  confirm: async (message2) => {
20943
21454
  const result = await confirm2({ message: message2 });
20944
- if (Ct(result)) {
21455
+ if (q(result)) {
20945
21456
  cancel("Operation cancelled.");
20946
21457
  throw new OperationCancelledError();
20947
21458
  }
@@ -20987,7 +21498,7 @@ var init_container2 = __esm({
20987
21498
  init_service_registry();
20988
21499
  init_context();
20989
21500
  init_prompts2();
20990
- init_src8();
21501
+ init_src9();
20991
21502
  init_options();
20992
21503
  init_logger2();
20993
21504
  init_error_logger();
@@ -21001,7 +21512,7 @@ var init_container2 = __esm({
21001
21512
  });
21002
21513
 
21003
21514
  // src/services/config.ts
21004
- import path33 from "node:path";
21515
+ import path35 from "node:path";
21005
21516
  async function deleteConfig(options) {
21006
21517
  const { fs: fs3, filePath } = options;
21007
21518
  try {
@@ -21082,7 +21593,7 @@ async function migrateLegacyCredentialsIfNeeded(fs3, filePath) {
21082
21593
  await migrateLegacyCredentialsFile(fs3, filePath);
21083
21594
  }
21084
21595
  async function migrateLegacyCredentialsFile(fs3, configPath) {
21085
- const legacyPath = path33.join(path33.dirname(configPath), "credentials.json");
21596
+ const legacyPath = path35.join(path35.dirname(configPath), "credentials.json");
21086
21597
  const raw = await readFileIfExists(fs3, legacyPath);
21087
21598
  if (raw === null) {
21088
21599
  return;
@@ -21150,9 +21661,9 @@ async function recoverInvalidConfig(fs3, filePath, content) {
21150
21661
  await fs3.writeFile(filePath, EMPTY_DOCUMENT3, { encoding: "utf8" });
21151
21662
  }
21152
21663
  function createInvalidBackupPath2(filePath) {
21153
- const directory = path33.dirname(filePath);
21154
- const baseName = path33.basename(filePath);
21155
- return path33.join(directory, `${baseName}.invalid-${createTimestamp()}.json`);
21664
+ const directory = path35.dirname(filePath);
21665
+ const baseName = path35.basename(filePath);
21666
+ return path35.join(directory, `${baseName}.invalid-${createTimestamp()}.json`);
21156
21667
  }
21157
21668
  function isRecord11(value) {
21158
21669
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
@@ -21371,7 +21882,7 @@ function registerAgentCommand(program, container) {
21371
21882
  }
21372
21883
  let session;
21373
21884
  try {
21374
- const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (init_src18(), src_exports));
21885
+ const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (init_src19(), src_exports));
21375
21886
  session = await createAgentSession2({
21376
21887
  model: options.model,
21377
21888
  apiKey: options.apiKey,
@@ -21430,13 +21941,12 @@ var init_agent2 = __esm({
21430
21941
  });
21431
21942
 
21432
21943
  // src/cli/commands/spawn.ts
21433
- import path34 from "node:path";
21434
21944
  function registerSpawnCommand(program, container, options = {}) {
21435
21945
  const spawnServices = container.registry.list().filter((service) => typeof service.spawn === "function" || getSpawnConfig(service.name)).map((service) => service.name);
21436
21946
  const extraServices = options.extraServices ?? [];
21437
21947
  const serviceList = [...spawnServices, ...extraServices];
21438
21948
  const serviceDescription = `Agent to spawn${formatServiceList(serviceList)}`;
21439
- program.command("spawn").alias("s").description("Run a single prompt through a configured agent CLI.").option("--model <model>", "Model identifier override passed to the agent CLI").option("-C, --cwd <path>", "Working directory for the agent CLI").option("--stdin", "Read the prompt from stdin").option("-i, --interactive", "Launch the agent in interactive TUI mode").option("--mode <mode>", "Permission mode: yolo | edit | read (default: yolo)").option("--mcp-config <json>", "MCP server config JSON: {name: {command, args?, env?}}").option("--log-dir <path>", "Directory override for ACP JSONL spawn logs").option(
21949
+ program.command("spawn").alias("s").description("Run a single prompt through a configured agent CLI.").option("--model <model>", "Model identifier override passed to the agent CLI").option("-C, --cwd <path>", "Working directory or workspace locator for the agent CLI").option("--stdin", "Read the prompt from stdin").option("-i, --interactive", "Launch the agent in interactive TUI mode").option("--mode <mode>", "Permission mode: yolo | edit | read (default: yolo)").option("--mcp-servers <json>", "MCP server config JSON: {name: {command, args?, env?}}").option("--mcp-config <json>", "[deprecated: use --mcp-servers]").option("--log-dir <path>", "Directory override for ACP JSONL spawn logs").option(
21440
21950
  "--activity-timeout-ms <ms>",
21441
21951
  "Kill the agent after N ms of inactivity",
21442
21952
  (value) => parsePositiveInt(value, "--activity-timeout-ms")
@@ -21444,8 +21954,7 @@ function registerSpawnCommand(program, container, options = {}) {
21444
21954
  const flags = resolveCommandFlags(program);
21445
21955
  const commandOptions = this.opts();
21446
21956
  const shouldEmitUiOutput = resolveOutputFormat() !== "json";
21447
- const mcpServers = parseMcpSpawnConfig2(commandOptions.mcpConfig);
21448
- const cwdOverride = resolveSpawnWorkingDirectory2(container.env.cwd, commandOptions.cwd);
21957
+ const mcpServers = parseMcpSpawnConfig2(commandOptions.mcpServers ?? commandOptions.mcpConfig);
21449
21958
  const wantsStdinFlag = commandOptions.stdin === true;
21450
21959
  const shouldReadFromStdin = wantsStdinFlag || promptText === "-" || !promptText && !process.stdin.isTTY;
21451
21960
  const forwardedArgs = wantsStdinFlag ? [...promptText ? [promptText] : [], ...agentArgs] : agentArgs;
@@ -21455,35 +21964,6 @@ function registerSpawnCommand(program, container, options = {}) {
21455
21964
  if (promptText === "-") {
21456
21965
  promptText = void 0;
21457
21966
  }
21458
- if (commandOptions.interactive) {
21459
- const adapter2 = resolveServiceAdapter(container, service);
21460
- const canonicalService2 = adapter2.name;
21461
- assertInteractiveSupport(adapter2.label, canonicalService2);
21462
- const proceed = await confirmUnconfiguredService(
21463
- container,
21464
- canonicalService2,
21465
- adapter2.label,
21466
- flags
21467
- );
21468
- if (!proceed) {
21469
- return;
21470
- }
21471
- const model2 = await resolveConfiguredModel(
21472
- container,
21473
- canonicalService2,
21474
- commandOptions.model
21475
- );
21476
- const result = await spawnInteractive(canonicalService2, {
21477
- prompt: promptText ?? "",
21478
- args: forwardedArgs,
21479
- model: model2,
21480
- mode: commandOptions.mode,
21481
- ...mcpServers ? { mcpServers } : {},
21482
- cwd: cwdOverride
21483
- });
21484
- process.exitCode = result.exitCode;
21485
- return;
21486
- }
21487
21967
  if (!promptText && shouldReadFromStdin) {
21488
21968
  const chunks = [];
21489
21969
  for await (const chunk of process.stdin) {
@@ -21491,154 +21971,197 @@ function registerSpawnCommand(program, container, options = {}) {
21491
21971
  }
21492
21972
  promptText = Buffer.concat(chunks).toString("utf8").trim();
21493
21973
  }
21494
- if (!promptText) {
21974
+ if (!promptText && !commandOptions.interactive) {
21495
21975
  throw new Error("No prompt provided via argument or stdin");
21496
21976
  }
21497
- const directSpawnOptions = {
21498
- prompt: promptText,
21499
- args: forwardedArgs,
21500
- model: commandOptions.model,
21977
+ const prompt = promptText ?? "";
21978
+ const workspace = await resolveSpawnWorkspace(commandOptions.cwd, {
21979
+ baseDir: container.env.cwd,
21980
+ homeDir: container.env.homeDir,
21501
21981
  mode: commandOptions.mode,
21502
- mcpServers,
21503
- cwd: cwdOverride,
21504
- logDir: commandOptions.logDir,
21505
- activityTimeoutMs: commandOptions.activityTimeoutMs,
21506
- useStdin: shouldReadFromStdin
21507
- };
21508
- const directHandler = options.handlers?.[service];
21509
- if (directHandler) {
21510
- const resources2 = createExecutionResources(container, flags, `spawn:${service}`);
21511
- if (shouldEmitUiOutput) {
21512
- resources2.logger.intro(`spawn ${service}`);
21513
- }
21514
- await directHandler({
21515
- container,
21516
- service,
21517
- options: directSpawnOptions,
21518
- flags,
21519
- resources: resources2
21520
- });
21521
- if (shouldEmitUiOutput) {
21522
- resources2.context.finalize();
21523
- }
21524
- return;
21525
- }
21526
- const adapter = resolveServiceAdapter(container, service);
21527
- const canonicalService = adapter.name;
21528
- const model = await resolveConfiguredModel(
21529
- container,
21530
- canonicalService,
21531
- commandOptions.model
21532
- );
21533
- const spawnOptions = {
21534
- ...directSpawnOptions,
21535
- model
21536
- };
21537
- const resources = createExecutionResources(container, flags, `spawn:${canonicalService}`);
21538
- if (shouldEmitUiOutput) {
21539
- resources.logger.intro(`spawn ${canonicalService}`);
21540
- }
21541
- const canonicalHandler = options.handlers?.[canonicalService];
21542
- if (canonicalHandler) {
21543
- try {
21544
- await canonicalHandler({
21982
+ resolveRemoteLocators: !flags.dryRun,
21983
+ fs: container.fs,
21984
+ exec: container.commandRunner
21985
+ });
21986
+ const cwdOverride = workspace.cwd;
21987
+ try {
21988
+ if (commandOptions.interactive) {
21989
+ const adapter2 = resolveServiceAdapter(container, service);
21990
+ const canonicalService2 = adapter2.name;
21991
+ assertInteractiveSupport(adapter2.label, canonicalService2);
21992
+ const proceed = await confirmUnconfiguredService(
21545
21993
  container,
21546
- service: canonicalService,
21547
- options: spawnOptions,
21548
- flags,
21549
- resources
21994
+ canonicalService2,
21995
+ adapter2.label,
21996
+ flags
21997
+ );
21998
+ if (!proceed) {
21999
+ return;
22000
+ }
22001
+ const model2 = await resolveConfiguredModel(
22002
+ container,
22003
+ canonicalService2,
22004
+ commandOptions.model
22005
+ );
22006
+ const result = await spawnInteractive(canonicalService2, {
22007
+ prompt,
22008
+ args: forwardedArgs,
22009
+ model: model2,
22010
+ mode: commandOptions.mode,
22011
+ ...mcpServers ? { mcpServers } : {},
22012
+ cwd: cwdOverride
21550
22013
  });
22014
+ process.exitCode = result.exitCode;
21551
22015
  return;
21552
- } finally {
22016
+ }
22017
+ const directSpawnOptions = {
22018
+ prompt,
22019
+ args: forwardedArgs,
22020
+ model: commandOptions.model,
22021
+ mode: commandOptions.mode,
22022
+ mcpServers,
22023
+ cwd: cwdOverride,
22024
+ logDir: commandOptions.logDir,
22025
+ activityTimeoutMs: commandOptions.activityTimeoutMs,
22026
+ useStdin: shouldReadFromStdin
22027
+ };
22028
+ const directHandler = options.handlers?.[service];
22029
+ if (directHandler) {
22030
+ const resources2 = createExecutionResources(container, flags, `spawn:${service}`);
21553
22031
  if (shouldEmitUiOutput) {
21554
- resources.context.finalize();
22032
+ resources2.logger.intro(`spawn ${service}`);
21555
22033
  }
21556
- }
21557
- }
21558
- try {
21559
- assertSpawnSupport(adapter.label, canonicalService, typeof adapter.spawn === "function");
21560
- assertMcpSpawnSupport(
21561
- adapter.label,
21562
- canonicalService,
21563
- adapter.supportsMcpSpawn === true,
21564
- mcpServers
21565
- );
21566
- if (flags.dryRun) {
21567
- await spawnCore(container, canonicalService, spawnOptions, {
21568
- dryRun: true,
21569
- verbose: flags.verbose
22034
+ await directHandler({
22035
+ container,
22036
+ service,
22037
+ options: directSpawnOptions,
22038
+ flags,
22039
+ resources: resources2
21570
22040
  });
22041
+ if (shouldEmitUiOutput) {
22042
+ resources2.context.finalize();
22043
+ }
21571
22044
  return;
21572
22045
  }
21573
- const proceed = await confirmUnconfiguredService(
22046
+ const adapter = resolveServiceAdapter(container, service);
22047
+ const canonicalService = adapter.name;
22048
+ const model = await resolveConfiguredModel(
21574
22049
  container,
21575
22050
  canonicalService,
21576
- adapter.label,
21577
- flags
22051
+ commandOptions.model
21578
22052
  );
21579
- if (!proceed) {
21580
- return;
22053
+ const spawnOptions = {
22054
+ ...directSpawnOptions,
22055
+ model
22056
+ };
22057
+ const resources = createExecutionResources(container, flags, `spawn:${canonicalService}`);
22058
+ if (shouldEmitUiOutput) {
22059
+ resources.logger.intro(`spawn ${canonicalService}`);
21581
22060
  }
21582
- const { events, result } = spawn4(canonicalService, {
21583
- prompt: spawnOptions.prompt,
21584
- args: spawnOptions.args,
21585
- model: spawnOptions.model,
21586
- mode: spawnOptions.mode,
21587
- cwd: spawnOptions.cwd,
21588
- ...spawnOptions.mcpServers ? { mcpConfig: spawnOptions.mcpServers } : {},
21589
- ...spawnOptions.logDir !== void 0 ? { logDir: spawnOptions.logDir } : {},
21590
- ...spawnOptions.activityTimeoutMs !== void 0 ? { activityTimeoutMs: spawnOptions.activityTimeoutMs } : {}
21591
- });
21592
- await renderAcpStream(events);
21593
- const final = await result;
21594
- process.exitCode = final.exitCode;
21595
- if (!shouldEmitUiOutput) {
21596
- renderAcpEvent({
21597
- event: "spawn_result",
21598
- exitCode: final.exitCode,
21599
- ...final.threadId ? { threadId: final.threadId } : {},
21600
- ...final.usage ? { usage: final.usage } : {},
21601
- protocolVersion: 1
21602
- });
22061
+ const canonicalHandler = options.handlers?.[canonicalService];
22062
+ if (canonicalHandler) {
22063
+ try {
22064
+ await canonicalHandler({
22065
+ container,
22066
+ service: canonicalService,
22067
+ options: spawnOptions,
22068
+ flags,
22069
+ resources
22070
+ });
22071
+ return;
22072
+ } finally {
22073
+ if (shouldEmitUiOutput) {
22074
+ resources.context.finalize();
22075
+ }
22076
+ }
21603
22077
  }
21604
- if (final.exitCode !== 0) {
21605
- if (!shouldEmitUiOutput) {
22078
+ try {
22079
+ assertSpawnSupport(adapter.label, canonicalService, typeof adapter.spawn === "function");
22080
+ assertMcpSpawnSupport(
22081
+ adapter.label,
22082
+ canonicalService,
22083
+ adapter.supportsMcpSpawn === true,
22084
+ mcpServers
22085
+ );
22086
+ if (flags.dryRun) {
22087
+ await spawnCore(container, canonicalService, spawnOptions, {
22088
+ dryRun: true,
22089
+ verbose: flags.verbose
22090
+ });
21606
22091
  return;
21607
22092
  }
21608
- const detail = final.stderr.trim() || final.stdout.trim();
21609
- const suffix = detail ? `: ${detail}` : "";
21610
- throw new Error(
21611
- `${adapter.label} spawn failed with exit code ${final.exitCode}${suffix}`
22093
+ const proceed = await confirmUnconfiguredService(
22094
+ container,
22095
+ canonicalService,
22096
+ adapter.label,
22097
+ flags
21612
22098
  );
21613
- }
21614
- if (shouldEmitUiOutput) {
21615
- const trimmedStdout = final.stdout.trim();
21616
- if (trimmedStdout) {
21617
- resources.logger.info(trimmedStdout);
21618
- } else {
21619
- const trimmedStderr = final.stderr.trim();
21620
- if (trimmedStderr) {
21621
- resources.logger.info(trimmedStderr);
22099
+ if (!proceed) {
22100
+ return;
22101
+ }
22102
+ const { events, result } = spawn4(canonicalService, {
22103
+ prompt: spawnOptions.prompt,
22104
+ args: spawnOptions.args,
22105
+ model: spawnOptions.model,
22106
+ mode: spawnOptions.mode,
22107
+ cwd: spawnOptions.cwd,
22108
+ ...spawnOptions.mcpServers ? { mcpServers: spawnOptions.mcpServers } : {},
22109
+ ...spawnOptions.logDir !== void 0 ? { logDir: spawnOptions.logDir } : {},
22110
+ ...spawnOptions.activityTimeoutMs !== void 0 ? { activityTimeoutMs: spawnOptions.activityTimeoutMs } : {}
22111
+ });
22112
+ await renderAcpStream(events);
22113
+ const final = await result;
22114
+ process.exitCode = final.exitCode;
22115
+ if (!shouldEmitUiOutput) {
22116
+ renderAcpEvent({
22117
+ event: "spawn_result",
22118
+ exitCode: final.exitCode,
22119
+ ...final.threadId ? { threadId: final.threadId } : {},
22120
+ ...final.usage ? { usage: final.usage } : {},
22121
+ protocolVersion: 1
22122
+ });
22123
+ }
22124
+ if (final.exitCode !== 0) {
22125
+ if (!shouldEmitUiOutput) {
22126
+ return;
22127
+ }
22128
+ const detail = final.stderr.trim() || final.stdout.trim();
22129
+ const suffix = detail ? `: ${detail}` : "";
22130
+ throw new Error(
22131
+ `${adapter.label} spawn failed with exit code ${final.exitCode}${suffix}`
22132
+ );
22133
+ }
22134
+ if (shouldEmitUiOutput) {
22135
+ const trimmedStdout = final.stdout.trim();
22136
+ if (trimmedStdout) {
22137
+ resources.logger.info(trimmedStdout);
21622
22138
  } else {
21623
- resources.logger.info(`${adapter.label} spawn completed.`);
22139
+ const trimmedStderr = final.stderr.trim();
22140
+ if (trimmedStderr) {
22141
+ resources.logger.info(trimmedStderr);
22142
+ } else {
22143
+ resources.logger.info(`${adapter.label} spawn completed.`);
22144
+ }
21624
22145
  }
21625
22146
  }
21626
- }
21627
- if (shouldEmitUiOutput && final.threadId) {
21628
- const resumeCommand = buildResumeCommand(
21629
- canonicalService,
21630
- final.threadId,
21631
- spawnOptions.cwd ?? process.cwd()
21632
- );
21633
- if (resumeCommand) {
21634
- resources.logger.info(text.muted(`
22147
+ if (shouldEmitUiOutput && final.threadId) {
22148
+ const resumeCommand = buildResumeCommand(
22149
+ canonicalService,
22150
+ final.threadId,
22151
+ spawnOptions.cwd ?? process.cwd()
22152
+ );
22153
+ if (resumeCommand) {
22154
+ resources.logger.info(text.muted(`
21635
22155
  Resume: ${resumeCommand}`));
22156
+ }
22157
+ }
22158
+ } finally {
22159
+ if (shouldEmitUiOutput) {
22160
+ resources.context.finalize();
21636
22161
  }
21637
22162
  }
21638
22163
  } finally {
21639
- if (shouldEmitUiOutput) {
21640
- resources.context.finalize();
21641
- }
22164
+ await workspace.cleanup?.();
21642
22165
  }
21643
22166
  });
21644
22167
  }
@@ -21654,22 +22177,13 @@ async function confirmUnconfiguredService(container, service, label, flags) {
21654
22177
  if (flags.assumeYes) {
21655
22178
  return true;
21656
22179
  }
21657
- const shouldProceed = await confirm2({
21658
- message: `${label} is not configured via poe. Do you want to proceed?`
21659
- });
21660
- if (Ct(shouldProceed)) {
21661
- throw new OperationCancelledError();
21662
- }
21663
- return shouldProceed === true;
21664
- }
21665
- function resolveSpawnWorkingDirectory2(baseDir, candidate) {
21666
- if (!candidate || candidate.trim().length === 0) {
21667
- return void 0;
21668
- }
21669
- if (path34.isAbsolute(candidate)) {
21670
- return candidate;
22180
+ const shouldProceed = await confirm2({
22181
+ message: `${label} is not configured via poe. Do you want to proceed?`
22182
+ });
22183
+ if (q(shouldProceed)) {
22184
+ throw new OperationCancelledError();
21671
22185
  }
21672
- return path34.resolve(baseDir, candidate);
22186
+ return shouldProceed === true;
21673
22187
  }
21674
22188
  function parseMcpSpawnConfig2(input) {
21675
22189
  if (!input) {
@@ -21680,37 +22194,37 @@ function parseMcpSpawnConfig2(input) {
21680
22194
  parsed = JSON.parse(input);
21681
22195
  } catch {
21682
22196
  throw new ValidationError(
21683
- "--mcp-config must be valid JSON in this shape: {name: {command, args?, env?}}"
22197
+ "--mcp-servers must be valid JSON in this shape: {name: {command, args?, env?}}"
21684
22198
  );
21685
22199
  }
21686
22200
  if (!isObjectRecord5(parsed)) {
21687
22201
  throw new ValidationError(
21688
- "--mcp-config must be an object in this shape: {name: {command, args?, env?}}"
22202
+ "--mcp-servers must be an object in this shape: {name: {command, args?, env?}}"
21689
22203
  );
21690
22204
  }
21691
22205
  const servers = {};
21692
22206
  for (const [name, value] of Object.entries(parsed)) {
21693
22207
  if (!isObjectRecord5(value)) {
21694
22208
  throw new ValidationError(
21695
- `--mcp-config entry "${name}" must be an object: {command, args?, env?}`
22209
+ `--mcp-servers entry "${name}" must be an object: {command, args?, env?}`
21696
22210
  );
21697
22211
  }
21698
22212
  const command = value.command;
21699
22213
  if (typeof command !== "string" || command.trim().length === 0) {
21700
22214
  throw new ValidationError(
21701
- `--mcp-config entry "${name}" must include a non-empty string "command"`
22215
+ `--mcp-servers entry "${name}" must include a non-empty string "command"`
21702
22216
  );
21703
22217
  }
21704
22218
  let args;
21705
22219
  if ("args" in value && value.args !== void 0) {
21706
22220
  if (!Array.isArray(value.args)) {
21707
- throw new ValidationError(`--mcp-config entry "${name}".args must be an array of strings`);
22221
+ throw new ValidationError(`--mcp-servers entry "${name}".args must be an array of strings`);
21708
22222
  }
21709
22223
  args = [];
21710
22224
  for (const arg of value.args) {
21711
22225
  if (typeof arg !== "string") {
21712
22226
  throw new ValidationError(
21713
- `--mcp-config entry "${name}".args must be an array of strings`
22227
+ `--mcp-servers entry "${name}".args must be an array of strings`
21714
22228
  );
21715
22229
  }
21716
22230
  args.push(arg);
@@ -21720,14 +22234,14 @@ function parseMcpSpawnConfig2(input) {
21720
22234
  if ("env" in value && value.env !== void 0) {
21721
22235
  if (!isObjectRecord5(value.env)) {
21722
22236
  throw new ValidationError(
21723
- `--mcp-config entry "${name}".env must be an object of string values`
22237
+ `--mcp-servers entry "${name}".env must be an object of string values`
21724
22238
  );
21725
22239
  }
21726
22240
  env = {};
21727
22241
  for (const [envKey, envValue] of Object.entries(value.env)) {
21728
22242
  if (typeof envValue !== "string") {
21729
22243
  throw new ValidationError(
21730
- `--mcp-config entry "${name}".env must be an object of string values`
22244
+ `--mcp-servers entry "${name}".env must be an object of string values`
21731
22245
  );
21732
22246
  }
21733
22247
  env[envKey] = envValue;
@@ -21790,502 +22304,7 @@ var init_spawn4 = __esm({
21790
22304
  init_spawn_core();
21791
22305
  await init_spawn3();
21792
22306
  init_errors();
21793
- }
21794
- });
21795
-
21796
- // src/sdk/research.ts
21797
- import path35 from "node:path";
21798
- async function research(container, options) {
21799
- const logger2 = options.logger;
21800
- const source = await resolveSource({
21801
- container,
21802
- options,
21803
- logger: logger2
21804
- });
21805
- const researchPrompt = buildResearchPrompt(options.prompt);
21806
- const mode = options.mode ?? "read";
21807
- const { events, result } = spawn4(options.agent, {
21808
- prompt: researchPrompt,
21809
- args: options.args ?? [],
21810
- model: options.model,
21811
- mode,
21812
- cwd: source.cwd
21813
- });
21814
- const { teed, getOutput, done } = teeAcpStream(events);
21815
- const resultPromise = (async () => {
21816
- let outputPath;
21817
- let markdownOutput = "";
21818
- try {
21819
- const final = await result;
21820
- await done;
21821
- markdownOutput = getOutput();
21822
- const resumeCommand = final.threadId && options.resolveResumeCommand ? options.resolveResumeCommand(final.threadId, source.cwd) : void 0;
21823
- const document = buildResearchDocument({
21824
- prompt: options.prompt,
21825
- agent: options.agent,
21826
- path: source.cwd,
21827
- github: source.github,
21828
- resumeCommand,
21829
- markdown: markdownOutput
21830
- });
21831
- outputPath = buildOutputPath(container.env.homeDir, options.prompt);
21832
- await ensureDirectory2(container.fs, path35.dirname(outputPath));
21833
- await container.fs.writeFile(outputPath, document, {
21834
- encoding: "utf8"
21835
- });
21836
- if (final.exitCode !== 0) {
21837
- const detail = final.stderr.trim() || final.stdout.trim();
21838
- const suffix = detail ? `: ${detail}` : "";
21839
- const label = options.agentLabel ?? options.agent;
21840
- throw new Error(
21841
- `${label} research failed with exit code ${final.exitCode}${suffix}`
21842
- );
21843
- }
21844
- if (outputPath) {
21845
- logger2?.info?.(`Saved research to ${outputPath}`);
21846
- }
21847
- return {
21848
- ...final,
21849
- markdownOutput,
21850
- outputPath,
21851
- cwd: source.cwd,
21852
- github: source.github
21853
- };
21854
- } finally {
21855
- if (source.shouldCleanup && source.clonePath) {
21856
- await removePath(container.fs, source.clonePath);
21857
- }
21858
- }
21859
- })();
21860
- return { events: teed, result: resultPromise };
21861
- }
21862
- function buildSlug(value) {
21863
- const trimmed = value.trim().toLowerCase();
21864
- const maxLength = 48;
21865
- let output = "";
21866
- let pendingSeparator = false;
21867
- for (let index = 0; index < trimmed.length; index += 1) {
21868
- const char = trimmed[index] ?? "";
21869
- const code = char.charCodeAt(0);
21870
- if (isSlugChar(code)) {
21871
- if (pendingSeparator && output.length > 0) {
21872
- output += "-";
21873
- }
21874
- pendingSeparator = false;
21875
- output += char;
21876
- } else {
21877
- pendingSeparator = true;
21878
- }
21879
- if (output.length >= maxLength) {
21880
- break;
21881
- }
21882
- }
21883
- output = trimTrailingDashes(output.slice(0, maxLength));
21884
- return output.length > 0 ? output : "research";
21885
- }
21886
- function buildResearchPrompt(prompt) {
21887
- return `${RESEARCH_SYSTEM_PROMPT}
21888
-
21889
- ${prompt}`;
21890
- }
21891
- function buildResearchDocument(input) {
21892
- const lines = ["---"];
21893
- lines.push(`research_prompt: ${formatYamlString(input.prompt)}`);
21894
- lines.push(`agent: ${formatYamlString(input.agent)}`);
21895
- lines.push(`path: ${formatYamlString(input.path)}`);
21896
- if (input.github) {
21897
- lines.push(`github: ${formatYamlString(input.github)}`);
21898
- }
21899
- if (input.resumeCommand) {
21900
- lines.push(`resume_session_cmd: ${formatYamlString(input.resumeCommand)}`);
21901
- }
21902
- lines.push("---", "", input.markdown);
21903
- return lines.join("\n");
21904
- }
21905
- function buildClonePath(homeDir, github) {
21906
- const slug = extractRepoSlug(github);
21907
- return path35.join(homeDir, ".poe-code", "repos", slug);
21908
- }
21909
- function extractRepoSlug(value) {
21910
- const trimmed = value.trim();
21911
- if (trimmed.length === 0) {
21912
- return "repo";
21913
- }
21914
- let pathPart = trimmed;
21915
- const schemeIndex = trimmed.indexOf("://");
21916
- if (schemeIndex !== -1) {
21917
- try {
21918
- const url = new URL(trimmed);
21919
- pathPart = url.pathname;
21920
- } catch {
21921
- pathPart = trimmed.slice(schemeIndex + 3);
21922
- }
21923
- } else if (trimmed.startsWith("git@")) {
21924
- const colonIndex = trimmed.indexOf(":");
21925
- if (colonIndex !== -1) {
21926
- pathPart = trimmed.slice(colonIndex + 1);
21927
- }
21928
- }
21929
- if (pathPart.startsWith("/")) {
21930
- pathPart = pathPart.slice(1);
21931
- }
21932
- if (pathPart.endsWith(".git")) {
21933
- pathPart = pathPart.slice(0, -4);
21934
- }
21935
- const parts = pathPart.split("/");
21936
- const owner = parts[0] ?? "";
21937
- const repo = parts[1] ?? "";
21938
- const combined = repo.length > 0 ? `${owner}-${repo}` : owner;
21939
- const slug = buildSlug(combined);
21940
- return slug.length > 0 ? slug : buildSlug(trimmed);
21941
- }
21942
- function buildOutputPath(homeDir, prompt, now = /* @__PURE__ */ new Date()) {
21943
- const timestamp = formatTimestamp2(now);
21944
- const slug = buildSlug(prompt);
21945
- return path35.join(
21946
- homeDir,
21947
- ".poe-code",
21948
- "research",
21949
- `${timestamp}-${slug}.md`
21950
- );
21951
- }
21952
- function resolveGithubCloneUrl(value) {
21953
- const trimmed = value.trim();
21954
- if (trimmed.startsWith("git@") || trimmed.includes("://")) {
21955
- return trimmed;
21956
- }
21957
- const suffix = trimmed.endsWith(".git") ? trimmed : `${trimmed}.git`;
21958
- return `https://github.com/${suffix}`;
21959
- }
21960
- async function resolveSource(input) {
21961
- const { container, options } = input;
21962
- const logger2 = input.logger;
21963
- if (options.github) {
21964
- const cloneUrl = resolveGithubCloneUrl(options.github);
21965
- const clonePath = buildClonePath(container.env.homeDir, options.github);
21966
- await ensureDirectory2(container.fs, path35.dirname(clonePath));
21967
- const exists = await pathExists2(container.fs, clonePath);
21968
- if (!exists) {
21969
- const cloneResult = await container.commandRunner(
21970
- "git",
21971
- ["clone", "--depth", "1", cloneUrl, clonePath]
21972
- );
21973
- if (cloneResult.exitCode !== 0) {
21974
- throw new Error(
21975
- `git clone failed with exit code ${cloneResult.exitCode}: ${cloneResult.stderr.trim()}`
21976
- );
21977
- }
21978
- return {
21979
- cwd: clonePath,
21980
- github: options.github,
21981
- clonePath,
21982
- shouldCleanup: !options.keep
21983
- };
21984
- }
21985
- const statusResult = await container.commandRunner(
21986
- "git",
21987
- ["status", "--porcelain"],
21988
- { cwd: clonePath }
21989
- );
21990
- if (statusResult.exitCode !== 0) {
21991
- logger2?.warn?.("Unable to check git status; using existing clone.");
21992
- } else if (statusResult.stdout.trim().length > 0) {
21993
- logger2?.warn?.("Repo has uncommitted changes; skipping update.");
21994
- } else {
21995
- const pullResult = await container.commandRunner(
21996
- "git",
21997
- ["pull", "--ff-only"],
21998
- { cwd: clonePath }
21999
- );
22000
- if (pullResult.exitCode !== 0) {
22001
- logger2?.warn?.("Git pull failed; using existing clone.");
22002
- }
22003
- }
22004
- return {
22005
- cwd: clonePath,
22006
- github: options.github,
22007
- clonePath,
22008
- shouldCleanup: false
22009
- };
22010
- }
22011
- if (options.path) {
22012
- return {
22013
- cwd: resolvePath2(container.env.cwd, options.path),
22014
- shouldCleanup: false
22015
- };
22016
- }
22017
- if (options.cwd) {
22018
- return {
22019
- cwd: resolvePath2(container.env.cwd, options.cwd),
22020
- shouldCleanup: false
22021
- };
22022
- }
22023
- return {
22024
- cwd: container.env.cwd,
22025
- shouldCleanup: false
22026
- };
22027
- }
22028
- function isSlugChar(code) {
22029
- if (code >= 48 && code <= 57) {
22030
- return true;
22031
- }
22032
- if (code >= 97 && code <= 122) {
22033
- return true;
22034
- }
22035
- return false;
22036
- }
22037
- function trimTrailingDashes(value) {
22038
- let output = value;
22039
- while (output.endsWith("-")) {
22040
- output = output.slice(0, -1);
22041
- }
22042
- return output;
22043
- }
22044
- function formatTimestamp2(now) {
22045
- const year = now.getUTCFullYear();
22046
- const month = padNumber(now.getUTCMonth() + 1, 2);
22047
- const day = padNumber(now.getUTCDate(), 2);
22048
- const hours = padNumber(now.getUTCHours(), 2);
22049
- const minutes = padNumber(now.getUTCMinutes(), 2);
22050
- const seconds = padNumber(now.getUTCSeconds(), 2);
22051
- return `${year}${month}${day}-${hours}${minutes}${seconds}`;
22052
- }
22053
- function padNumber(value, length) {
22054
- let output = String(value);
22055
- while (output.length < length) {
22056
- output = `0${output}`;
22057
- }
22058
- return output;
22059
- }
22060
- function formatYamlString(value) {
22061
- return JSON.stringify(value);
22062
- }
22063
- function resolvePath2(baseDir, candidate) {
22064
- if (path35.isAbsolute(candidate)) {
22065
- return candidate;
22066
- }
22067
- return path35.resolve(baseDir, candidate);
22068
- }
22069
- function teeAcpStream(events) {
22070
- const chunks = [];
22071
- let resolveDone;
22072
- const done = new Promise((resolve) => {
22073
- resolveDone = resolve;
22074
- });
22075
- const teed = (async function* () {
22076
- try {
22077
- for await (const event of events) {
22078
- if (event.event === "agent_message") {
22079
- chunks.push(event.text);
22080
- }
22081
- yield event;
22082
- }
22083
- } finally {
22084
- resolveDone?.();
22085
- }
22086
- })();
22087
- return {
22088
- teed,
22089
- getOutput: () => chunks.join(""),
22090
- done
22091
- };
22092
- }
22093
- async function ensureDirectory2(fs3, target) {
22094
- await fs3.mkdir(target, { recursive: true });
22095
- }
22096
- async function pathExists2(fs3, target) {
22097
- try {
22098
- await fs3.stat(target);
22099
- return true;
22100
- } catch (error2) {
22101
- if (error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT") {
22102
- return false;
22103
- }
22104
- throw error2;
22105
- }
22106
- }
22107
- async function removePath(fs3, target) {
22108
- if (typeof fs3.rm === "function") {
22109
- await fs3.rm(target, { recursive: true, force: true });
22110
- return;
22111
- }
22112
- await removePathFallback(fs3, target);
22113
- }
22114
- async function removePathFallback(fs3, target) {
22115
- let stats;
22116
- try {
22117
- stats = await fs3.stat(target);
22118
- } catch (error2) {
22119
- if (error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT") {
22120
- return;
22121
- }
22122
- throw error2;
22123
- }
22124
- if (stats && typeof stats.isDirectory === "function" && stats.isDirectory()) {
22125
- const entries = await fs3.readdir(target);
22126
- for (const entry of entries) {
22127
- await removePathFallback(fs3, path35.join(target, entry));
22128
- }
22129
- }
22130
- try {
22131
- await fs3.unlink(target);
22132
- } catch {
22133
- }
22134
- }
22135
- var RESEARCH_SYSTEM_PROMPT;
22136
- var init_research = __esm({
22137
- async "src/sdk/research.ts"() {
22138
- "use strict";
22139
- await init_spawn3();
22140
- RESEARCH_SYSTEM_PROMPT = [
22141
- "You are a codebase research assistant.",
22142
- "Read files and answer the user's question about the codebase.",
22143
- "Do not modify files or suggest edits.",
22144
- "Respond in Markdown."
22145
- ].join("\n");
22146
- }
22147
- });
22148
-
22149
- // src/cli/commands/research.ts
22150
- function registerResearchCommand(program, container) {
22151
- const spawnServices = container.registry.list().filter((service) => typeof service.spawn === "function" || getSpawnConfig(service.name)).map((service) => service.name);
22152
- const serviceDescription = `Agent to research with${formatServiceList(spawnServices)}`;
22153
- program.command("research").description("Research a codebase using a coding agent.").option("--agent <agent>", serviceDescription).option("--model <model>", "Model identifier override passed to the agent CLI").option("--mode <mode>", "Permission mode: yolo | edit | read (default: read)").option("-C, --cwd <path>", "Working directory override").option("--path <path>", "Local directory to research").option("--github <repo>", "Clone and research a GitHub repo").option("--stdin", "Read the prompt from stdin").option("--keep", "Keep the cloned repo when using --github").argument("[prompt]", "Prompt text to send (or '-' / stdin)").argument("[agentArgs...]", "Additional arguments forwarded to the agent CLI").action(async function(promptText, agentArgs = []) {
22154
- const flags = resolveCommandFlags(program);
22155
- const commandOptions = this.opts();
22156
- const wantsStdinFlag = commandOptions.stdin === true;
22157
- const shouldReadFromStdin = wantsStdinFlag || promptText === "-" || !promptText && !process.stdin.isTTY;
22158
- const forwardedArgs = wantsStdinFlag ? [...promptText ? [promptText] : [], ...agentArgs] : agentArgs;
22159
- if (wantsStdinFlag) {
22160
- promptText = void 0;
22161
- }
22162
- if (promptText === "-") {
22163
- promptText = void 0;
22164
- }
22165
- if (!promptText && shouldReadFromStdin) {
22166
- const chunks = [];
22167
- for await (const chunk of process.stdin) {
22168
- chunks.push(chunk);
22169
- }
22170
- promptText = Buffer.concat(chunks).toString("utf8").trim();
22171
- }
22172
- if (!promptText) {
22173
- throw new Error("No prompt provided via argument or stdin");
22174
- }
22175
- const resolvedAgent = await resolveResearchAgent({
22176
- container,
22177
- flags,
22178
- agent: commandOptions.agent
22179
- });
22180
- const adapter = resolveServiceAdapter(container, resolvedAgent);
22181
- const canonicalService = adapter.name;
22182
- const resources = createExecutionResources(container, flags, `research:${canonicalService}`);
22183
- resources.logger.intro(`research ${canonicalService}`);
22184
- const model = await resolveResearchModel({
22185
- container,
22186
- flags,
22187
- adapter,
22188
- value: commandOptions.model
22189
- });
22190
- try {
22191
- const { events, result } = await research(container, {
22192
- prompt: promptText,
22193
- agent: canonicalService,
22194
- agentLabel: adapter.label,
22195
- model,
22196
- mode: commandOptions.mode,
22197
- args: forwardedArgs,
22198
- cwd: commandOptions.cwd,
22199
- path: commandOptions.path,
22200
- github: commandOptions.github,
22201
- keep: commandOptions.keep,
22202
- logger: resources.logger,
22203
- resolveResumeCommand: (threadId, cwdValue) => buildResumeCommand(canonicalService, threadId, cwdValue)
22204
- });
22205
- await renderAcpStream(events);
22206
- await result;
22207
- } finally {
22208
- resources.context.finalize();
22209
- }
22210
- });
22211
- }
22212
- async function resolveResearchAgent(input) {
22213
- if (input.agent) {
22214
- return input.agent;
22215
- }
22216
- const spawnable = input.container.registry.list().filter((service) => typeof service.spawn === "function" || getSpawnConfig(service.name));
22217
- if (spawnable.length === 0) {
22218
- throw new Error("No spawn-capable agents available.");
22219
- }
22220
- if (input.flags.assumeYes) {
22221
- const configured = await loadConfiguredServices({
22222
- fs: input.container.fs,
22223
- filePath: input.container.env.configPath,
22224
- projectFilePath: input.container.env.projectConfigPath
22225
- });
22226
- const configuredService = spawnable.find((service) => service.name in configured);
22227
- return configuredService?.name ?? spawnable[0].name;
22228
- }
22229
- const choices = spawnable.map((service) => ({
22230
- title: service.label,
22231
- value: service.name
22232
- }));
22233
- const descriptor = input.container.promptLibrary.serviceSelection({
22234
- message: "Pick an agent to research with:",
22235
- choices
22236
- });
22237
- const response = await input.container.prompts(descriptor);
22238
- const selectionValue = response[descriptor.name];
22239
- if (typeof selectionValue !== "string") {
22240
- throw new OperationCancelledError();
22241
- }
22242
- const resolved = spawnable.find((service) => service.name === selectionValue);
22243
- if (!resolved) {
22244
- throw new Error("Invalid agent selection.");
22245
- }
22246
- return resolved.name;
22247
- }
22248
- async function resolveResearchModel(input) {
22249
- if (input.value) {
22250
- return input.value;
22251
- }
22252
- const modelPrompt = input.adapter.configurePrompts?.model;
22253
- if (modelPrompt) {
22254
- return await input.container.options.resolveModel({
22255
- value: input.value,
22256
- assumeDefault: input.flags.assumeYes,
22257
- defaultValue: modelPrompt.defaultValue,
22258
- choices: modelPrompt.choices,
22259
- label: modelPrompt.label
22260
- });
22261
- }
22262
- if (input.flags.assumeYes) {
22263
- return void 0;
22264
- }
22265
- const descriptor = {
22266
- name: "model",
22267
- message: "Model identifier",
22268
- type: "text"
22269
- };
22270
- const response = await input.container.prompts(descriptor);
22271
- const result = response[descriptor.name];
22272
- if (typeof result !== "string") {
22273
- throw new OperationCancelledError();
22274
- }
22275
- const trimmed = result.trim();
22276
- if (trimmed.length === 0) {
22277
- throw new Error("Model identifier is required.");
22278
- }
22279
- return trimmed;
22280
- }
22281
- var init_research2 = __esm({
22282
- async "src/cli/commands/research.ts"() {
22283
- "use strict";
22284
- init_src7();
22285
- init_config3();
22286
- await init_research();
22287
- init_errors();
22288
- init_shared();
22307
+ init_resolve_spawn_workspace();
22289
22308
  }
22290
22309
  });
22291
22310
 
@@ -22893,7 +22912,7 @@ function registerUtilsCommand(program, container) {
22893
22912
  const utils = program.command("utils").description("Utility commands for inspecting and managing poe-code.");
22894
22913
  registerConfigCommand(utils, container);
22895
22914
  }
22896
- var init_utils3 = __esm({
22915
+ var init_utils4 = __esm({
22897
22916
  "src/cli/commands/utils.ts"() {
22898
22917
  "use strict";
22899
22918
  init_config4();
@@ -23589,6 +23608,8 @@ var init_image = __esm({
23589
23608
  this.base64Data = base64Data;
23590
23609
  this.mimeType = mimeType;
23591
23610
  }
23611
+ base64Data;
23612
+ mimeType;
23592
23613
  static async fromUrl(url) {
23593
23614
  const response = await fetch(url);
23594
23615
  if (!response.ok) {
@@ -23663,6 +23684,8 @@ var init_audio = __esm({
23663
23684
  this.base64Data = base64Data;
23664
23685
  this.mimeType = mimeType;
23665
23686
  }
23687
+ base64Data;
23688
+ mimeType;
23666
23689
  static async fromUrl(url) {
23667
23690
  const response = await fetch(url);
23668
23691
  if (!response.ok) {
@@ -23733,6 +23756,10 @@ var init_file = __esm({
23733
23756
  this.isText = isText;
23734
23757
  this.name = name;
23735
23758
  }
23759
+ data;
23760
+ mimeType;
23761
+ isText;
23762
+ name;
23736
23763
  static async fromUrl(url) {
23737
23764
  const response = await fetch(url);
23738
23765
  if (!response.ok) {
@@ -24114,7 +24141,7 @@ var init_content = __esm({
24114
24141
  });
24115
24142
 
24116
24143
  // packages/tiny-stdio-mcp-server/src/index.ts
24117
- var init_src19 = __esm({
24144
+ var init_src20 = __esm({
24118
24145
  "packages/tiny-stdio-mcp-server/src/index.ts"() {
24119
24146
  "use strict";
24120
24147
  init_server();
@@ -24417,7 +24444,7 @@ var generateTextSchema, generateImageSchema, generateVideoSchema, generateAudioS
24417
24444
  var init_mcp_server = __esm({
24418
24445
  "src/cli/mcp-server.ts"() {
24419
24446
  "use strict";
24420
- init_src19();
24447
+ init_src20();
24421
24448
  init_client_instance();
24422
24449
  init_constants();
24423
24450
  generateTextSchema = defineSchema({
@@ -24805,7 +24832,7 @@ var init_apply = __esm({
24805
24832
  });
24806
24833
 
24807
24834
  // packages/agent-mcp-config/src/index.ts
24808
- var init_src20 = __esm({
24835
+ var init_src21 = __esm({
24809
24836
  "packages/agent-mcp-config/src/index.ts"() {
24810
24837
  "use strict";
24811
24838
  init_configs2();
@@ -24878,7 +24905,7 @@ function registerMcpCommand(program, container) {
24878
24905
  message: "Select agent to configure:",
24879
24906
  options: supportedAgents.map((a) => ({ value: a, label: a }))
24880
24907
  });
24881
- if (Ct(selected)) {
24908
+ if (q(selected)) {
24882
24909
  cancel("Operation cancelled");
24883
24910
  return;
24884
24911
  }
@@ -24985,14 +25012,14 @@ var init_mcp2 = __esm({
24985
25012
  init_shared();
24986
25013
  init_mcp_output_format();
24987
25014
  init_command_not_found();
24988
- init_src20();
25015
+ init_src21();
24989
25016
  init_execution_context();
24990
25017
  DEFAULT_MCP_AGENT = "claude-code";
24991
25018
  }
24992
25019
  });
24993
25020
 
24994
25021
  // packages/agent-skill-config/src/configs.ts
24995
- import os2 from "node:os";
25022
+ import os4 from "node:os";
24996
25023
  import path38 from "node:path";
24997
25024
  function resolveAgentSupport2(input, registry = agentSkillConfigs) {
24998
25025
  const resolvedId = resolveAgentId(input);
@@ -25185,7 +25212,7 @@ var init_apply2 = __esm({
25185
25212
  });
25186
25213
 
25187
25214
  // packages/agent-skill-config/src/index.ts
25188
- var init_src21 = __esm({
25215
+ var init_src22 = __esm({
25189
25216
  "packages/agent-skill-config/src/index.ts"() {
25190
25217
  "use strict";
25191
25218
  init_configs3();
@@ -25231,7 +25258,7 @@ function registerSkillCommand(program, container) {
25231
25258
  message: "Select agent to configure:",
25232
25259
  options: supportedAgents2.map((a) => ({ value: a, label: a }))
25233
25260
  });
25234
- if (Ct(selected)) {
25261
+ if (q(selected)) {
25235
25262
  cancel("Operation cancelled");
25236
25263
  return;
25237
25264
  }
@@ -25264,7 +25291,7 @@ function registerSkillCommand(program, container) {
25264
25291
  { value: "local", label: "Local" }
25265
25292
  ]
25266
25293
  });
25267
- if (Ct(selected)) {
25294
+ if (q(selected)) {
25268
25295
  cancel("Operation cancelled");
25269
25296
  return;
25270
25297
  }
@@ -25310,7 +25337,7 @@ function registerSkillCommand(program, container) {
25310
25337
  message: "Select agent to unconfigure:",
25311
25338
  options: supportedAgents2.map((a) => ({ value: a, label: a }))
25312
25339
  });
25313
- if (Ct(selected)) {
25340
+ if (q(selected)) {
25314
25341
  cancel("Operation cancelled");
25315
25342
  return;
25316
25343
  }
@@ -25340,7 +25367,7 @@ function registerSkillCommand(program, container) {
25340
25367
  { value: "local", label: "Local" }
25341
25368
  ]
25342
25369
  });
25343
- if (Ct(selected)) {
25370
+ if (q(selected)) {
25344
25371
  cancel("Operation cancelled");
25345
25372
  return;
25346
25373
  }
@@ -25410,7 +25437,7 @@ var init_skill = __esm({
25410
25437
  "src/cli/commands/skill.ts"() {
25411
25438
  "use strict";
25412
25439
  init_src5();
25413
- init_src21();
25440
+ init_src22();
25414
25441
  init_shared();
25415
25442
  init_command_not_found();
25416
25443
  DEFAULT_SKILL_AGENT = "claude-code";
@@ -25703,7 +25730,7 @@ function registerUsageCommand(program, container) {
25703
25730
  startingAfter = result.data[result.data.length - 1].query_id;
25704
25731
  if (maxPages === void 0) {
25705
25732
  const shouldContinue = await confirm2({ message: "Load more?" });
25706
- if (Ct(shouldContinue)) {
25733
+ if (q(shouldContinue)) {
25707
25734
  throw new OperationCancelledError();
25708
25735
  }
25709
25736
  if (!shouldContinue) {
@@ -26080,7 +26107,7 @@ var init_models2 = __esm({
26080
26107
 
26081
26108
  // src/cli/commands/pipeline.ts
26082
26109
  import path39 from "node:path";
26083
- import { readFile as readFile13, stat as stat9 } from "node:fs/promises";
26110
+ import { readFile as readFile13, stat as stat11 } from "node:fs/promises";
26084
26111
  import { fileURLToPath as fileURLToPath7 } from "node:url";
26085
26112
  async function resolvePipelinePlanDirectory(container) {
26086
26113
  const configDoc = await readMergedDocument(
@@ -26160,7 +26187,7 @@ async function loadPipelineTemplates() {
26160
26187
  }
26161
26188
  async function pathExistsOnDisk(targetPath) {
26162
26189
  try {
26163
- await stat9(targetPath);
26190
+ await stat11(targetPath);
26164
26191
  return true;
26165
26192
  } catch (error2) {
26166
26193
  if (error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT") {
@@ -26218,7 +26245,7 @@ function registerPipelineCommand(program, container) {
26218
26245
  label: value
26219
26246
  }))
26220
26247
  });
26221
- if (Ct(selected)) {
26248
+ if (q(selected)) {
26222
26249
  cancel("Pipeline run cancelled.");
26223
26250
  return;
26224
26251
  }
@@ -26250,7 +26277,7 @@ function registerPipelineCommand(program, container) {
26250
26277
  },
26251
26278
  selectPlan: async (input) => {
26252
26279
  const selected = await select2(input);
26253
- if (Ct(selected)) {
26280
+ if (q(selected)) {
26254
26281
  cancel("Pipeline run cancelled.");
26255
26282
  return null;
26256
26283
  }
@@ -26258,7 +26285,7 @@ function registerPipelineCommand(program, container) {
26258
26285
  },
26259
26286
  promptForPath: async (input) => {
26260
26287
  const value = await text3(input);
26261
- if (Ct(value)) {
26288
+ if (q(value)) {
26262
26289
  cancel("Pipeline run cancelled.");
26263
26290
  return null;
26264
26291
  }
@@ -26438,7 +26465,7 @@ function registerPipelineCommand(program, container) {
26438
26465
  label: value
26439
26466
  }))
26440
26467
  });
26441
- if (Ct(selected)) {
26468
+ if (q(selected)) {
26442
26469
  cancel("Pipeline install cancelled.");
26443
26470
  return;
26444
26471
  }
@@ -26464,7 +26491,7 @@ function registerPipelineCommand(program, container) {
26464
26491
  { value: "global", label: "Global" }
26465
26492
  ]
26466
26493
  });
26467
- if (Ct(selected)) {
26494
+ if (q(selected)) {
26468
26495
  cancel("Pipeline install cancelled.");
26469
26496
  return;
26470
26497
  }
@@ -26539,13 +26566,13 @@ var init_pipeline3 = __esm({
26539
26566
  "use strict";
26540
26567
  init_src5();
26541
26568
  init_src2();
26542
- init_src21();
26569
+ init_src22();
26543
26570
  init_src4();
26544
26571
  init_config3();
26545
26572
  init_errors();
26546
26573
  init_shared();
26547
26574
  await init_pipeline2();
26548
- init_src9();
26575
+ init_src10();
26549
26576
  DEFAULT_PIPELINE_AGENT = "claude-code";
26550
26577
  DEFAULT_PIPELINE_SCOPE = "local";
26551
26578
  pipelineTemplatesCache = null;
@@ -26662,7 +26689,7 @@ async function resolveDocPath(options) {
26662
26689
  value: doc.path
26663
26690
  }))
26664
26691
  });
26665
- if (Ct(selected)) {
26692
+ if (q(selected)) {
26666
26693
  cancel("Ralph run cancelled.");
26667
26694
  return null;
26668
26695
  }
@@ -26706,7 +26733,7 @@ async function promptForAgent(program) {
26706
26733
  value: config.agentId
26707
26734
  }))
26708
26735
  });
26709
- if (Ct(selected)) {
26736
+ if (q(selected)) {
26710
26737
  cancel("Ralph run cancelled.");
26711
26738
  return null;
26712
26739
  }
@@ -26743,7 +26770,7 @@ async function resolveRunIterations(options) {
26743
26770
  const entered = await text3({
26744
26771
  message: "How many Ralph iterations should run?"
26745
26772
  });
26746
- if (Ct(entered)) {
26773
+ if (q(entered)) {
26747
26774
  cancel("Ralph run cancelled.");
26748
26775
  return null;
26749
26776
  }
@@ -26773,7 +26800,7 @@ async function resolveInitIterations(options) {
26773
26800
  const entered = await text3({
26774
26801
  message: "How many Ralph iterations should run?"
26775
26802
  });
26776
- if (Ct(entered)) {
26803
+ if (q(entered)) {
26777
26804
  cancel("Ralph init cancelled.");
26778
26805
  return null;
26779
26806
  }
@@ -26950,7 +26977,7 @@ var init_ralph3 = __esm({
26950
26977
  init_src5();
26951
26978
  init_src2();
26952
26979
  init_src7();
26953
- init_src12();
26980
+ init_src13();
26954
26981
  init_src4();
26955
26982
  init_config3();
26956
26983
  init_errors();
@@ -26963,7 +26990,7 @@ var init_ralph3 = __esm({
26963
26990
 
26964
26991
  // src/cli/commands/experiment.ts
26965
26992
  import path41 from "node:path";
26966
- import { readFile as readFile14, stat as stat10 } from "node:fs/promises";
26993
+ import { readFile as readFile14, stat as stat12 } from "node:fs/promises";
26967
26994
  import { fileURLToPath as fileURLToPath8 } from "node:url";
26968
26995
  function resolveExperimentPaths(scope, cwd, homeDir) {
26969
26996
  const rootPath = scope === "global" ? path41.join(homeDir, ".poe-code", "experiments") : path41.join(cwd, ".poe-code", "experiments");
@@ -26975,7 +27002,7 @@ function resolveExperimentPaths(scope, cwd, homeDir) {
26975
27002
  }
26976
27003
  async function pathExistsOnDisk2(targetPath) {
26977
27004
  try {
26978
- await stat10(targetPath);
27005
+ await stat12(targetPath);
26979
27006
  return true;
26980
27007
  } catch (error2) {
26981
27008
  if (error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT") {
@@ -27107,8 +27134,8 @@ async function discoverExperimentDocs(container) {
27107
27134
  }
27108
27135
  const relativePath = path41.join(EXPERIMENTS_DIRECTORY, name);
27109
27136
  const absolutePath = path41.join(directoryPath, name);
27110
- const stat11 = await container.fs.stat(absolutePath);
27111
- if (!stat11.isFile()) {
27137
+ const stat13 = await container.fs.stat(absolutePath);
27138
+ if (!stat13.isFile()) {
27112
27139
  continue;
27113
27140
  }
27114
27141
  docs.push({
@@ -27139,7 +27166,7 @@ async function resolveDocPath2(options) {
27139
27166
  value: doc.path
27140
27167
  }))
27141
27168
  });
27142
- if (Ct(selected)) {
27169
+ if (q(selected)) {
27143
27170
  cancel(options.cancelMessage);
27144
27171
  return null;
27145
27172
  }
@@ -27169,7 +27196,7 @@ async function promptForAgent2(program) {
27169
27196
  value: config.agentId
27170
27197
  }))
27171
27198
  });
27172
- if (Ct(selected)) {
27199
+ if (q(selected)) {
27173
27200
  cancel("Experiment run cancelled.");
27174
27201
  return null;
27175
27202
  }
@@ -27452,7 +27479,7 @@ function registerExperimentCommand(program, container) {
27452
27479
  label: value
27453
27480
  }))
27454
27481
  });
27455
- if (Ct(selected)) {
27482
+ if (q(selected)) {
27456
27483
  cancel("Experiment install cancelled.");
27457
27484
  return;
27458
27485
  }
@@ -27478,7 +27505,7 @@ function registerExperimentCommand(program, container) {
27478
27505
  { value: "global", label: "Global" }
27479
27506
  ]
27480
27507
  });
27481
- if (Ct(selected)) {
27508
+ if (q(selected)) {
27482
27509
  cancel("Experiment install cancelled.");
27483
27510
  return;
27484
27511
  }
@@ -27550,8 +27577,8 @@ var init_experiment2 = __esm({
27550
27577
  init_src5();
27551
27578
  init_src2();
27552
27579
  init_src7();
27553
- init_src21();
27554
- init_src13();
27580
+ init_src22();
27581
+ init_src14();
27555
27582
  init_errors();
27556
27583
  init_shared();
27557
27584
  await init_experiment();
@@ -27732,7 +27759,7 @@ async function resolveProcessId(value) {
27732
27759
  const entered = await text3({
27733
27760
  message: "Process ID"
27734
27761
  });
27735
- if (Ct(entered)) {
27762
+ if (q(entered)) {
27736
27763
  cancel("Launch start cancelled.");
27737
27764
  return null;
27738
27765
  }
@@ -27749,7 +27776,7 @@ async function resolveCommandParts(commandArgs) {
27749
27776
  const entered = await text3({
27750
27777
  message: "Command to run"
27751
27778
  });
27752
- if (Ct(entered)) {
27779
+ if (q(entered)) {
27753
27780
  cancel("Launch start cancelled.");
27754
27781
  return null;
27755
27782
  }
@@ -27773,7 +27800,7 @@ async function resolveRuntime(options) {
27773
27800
  { label: "docker", value: "docker" }
27774
27801
  ]
27775
27802
  });
27776
- if (Ct(selected)) {
27803
+ if (q(selected)) {
27777
27804
  cancel("Launch start cancelled.");
27778
27805
  return null;
27779
27806
  }
@@ -27786,7 +27813,7 @@ async function resolveDockerImage(value) {
27786
27813
  const entered = await text3({
27787
27814
  message: "Docker image"
27788
27815
  });
27789
- if (Ct(entered)) {
27816
+ if (q(entered)) {
27790
27817
  cancel("Launch start cancelled.");
27791
27818
  return null;
27792
27819
  }
@@ -27811,7 +27838,7 @@ async function resolveRestart(restart, assumeYes) {
27811
27838
  { label: "always", value: "always" }
27812
27839
  ]
27813
27840
  });
27814
- if (Ct(selected)) {
27841
+ if (q(selected)) {
27815
27842
  cancel("Launch start cancelled.");
27816
27843
  return null;
27817
27844
  }
@@ -27989,7 +28016,7 @@ var init_package = __esm({
27989
28016
  "package.json"() {
27990
28017
  package_default = {
27991
28018
  name: "poe-code",
27992
- version: "3.0.131",
28019
+ version: "3.0.133",
27993
28020
  description: "CLI tool to configure Poe API for developer workflows.",
27994
28021
  type: "module",
27995
28022
  main: "./dist/index.js",
@@ -28105,6 +28132,7 @@ var init_package = __esm({
28105
28132
  "@poe-code/process-runner": "*",
28106
28133
  "@poe-code/ralph": "*",
28107
28134
  "@poe-code/worktree": "*",
28135
+ "@poe-code/workspace-resolver": "*",
28108
28136
  "@types/mustache": "^4.2.6",
28109
28137
  "@types/node": "^25.2.2",
28110
28138
  "@types/semver": "^7.7.1",
@@ -28466,7 +28494,6 @@ function bootstrapProgram(container) {
28466
28494
  registerConfigureCommand(program, container);
28467
28495
  registerAgentCommand(program, container);
28468
28496
  registerSpawnCommand(program, container);
28469
- registerResearchCommand(program, container);
28470
28497
  registerWrapCommand(program, container);
28471
28498
  registerGenerateCommand(program, container);
28472
28499
  registerTestCommand(program, container);
@@ -28529,18 +28556,17 @@ var init_program = __esm({
28529
28556
  async "src/cli/program.ts"() {
28530
28557
  "use strict";
28531
28558
  init_cli();
28532
- init_src16();
28559
+ init_src17();
28533
28560
  await init_container2();
28534
28561
  init_src5();
28535
28562
  init_configure();
28536
28563
  init_agent2();
28537
28564
  await init_spawn4();
28538
- await init_research2();
28539
28565
  init_wrap();
28540
28566
  init_login();
28541
28567
  init_logout();
28542
28568
  init_auth();
28543
- init_utils3();
28569
+ init_utils4();
28544
28570
  init_install();
28545
28571
  init_unconfigure();
28546
28572
  init_test();
@@ -28581,7 +28607,7 @@ function createPromptRunner(adapter = {
28581
28607
  text: text3,
28582
28608
  password: password2,
28583
28609
  select: select2,
28584
- isCancel: Ct,
28610
+ isCancel: q,
28585
28611
  cancel
28586
28612
  }) {
28587
28613
  const runPrompt = async (descriptor) => {
@@ -28646,7 +28672,7 @@ __export(bootstrap_exports, {
28646
28672
  createCliMain: () => createCliMain,
28647
28673
  isCliInvocation: () => isCliInvocation
28648
28674
  });
28649
- import * as nodeFs4 from "node:fs/promises";
28675
+ import * as nodeFs6 from "node:fs/promises";
28650
28676
  import * as nodeFsSync3 from "node:fs";
28651
28677
  import { realpathSync } from "node:fs";
28652
28678
  import { homedir as homedir5 } from "node:os";
@@ -28721,7 +28747,7 @@ var init_bootstrap = __esm({
28721
28747
  init_error_logger();
28722
28748
  init_errors();
28723
28749
  init_prompt_runner();
28724
- fsAdapter = nodeFs4;
28750
+ fsAdapter = nodeFs6;
28725
28751
  }
28726
28752
  });
28727
28753
 
@@ -28732,7 +28758,7 @@ import { realpathSync as realpathSync2 } from "node:fs";
28732
28758
  import { pathToFileURL as pathToFileURL3 } from "node:url";
28733
28759
 
28734
28760
  // src/sdk/process-launcher.ts
28735
- init_src11();
28761
+ init_src12();
28736
28762
 
28737
28763
  // src/index.ts
28738
28764
  await init_ralph2();
@@ -28837,7 +28863,7 @@ function normalizeBaseUrl(value) {
28837
28863
 
28838
28864
  // src/index.ts
28839
28865
  init_credentials();
28840
- init_src16();
28866
+ init_src17();
28841
28867
  init_launch();
28842
28868
 
28843
28869
  // src/cli/poe-agent-main.ts
@@ -28845,7 +28871,7 @@ init_src7();
28845
28871
  init_src5();
28846
28872
  init_constants();
28847
28873
  init_errors();
28848
- import path31 from "node:path";
28874
+ import path33 from "node:path";
28849
28875
  import { Command } from "commander";
28850
28876
  function parseMcpSpawnConfig(input) {
28851
28877
  if (!input) {
@@ -28856,33 +28882,33 @@ function parseMcpSpawnConfig(input) {
28856
28882
  parsed = JSON.parse(input);
28857
28883
  } catch {
28858
28884
  throw new ValidationError(
28859
- "--mcp-config must be valid JSON in this shape: {name: {command, args?, env?}}"
28885
+ "--mcp-servers must be valid JSON in this shape: {name: {command, args?, env?}}"
28860
28886
  );
28861
28887
  }
28862
28888
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
28863
28889
  throw new ValidationError(
28864
- "--mcp-config must be an object in this shape: {name: {command, args?, env?}}"
28890
+ "--mcp-servers must be an object in this shape: {name: {command, args?, env?}}"
28865
28891
  );
28866
28892
  }
28867
28893
  const servers = {};
28868
28894
  for (const [name, value] of Object.entries(parsed)) {
28869
28895
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
28870
28896
  throw new ValidationError(
28871
- `--mcp-config entry "${name}" must be an object: {command, args?, env?}`
28897
+ `--mcp-servers entry "${name}" must be an object: {command, args?, env?}`
28872
28898
  );
28873
28899
  }
28874
28900
  const entry = value;
28875
28901
  const command = entry.command;
28876
28902
  if (typeof command !== "string" || command.trim().length === 0) {
28877
28903
  throw new ValidationError(
28878
- `--mcp-config entry "${name}" must include a non-empty string "command"`
28904
+ `--mcp-servers entry "${name}" must include a non-empty string "command"`
28879
28905
  );
28880
28906
  }
28881
28907
  let args;
28882
28908
  if ("args" in entry && entry.args !== void 0) {
28883
28909
  if (!Array.isArray(entry.args) || entry.args.some((a) => typeof a !== "string")) {
28884
28910
  throw new ValidationError(
28885
- `--mcp-config entry "${name}".args must be an array of strings`
28911
+ `--mcp-servers entry "${name}".args must be an array of strings`
28886
28912
  );
28887
28913
  }
28888
28914
  args = entry.args;
@@ -28891,14 +28917,14 @@ function parseMcpSpawnConfig(input) {
28891
28917
  if ("env" in entry && entry.env !== void 0) {
28892
28918
  if (typeof entry.env !== "object" || entry.env === null || Array.isArray(entry.env)) {
28893
28919
  throw new ValidationError(
28894
- `--mcp-config entry "${name}".env must be an object of string values`
28920
+ `--mcp-servers entry "${name}".env must be an object of string values`
28895
28921
  );
28896
28922
  }
28897
28923
  env = {};
28898
28924
  for (const [envKey, envValue] of Object.entries(entry.env)) {
28899
28925
  if (typeof envValue !== "string") {
28900
28926
  throw new ValidationError(
28901
- `--mcp-config entry "${name}".env must be an object of string values`
28927
+ `--mcp-servers entry "${name}".env must be an object of string values`
28902
28928
  );
28903
28929
  }
28904
28930
  env[envKey] = envValue;
@@ -28916,19 +28942,19 @@ function resolveWorkingDirectory(baseDir, candidate) {
28916
28942
  if (!candidate || candidate.trim().length === 0) {
28917
28943
  return void 0;
28918
28944
  }
28919
- if (path31.isAbsolute(candidate)) {
28945
+ if (path33.isAbsolute(candidate)) {
28920
28946
  return candidate;
28921
28947
  }
28922
- return path31.resolve(baseDir, candidate);
28948
+ return path33.resolve(baseDir, candidate);
28923
28949
  }
28924
28950
  function createPoeAgentProgram() {
28925
28951
  const program = new Command();
28926
28952
  program.name("poe-agent").description("Run a single prompt through the Poe agent runtime.").version("0.0.0").option("--model <model>", "Model identifier override").option("-C, --cwd <path>", "Working directory for the agent").option("--stdin", "Read the prompt from stdin").option(
28927
- "--mcp-config <json>",
28953
+ "--mcp-servers <json>",
28928
28954
  "MCP server config JSON: {name: {command, args?, env?}}"
28929
- ).argument("[prompt]", "Prompt text to send (or '-' / stdin)").argument("[args...]", "Additional arguments forwarded to the agent").action(async function(promptText, _args = []) {
28955
+ ).option("--mcp-config <json>", "[deprecated: use --mcp-servers]").argument("[prompt]", "Prompt text to send (or '-' / stdin)").argument("[args...]", "Additional arguments forwarded to the agent").action(async function(promptText, _args = []) {
28930
28956
  const commandOptions = this.opts();
28931
- const mcpServers = parseMcpSpawnConfig(commandOptions.mcpConfig);
28957
+ const mcpServers = parseMcpSpawnConfig(commandOptions.mcpServers ?? commandOptions.mcpConfig);
28932
28958
  const cwdOverride = resolveWorkingDirectory(
28933
28959
  process.cwd(),
28934
28960
  commandOptions.cwd