poe-code 3.0.100 → 3.0.102

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -714,16 +714,16 @@ function getConfigFormat(pathOrFormat) {
714
714
  }
715
715
  return formatRegistry[formatName];
716
716
  }
717
- function detectFormat(path24) {
718
- const ext = getExtension(path24);
717
+ function detectFormat(path27) {
718
+ const ext = getExtension(path27);
719
719
  return extensionMap[ext];
720
720
  }
721
- function getExtension(path24) {
722
- const lastDot = path24.lastIndexOf(".");
721
+ function getExtension(path27) {
722
+ const lastDot = path27.lastIndexOf(".");
723
723
  if (lastDot === -1) {
724
724
  return "";
725
725
  }
726
- return path24.slice(lastDot).toLowerCase();
726
+ return path27.slice(lastDot).toLowerCase();
727
727
  }
728
728
  var formatRegistry, extensionMap;
729
729
  var init_formats = __esm({
@@ -1054,8 +1054,8 @@ async function applyChmod(mutation, context, options) {
1054
1054
  };
1055
1055
  }
1056
1056
  try {
1057
- const stat6 = await context.fs.stat(targetPath);
1058
- const currentMode = typeof stat6.mode === "number" ? stat6.mode & 511 : null;
1057
+ const stat8 = await context.fs.stat(targetPath);
1058
+ const currentMode = typeof stat8.mode === "number" ? stat8.mode & 511 : null;
1059
1059
  if (currentMode === mutation.mode) {
1060
1060
  return {
1061
1061
  outcome: { changed: false, effect: "none", detail: "noop" },
@@ -1450,38 +1450,38 @@ import { createTwoFilesPatch } from "diff";
1450
1450
  import chalk from "chalk";
1451
1451
  function createDryRunFileSystem(base, recorder) {
1452
1452
  const proxy = {
1453
- async readFile(path24, encoding) {
1453
+ async readFile(path27, encoding) {
1454
1454
  if (encoding) {
1455
- return base.readFile(path24, encoding);
1455
+ return base.readFile(path27, encoding);
1456
1456
  }
1457
- return base.readFile(path24);
1457
+ return base.readFile(path27);
1458
1458
  },
1459
- async writeFile(path24, data, options) {
1460
- const previousContent = await tryReadText(base, path24);
1459
+ async writeFile(path27, data, options) {
1460
+ const previousContent = await tryReadText(base, path27);
1461
1461
  const nextContent = formatData(data, options?.encoding);
1462
1462
  recorder.record({
1463
1463
  type: "writeFile",
1464
- path: path24,
1464
+ path: path27,
1465
1465
  nextContent,
1466
1466
  previousContent
1467
1467
  });
1468
1468
  },
1469
- async mkdir(path24, options) {
1470
- recorder.record({ type: "mkdir", path: path24, options });
1469
+ async mkdir(path27, options) {
1470
+ recorder.record({ type: "mkdir", path: path27, options });
1471
1471
  },
1472
- async stat(path24) {
1473
- return base.stat(path24);
1472
+ async stat(path27) {
1473
+ return base.stat(path27);
1474
1474
  },
1475
- async unlink(path24) {
1476
- recorder.record({ type: "unlink", path: path24 });
1475
+ async unlink(path27) {
1476
+ recorder.record({ type: "unlink", path: path27 });
1477
1477
  },
1478
- async readdir(path24) {
1479
- return base.readdir(path24);
1478
+ async readdir(path27) {
1479
+ return base.readdir(path27);
1480
1480
  }
1481
1481
  };
1482
1482
  if (typeof base.rm === "function") {
1483
- proxy.rm = async (path24, options) => {
1484
- recorder.record({ type: "rm", path: path24, options });
1483
+ proxy.rm = async (path27, options) => {
1484
+ recorder.record({ type: "rm", path: path27, options });
1485
1485
  };
1486
1486
  }
1487
1487
  if (typeof base.copyFile === "function") {
@@ -1571,8 +1571,8 @@ function describeWriteChange(previous, next) {
1571
1571
  }
1572
1572
  return "update";
1573
1573
  }
1574
- function renderWriteCommand(path24, change) {
1575
- const command = `cat > ${path24}`;
1574
+ function renderWriteCommand(path27, change) {
1575
+ const command = `cat > ${path27}`;
1576
1576
  if (change === "create") {
1577
1577
  return renderOperationCommand(command, chalk.green, "# create");
1578
1578
  }
@@ -1734,9 +1734,9 @@ function redactTomlLine(line) {
1734
1734
  }
1735
1735
  return line;
1736
1736
  }
1737
- async function tryReadText(base, path24) {
1737
+ async function tryReadText(base, path27) {
1738
1738
  try {
1739
- return await base.readFile(path24, "utf8");
1739
+ return await base.readFile(path27, "utf8");
1740
1740
  } catch (error2) {
1741
1741
  if (isNotFound(error2)) {
1742
1742
  return null;
@@ -3730,21 +3730,21 @@ async function* adaptClaude(lines) {
3730
3730
  if (blockType !== "tool_result") continue;
3731
3731
  const kind = toolKindsById.get(item.tool_use_id);
3732
3732
  toolKindsById.delete(item.tool_use_id);
3733
- let path24;
3733
+ let path27;
3734
3734
  if (typeof item.content === "string") {
3735
- path24 = item.content;
3735
+ path27 = item.content;
3736
3736
  } else {
3737
3737
  try {
3738
- path24 = JSON.stringify(item.content);
3738
+ path27 = JSON.stringify(item.content);
3739
3739
  } catch {
3740
- path24 = String(item.content);
3740
+ path27 = String(item.content);
3741
3741
  }
3742
3742
  }
3743
3743
  yield {
3744
3744
  event: "tool_complete",
3745
3745
  id: item.tool_use_id,
3746
3746
  kind,
3747
- path: path24
3747
+ path: path27
3748
3748
  };
3749
3749
  }
3750
3750
  }
@@ -3866,10 +3866,10 @@ async function* adaptCodex(lines) {
3866
3866
  const kindFromStart = toolKindById.get(item.id);
3867
3867
  const kind = kindFromStart ?? (itemType === "command_execution" ? "exec" : itemType === "file_edit" ? "edit" : "other");
3868
3868
  const titleFromEvent = isNonEmptyString(item.path) ? item.path : itemType === "mcp_tool_call" ? `${isNonEmptyString(item.server) ? item.server : "unknown"}.${isNonEmptyString(item.tool) ? item.tool : "unknown"}` : void 0;
3869
- const path24 = titleFromEvent ?? toolTitleById.get(item.id) ?? "";
3869
+ const path27 = titleFromEvent ?? toolTitleById.get(item.id) ?? "";
3870
3870
  toolTitleById.delete(item.id);
3871
3871
  toolKindById.delete(item.id);
3872
- yield { event: "tool_complete", id: item.id, kind, path: path24 };
3872
+ yield { event: "tool_complete", id: item.id, kind, path: path27 };
3873
3873
  }
3874
3874
  }
3875
3875
  }
@@ -4311,7 +4311,7 @@ function updateSessionFromEvent(ctx, event, toolCallsById) {
4311
4311
  }
4312
4312
  const id = readString(event.id);
4313
4313
  const kind = readString(event.kind);
4314
- const path24 = readString(event.path);
4314
+ const path27 = readString(event.path);
4315
4315
  let toolCall = id ? toolCallsById.get(id) : void 0;
4316
4316
  if (!toolCall) {
4317
4317
  toolCall = {};
@@ -4326,8 +4326,8 @@ function updateSessionFromEvent(ctx, event, toolCallsById) {
4326
4326
  if (kind) {
4327
4327
  toolCall.kind = kind;
4328
4328
  }
4329
- if (path24) {
4330
- toolCall.path = path24;
4329
+ if (path27) {
4330
+ toolCall.path = path27;
4331
4331
  }
4332
4332
  }
4333
4333
  var sessionCapture;
@@ -4835,15 +4835,142 @@ var init_spawn_core = __esm({
4835
4835
  }
4836
4836
  });
4837
4837
 
4838
- // src/cli/environment.ts
4838
+ // packages/poe-code-config/src/schema.ts
4839
+ var init_schema = __esm({
4840
+ "packages/poe-code-config/src/schema.ts"() {
4841
+ "use strict";
4842
+ }
4843
+ });
4844
+
4845
+ // packages/poe-code-config/src/store.ts
4839
4846
  import path7 from "node:path";
4847
+ async function readDocument(fs3, filePath) {
4848
+ try {
4849
+ const raw = await fs3.readFile(filePath, "utf8");
4850
+ return await parseDocument(fs3, filePath, raw);
4851
+ } catch (error2) {
4852
+ if (isNotFound(error2)) {
4853
+ return {};
4854
+ }
4855
+ throw error2;
4856
+ }
4857
+ }
4858
+ async function writeScope(fs3, filePath, scope, values) {
4859
+ const document = await readDocument(fs3, filePath);
4860
+ const normalizedValues = normalizeScopeValues(values);
4861
+ if (Object.keys(normalizedValues).length === 0) {
4862
+ delete document[scope];
4863
+ } else {
4864
+ document[scope] = normalizedValues;
4865
+ }
4866
+ await writeDocument(fs3, filePath, document);
4867
+ }
4868
+ async function parseDocument(fs3, filePath, raw) {
4869
+ try {
4870
+ return normalizeDocument(JSON.parse(raw));
4871
+ } catch (error2) {
4872
+ if (error2 instanceof SyntaxError) {
4873
+ await recoverInvalidDocument(fs3, filePath, raw);
4874
+ return {};
4875
+ }
4876
+ throw error2;
4877
+ }
4878
+ }
4879
+ function normalizeDocument(value) {
4880
+ if (!isRecord2(value)) {
4881
+ return {};
4882
+ }
4883
+ const document = {};
4884
+ for (const [scope, scopeValues] of Object.entries(value)) {
4885
+ const normalizedValues = normalizeScopeValues(scopeValues);
4886
+ if (Object.keys(normalizedValues).length > 0) {
4887
+ document[scope] = normalizedValues;
4888
+ }
4889
+ }
4890
+ return document;
4891
+ }
4892
+ function normalizeScopeValues(value) {
4893
+ if (!isRecord2(value)) {
4894
+ return {};
4895
+ }
4896
+ const normalized = {};
4897
+ for (const [key, entry] of Object.entries(value)) {
4898
+ if (entry !== void 0) {
4899
+ normalized[key] = entry;
4900
+ }
4901
+ }
4902
+ return normalized;
4903
+ }
4904
+ async function writeDocument(fs3, filePath, document) {
4905
+ await fs3.mkdir(path7.dirname(filePath), { recursive: true });
4906
+ await fs3.writeFile(filePath, `${JSON.stringify(document, null, 2)}
4907
+ `, {
4908
+ encoding: "utf8"
4909
+ });
4910
+ }
4911
+ async function recoverInvalidDocument(fs3, filePath, content) {
4912
+ await fs3.mkdir(path7.dirname(filePath), { recursive: true });
4913
+ const backupPath = createInvalidBackupPath(filePath);
4914
+ await fs3.writeFile(backupPath, content, { encoding: "utf8" });
4915
+ await fs3.writeFile(filePath, EMPTY_DOCUMENT, { encoding: "utf8" });
4916
+ }
4917
+ function createInvalidBackupPath(filePath) {
4918
+ const directory = path7.dirname(filePath);
4919
+ const baseName = path7.basename(filePath);
4920
+ return path7.join(directory, `${baseName}.invalid-${createTimestamp()}.json`);
4921
+ }
4922
+ function isRecord2(value) {
4923
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
4924
+ }
4925
+ function resolveConfigPath(homeDir) {
4926
+ return path7.join(homeDir, ".poe-code", "config.json");
4927
+ }
4928
+ var EMPTY_DOCUMENT;
4929
+ var init_store = __esm({
4930
+ "packages/poe-code-config/src/store.ts"() {
4931
+ "use strict";
4932
+ init_src2();
4933
+ EMPTY_DOCUMENT = `${JSON.stringify({}, null, 2)}
4934
+ `;
4935
+ }
4936
+ });
4937
+
4938
+ // packages/poe-code-config/src/resolve.ts
4939
+ var init_resolve = __esm({
4940
+ "packages/poe-code-config/src/resolve.ts"() {
4941
+ "use strict";
4942
+ }
4943
+ });
4944
+
4945
+ // packages/poe-code-config/src/config.ts
4946
+ var init_config = __esm({
4947
+ "packages/poe-code-config/src/config.ts"() {
4948
+ "use strict";
4949
+ init_store();
4950
+ init_resolve();
4951
+ }
4952
+ });
4953
+
4954
+ // packages/poe-code-config/src/index.ts
4955
+ var init_src6 = __esm({
4956
+ "packages/poe-code-config/src/index.ts"() {
4957
+ "use strict";
4958
+ init_schema();
4959
+ init_config();
4960
+ init_resolve();
4961
+ init_store();
4962
+ }
4963
+ });
4964
+
4965
+ // src/cli/environment.ts
4966
+ import path8 from "node:path";
4840
4967
  function createCliEnvironment(init) {
4841
4968
  const platform = init.platform ?? process.platform;
4842
4969
  const variables = init.variables ?? process.env;
4843
4970
  const configPath = resolveConfigPath(init.homeDir);
4844
4971
  const logDir = resolveLogDir(init.homeDir);
4845
4972
  const { poeApiBaseUrl, poeBaseUrl } = resolvePoeBaseUrls(variables);
4846
- const resolveHomePath = (...segments) => path7.join(init.homeDir, ...segments);
4973
+ const resolveHomePath = (...segments) => path8.join(init.homeDir, ...segments);
4847
4974
  const getVariable = (name) => variables[name];
4848
4975
  return {
4849
4976
  cwd: init.cwd,
@@ -4858,11 +4985,8 @@ function createCliEnvironment(init) {
4858
4985
  getVariable
4859
4986
  };
4860
4987
  }
4861
- function resolveConfigPath(homeDir) {
4862
- return path7.join(homeDir, ".poe-code", "config.json");
4863
- }
4864
4988
  function resolveLogDir(homeDir) {
4865
- return path7.join(homeDir, ".poe-code", "logs");
4989
+ return path8.join(homeDir, ".poe-code", "logs");
4866
4990
  }
4867
4991
  function resolvePoeBaseUrls(variables) {
4868
4992
  const raw = variables.POE_BASE_URL;
@@ -4941,6 +5065,7 @@ var DEFAULT_POE_API_BASE_URL;
4941
5065
  var init_environment = __esm({
4942
5066
  "src/cli/environment.ts"() {
4943
5067
  "use strict";
5068
+ init_src6();
4944
5069
  DEFAULT_POE_API_BASE_URL = "https://api.poe.com/v1";
4945
5070
  }
4946
5071
  });
@@ -5555,7 +5680,7 @@ var init_logger2 = __esm({
5555
5680
  });
5556
5681
 
5557
5682
  // src/cli/error-logger.ts
5558
- import path8 from "node:path";
5683
+ import path9 from "node:path";
5559
5684
  var DEFAULT_MAX_SIZE, DEFAULT_MAX_BACKUPS, ErrorLogger;
5560
5685
  var init_error_logger = __esm({
5561
5686
  "src/cli/error-logger.ts"() {
@@ -5572,7 +5697,7 @@ var init_error_logger = __esm({
5572
5697
  fileLoggingAvailable;
5573
5698
  constructor(options) {
5574
5699
  this.fs = options.fs;
5575
- this.logFilePath = path8.join(options.logDir, "errors.log");
5700
+ this.logFilePath = path9.join(options.logDir, "errors.log");
5576
5701
  this.logToStderr = options.logToStderr ?? true;
5577
5702
  this.maxSize = options.maxSize ?? DEFAULT_MAX_SIZE;
5578
5703
  this.maxBackups = options.maxBackups ?? DEFAULT_MAX_BACKUPS;
@@ -5691,7 +5816,7 @@ ${entry.stack}`);
5691
5816
  return `${this.logFilePath}.${index}`;
5692
5817
  }
5693
5818
  ensureLogDirectory() {
5694
- const directory = path8.dirname(this.logFilePath);
5819
+ const directory = path9.dirname(this.logFilePath);
5695
5820
  try {
5696
5821
  if (!this.fs.existsSync(directory)) {
5697
5822
  this.fs.mkdirSync(directory, { recursive: true });
@@ -5709,7 +5834,7 @@ ${entry.stack}`);
5709
5834
  });
5710
5835
 
5711
5836
  // src/providers/index.ts
5712
- import path9 from "node:path";
5837
+ import path10 from "node:path";
5713
5838
  import { readdir } from "node:fs/promises";
5714
5839
  import { fileURLToPath, pathToFileURL } from "node:url";
5715
5840
  function isProviderModule(filename) {
@@ -5736,7 +5861,7 @@ async function loadProviders() {
5736
5861
  for (const entry of entries) {
5737
5862
  if (!entry.isFile()) continue;
5738
5863
  if (!isProviderModule(entry.name)) continue;
5739
- const moduleUrl = pathToFileURL(path9.join(currentDir, entry.name)).href;
5864
+ const moduleUrl = pathToFileURL(path10.join(currentDir, entry.name)).href;
5740
5865
  const moduleExports = await import(moduleUrl);
5741
5866
  if (!moduleExports.provider) {
5742
5867
  throw new Error(`Provider module "${entry.name}" must export "provider".`);
@@ -5752,8 +5877,8 @@ var moduleDir, currentDir, defaultProviders;
5752
5877
  var init_providers = __esm({
5753
5878
  async "src/providers/index.ts"() {
5754
5879
  "use strict";
5755
- moduleDir = path9.dirname(fileURLToPath(import.meta.url));
5756
- currentDir = path9.basename(moduleDir) === "providers" ? moduleDir : path9.join(moduleDir, "providers");
5880
+ moduleDir = path10.dirname(fileURLToPath(import.meta.url));
5881
+ currentDir = path10.basename(moduleDir) === "providers" ? moduleDir : path10.join(moduleDir, "providers");
5757
5882
  defaultProviders = await loadProviders();
5758
5883
  }
5759
5884
  });
@@ -6095,21 +6220,21 @@ function createSdkContainer(options) {
6095
6220
  });
6096
6221
  loggerFactory.setErrorLogger(errorLogger);
6097
6222
  const asyncFs = {
6098
- readFile: ((path24, encoding) => {
6223
+ readFile: ((path27, encoding) => {
6099
6224
  if (encoding) {
6100
- return fs2.readFile(path24, encoding);
6225
+ return fs2.readFile(path27, encoding);
6101
6226
  }
6102
- return fs2.readFile(path24);
6227
+ return fs2.readFile(path27);
6103
6228
  }),
6104
- writeFile: (path24, data, opts) => fs2.writeFile(path24, data, opts),
6105
- mkdir: (path24, opts) => fs2.mkdir(path24, opts).then(() => {
6229
+ writeFile: (path27, data, opts) => fs2.writeFile(path27, data, opts),
6230
+ mkdir: (path27, opts) => fs2.mkdir(path27, opts).then(() => {
6106
6231
  }),
6107
- stat: (path24) => fs2.stat(path24),
6108
- rm: (path24, opts) => fs2.rm(path24, opts),
6109
- unlink: (path24) => fs2.unlink(path24),
6110
- readdir: (path24) => fs2.readdir(path24),
6232
+ stat: (path27) => fs2.stat(path27),
6233
+ rm: (path27, opts) => fs2.rm(path27, opts),
6234
+ unlink: (path27) => fs2.unlink(path27),
6235
+ readdir: (path27) => fs2.readdir(path27),
6111
6236
  copyFile: (src, dest) => fs2.copyFile(src, dest),
6112
- chmod: (path24, mode) => fs2.chmod(path24, mode)
6237
+ chmod: (path27, mode) => fs2.chmod(path27, mode)
6113
6238
  };
6114
6239
  const contextFactory = createCommandContextFactory({ fs: asyncFs });
6115
6240
  const authFs = {
@@ -6811,8 +6936,8 @@ function resourceNotFound(resource) {
6811
6936
  `Resource not found: ${resource}`
6812
6937
  );
6813
6938
  }
6814
- function assertAbsolutePath(path24) {
6815
- if (!isAbsolute(path24)) {
6939
+ function assertAbsolutePath(path27) {
6940
+ if (!isAbsolute(path27)) {
6816
6941
  throw invalidParams('"path" must be an absolute path');
6817
6942
  }
6818
6943
  }
@@ -7546,7 +7671,7 @@ var init_run_report = __esm({
7546
7671
  });
7547
7672
 
7548
7673
  // packages/poe-acp-client/src/index.ts
7549
- var init_src6 = __esm({
7674
+ var init_src7 = __esm({
7550
7675
  "packages/poe-acp-client/src/index.ts"() {
7551
7676
  "use strict";
7552
7677
  init_acp_client();
@@ -8573,7 +8698,7 @@ var init_acp_core = __esm({
8573
8698
  });
8574
8699
 
8575
8700
  // packages/poe-agent/src/plugins/plugin-args.ts
8576
- import path10 from "node:path";
8701
+ import path11 from "node:path";
8577
8702
  function isObjectRecord3(value) {
8578
8703
  return typeof value === "object" && value !== null && !Array.isArray(value);
8579
8704
  }
@@ -8604,13 +8729,13 @@ function getOptionalString(args, key) {
8604
8729
  return value;
8605
8730
  }
8606
8731
  function resolveAllowedPath(cwd, allowedPaths, inputPath) {
8607
- const resolvedPath = path10.resolve(cwd, inputPath);
8732
+ const resolvedPath = path11.resolve(cwd, inputPath);
8608
8733
  const isAllowed = allowedPaths.some((allowedPath) => {
8609
8734
  if (allowedPath === resolvedPath) {
8610
8735
  return true;
8611
8736
  }
8612
- const rel = path10.relative(allowedPath, resolvedPath);
8613
- return rel.length > 0 && !rel.startsWith("..") && !path10.isAbsolute(rel);
8737
+ const rel = path11.relative(allowedPath, resolvedPath);
8738
+ return rel.length > 0 && !rel.startsWith("..") && !path11.isAbsolute(rel);
8614
8739
  });
8615
8740
  if (!isAllowed) {
8616
8741
  throw new Error(`Path is outside allowed paths: ${inputPath}`);
@@ -8625,7 +8750,7 @@ var init_plugin_args = __esm({
8625
8750
 
8626
8751
  // packages/poe-agent/src/plugins/poe-agent-plugin-files.ts
8627
8752
  import fsPromises2 from "node:fs/promises";
8628
- import path11 from "node:path";
8753
+ import path12 from "node:path";
8629
8754
  async function fileExists(fs3, filePath) {
8630
8755
  try {
8631
8756
  await fs3.readFile(filePath, "utf8");
@@ -8649,9 +8774,9 @@ var init_poe_agent_plugin_files = __esm({
8649
8774
  "use strict";
8650
8775
  init_plugin_args();
8651
8776
  filesPlugin = (options = {}) => {
8652
- const cwd = path11.resolve(options.cwd ?? process.cwd());
8777
+ const cwd = path12.resolve(options.cwd ?? process.cwd());
8653
8778
  const allowedPaths = (options.allowedPaths ?? [cwd]).map(
8654
- (allowedPath) => path11.resolve(cwd, allowedPath)
8779
+ (allowedPath) => path12.resolve(cwd, allowedPath)
8655
8780
  );
8656
8781
  const fs3 = options.fs ?? fsPromises2;
8657
8782
  const readFileTool = {
@@ -8705,7 +8830,7 @@ var init_poe_agent_plugin_files = __esm({
8705
8830
  async call(args) {
8706
8831
  const command = getRequiredString(args, "command");
8707
8832
  const filePath = resolveAllowedPath(cwd, allowedPaths, getRequiredString(args, "path"));
8708
- const displayedPath = path11.relative(cwd, filePath) || path11.basename(filePath);
8833
+ const displayedPath = path12.relative(cwd, filePath) || path12.basename(filePath);
8709
8834
  if (command === "str_replace") {
8710
8835
  const oldStr = getRequiredString(args, "old_str", true);
8711
8836
  const newStr = getRequiredString(args, "new_str", true);
@@ -8725,7 +8850,7 @@ var init_poe_agent_plugin_files = __esm({
8725
8850
  if (await fileExists(fs3, filePath)) {
8726
8851
  throw new Error("File already exists \u2014 use str_replace to edit");
8727
8852
  }
8728
- await fs3.mkdir(path11.dirname(filePath), { recursive: true });
8853
+ await fs3.mkdir(path12.dirname(filePath), { recursive: true });
8729
8854
  await fs3.writeFile(filePath, fileText, "utf8");
8730
8855
  return `Created file: ${displayedPath}`;
8731
8856
  }
@@ -8766,7 +8891,7 @@ var init_poe_agent_plugin_files = __esm({
8766
8891
 
8767
8892
  // packages/poe-agent/src/plugins/poe-agent-plugin-shell.ts
8768
8893
  import { exec as execCallback } from "node:child_process";
8769
- import path12 from "node:path";
8894
+ import path13 from "node:path";
8770
8895
  import { promisify } from "node:util";
8771
8896
  async function defaultRunCommand(command, cwd) {
8772
8897
  try {
@@ -8799,9 +8924,9 @@ var init_poe_agent_plugin_shell = __esm({
8799
8924
  init_plugin_args();
8800
8925
  exec = promisify(execCallback);
8801
8926
  shellPlugin = (options = {}) => {
8802
- const cwd = path12.resolve(options.cwd ?? process.cwd());
8927
+ const cwd = path13.resolve(options.cwd ?? process.cwd());
8803
8928
  const allowedPaths = (options.allowedPaths ?? [cwd]).map(
8804
- (allowedPath) => path12.resolve(cwd, allowedPath)
8929
+ (allowedPath) => path13.resolve(cwd, allowedPath)
8805
8930
  );
8806
8931
  const runCommand2 = options.runCommand ?? defaultRunCommand;
8807
8932
  const runCommandTool = {
@@ -9585,7 +9710,7 @@ var AgentHost;
9585
9710
  var init_agent_host = __esm({
9586
9711
  "packages/poe-agent/src/runtime/agent-host.ts"() {
9587
9712
  "use strict";
9588
- init_src6();
9713
+ init_src7();
9589
9714
  init_agent_session();
9590
9715
  init_acp_core();
9591
9716
  init_run_context();
@@ -9945,7 +10070,7 @@ function readDependencies(plugin) {
9945
10070
  }
9946
10071
  return normalized;
9947
10072
  }
9948
- var init_config = __esm({
10073
+ var init_config2 = __esm({
9949
10074
  "packages/poe-agent/src/runtime/config.ts"() {
9950
10075
  "use strict";
9951
10076
  }
@@ -10872,7 +10997,7 @@ var init_internal = __esm({
10872
10997
  });
10873
10998
 
10874
10999
  // packages/tiny-mcp-client/src/index.ts
10875
- var init_src7 = __esm({
11000
+ var init_src8 = __esm({
10876
11001
  "packages/tiny-mcp-client/src/index.ts"() {
10877
11002
  "use strict";
10878
11003
  init_internal();
@@ -10921,7 +11046,7 @@ var DEFAULT_MCP_CLIENT_INFO, PluginApiImpl;
10921
11046
  var init_plugin_api_impl = __esm({
10922
11047
  "packages/poe-agent/src/runtime/plugin-api-impl.ts"() {
10923
11048
  "use strict";
10924
- init_src7();
11049
+ init_src8();
10925
11050
  init_hooks();
10926
11051
  DEFAULT_MCP_CLIENT_INFO = {
10927
11052
  name: "poe-agent",
@@ -11252,7 +11377,7 @@ var init_agent = __esm({
11252
11377
  init_acp_core();
11253
11378
  init_agent_host();
11254
11379
  init_hooks();
11255
- init_config();
11380
+ init_config2();
11256
11381
  init_plugin_setup();
11257
11382
  init_run_context();
11258
11383
  ImmutableAgentBuilder = class _ImmutableAgentBuilder {
@@ -11488,7 +11613,7 @@ __export(src_exports, {
11488
11613
  agent: () => agent,
11489
11614
  createAgentSession: () => createAgentSession
11490
11615
  });
11491
- var init_src8 = __esm({
11616
+ var init_src9 = __esm({
11492
11617
  "packages/poe-agent/src/index.ts"() {
11493
11618
  "use strict";
11494
11619
  init_agent();
@@ -11826,7 +11951,7 @@ function createInMemoryAcpTransport2(options) {
11826
11951
  }
11827
11952
  if (method === "session/new") {
11828
11953
  const request = params;
11829
- const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (init_src8(), src_exports));
11954
+ const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (init_src9(), src_exports));
11830
11955
  const session = await createAgentSession2({
11831
11956
  model: options.model,
11832
11957
  cwd: request.cwd || options.cwd,
@@ -11976,7 +12101,7 @@ var init_poe_agent = __esm({
11976
12101
  "src/providers/poe-agent.ts"() {
11977
12102
  "use strict";
11978
12103
  init_constants();
11979
- init_src6();
12104
+ init_src7();
11980
12105
  init_create_provider();
11981
12106
  poeAgentService = createProvider({
11982
12107
  id: "poe-agent",
@@ -12145,7 +12270,7 @@ var init_spawn3 = __esm({
12145
12270
  });
12146
12271
 
12147
12272
  // packages/pipeline/src/utils.ts
12148
- function isRecord2(value) {
12273
+ function isRecord3(value) {
12149
12274
  return typeof value === "object" && value !== null && !Array.isArray(value);
12150
12275
  }
12151
12276
  function isNotFound2(error2) {
@@ -12179,7 +12304,7 @@ var init_utils2 = __esm({
12179
12304
  });
12180
12305
 
12181
12306
  // packages/pipeline/src/config/loader.ts
12182
- import path13 from "node:path";
12307
+ import path14 from "node:path";
12183
12308
  import { parse as parse4 } from "yaml";
12184
12309
  function asStepMode(value) {
12185
12310
  if (value === void 0 || value === null) {
@@ -12203,19 +12328,19 @@ function parseStepConfigDocument(filePath, content) {
12203
12328
  if (document === null || document === void 0) {
12204
12329
  return {};
12205
12330
  }
12206
- if (!isRecord2(document)) {
12331
+ if (!isRecord3(document)) {
12207
12332
  throw new Error(`Invalid pipeline step config in "${filePath}": expected a top-level object.`);
12208
12333
  }
12209
12334
  const stepsValue = document.steps;
12210
12335
  if (stepsValue === void 0 || stepsValue === null) {
12211
12336
  return {};
12212
12337
  }
12213
- if (!isRecord2(stepsValue)) {
12338
+ if (!isRecord3(stepsValue)) {
12214
12339
  throw new Error(`Invalid pipeline step config in "${filePath}": "steps" must be an object.`);
12215
12340
  }
12216
12341
  const steps = {};
12217
12342
  for (const [stepName, value] of Object.entries(stepsValue)) {
12218
- if (!isRecord2(value)) {
12343
+ if (!isRecord3(value)) {
12219
12344
  throw new Error(`Invalid step "${stepName}" in "${filePath}": expected an object.`);
12220
12345
  }
12221
12346
  const instruction = value.instruction;
@@ -12237,7 +12362,7 @@ function parseConfigDocument(filePath, content) {
12237
12362
  if (document === null || document === void 0) {
12238
12363
  return {};
12239
12364
  }
12240
- if (!isRecord2(document)) {
12365
+ if (!isRecord3(document)) {
12241
12366
  throw new Error(`Invalid pipeline config in "${filePath}": expected a top-level object.`);
12242
12367
  }
12243
12368
  const planPath = document.planPath;
@@ -12263,8 +12388,8 @@ async function loadStepsFile(fs3, filePath) {
12263
12388
  return parseStepConfigDocument(filePath, content);
12264
12389
  }
12265
12390
  async function loadPipelineConfig(options) {
12266
- const globalPath = path13.join(options.homeDir, ".poe-code", "pipeline", "config.yaml");
12267
- const projectPath = path13.join(options.cwd, ".poe-code", "pipeline", "config.yaml");
12391
+ const globalPath = path14.join(options.homeDir, ".poe-code", "pipeline", "config.yaml");
12392
+ const projectPath = path14.join(options.cwd, ".poe-code", "pipeline", "config.yaml");
12268
12393
  const [globalConfig2, projectConfig] = await Promise.all([
12269
12394
  loadConfigFile(options.fs, globalPath),
12270
12395
  loadConfigFile(options.fs, projectPath)
@@ -12275,8 +12400,8 @@ async function loadPipelineConfig(options) {
12275
12400
  };
12276
12401
  }
12277
12402
  async function loadResolvedSteps(options) {
12278
- const globalPath = path13.join(options.homeDir, ".poe-code", "pipeline", "steps.yaml");
12279
- const projectPath = path13.join(options.cwd, ".poe-code", "pipeline", "steps.yaml");
12403
+ const globalPath = path14.join(options.homeDir, ".poe-code", "pipeline", "steps.yaml");
12404
+ const projectPath = path14.join(options.cwd, ".poe-code", "pipeline", "steps.yaml");
12280
12405
  const [globalSteps, projectSteps] = await Promise.all([
12281
12406
  loadStepsFile(options.fs, globalPath),
12282
12407
  loadStepsFile(options.fs, projectPath)
@@ -12315,7 +12440,7 @@ function parseTaskStatus(value, availableSteps, taskId) {
12315
12440
  if (typeof value === "string") {
12316
12441
  return normalizeStatus(value, "task status");
12317
12442
  }
12318
- if (!isRecord2(value)) {
12443
+ if (!isRecord3(value)) {
12319
12444
  throw new Error(`Invalid status for task "${taskId}": expected a string or step-status map.`);
12320
12445
  }
12321
12446
  const statusMap = {};
@@ -12335,7 +12460,7 @@ function parsePlan(yamlContent, options = {}) {
12335
12460
  const message = error2 instanceof Error ? error2.message : String(error2);
12336
12461
  throw new Error(`Invalid plan YAML: ${message}`);
12337
12462
  }
12338
- if (!isRecord2(document)) {
12463
+ if (!isRecord3(document)) {
12339
12464
  throw new Error("Invalid plan YAML: expected a top-level object.");
12340
12465
  }
12341
12466
  const tasksValue = document.tasks;
@@ -12344,7 +12469,7 @@ function parsePlan(yamlContent, options = {}) {
12344
12469
  }
12345
12470
  const ids = /* @__PURE__ */ new Set();
12346
12471
  const tasks = tasksValue.map((value, index) => {
12347
- if (!isRecord2(value)) {
12472
+ if (!isRecord3(value)) {
12348
12473
  throw new Error(`Invalid tasks[${index}]: expected an object.`);
12349
12474
  }
12350
12475
  const id = asRequiredString(value.id, `tasks[${index}].id`);
@@ -12369,18 +12494,18 @@ var init_parser = __esm({
12369
12494
  });
12370
12495
 
12371
12496
  // packages/pipeline/src/plan/discovery.ts
12372
- import path14 from "node:path";
12497
+ import path15 from "node:path";
12373
12498
  import * as fsPromises3 from "node:fs/promises";
12374
12499
  function createDefaultFs() {
12375
12500
  return {
12376
12501
  readFile: fsPromises3.readFile,
12377
12502
  readdir: fsPromises3.readdir,
12378
12503
  stat: async (filePath) => {
12379
- const stat6 = await fsPromises3.stat(filePath);
12504
+ const stat8 = await fsPromises3.stat(filePath);
12380
12505
  return {
12381
- isFile: () => stat6.isFile(),
12382
- isDirectory: () => stat6.isDirectory(),
12383
- mtimeMs: stat6.mtimeMs
12506
+ isFile: () => stat8.isFile(),
12507
+ isDirectory: () => stat8.isDirectory(),
12508
+ mtimeMs: stat8.mtimeMs
12384
12509
  };
12385
12510
  }
12386
12511
  };
@@ -12405,10 +12530,10 @@ function countCompletedTasks(planPath, content) {
12405
12530
  };
12406
12531
  }
12407
12532
  async function ensurePlanExists(fs3, cwd, planPath) {
12408
- const absolutePath = path14.isAbsolute(planPath) ? planPath : path14.resolve(cwd, planPath);
12533
+ const absolutePath = path15.isAbsolute(planPath) ? planPath : path15.resolve(cwd, planPath);
12409
12534
  try {
12410
- const stat6 = await fs3.stat(absolutePath);
12411
- if (!stat6.isFile()) {
12535
+ const stat8 = await fs3.stat(absolutePath);
12536
+ if (!stat8.isFile()) {
12412
12537
  throw new Error(`Plan not found at "${planPath}".`);
12413
12538
  }
12414
12539
  } catch (error2) {
@@ -12433,20 +12558,20 @@ async function scanPlansDir(fs3, plansDir, displayPrefix) {
12433
12558
  if (!isPlanCandidateFile(entry)) {
12434
12559
  continue;
12435
12560
  }
12436
- const absolutePath = path14.join(plansDir, entry);
12437
- const stat6 = await fs3.stat(absolutePath);
12438
- if (!stat6.isFile()) {
12561
+ const absolutePath = path15.join(plansDir, entry);
12562
+ const stat8 = await fs3.stat(absolutePath);
12563
+ if (!stat8.isFile()) {
12439
12564
  continue;
12440
12565
  }
12441
- const displayPath = path14.join(displayPrefix, entry);
12566
+ const displayPath = path15.join(displayPrefix, entry);
12442
12567
  const content = await fs3.readFile(absolutePath, "utf8");
12443
12568
  candidates.push(countCompletedTasks(displayPath, content));
12444
12569
  }
12445
12570
  return candidates;
12446
12571
  }
12447
12572
  async function listPlanCandidates(fs3, cwd, homeDir) {
12448
- const projectDir = path14.join(cwd, ".poe-code", "pipeline", "plans");
12449
- const globalDir = path14.join(homeDir, ".poe-code", "pipeline", "plans");
12573
+ const projectDir = path15.join(cwd, ".poe-code", "pipeline", "plans");
12574
+ const globalDir = path15.join(homeDir, ".poe-code", "pipeline", "plans");
12450
12575
  const [projectCandidates, globalCandidates] = await Promise.all([
12451
12576
  scanPlansDir(fs3, projectDir, ".poe-code/pipeline/plans"),
12452
12577
  scanPlansDir(fs3, globalDir, "~/.poe-code/pipeline/plans")
@@ -12457,9 +12582,9 @@ async function listPlanCandidates(fs3, cwd, homeDir) {
12457
12582
  }
12458
12583
  function resolveAbsolutePlanPath(planPath, cwd, homeDir) {
12459
12584
  if (planPath.startsWith("~/")) {
12460
- return path14.join(homeDir, planPath.slice(2));
12585
+ return path15.join(homeDir, planPath.slice(2));
12461
12586
  }
12462
- return path14.isAbsolute(planPath) ? planPath : path14.resolve(cwd, planPath);
12587
+ return path15.isAbsolute(planPath) ? planPath : path15.resolve(cwd, planPath);
12463
12588
  }
12464
12589
  async function resolvePlanPath(options) {
12465
12590
  const fs3 = options.fs ?? createDefaultFs();
@@ -12516,7 +12641,7 @@ var init_discovery = __esm({
12516
12641
  });
12517
12642
 
12518
12643
  // packages/pipeline/src/plan/writer.ts
12519
- import { parseDocument, isMap, isSeq } from "yaml";
12644
+ import { parseDocument as parseDocument2, isMap, isSeq } from "yaml";
12520
12645
  function getTasksNode(document) {
12521
12646
  const tasksNode = document.get("tasks", true);
12522
12647
  if (!tasksNode || !isSeq(tasksNode)) {
@@ -12540,7 +12665,7 @@ async function readPlanFile(fs3, planPath) {
12540
12665
  }
12541
12666
  async function writeTaskStatus(options) {
12542
12667
  const content = await readPlanFile(options.fs, options.planPath);
12543
- const document = parseDocument(content);
12668
+ const document = parseDocument2(content);
12544
12669
  const tasksNode = getTasksNode(document);
12545
12670
  const taskNode = getTaskNode(tasksNode, options.taskId);
12546
12671
  if (options.stepName) {
@@ -12646,11 +12771,11 @@ function createDefaultFs2() {
12646
12771
  },
12647
12772
  rmdir: fsPromises4.rmdir,
12648
12773
  stat: async (filePath) => {
12649
- const stat6 = await fsPromises4.stat(filePath);
12774
+ const stat8 = await fsPromises4.stat(filePath);
12650
12775
  return {
12651
- isFile: () => stat6.isFile(),
12652
- isDirectory: () => stat6.isDirectory(),
12653
- mtimeMs: stat6.mtimeMs
12776
+ isFile: () => stat8.isFile(),
12777
+ isDirectory: () => stat8.isDirectory(),
12778
+ mtimeMs: stat8.mtimeMs
12654
12779
  };
12655
12780
  }
12656
12781
  };
@@ -12683,8 +12808,8 @@ async function lockFile(filePath, options = {}) {
12683
12808
  if (!error2 || typeof error2 !== "object" || !("code" in error2) || error2.code !== "EEXIST") {
12684
12809
  throw error2;
12685
12810
  }
12686
- const stat6 = await fs3.stat(lockPath);
12687
- if (Date.now() - stat6.mtimeMs > staleMs) {
12811
+ const stat8 = await fs3.stat(lockPath);
12812
+ if (Date.now() - stat8.mtimeMs > staleMs) {
12688
12813
  await fs3.rmdir(lockPath);
12689
12814
  continue;
12690
12815
  }
@@ -12702,7 +12827,7 @@ var init_lock = __esm({
12702
12827
  });
12703
12828
 
12704
12829
  // packages/pipeline/src/run/pipeline.ts
12705
- import path15 from "node:path";
12830
+ import path16 from "node:path";
12706
12831
  import * as fsPromises5 from "node:fs/promises";
12707
12832
  function createDefaultFs3() {
12708
12833
  return {
@@ -12710,11 +12835,11 @@ function createDefaultFs3() {
12710
12835
  writeFile: fsPromises5.writeFile,
12711
12836
  readdir: fsPromises5.readdir,
12712
12837
  stat: async (filePath) => {
12713
- const stat6 = await fsPromises5.stat(filePath);
12838
+ const stat8 = await fsPromises5.stat(filePath);
12714
12839
  return {
12715
- isFile: () => stat6.isFile(),
12716
- isDirectory: () => stat6.isDirectory(),
12717
- mtimeMs: stat6.mtimeMs
12840
+ isFile: () => stat8.isFile(),
12841
+ isDirectory: () => stat8.isDirectory(),
12842
+ mtimeMs: stat8.mtimeMs
12718
12843
  };
12719
12844
  },
12720
12845
  mkdir: async (filePath, options) => {
@@ -12738,9 +12863,9 @@ function resolveMode(stepName, steps) {
12738
12863
  return step.mode;
12739
12864
  }
12740
12865
  async function archivePlan(fs3, absolutePlanPath) {
12741
- const dir = path15.dirname(absolutePlanPath);
12742
- const archiveDir = path15.join(dir, "archive");
12743
- const archivePath = path15.join(archiveDir, path15.basename(absolutePlanPath));
12866
+ const dir = path16.dirname(absolutePlanPath);
12867
+ const archiveDir = path16.join(dir, "archive");
12868
+ const archivePath = path16.join(archiveDir, path16.basename(absolutePlanPath));
12744
12869
  await fs3.mkdir(archiveDir, { recursive: true });
12745
12870
  await fs3.rename(absolutePlanPath, archivePath);
12746
12871
  }
@@ -12975,7 +13100,7 @@ var init_pipeline = __esm({
12975
13100
  });
12976
13101
 
12977
13102
  // packages/pipeline/src/index.ts
12978
- var init_src9 = __esm({
13103
+ var init_src10 = __esm({
12979
13104
  "packages/pipeline/src/index.ts"() {
12980
13105
  "use strict";
12981
13106
  init_loader();
@@ -13007,7 +13132,286 @@ async function runPipeline2(options) {
13007
13132
  var init_pipeline2 = __esm({
13008
13133
  async "src/sdk/pipeline.ts"() {
13009
13134
  "use strict";
13010
- init_src9();
13135
+ init_src10();
13136
+ init_src5();
13137
+ await init_spawn3();
13138
+ }
13139
+ });
13140
+
13141
+ // packages/ralph/src/discovery/discovery.ts
13142
+ import path17 from "node:path";
13143
+ import * as fsPromises6 from "node:fs/promises";
13144
+ function createDefaultFs4() {
13145
+ return {
13146
+ readFile: fsPromises6.readFile,
13147
+ readdir: fsPromises6.readdir,
13148
+ stat: async (filePath) => {
13149
+ const stat8 = await fsPromises6.stat(filePath);
13150
+ return {
13151
+ isFile: () => stat8.isFile(),
13152
+ mtimeMs: stat8.mtimeMs
13153
+ };
13154
+ }
13155
+ };
13156
+ }
13157
+ function isNotFound3(error2) {
13158
+ return !!error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT";
13159
+ }
13160
+ function isMarkdownFile(entry) {
13161
+ return entry.toLowerCase().endsWith(".md");
13162
+ }
13163
+ async function scanDir(fs3, absoluteDir, displayDir) {
13164
+ let entries;
13165
+ try {
13166
+ entries = await fs3.readdir(absoluteDir);
13167
+ } catch (error2) {
13168
+ if (isNotFound3(error2)) {
13169
+ return [];
13170
+ }
13171
+ throw error2;
13172
+ }
13173
+ const docs = [];
13174
+ for (const entry of entries) {
13175
+ if (!isMarkdownFile(entry)) {
13176
+ continue;
13177
+ }
13178
+ const absolutePath = path17.join(absoluteDir, entry);
13179
+ const stat8 = await fs3.stat(absolutePath);
13180
+ if (!stat8.isFile()) {
13181
+ continue;
13182
+ }
13183
+ const displayPath = path17.join(displayDir, entry);
13184
+ docs.push({
13185
+ path: displayPath,
13186
+ displayPath
13187
+ });
13188
+ }
13189
+ return docs;
13190
+ }
13191
+ async function discoverDocs(options) {
13192
+ const fs3 = options.fs ?? createDefaultFs4();
13193
+ const [localDocs, globalDocs] = await Promise.all([
13194
+ scanDir(
13195
+ fs3,
13196
+ path17.join(options.cwd, ".poe-code", "ralph", "plans"),
13197
+ ".poe-code/ralph/plans"
13198
+ ),
13199
+ scanDir(
13200
+ fs3,
13201
+ path17.join(options.homeDir, ".poe-code", "ralph", "plans"),
13202
+ "~/.poe-code/ralph/plans"
13203
+ )
13204
+ ]);
13205
+ return [...localDocs, ...globalDocs].sort((left, right) => {
13206
+ const leftName = path17.basename(left.displayPath).toLowerCase();
13207
+ const rightName = path17.basename(right.displayPath).toLowerCase();
13208
+ return leftName === rightName ? left.displayPath.localeCompare(right.displayPath) : leftName.localeCompare(rightName);
13209
+ });
13210
+ }
13211
+ var init_discovery2 = __esm({
13212
+ "packages/ralph/src/discovery/discovery.ts"() {
13213
+ "use strict";
13214
+ }
13215
+ });
13216
+
13217
+ // packages/ralph/src/overbaking/detector.ts
13218
+ var OverbakingDetector;
13219
+ var init_detector = __esm({
13220
+ "packages/ralph/src/overbaking/detector.ts"() {
13221
+ "use strict";
13222
+ OverbakingDetector = class {
13223
+ threshold;
13224
+ consecutiveFailures = 0;
13225
+ constructor(threshold) {
13226
+ this.threshold = threshold;
13227
+ }
13228
+ record(_success) {
13229
+ if (_success) {
13230
+ this.consecutiveFailures = 0;
13231
+ return {
13232
+ consecutiveFailures: 0,
13233
+ overbaked: false,
13234
+ shouldWarn: false
13235
+ };
13236
+ }
13237
+ this.consecutiveFailures += 1;
13238
+ return {
13239
+ consecutiveFailures: this.consecutiveFailures,
13240
+ overbaked: this.consecutiveFailures >= this.threshold,
13241
+ shouldWarn: this.consecutiveFailures === this.threshold
13242
+ };
13243
+ }
13244
+ };
13245
+ }
13246
+ });
13247
+
13248
+ // packages/ralph/src/run/ralph.ts
13249
+ import path18 from "node:path";
13250
+ import * as fsPromises7 from "node:fs/promises";
13251
+ async function runRalph(options) {
13252
+ const fs3 = options.fs ?? createDefaultFs5();
13253
+ const runAgent = options.runAgent;
13254
+ if (!runAgent) {
13255
+ throw new Error("runRalph requires a runAgent implementation.");
13256
+ }
13257
+ if (!Number.isInteger(options.maxIterations) || options.maxIterations < 1) {
13258
+ throw new Error("maxIterations must be a positive integer.");
13259
+ }
13260
+ const threshold = options.maxFailures ?? 3;
13261
+ if (!Number.isInteger(threshold) || threshold < 1) {
13262
+ throw new Error("maxFailures must be a positive integer.");
13263
+ }
13264
+ const absoluteDocPath = resolveAbsoluteDocPath(
13265
+ options.docPath,
13266
+ options.cwd,
13267
+ options.homeDir
13268
+ );
13269
+ const prompt = await fs3.readFile(absoluteDocPath, "utf8");
13270
+ const detector = new OverbakingDetector(threshold);
13271
+ const startTime = Date.now();
13272
+ let iterationsCompleted = 0;
13273
+ try {
13274
+ for (let iteration = 1; iteration <= options.maxIterations; iteration += 1) {
13275
+ assertNotAborted5(options.signal);
13276
+ options.onIterationStart?.(iteration, options.maxIterations);
13277
+ const iterationStart = Date.now();
13278
+ let result;
13279
+ try {
13280
+ result = await runAgent({
13281
+ agent: options.agent,
13282
+ prompt,
13283
+ cwd: options.cwd,
13284
+ ...options.model ? { model: options.model } : {},
13285
+ ...options.signal ? { signal: options.signal } : {}
13286
+ });
13287
+ } catch (error2) {
13288
+ if (isAbortError2(error2)) {
13289
+ return {
13290
+ stopReason: "cancelled",
13291
+ docPath: options.docPath,
13292
+ iterationsCompleted,
13293
+ totalDurationMs: Date.now() - startTime
13294
+ };
13295
+ }
13296
+ throw error2;
13297
+ }
13298
+ const success2 = result.exitCode === 0;
13299
+ iterationsCompleted += 1;
13300
+ options.onIterationComplete?.(
13301
+ iteration,
13302
+ Date.now() - iterationStart,
13303
+ success2
13304
+ );
13305
+ const overbake = detector.record(success2);
13306
+ if (!overbake.shouldWarn) {
13307
+ continue;
13308
+ }
13309
+ options.onOverbakeWarning?.(
13310
+ overbake.consecutiveFailures,
13311
+ threshold
13312
+ );
13313
+ const action = options.promptOverbake ? await options.promptOverbake({
13314
+ consecutiveFailures: overbake.consecutiveFailures,
13315
+ threshold
13316
+ }) : "abort";
13317
+ if (action === "abort") {
13318
+ return {
13319
+ stopReason: "overbake_abort",
13320
+ docPath: options.docPath,
13321
+ iterationsCompleted,
13322
+ totalDurationMs: Date.now() - startTime
13323
+ };
13324
+ }
13325
+ }
13326
+ } catch (error2) {
13327
+ if (isAbortError2(error2)) {
13328
+ return {
13329
+ stopReason: "cancelled",
13330
+ docPath: options.docPath,
13331
+ iterationsCompleted,
13332
+ totalDurationMs: Date.now() - startTime
13333
+ };
13334
+ }
13335
+ throw error2;
13336
+ }
13337
+ return {
13338
+ stopReason: "max_iterations",
13339
+ docPath: options.docPath,
13340
+ iterationsCompleted,
13341
+ totalDurationMs: Date.now() - startTime
13342
+ };
13343
+ }
13344
+ function createDefaultFs5() {
13345
+ return {
13346
+ readFile: fsPromises7.readFile,
13347
+ readdir: fsPromises7.readdir,
13348
+ stat: async (filePath) => {
13349
+ const stat8 = await fsPromises7.stat(filePath);
13350
+ return {
13351
+ isFile: () => stat8.isFile(),
13352
+ mtimeMs: stat8.mtimeMs
13353
+ };
13354
+ }
13355
+ };
13356
+ }
13357
+ function resolveAbsoluteDocPath(docPath, cwd, homeDir) {
13358
+ if (docPath.startsWith("~/")) {
13359
+ return path18.join(homeDir, docPath.slice(2));
13360
+ }
13361
+ return path18.isAbsolute(docPath) ? docPath : path18.resolve(cwd, docPath);
13362
+ }
13363
+ function assertNotAborted5(signal) {
13364
+ if (!signal?.aborted) {
13365
+ return;
13366
+ }
13367
+ throw createAbortError4();
13368
+ }
13369
+ function createAbortError4() {
13370
+ const error2 = new Error("Ralph run cancelled");
13371
+ error2.name = "AbortError";
13372
+ return error2;
13373
+ }
13374
+ function isAbortError2(error2) {
13375
+ return error2 instanceof Error && error2.name === "AbortError";
13376
+ }
13377
+ var init_ralph = __esm({
13378
+ "packages/ralph/src/run/ralph.ts"() {
13379
+ "use strict";
13380
+ init_detector();
13381
+ }
13382
+ });
13383
+
13384
+ // packages/ralph/src/index.ts
13385
+ var init_src11 = __esm({
13386
+ "packages/ralph/src/index.ts"() {
13387
+ "use strict";
13388
+ init_discovery2();
13389
+ init_detector();
13390
+ init_ralph();
13391
+ }
13392
+ });
13393
+
13394
+ // src/sdk/ralph.ts
13395
+ async function runRalph2(options) {
13396
+ return runRalph({
13397
+ ...options,
13398
+ runAgent: async (input) => {
13399
+ const { events, result } = spawn5(input.agent, {
13400
+ prompt: input.prompt,
13401
+ cwd: input.cwd,
13402
+ model: input.model,
13403
+ mode: "yolo",
13404
+ ...input.signal ? { signal: input.signal } : {}
13405
+ });
13406
+ await renderAcpStream(events);
13407
+ return result;
13408
+ }
13409
+ });
13410
+ }
13411
+ var init_ralph2 = __esm({
13412
+ async "src/sdk/ralph.ts"() {
13413
+ "use strict";
13414
+ init_src11();
13011
13415
  init_src5();
13012
13416
  await init_spawn3();
13013
13417
  }
@@ -13077,13 +13481,13 @@ async function readErrorBody(response) {
13077
13481
  }
13078
13482
  }
13079
13483
  function extractTextContent(data) {
13080
- if (!isRecord3(data)) return void 0;
13484
+ if (!isRecord4(data)) return void 0;
13081
13485
  const choices = data.choices;
13082
13486
  if (!Array.isArray(choices) || choices.length === 0) return void 0;
13083
13487
  const first = choices[0];
13084
- if (!isRecord3(first)) return void 0;
13488
+ if (!isRecord4(first)) return void 0;
13085
13489
  const message = first.message;
13086
- if (!isRecord3(message)) return void 0;
13490
+ if (!isRecord4(message)) return void 0;
13087
13491
  return typeof message.content === "string" ? message.content : void 0;
13088
13492
  }
13089
13493
  function extractMediaFromCompletion(data) {
@@ -13091,14 +13495,14 @@ function extractMediaFromCompletion(data) {
13091
13495
  if (!content) return {};
13092
13496
  try {
13093
13497
  const parsed = JSON.parse(content);
13094
- if (isRecord3(parsed) && typeof parsed.url === "string") {
13498
+ if (isRecord4(parsed) && typeof parsed.url === "string") {
13095
13499
  return {
13096
13500
  url: parsed.url,
13097
13501
  mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0,
13098
13502
  data: typeof parsed.data === "string" ? parsed.data : void 0
13099
13503
  };
13100
13504
  }
13101
- if (isRecord3(parsed) && typeof parsed.data === "string") {
13505
+ if (isRecord4(parsed) && typeof parsed.data === "string") {
13102
13506
  return {
13103
13507
  data: parsed.data,
13104
13508
  mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0
@@ -13132,7 +13536,7 @@ function isValidUrl(value) {
13132
13536
  return false;
13133
13537
  }
13134
13538
  }
13135
- function isRecord3(value) {
13539
+ function isRecord4(value) {
13136
13540
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
13137
13541
  }
13138
13542
  var init_llm_client = __esm({
@@ -13202,13 +13606,15 @@ function generateCodeChallenge(verifier) {
13202
13606
  return crypto.createHash("sha256").update(verifier).digest("base64url");
13203
13607
  }
13204
13608
  async function startAuthorization(config2, fetchFn) {
13609
+ const authorizationEndpoint = config2.authorizationEndpoint ?? DEFAULT_AUTHORIZATION_ENDPOINT;
13610
+ const tokenEndpoint = config2.tokenEndpoint ?? DEFAULT_TOKEN_ENDPOINT;
13205
13611
  const codeVerifier = generateCodeVerifier();
13206
13612
  const codeChallenge = generateCodeChallenge(codeVerifier);
13207
13613
  const server = config2.createServer ? config2.createServer() : http.createServer();
13208
13614
  const port = await startServer(server);
13209
13615
  const redirectUri = `http://127.0.0.1:${port}/callback`;
13210
13616
  const authorizationUrl = buildAuthorizationUrl({
13211
- endpoint: config2.authorizationEndpoint,
13617
+ endpoint: authorizationEndpoint,
13212
13618
  clientId: config2.clientId,
13213
13619
  redirectUri,
13214
13620
  codeChallenge
@@ -13217,7 +13623,7 @@ async function startAuthorization(config2, fetchFn) {
13217
13623
  try {
13218
13624
  const code = await waitForAuthorizationCode(server, config2, authorizationUrl);
13219
13625
  return await exchangeCodeForApiKey({
13220
- tokenEndpoint: config2.tokenEndpoint,
13626
+ tokenEndpoint,
13221
13627
  code,
13222
13628
  codeVerifier,
13223
13629
  clientId: config2.clientId,
@@ -13363,14 +13769,17 @@ function buildSuccessPage() {
13363
13769
  "</div></body></html>"
13364
13770
  ].join("");
13365
13771
  }
13772
+ var DEFAULT_AUTHORIZATION_ENDPOINT, DEFAULT_TOKEN_ENDPOINT;
13366
13773
  var init_oauth_client = __esm({
13367
13774
  "packages/poe-oauth/src/oauth-client.ts"() {
13368
13775
  "use strict";
13776
+ DEFAULT_AUTHORIZATION_ENDPOINT = "https://poe.com/oauth/authorize";
13777
+ DEFAULT_TOKEN_ENDPOINT = "https://api.poe.com/token";
13369
13778
  }
13370
13779
  });
13371
13780
 
13372
13781
  // packages/poe-oauth/src/index.ts
13373
- var init_src10 = __esm({
13782
+ var init_src12 = __esm({
13374
13783
  "packages/poe-oauth/src/index.ts"() {
13375
13784
  "use strict";
13376
13785
  init_check_auth();
@@ -13389,8 +13798,6 @@ async function resolveApiKeyViaOAuth() {
13389
13798
  try {
13390
13799
  const client = createOAuthClient({
13391
13800
  clientId: "client_f520ee4d8ca84a13ba876a8731d264d0",
13392
- authorizationEndpoint: "https://poe.com/oauth/authorize",
13393
- tokenEndpoint: "https://api.poe.com/token",
13394
13801
  openBrowser: (url2) => openInBrowser(url2).catch(() => {
13395
13802
  log2.warn("Could not open browser automatically.");
13396
13803
  }),
@@ -13423,7 +13830,7 @@ function openInBrowser(url2) {
13423
13830
  var init_oauth_login = __esm({
13424
13831
  "src/cli/oauth-login.ts"() {
13425
13832
  "use strict";
13426
- init_src10();
13833
+ init_src12();
13427
13834
  init_src4();
13428
13835
  }
13429
13836
  });
@@ -13554,7 +13961,7 @@ var init_container2 = __esm({
13554
13961
  });
13555
13962
 
13556
13963
  // src/services/config.ts
13557
- import path17 from "node:path";
13964
+ import path20 from "node:path";
13558
13965
  async function deleteConfig(options) {
13559
13966
  const { fs: fs3, filePath } = options;
13560
13967
  try {
@@ -13569,31 +13976,32 @@ async function deleteConfig(options) {
13569
13976
  }
13570
13977
  async function loadConfiguredServices(options) {
13571
13978
  const { fs: fs3, filePath } = options;
13572
- const document = await readConfigDocument(fs3, filePath);
13573
- return { ...document.configured_services ?? {} };
13979
+ await migrateLegacyCredentialsIfNeeded(fs3, filePath);
13980
+ const document = await readDocument(fs3, filePath);
13981
+ return normalizeConfiguredServices(document[configuredServicesScope]);
13574
13982
  }
13575
13983
  async function saveConfiguredService(options) {
13576
13984
  const { fs: fs3, filePath, service, metadata } = options;
13577
- const document = await readConfigDocument(fs3, filePath);
13578
- const normalized = normalizeConfiguredServiceMetadata(metadata);
13579
- document.configured_services = {
13580
- ...document.configured_services ?? {},
13581
- [service]: normalized
13582
- };
13583
- await writeConfigDocument(fs3, filePath, document);
13985
+ await migrateLegacyConfigIfNeeded(fs3, filePath);
13986
+ const document = await readDocument(fs3, filePath);
13987
+ const services = normalizeConfiguredServices(
13988
+ document[configuredServicesScope]
13989
+ );
13990
+ services[service] = normalizeConfiguredServiceMetadata(metadata);
13991
+ await writeScope(fs3, filePath, configuredServicesScope, services);
13584
13992
  }
13585
13993
  async function unconfigureService(options) {
13586
13994
  const { fs: fs3, filePath, service } = options;
13587
- const document = await readConfigDocument(fs3, filePath);
13588
- const services = document.configured_services;
13589
- if (!services || !(service in services)) {
13995
+ await migrateLegacyConfigIfNeeded(fs3, filePath);
13996
+ const document = await readDocument(fs3, filePath);
13997
+ const services = normalizeConfiguredServices(
13998
+ document[configuredServicesScope]
13999
+ );
14000
+ if (!(service in services)) {
13590
14001
  return false;
13591
14002
  }
13592
14003
  delete services[service];
13593
- if (Object.keys(services).length === 0) {
13594
- delete document.configured_services;
13595
- }
13596
- await writeConfigDocument(fs3, filePath, document);
14004
+ await writeScope(fs3, filePath, configuredServicesScope, services);
13597
14005
  return true;
13598
14006
  }
13599
14007
  function normalizeConfiguredServiceMetadata(metadata) {
@@ -13608,47 +14016,78 @@ function normalizeConfiguredServiceMetadata(metadata) {
13608
14016
  seen.add(entry);
13609
14017
  }
13610
14018
  }
13611
- return {
13612
- files
13613
- };
14019
+ return { files };
13614
14020
  }
13615
- async function readConfigDocument(fs3, filePath) {
13616
- try {
13617
- const raw = await fs3.readFile(filePath, "utf8");
13618
- return await parseConfigDocument2(fs3, filePath, raw);
13619
- } catch (error2) {
13620
- if (isNotFound(error2)) {
13621
- return migrateLegacyCredentialsFile(fs3, filePath);
13622
- }
13623
- throw error2;
14021
+ async function migrateLegacyConfigIfNeeded(fs3, filePath) {
14022
+ await migrateLegacyCredentialsIfNeeded(fs3, filePath);
14023
+ const currentRaw = await readFileIfExists(fs3, filePath);
14024
+ if (currentRaw === null) {
14025
+ return;
14026
+ }
14027
+ const legacyDocument = normalizeLegacyConfigDocument(
14028
+ parseLegacyConfigDocument(currentRaw)
14029
+ );
14030
+ if (!legacyDocument.apiKey) {
14031
+ return;
13624
14032
  }
14033
+ const document = await readDocument(fs3, filePath);
14034
+ const existingCore = document[CORE_SCOPE] ?? {};
14035
+ if (typeof existingCore.apiKey === "string" && existingCore.apiKey.length > 0) {
14036
+ return;
14037
+ }
14038
+ await writeScope(fs3, filePath, CORE_SCOPE, {
14039
+ ...existingCore,
14040
+ apiKey: legacyDocument.apiKey
14041
+ });
13625
14042
  }
13626
- async function migrateLegacyCredentialsFile(fs3, configPath) {
13627
- const legacyPath = path17.join(path17.dirname(configPath), "credentials.json");
13628
- try {
13629
- const raw = await fs3.readFile(legacyPath, "utf8");
13630
- const document = await parseConfigDocument2(fs3, legacyPath, raw);
13631
- await writeConfigDocument(fs3, configPath, document);
13632
- await fs3.unlink(legacyPath);
13633
- return document;
13634
- } catch {
13635
- return {};
14043
+ async function migrateLegacyCredentialsIfNeeded(fs3, filePath) {
14044
+ const currentRaw = await readFileIfExists(fs3, filePath);
14045
+ if (currentRaw !== null) {
14046
+ return;
13636
14047
  }
14048
+ await migrateLegacyCredentialsFile(fs3, filePath);
13637
14049
  }
13638
- async function parseConfigDocument2(fs3, filePath, raw) {
14050
+ async function migrateLegacyCredentialsFile(fs3, configPath) {
14051
+ const legacyPath = path20.join(path20.dirname(configPath), "credentials.json");
14052
+ const raw = await readFileIfExists(fs3, legacyPath);
14053
+ if (raw === null) {
14054
+ return;
14055
+ }
14056
+ let legacyDocument;
13639
14057
  try {
13640
- const parsed = JSON.parse(raw);
13641
- return normalizeConfigDocument(parsed);
14058
+ legacyDocument = normalizeLegacyConfigDocument(JSON.parse(raw));
13642
14059
  } catch (error2) {
13643
14060
  if (error2 instanceof SyntaxError) {
13644
- await recoverInvalidConfig(fs3, filePath, raw);
13645
- return {};
14061
+ await recoverInvalidConfig(fs3, legacyPath, raw);
14062
+ await fs3.unlink(legacyPath);
14063
+ return;
13646
14064
  }
13647
14065
  throw error2;
13648
14066
  }
14067
+ if (legacyDocument.configured_services) {
14068
+ await writeScope(
14069
+ fs3,
14070
+ configPath,
14071
+ configuredServicesScope,
14072
+ legacyDocument.configured_services
14073
+ );
14074
+ }
14075
+ if (legacyDocument.apiKey) {
14076
+ await writeScope(fs3, configPath, CORE_SCOPE, {
14077
+ apiKey: legacyDocument.apiKey
14078
+ });
14079
+ }
14080
+ await fs3.unlink(legacyPath);
14081
+ }
14082
+ function parseLegacyConfigDocument(raw) {
14083
+ try {
14084
+ return JSON.parse(raw);
14085
+ } catch {
14086
+ return null;
14087
+ }
13649
14088
  }
13650
- function normalizeConfigDocument(value) {
13651
- if (!isRecord4(value)) {
14089
+ function normalizeLegacyConfigDocument(value) {
14090
+ if (!isRecord5(value)) {
13652
14091
  return {};
13653
14092
  }
13654
14093
  const document = {};
@@ -13662,55 +14101,42 @@ function normalizeConfigDocument(value) {
13662
14101
  return document;
13663
14102
  }
13664
14103
  function normalizeConfiguredServices(value) {
13665
- if (!isRecord4(value)) {
14104
+ if (!isRecord5(value)) {
13666
14105
  return {};
13667
14106
  }
13668
14107
  const entries = {};
13669
14108
  for (const [key, entry] of Object.entries(value)) {
13670
- if (!isRecord4(entry)) {
14109
+ if (!isRecord5(entry)) {
13671
14110
  continue;
13672
14111
  }
13673
- const normalized = normalizeConfiguredServiceMetadata({
14112
+ entries[key] = normalizeConfiguredServiceMetadata({
13674
14113
  files: Array.isArray(entry.files) ? entry.files : []
13675
14114
  });
13676
- entries[key] = normalized;
13677
14115
  }
13678
14116
  return entries;
13679
14117
  }
13680
- async function writeConfigDocument(fs3, filePath, document) {
13681
- await fs3.mkdir(path17.dirname(filePath), { recursive: true });
13682
- const payload = {};
13683
- if (document.apiKey) {
13684
- payload.apiKey = document.apiKey;
13685
- }
13686
- if (document.configured_services) {
13687
- payload.configured_services = document.configured_services;
13688
- }
13689
- await fs3.writeFile(filePath, `${JSON.stringify(payload, null, 2)}
13690
- `, {
13691
- encoding: "utf8"
13692
- });
13693
- }
13694
14118
  async function recoverInvalidConfig(fs3, filePath, content) {
13695
- const backupPath = createInvalidBackupPath(filePath);
14119
+ const backupPath = createInvalidBackupPath2(filePath);
13696
14120
  await fs3.writeFile(backupPath, content, { encoding: "utf8" });
13697
- await fs3.writeFile(filePath, EMPTY_DOCUMENT, { encoding: "utf8" });
14121
+ await fs3.writeFile(filePath, EMPTY_DOCUMENT2, { encoding: "utf8" });
13698
14122
  }
13699
- function createInvalidBackupPath(filePath) {
13700
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
13701
- const dir = path17.dirname(filePath);
13702
- const base = path17.basename(filePath);
13703
- return path17.join(dir, `${base}.invalid-${timestamp}.json`);
14123
+ function createInvalidBackupPath2(filePath) {
14124
+ const directory = path20.dirname(filePath);
14125
+ const baseName = path20.basename(filePath);
14126
+ return path20.join(directory, `${baseName}.invalid-${createTimestamp()}.json`);
13704
14127
  }
13705
- function isRecord4(value) {
14128
+ function isRecord5(value) {
13706
14129
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
13707
14130
  }
13708
- var EMPTY_DOCUMENT;
13709
- var init_config2 = __esm({
14131
+ var CORE_SCOPE, configuredServicesScope, EMPTY_DOCUMENT2;
14132
+ var init_config3 = __esm({
13710
14133
  "src/services/config.ts"() {
13711
14134
  "use strict";
13712
14135
  init_src2();
13713
- EMPTY_DOCUMENT = `${JSON.stringify({}, null, 2)}
14136
+ init_src6();
14137
+ CORE_SCOPE = "core";
14138
+ configuredServicesScope = "configured_services";
14139
+ EMPTY_DOCUMENT2 = `${JSON.stringify({}, null, 2)}
13714
14140
  `;
13715
14141
  }
13716
14142
  });
@@ -13879,7 +14305,7 @@ var init_configure = __esm({
13879
14305
  "use strict";
13880
14306
  init_shared();
13881
14307
  init_errors();
13882
- init_config2();
14308
+ init_config3();
13883
14309
  init_mutation_events();
13884
14310
  init_configure_payload();
13885
14311
  serviceSelectionPrompt = (action) => `Pick an agent to ${action}:`;
@@ -13903,7 +14329,7 @@ function registerAgentCommand(program, container) {
13903
14329
  }
13904
14330
  let session;
13905
14331
  try {
13906
- const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (init_src8(), src_exports));
14332
+ const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (init_src9(), src_exports));
13907
14333
  session = await createAgentSession2({
13908
14334
  model: options.model,
13909
14335
  apiKey: options.apiKey,
@@ -13962,7 +14388,7 @@ var init_agent2 = __esm({
13962
14388
  });
13963
14389
 
13964
14390
  // src/cli/commands/spawn.ts
13965
- import path18 from "node:path";
14391
+ import path21 from "node:path";
13966
14392
  function registerSpawnCommand(program, container, options = {}) {
13967
14393
  const spawnServices = container.registry.list().filter((service) => typeof service.spawn === "function" || getSpawnConfig(service.name)).map((service) => service.name);
13968
14394
  const extraServices = options.extraServices ?? [];
@@ -14173,10 +14599,10 @@ function resolveSpawnWorkingDirectory2(baseDir, candidate) {
14173
14599
  if (!candidate || candidate.trim().length === 0) {
14174
14600
  return void 0;
14175
14601
  }
14176
- if (path18.isAbsolute(candidate)) {
14602
+ if (path21.isAbsolute(candidate)) {
14177
14603
  return candidate;
14178
14604
  }
14179
- return path18.resolve(baseDir, candidate);
14605
+ return path21.resolve(baseDir, candidate);
14180
14606
  }
14181
14607
  function parseMcpSpawnConfig2(input) {
14182
14608
  if (!input) {
@@ -14287,7 +14713,7 @@ var init_spawn4 = __esm({
14287
14713
  init_src5();
14288
14714
  init_src3();
14289
14715
  init_src4();
14290
- init_config2();
14716
+ init_config3();
14291
14717
  init_shared();
14292
14718
  init_spawn_core();
14293
14719
  await init_spawn3();
@@ -14296,7 +14722,7 @@ var init_spawn4 = __esm({
14296
14722
  });
14297
14723
 
14298
14724
  // src/sdk/research.ts
14299
- import path19 from "node:path";
14725
+ import path22 from "node:path";
14300
14726
  async function research(container, options) {
14301
14727
  const logger2 = options.logger;
14302
14728
  const source = await resolveSource({
@@ -14331,7 +14757,7 @@ async function research(container, options) {
14331
14757
  markdown: markdownOutput
14332
14758
  });
14333
14759
  outputPath = buildOutputPath(container.env.homeDir, options.prompt);
14334
- await ensureDirectory2(container.fs, path19.dirname(outputPath));
14760
+ await ensureDirectory2(container.fs, path22.dirname(outputPath));
14335
14761
  await container.fs.writeFile(outputPath, document, {
14336
14762
  encoding: "utf8"
14337
14763
  });
@@ -14406,7 +14832,7 @@ function buildResearchDocument(input) {
14406
14832
  }
14407
14833
  function buildClonePath(homeDir, github) {
14408
14834
  const slug = extractRepoSlug(github);
14409
- return path19.join(homeDir, ".poe-code", "repos", slug);
14835
+ return path22.join(homeDir, ".poe-code", "repos", slug);
14410
14836
  }
14411
14837
  function extractRepoSlug(value) {
14412
14838
  const trimmed = value.trim();
@@ -14444,7 +14870,7 @@ function extractRepoSlug(value) {
14444
14870
  function buildOutputPath(homeDir, prompt, now = /* @__PURE__ */ new Date()) {
14445
14871
  const timestamp = formatTimestamp2(now);
14446
14872
  const slug = buildSlug(prompt);
14447
- return path19.join(
14873
+ return path22.join(
14448
14874
  homeDir,
14449
14875
  ".poe-code",
14450
14876
  "research",
@@ -14465,7 +14891,7 @@ async function resolveSource(input) {
14465
14891
  if (options.github) {
14466
14892
  const cloneUrl = resolveGithubCloneUrl(options.github);
14467
14893
  const clonePath = buildClonePath(container.env.homeDir, options.github);
14468
- await ensureDirectory2(container.fs, path19.dirname(clonePath));
14894
+ await ensureDirectory2(container.fs, path22.dirname(clonePath));
14469
14895
  const exists = await pathExists2(container.fs, clonePath);
14470
14896
  if (!exists) {
14471
14897
  const cloneResult = await container.commandRunner(
@@ -14563,10 +14989,10 @@ function formatYamlString(value) {
14563
14989
  return JSON.stringify(value);
14564
14990
  }
14565
14991
  function resolvePath2(baseDir, candidate) {
14566
- if (path19.isAbsolute(candidate)) {
14992
+ if (path22.isAbsolute(candidate)) {
14567
14993
  return candidate;
14568
14994
  }
14569
- return path19.resolve(baseDir, candidate);
14995
+ return path22.resolve(baseDir, candidate);
14570
14996
  }
14571
14997
  function teeAcpStream(events) {
14572
14998
  const chunks = [];
@@ -14626,7 +15052,7 @@ async function removePathFallback(fs3, target) {
14626
15052
  if (stats && typeof stats.isDirectory === "function" && stats.isDirectory()) {
14627
15053
  const entries = await fs3.readdir(target);
14628
15054
  for (const entry of entries) {
14629
- await removePathFallback(fs3, path19.join(target, entry));
15055
+ await removePathFallback(fs3, path22.join(target, entry));
14630
15056
  }
14631
15057
  }
14632
15058
  try {
@@ -14793,7 +15219,7 @@ var init_research2 = __esm({
14793
15219
  async "src/cli/commands/research.ts"() {
14794
15220
  "use strict";
14795
15221
  init_src5();
14796
- init_config2();
15222
+ init_config3();
14797
15223
  await init_research();
14798
15224
  init_errors();
14799
15225
  init_shared();
@@ -15023,7 +15449,7 @@ var init_login = __esm({
15023
15449
  "use strict";
15024
15450
  init_shared();
15025
15451
  init_errors();
15026
- init_config2();
15452
+ init_config3();
15027
15453
  init_mutation_events();
15028
15454
  }
15029
15455
  });
@@ -15148,7 +15574,7 @@ function formatUnconfigureMessages(service, label, unconfigured, _payload) {
15148
15574
  var init_unconfigure = __esm({
15149
15575
  "src/cli/commands/unconfigure.ts"() {
15150
15576
  "use strict";
15151
- init_config2();
15577
+ init_config3();
15152
15578
  init_mutation_events();
15153
15579
  init_isolated_env();
15154
15580
  init_shared();
@@ -15202,7 +15628,7 @@ async function executeLogout(program, container) {
15202
15628
  var init_logout = __esm({
15203
15629
  "src/cli/commands/logout.ts"() {
15204
15630
  "use strict";
15205
- init_config2();
15631
+ init_config3();
15206
15632
  init_shared();
15207
15633
  init_unconfigure();
15208
15634
  }
@@ -15302,7 +15728,7 @@ var init_auth = __esm({
15302
15728
  "src/cli/commands/auth.ts"() {
15303
15729
  "use strict";
15304
15730
  init_errors();
15305
- init_config2();
15731
+ init_config3();
15306
15732
  init_shared();
15307
15733
  init_login();
15308
15734
  init_logout();
@@ -15505,7 +15931,7 @@ var init_media_download = __esm({
15505
15931
  });
15506
15932
 
15507
15933
  // src/cli/commands/generate.ts
15508
- import path20 from "node:path";
15934
+ import path23 from "node:path";
15509
15935
  function registerGenerateCommand(program, container) {
15510
15936
  const generate2 = program.command("generate").description("Generate content via Poe API").option("--model <model>", `Model identifier (default: ${DEFAULT_TEXT_MODEL})`).option(
15511
15937
  "--param <key=value>",
@@ -15771,11 +16197,11 @@ function getDefaultMimeType(type) {
15771
16197
  return defaults[type];
15772
16198
  }
15773
16199
  function resolveOutputPath(filename, cwd) {
15774
- if (path20.isAbsolute(filename)) {
16200
+ if (path23.isAbsolute(filename)) {
15775
16201
  return { path: filename, label: filename };
15776
16202
  }
15777
16203
  return {
15778
- path: path20.join(cwd, filename),
16204
+ path: path23.join(cwd, filename),
15779
16205
  label: `./${filename}`
15780
16206
  };
15781
16207
  }
@@ -16468,7 +16894,7 @@ function defineSchema(definition) {
16468
16894
  required: required2
16469
16895
  };
16470
16896
  }
16471
- var init_schema = __esm({
16897
+ var init_schema2 = __esm({
16472
16898
  "packages/tiny-stdio-mcp-server/src/schema.ts"() {
16473
16899
  "use strict";
16474
16900
  }
@@ -16879,8 +17305,8 @@ var init_parseUtil = __esm({
16879
17305
  init_errors3();
16880
17306
  init_en();
16881
17307
  makeIssue = (params) => {
16882
- const { data, path: path24, errorMaps, issueData } = params;
16883
- const fullPath = [...path24, ...issueData.path || []];
17308
+ const { data, path: path27, errorMaps, issueData } = params;
17309
+ const fullPath = [...path27, ...issueData.path || []];
16884
17310
  const fullIssue = {
16885
17311
  ...issueData,
16886
17312
  path: fullPath
@@ -17160,11 +17586,11 @@ var init_types4 = __esm({
17160
17586
  init_parseUtil();
17161
17587
  init_util();
17162
17588
  ParseInputLazyPath = class {
17163
- constructor(parent, value, path24, key) {
17589
+ constructor(parent, value, path27, key) {
17164
17590
  this._cachedPath = [];
17165
17591
  this.parent = parent;
17166
17592
  this.data = value;
17167
- this._path = path24;
17593
+ this._path = path27;
17168
17594
  this._key = key;
17169
17595
  }
17170
17596
  get path() {
@@ -20668,10 +21094,10 @@ function mergeDefs(...defs) {
20668
21094
  function cloneDef(schema) {
20669
21095
  return mergeDefs(schema._zod.def);
20670
21096
  }
20671
- function getElementAtPath(obj, path24) {
20672
- if (!path24)
21097
+ function getElementAtPath(obj, path27) {
21098
+ if (!path27)
20673
21099
  return obj;
20674
- return path24.reduce((acc, key) => acc?.[key], obj);
21100
+ return path27.reduce((acc, key) => acc?.[key], obj);
20675
21101
  }
20676
21102
  function promiseAllObject(promisesObj) {
20677
21103
  const keys = Object.keys(promisesObj);
@@ -20983,11 +21409,11 @@ function aborted(x, startIndex = 0) {
20983
21409
  }
20984
21410
  return false;
20985
21411
  }
20986
- function prefixIssues(path24, issues) {
21412
+ function prefixIssues(path27, issues) {
20987
21413
  return issues.map((iss) => {
20988
21414
  var _a2;
20989
21415
  (_a2 = iss).path ?? (_a2.path = []);
20990
- iss.path.unshift(path24);
21416
+ iss.path.unshift(path27);
20991
21417
  return iss;
20992
21418
  });
20993
21419
  }
@@ -33148,8 +33574,8 @@ var require_utils = __commonJS({
33148
33574
  }
33149
33575
  return ind;
33150
33576
  }
33151
- function removeDotSegments(path24) {
33152
- let input = path24;
33577
+ function removeDotSegments(path27) {
33578
+ let input = path27;
33153
33579
  const output = [];
33154
33580
  let nextSlash = -1;
33155
33581
  let len = 0;
@@ -33348,8 +33774,8 @@ var require_schemes = __commonJS({
33348
33774
  wsComponent.secure = void 0;
33349
33775
  }
33350
33776
  if (wsComponent.resourceName) {
33351
- const [path24, query] = wsComponent.resourceName.split("?");
33352
- wsComponent.path = path24 && path24 !== "/" ? path24 : void 0;
33777
+ const [path27, query] = wsComponent.resourceName.split("?");
33778
+ wsComponent.path = path27 && path27 !== "/" ? path27 : void 0;
33353
33779
  wsComponent.query = query;
33354
33780
  wsComponent.resourceName = void 0;
33355
33781
  }
@@ -36582,11 +37008,11 @@ var init_content = __esm({
36582
37008
  });
36583
37009
 
36584
37010
  // packages/tiny-stdio-mcp-server/src/index.ts
36585
- var init_src11 = __esm({
37011
+ var init_src13 = __esm({
36586
37012
  "packages/tiny-stdio-mcp-server/src/index.ts"() {
36587
37013
  "use strict";
36588
37014
  init_server();
36589
- init_schema();
37015
+ init_schema2();
36590
37016
  init_testing();
36591
37017
  init_content();
36592
37018
  init_types3();
@@ -36886,7 +37312,7 @@ var generateTextSchema, generateImageSchema, generateVideoSchema, generateAudioS
36886
37312
  var init_mcp_server = __esm({
36887
37313
  "src/cli/mcp-server.ts"() {
36888
37314
  "use strict";
36889
- init_src11();
37315
+ init_src13();
36890
37316
  init_client_instance();
36891
37317
  init_constants();
36892
37318
  generateTextSchema = defineSchema({
@@ -37292,9 +37718,9 @@ var init_shapes = __esm({
37292
37718
  });
37293
37719
 
37294
37720
  // packages/agent-mcp-config/src/apply.ts
37295
- import path21 from "node:path";
37721
+ import path24 from "node:path";
37296
37722
  function getConfigDirectory(configPath) {
37297
- return path21.dirname(configPath);
37723
+ return path24.dirname(configPath);
37298
37724
  }
37299
37725
  function isConfigObject5(value) {
37300
37726
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
@@ -37396,7 +37822,7 @@ var init_apply = __esm({
37396
37822
  });
37397
37823
 
37398
37824
  // packages/agent-mcp-config/src/index.ts
37399
- var init_src12 = __esm({
37825
+ var init_src14 = __esm({
37400
37826
  "packages/agent-mcp-config/src/index.ts"() {
37401
37827
  "use strict";
37402
37828
  init_configs2();
@@ -37576,7 +38002,7 @@ var init_mcp2 = __esm({
37576
38002
  init_shared();
37577
38003
  init_mcp_output_format();
37578
38004
  init_command_not_found();
37579
- init_src12();
38005
+ init_src14();
37580
38006
  init_execution_context();
37581
38007
  DEFAULT_MCP_AGENT = "claude-code";
37582
38008
  }
@@ -37584,7 +38010,7 @@ var init_mcp2 = __esm({
37584
38010
 
37585
38011
  // packages/agent-skill-config/src/configs.ts
37586
38012
  import os2 from "node:os";
37587
- import path22 from "node:path";
38013
+ import path25 from "node:path";
37588
38014
  function resolveAgentSupport2(input, registry2 = agentSkillConfigs) {
37589
38015
  const resolvedId = resolveAgentId(input);
37590
38016
  if (!resolvedId) {
@@ -37620,7 +38046,7 @@ var init_configs3 = __esm({
37620
38046
  });
37621
38047
 
37622
38048
  // packages/agent-skill-config/src/templates.ts
37623
- import { readFile as readFile5 } from "node:fs/promises";
38049
+ import { readFile as readFile7 } from "node:fs/promises";
37624
38050
  async function getTemplates() {
37625
38051
  if (templatesCache) {
37626
38052
  return templatesCache;
@@ -37629,7 +38055,7 @@ async function getTemplates() {
37629
38055
  "./templates/poe-generate.md",
37630
38056
  import.meta.url
37631
38057
  );
37632
- const poeGenerateTemplate = await readFile5(poeGenerateTemplateUrl, "utf8");
38058
+ const poeGenerateTemplate = await readFile7(poeGenerateTemplateUrl, "utf8");
37633
38059
  templatesCache = {
37634
38060
  "poe-generate.md": poeGenerateTemplate
37635
38061
  };
@@ -37776,7 +38202,7 @@ var init_apply2 = __esm({
37776
38202
  });
37777
38203
 
37778
38204
  // packages/agent-skill-config/src/index.ts
37779
- var init_src13 = __esm({
38205
+ var init_src15 = __esm({
37780
38206
  "packages/agent-skill-config/src/index.ts"() {
37781
38207
  "use strict";
37782
38208
  init_configs3();
@@ -38001,7 +38427,7 @@ var init_skill = __esm({
38001
38427
  "src/cli/commands/skill.ts"() {
38002
38428
  "use strict";
38003
38429
  init_src4();
38004
- init_src13();
38430
+ init_src15();
38005
38431
  init_shared();
38006
38432
  init_command_not_found();
38007
38433
  DEFAULT_SKILL_AGENT = "claude-code";
@@ -38595,8 +39021,8 @@ var init_models = __esm({
38595
39021
  });
38596
39022
 
38597
39023
  // src/cli/commands/pipeline.ts
38598
- import path23 from "node:path";
38599
- import { readFile as readFile6, stat as stat5 } from "node:fs/promises";
39024
+ import path26 from "node:path";
39025
+ import { readFile as readFile8, stat as stat7 } from "node:fs/promises";
38600
39026
  import { fileURLToPath as fileURLToPath4 } from "node:url";
38601
39027
  function formatDuration(ms) {
38602
39028
  const totalSeconds = Math.round(ms / 1e3);
@@ -38627,11 +39053,11 @@ function resolveMaxRuns(value) {
38627
39053
  return parsed;
38628
39054
  }
38629
39055
  function resolvePipelinePaths(scope, cwd, homeDir) {
38630
- const rootPath = scope === "global" ? path23.join(homeDir, ".poe-code", "pipeline") : path23.join(cwd, ".poe-code", "pipeline");
39056
+ const rootPath = scope === "global" ? path26.join(homeDir, ".poe-code", "pipeline") : path26.join(cwd, ".poe-code", "pipeline");
38631
39057
  const displayRoot = scope === "global" ? "~/.poe-code/pipeline" : ".poe-code/pipeline";
38632
39058
  return {
38633
- plansPath: path23.join(rootPath, "plans"),
38634
- stepsPath: path23.join(rootPath, "steps.yaml"),
39059
+ plansPath: path26.join(rootPath, "plans"),
39060
+ stepsPath: path26.join(rootPath, "steps.yaml"),
38635
39061
  displayPlansPath: `${displayRoot}/plans`,
38636
39062
  displayStepsPath: `${displayRoot}/steps.yaml`
38637
39063
  };
@@ -38642,16 +39068,16 @@ async function loadPipelineTemplates() {
38642
39068
  }
38643
39069
  const packageRoot = await findPackageRoot(fileURLToPath4(import.meta.url));
38644
39070
  const templateRoots = [
38645
- path23.join(packageRoot, "src", "templates", "pipeline"),
38646
- path23.join(packageRoot, "dist", "templates", "pipeline")
39071
+ path26.join(packageRoot, "src", "templates", "pipeline"),
39072
+ path26.join(packageRoot, "dist", "templates", "pipeline")
38647
39073
  ];
38648
39074
  for (const templateRoot of templateRoots) {
38649
39075
  if (!await pathExistsOnDisk(templateRoot)) {
38650
39076
  continue;
38651
39077
  }
38652
39078
  const [skillPlan, steps] = await Promise.all([
38653
- readFile6(path23.join(templateRoot, "SKILL_plan.md"), "utf8"),
38654
- readFile6(path23.join(templateRoot, "steps.yaml.hbs"), "utf8")
39079
+ readFile8(path26.join(templateRoot, "SKILL_plan.md"), "utf8"),
39080
+ readFile8(path26.join(templateRoot, "steps.yaml.hbs"), "utf8")
38655
39081
  ]);
38656
39082
  pipelineTemplatesCache = { skillPlan, steps };
38657
39083
  return pipelineTemplatesCache;
@@ -38660,7 +39086,7 @@ async function loadPipelineTemplates() {
38660
39086
  }
38661
39087
  async function pathExistsOnDisk(targetPath) {
38662
39088
  try {
38663
- await stat5(targetPath);
39089
+ await stat7(targetPath);
38664
39090
  return true;
38665
39091
  } catch (error2) {
38666
39092
  if (error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT") {
@@ -38670,12 +39096,12 @@ async function pathExistsOnDisk(targetPath) {
38670
39096
  }
38671
39097
  }
38672
39098
  async function findPackageRoot(entryFilePath) {
38673
- let currentPath = path23.dirname(entryFilePath);
39099
+ let currentPath = path26.dirname(entryFilePath);
38674
39100
  while (true) {
38675
- if (await pathExistsOnDisk(path23.join(currentPath, "package.json"))) {
39101
+ if (await pathExistsOnDisk(path26.join(currentPath, "package.json"))) {
38676
39102
  return currentPath;
38677
39103
  }
38678
- const parentPath = path23.dirname(currentPath);
39104
+ const parentPath = path26.dirname(currentPath);
38679
39105
  if (parentPath === currentPath) {
38680
39106
  throw new Error("Unable to locate package root for Pipeline templates.");
38681
39107
  }
@@ -38953,7 +39379,7 @@ function registerPipelineCommand(program, container) {
38953
39379
  `Would ${stepsExists ? "overwrite" : "create"}: ${pipelinePaths.displayStepsPath}`
38954
39380
  );
38955
39381
  } else {
38956
- await container.fs.mkdir(path23.dirname(pipelinePaths.stepsPath), {
39382
+ await container.fs.mkdir(path26.dirname(pipelinePaths.stepsPath), {
38957
39383
  recursive: true
38958
39384
  });
38959
39385
  await container.fs.writeFile(pipelinePaths.stepsPath, templates.steps, {
@@ -38978,24 +39404,244 @@ var init_pipeline4 = __esm({
38978
39404
  "use strict";
38979
39405
  init_src4();
38980
39406
  init_src3();
38981
- init_src13();
39407
+ init_src15();
38982
39408
  init_errors();
38983
39409
  init_shared();
38984
39410
  await init_pipeline2();
38985
- init_src9();
39411
+ init_src10();
38986
39412
  DEFAULT_PIPELINE_AGENT = "claude-code";
38987
39413
  DEFAULT_PIPELINE_SCOPE = "local";
38988
39414
  pipelineTemplatesCache = null;
38989
39415
  }
38990
39416
  });
38991
39417
 
39418
+ // src/cli/commands/ralph.ts
39419
+ function formatDuration2(ms) {
39420
+ const totalSeconds = Math.round(ms / 1e3);
39421
+ const minutes = Math.floor(totalSeconds / 60);
39422
+ const seconds = totalSeconds % 60;
39423
+ return minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
39424
+ }
39425
+ function resolveRalphAgent(value) {
39426
+ if (!value || value.trim().length === 0) {
39427
+ return DEFAULT_RALPH_AGENT;
39428
+ }
39429
+ const resolved = resolveAgentId(value.trim());
39430
+ if (!resolved) {
39431
+ throw new ValidationError(`Unsupported agent: ${value}`);
39432
+ }
39433
+ return resolved;
39434
+ }
39435
+ function parsePositiveInt(value, fieldName) {
39436
+ if (value == null) {
39437
+ return void 0;
39438
+ }
39439
+ const parsed = Number.parseInt(value, 10);
39440
+ if (!Number.isFinite(parsed) || parsed < 1) {
39441
+ throw new ValidationError(
39442
+ `Invalid ${fieldName} "${value}". Expected a positive integer.`
39443
+ );
39444
+ }
39445
+ return parsed;
39446
+ }
39447
+ async function resolveAgent(options) {
39448
+ if (options.providedAgent) {
39449
+ return resolveRalphAgent(options.providedAgent);
39450
+ }
39451
+ const flags = resolveCommandFlags(options.program);
39452
+ if (flags.assumeYes) {
39453
+ return DEFAULT_RALPH_AGENT;
39454
+ }
39455
+ const selected = await select2({
39456
+ message: "Select agent to run Ralph with:",
39457
+ options: allSpawnConfigs.map((config2) => ({
39458
+ label: config2.agentId,
39459
+ value: config2.agentId
39460
+ }))
39461
+ });
39462
+ if (isCancel2(selected)) {
39463
+ cancel2("Ralph run cancelled.");
39464
+ return null;
39465
+ }
39466
+ return resolveRalphAgent(typeof selected === "string" ? selected : void 0);
39467
+ }
39468
+ async function resolveDocPath(options) {
39469
+ if (options.providedDoc && options.providedDoc.trim().length > 0) {
39470
+ return options.providedDoc.trim();
39471
+ }
39472
+ const docs = await discoverDocs({
39473
+ cwd: options.container.env.cwd,
39474
+ homeDir: options.container.env.homeDir,
39475
+ fs: options.container.fs
39476
+ });
39477
+ if (docs.length === 0) {
39478
+ throw new ValidationError(
39479
+ "No markdown doc found under .poe-code/ralph/plans/ or ~/.poe-code/ralph/plans/. Provide a doc path."
39480
+ );
39481
+ }
39482
+ const flags = resolveCommandFlags(options.program);
39483
+ if (flags.assumeYes) {
39484
+ return docs[0].path;
39485
+ }
39486
+ const selected = await select2({
39487
+ message: "Select the Ralph markdown doc to run:",
39488
+ options: docs.map((doc) => ({
39489
+ label: doc.displayPath,
39490
+ value: doc.path
39491
+ }))
39492
+ });
39493
+ if (isCancel2(selected)) {
39494
+ cancel2("Ralph run cancelled.");
39495
+ return null;
39496
+ }
39497
+ return typeof selected === "string" ? selected : null;
39498
+ }
39499
+ async function resolveIterations(options) {
39500
+ const explicitIterations = parsePositiveInt(
39501
+ options.providedIterations,
39502
+ "iterations"
39503
+ );
39504
+ if (explicitIterations != null) {
39505
+ return explicitIterations;
39506
+ }
39507
+ const flags = resolveCommandFlags(options.program);
39508
+ if (flags.assumeYes) {
39509
+ throw new ValidationError(
39510
+ "Iterations are required when using --yes. Provide poe-code ralph run <iterations> [doc]."
39511
+ );
39512
+ }
39513
+ const entered = await text3({
39514
+ message: "How many Ralph iterations should run?"
39515
+ });
39516
+ if (isCancel2(entered)) {
39517
+ cancel2("Ralph run cancelled.");
39518
+ return null;
39519
+ }
39520
+ return parsePositiveInt(
39521
+ typeof entered === "string" ? entered.trim() : void 0,
39522
+ "iterations"
39523
+ ) ?? null;
39524
+ }
39525
+ function registerRalphCommand(program, container) {
39526
+ const ralph = program.command("ralph").description("Run a simple iterative markdown loop.");
39527
+ ralph.command("run").description("Run the selected markdown doc through repeated agent iterations.").argument("[iterations]", "Number of Ralph iterations to run").argument("[doc]", "Markdown doc path").option("--agent <name>", "Agent to run each iteration with").option("--model <model>", "Model override passed to the agent").option(
39528
+ "--max-failures <n>",
39529
+ "Consecutive failure threshold before overbake protection prompts"
39530
+ ).action(async function(iterationsArg, docArg) {
39531
+ const flags = resolveCommandFlags(program);
39532
+ const resources = createExecutionResources(container, flags, "ralph:run");
39533
+ const options = this.opts();
39534
+ resources.logger.intro("ralph run");
39535
+ try {
39536
+ const docPath = await resolveDocPath({
39537
+ container,
39538
+ program,
39539
+ providedDoc: docArg
39540
+ });
39541
+ if (!docPath) {
39542
+ return;
39543
+ }
39544
+ const agent2 = await resolveAgent({
39545
+ program,
39546
+ providedAgent: options.agent
39547
+ });
39548
+ if (!agent2) {
39549
+ return;
39550
+ }
39551
+ const maxIterations = await resolveIterations({
39552
+ program,
39553
+ providedIterations: iterationsArg
39554
+ });
39555
+ if (maxIterations == null) {
39556
+ return;
39557
+ }
39558
+ const maxFailures = parsePositiveInt(
39559
+ options.maxFailures,
39560
+ "max-failures"
39561
+ );
39562
+ const result = await runRalph2({
39563
+ agent: agent2,
39564
+ cwd: container.env.cwd,
39565
+ homeDir: container.env.homeDir,
39566
+ docPath,
39567
+ maxIterations,
39568
+ ...options.model ? { model: options.model } : {},
39569
+ ...maxFailures != null ? { maxFailures } : {},
39570
+ promptOverbake: async (input) => {
39571
+ const selected = await select2({
39572
+ message: `Ralph hit ${input.consecutiveFailures} consecutive failures (threshold ${input.threshold}). What should happen next?`,
39573
+ options: [
39574
+ { label: "Continue", value: "continue" },
39575
+ { label: "Abort", value: "abort" }
39576
+ ]
39577
+ });
39578
+ if (isCancel2(selected)) {
39579
+ cancel2("Ralph run cancelled.");
39580
+ return "abort";
39581
+ }
39582
+ return selected === "continue" ? "continue" : "abort";
39583
+ },
39584
+ onIterationStart(iteration, total) {
39585
+ resources.logger.info(`Iteration ${iteration}/${total}`);
39586
+ },
39587
+ onIterationComplete(iteration, durationMs, success2) {
39588
+ const status = success2 ? "done" : "failed";
39589
+ resources.logger.info(
39590
+ `Iteration ${iteration} ${status} in ${formatDuration2(durationMs)}`
39591
+ );
39592
+ },
39593
+ onOverbakeWarning(consecutiveFailures, threshold) {
39594
+ resources.logger.warn(
39595
+ `Overbake protection triggered at ${consecutiveFailures} consecutive failures (threshold ${threshold}).`
39596
+ );
39597
+ }
39598
+ });
39599
+ const summary = [
39600
+ `Iterations: ${result.iterationsCompleted}/${maxIterations}`,
39601
+ `Doc: ${result.docPath}`,
39602
+ `Duration: ${formatDuration2(result.totalDurationMs)}`
39603
+ ].join("\n ");
39604
+ if (result.stopReason === "cancelled") {
39605
+ process.exitCode = 130;
39606
+ resources.logger.warn("Ralph run cancelled.");
39607
+ resources.logger.resolved("Run summary", summary);
39608
+ return;
39609
+ }
39610
+ if (result.stopReason === "overbake_abort") {
39611
+ process.exitCode = 1;
39612
+ resources.logger.warn("Ralph stopped after repeated failures.");
39613
+ resources.logger.resolved("Run summary", summary);
39614
+ return;
39615
+ }
39616
+ resources.logger.resolved("Run summary", summary);
39617
+ resources.logger.success("Ralph run finished.");
39618
+ } finally {
39619
+ resources.context.finalize();
39620
+ }
39621
+ });
39622
+ }
39623
+ var DEFAULT_RALPH_AGENT;
39624
+ var init_ralph3 = __esm({
39625
+ async "src/cli/commands/ralph.ts"() {
39626
+ "use strict";
39627
+ init_src4();
39628
+ init_src3();
39629
+ init_src5();
39630
+ init_src11();
39631
+ init_errors();
39632
+ init_shared();
39633
+ await init_ralph2();
39634
+ DEFAULT_RALPH_AGENT = "claude-code";
39635
+ }
39636
+ });
39637
+
38992
39638
  // package.json
38993
39639
  var package_default;
38994
39640
  var init_package = __esm({
38995
39641
  "package.json"() {
38996
39642
  package_default = {
38997
39643
  name: "poe-code",
38998
- version: "3.0.100",
39644
+ version: "3.0.102",
38999
39645
  description: "CLI tool to configure Poe API for developer workflows.",
39000
39646
  type: "module",
39001
39647
  main: "./dist/index.js",
@@ -39088,6 +39734,8 @@ var init_package = __esm({
39088
39734
  "@poe-code/freeze-cli": "*",
39089
39735
  "@poe-code/pipeline": "*",
39090
39736
  "@poe-code/poe-acp-client": "*",
39737
+ "@poe-code/poe-code-config": "*",
39738
+ "@poe-code/ralph": "*",
39091
39739
  "@types/mustache": "^4.2.6",
39092
39740
  "@types/node": "^25.2.2",
39093
39741
  "@types/semver": "^7.7.1",
@@ -39211,6 +39859,11 @@ function formatHelpText(input) {
39211
39859
  args: "",
39212
39860
  description: "Run a fixed-step task pipeline plan"
39213
39861
  },
39862
+ {
39863
+ name: "ralph run",
39864
+ args: "[iterations] [doc]",
39865
+ description: "Run a markdown doc through repeated agent iterations"
39866
+ },
39214
39867
  {
39215
39868
  name: "usage",
39216
39869
  args: "",
@@ -39220,11 +39873,6 @@ function formatHelpText(input) {
39220
39873
  name: "usage list",
39221
39874
  args: "",
39222
39875
  description: "Display usage history"
39223
- },
39224
- {
39225
- name: "pipeline run",
39226
- args: "",
39227
- description: "Run a fixed-step task pipeline plan"
39228
39876
  }
39229
39877
  ];
39230
39878
  const nameWidth = Math.max(0, ...commandRows.map((row) => row.name.length));
@@ -39374,6 +40022,7 @@ function bootstrapProgram(container) {
39374
40022
  registerMcpCommand(program, container);
39375
40023
  registerSkillCommand(program, container);
39376
40024
  registerPipelineCommand(program, container);
40025
+ registerRalphCommand(program, container);
39377
40026
  registerUsageCommand(program, container);
39378
40027
  registerModelsCommand(program, container);
39379
40028
  program.allowExcessArguments().action(function() {
@@ -39431,6 +40080,7 @@ var init_program = __esm({
39431
40080
  init_usage();
39432
40081
  init_models();
39433
40082
  await init_pipeline4();
40083
+ await init_ralph3();
39434
40084
  init_package();
39435
40085
  init_command_not_found();
39436
40086
  init_execution_context();
@@ -39604,6 +40254,7 @@ var init_bootstrap = __esm({
39604
40254
  // src/index.ts
39605
40255
  await init_spawn3();
39606
40256
  await init_pipeline2();
40257
+ await init_ralph2();
39607
40258
  import { realpathSync as realpathSync2 } from "node:fs";
39608
40259
  import { pathToFileURL as pathToFileURL3 } from "node:url";
39609
40260
 
@@ -39712,7 +40363,7 @@ init_src5();
39712
40363
  init_src4();
39713
40364
  init_constants();
39714
40365
  init_errors();
39715
- import path16 from "node:path";
40366
+ import path19 from "node:path";
39716
40367
  import { Command } from "commander";
39717
40368
  function parseMcpSpawnConfig(input) {
39718
40369
  if (!input) {
@@ -39783,10 +40434,10 @@ function resolveWorkingDirectory(baseDir, candidate) {
39783
40434
  if (!candidate || candidate.trim().length === 0) {
39784
40435
  return void 0;
39785
40436
  }
39786
- if (path16.isAbsolute(candidate)) {
40437
+ if (path19.isAbsolute(candidate)) {
39787
40438
  return candidate;
39788
40439
  }
39789
- return path16.resolve(baseDir, candidate);
40440
+ return path19.resolve(baseDir, candidate);
39790
40441
  }
39791
40442
  function createPoeAgentProgram() {
39792
40443
  const program = new Command();
@@ -39889,6 +40540,7 @@ export {
39889
40540
  main,
39890
40541
  poeAgentMain,
39891
40542
  runPipeline2 as runPipeline,
40543
+ runRalph2 as runRalph,
39892
40544
  spawn5 as spawn
39893
40545
  };
39894
40546
  //# sourceMappingURL=index.js.map