poe-code 3.0.224 → 3.0.225

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/bin/poe-gemini.js +23 -0
  2. package/dist/cli/commands/configure-payload.js +50 -3
  3. package/dist/cli/commands/configure-payload.js.map +1 -1
  4. package/dist/cli/commands/pipeline.js +4 -2
  5. package/dist/cli/commands/pipeline.js.map +1 -1
  6. package/dist/cli/commands/ralph.js +1 -0
  7. package/dist/cli/commands/ralph.js.map +1 -1
  8. package/dist/cli/commands/shared.d.ts +4 -0
  9. package/dist/cli/commands/shared.js +33 -2
  10. package/dist/cli/commands/shared.js.map +1 -1
  11. package/dist/cli/commands/spawn.js +20 -0
  12. package/dist/cli/commands/spawn.js.map +1 -1
  13. package/dist/cli/commands/test.d.ts +5 -1
  14. package/dist/cli/commands/test.js +58 -6
  15. package/dist/cli/commands/test.js.map +1 -1
  16. package/dist/cli/constants.d.ts +1 -0
  17. package/dist/cli/constants.js +2 -1
  18. package/dist/cli/constants.js.map +1 -1
  19. package/dist/cli/isolated-env.d.ts +2 -1
  20. package/dist/cli/isolated-env.js +20 -2
  21. package/dist/cli/isolated-env.js.map +1 -1
  22. package/dist/cli/options.d.ts +2 -5
  23. package/dist/cli/poe-code-command-runner.js +7 -2
  24. package/dist/cli/poe-code-command-runner.js.map +1 -1
  25. package/dist/cli/prompts.d.ts +21 -13
  26. package/dist/cli/prompts.js.map +1 -1
  27. package/dist/cli/service-registry.d.ts +12 -3
  28. package/dist/cli/service-registry.js.map +1 -1
  29. package/dist/index.d.ts +3 -1
  30. package/dist/index.js +4694 -2378
  31. package/dist/index.js.map +4 -4
  32. package/dist/providers/claude-code.js +913 -152
  33. package/dist/providers/claude-code.js.map +4 -4
  34. package/dist/providers/codex.js +897 -149
  35. package/dist/providers/codex.js.map +4 -4
  36. package/dist/providers/create-provider.d.ts +1 -0
  37. package/dist/providers/create-provider.js +1 -0
  38. package/dist/providers/create-provider.js.map +1 -1
  39. package/dist/providers/gemini-cli.d.ts +16 -0
  40. package/dist/providers/gemini-cli.js +11349 -0
  41. package/dist/providers/gemini-cli.js.map +7 -0
  42. package/dist/providers/goose.js +870 -161
  43. package/dist/providers/goose.js.map +4 -4
  44. package/dist/providers/kimi.js +894 -143
  45. package/dist/providers/kimi.js.map +4 -4
  46. package/dist/providers/opencode.js +894 -143
  47. package/dist/providers/opencode.js.map +4 -4
  48. package/dist/providers/poe-agent.js +1144 -335
  49. package/dist/providers/poe-agent.js.map +4 -4
  50. package/dist/providers/spawn-options.d.ts +3 -0
  51. package/dist/sdk/pipeline.d.ts +1 -1
  52. package/dist/sdk/pipeline.js +22 -19
  53. package/dist/sdk/pipeline.js.map +1 -1
  54. package/dist/sdk/ralph.js +5 -0
  55. package/dist/sdk/ralph.js.map +1 -1
  56. package/dist/sdk/spawn-core.d.ts +3 -0
  57. package/dist/sdk/spawn-core.js +6 -8
  58. package/dist/sdk/spawn-core.js.map +1 -1
  59. package/dist/sdk/spawn.d.ts +8 -8
  60. package/dist/sdk/spawn.js +26 -3
  61. package/dist/sdk/spawn.js.map +1 -1
  62. package/dist/sdk/types.d.ts +7 -0
  63. package/dist/utils/command-checks.d.ts +8 -0
  64. package/dist/utils/command-checks.js +35 -9
  65. package/dist/utils/command-checks.js.map +1 -1
  66. package/dist/utils/dry-run.js +7 -1
  67. package/dist/utils/dry-run.js.map +1 -1
  68. package/dist/workflow-templates/github-issue-opened.caller.yml +2 -1
  69. package/dist/workflow-templates/github-issue-opened.ejected.yml +2 -1
  70. package/package.json +2 -1
  71. package/packages/agent-skill-config/dist/configs.js +4 -0
  72. package/packages/agent-skill-config/dist/git-exclude.d.ts +6 -2
  73. package/packages/agent-skill-config/dist/git-exclude.js +12 -12
  74. package/packages/memory/dist/index.js +914 -192
  75. package/packages/memory/dist/index.js.map +4 -4
  76. package/packages/superintendent/dist/index.d.ts +2 -1
  77. package/packages/superintendent/dist/runtime/loop.d.ts +1 -0
  78. package/packages/superintendent/dist/runtime/loop.js +14 -2
@@ -523,7 +523,7 @@ import path7 from "node:path";
523
523
 
524
524
  // packages/config-extends/src/discover.ts
525
525
  import path3 from "node:path";
526
- async function findBase(name, bases, fs16) {
526
+ async function findBase(name, bases, fs17) {
527
527
  const checkedPaths = [];
528
528
  for (const basePath of bases) {
529
529
  for (const extension of [".md", ".yaml", ".yml", ".json"]) {
@@ -531,7 +531,7 @@ async function findBase(name, bases, fs16) {
531
531
  checkedPaths.push(filePath);
532
532
  try {
533
533
  return {
534
- content: await fs16.readFile(filePath, "utf8"),
534
+ content: await fs17.readFile(filePath, "utf8"),
535
535
  filePath
536
536
  };
537
537
  } catch (error2) {
@@ -611,11 +611,11 @@ function stripBom(content) {
611
611
  function mergeLayers(layers) {
612
612
  return mergeObjectLayers(layers, []);
613
613
  }
614
- function mergeObjectLayers(layers, path50) {
614
+ function mergeObjectLayers(layers, path55) {
615
615
  const data = {};
616
616
  const sources = {};
617
617
  for (const key of collectKeys(layers)) {
618
- const resolved = resolveKey(layers, key, path50);
618
+ const resolved = resolveKey(layers, key, path55);
619
619
  if (resolved === void 0) {
620
620
  continue;
621
621
  }
@@ -633,7 +633,7 @@ function collectKeys(layers) {
633
633
  }
634
634
  return [...keys];
635
635
  }
636
- function resolveKey(layers, key, path50) {
636
+ function resolveKey(layers, key, path55) {
637
637
  let winningSource;
638
638
  let winningValue;
639
639
  const objectLayers = [];
@@ -663,9 +663,9 @@ function resolveKey(layers, key, path50) {
663
663
  if (winningSource === void 0) {
664
664
  return void 0;
665
665
  }
666
- const fullPath = buildPath(path50, key);
666
+ const fullPath = buildPath(path55, key);
667
667
  if (isPlainObject(winningValue)) {
668
- const merged = mergeObjectLayers(objectLayers, [...path50, key]);
668
+ const merged = mergeObjectLayers(objectLayers, [...path55, key]);
669
669
  return {
670
670
  value: merged.data,
671
671
  sources: {
@@ -690,8 +690,8 @@ function isWinningCandidate(key, value) {
690
690
  }
691
691
  return true;
692
692
  }
693
- function buildPath(path50, key) {
694
- return [...path50, key].join(".");
693
+ function buildPath(path55, key) {
694
+ return [...path55, key].join(".");
695
695
  }
696
696
  function isPlainObject(value) {
697
697
  if (value === null || Array.isArray(value) || typeof value !== "object") {
@@ -2079,16 +2079,16 @@ function getConfigFormat(pathOrFormat) {
2079
2079
  }
2080
2080
  return formatRegistry[formatName];
2081
2081
  }
2082
- function detectFormat2(path50) {
2083
- const ext = getExtension(path50);
2082
+ function detectFormat2(path55) {
2083
+ const ext = getExtension(path55);
2084
2084
  return extensionMap[ext];
2085
2085
  }
2086
- function getExtension(path50) {
2087
- const lastDot = path50.lastIndexOf(".");
2086
+ function getExtension(path55) {
2087
+ const lastDot = path55.lastIndexOf(".");
2088
2088
  if (lastDot === -1) {
2089
2089
  return "";
2090
2090
  }
2091
- return path50.slice(lastDot).toLowerCase();
2091
+ return path55.slice(lastDot).toLowerCase();
2092
2092
  }
2093
2093
 
2094
2094
  // packages/config-mutations/src/execution/path-utils.ts
@@ -2139,9 +2139,9 @@ function resolvePath(rawPath, homeDir, pathMapper) {
2139
2139
  function isNotFound(error2) {
2140
2140
  return typeof error2 === "object" && error2 !== null && "code" in error2 && error2.code === "ENOENT";
2141
2141
  }
2142
- async function readFileIfExists(fs16, target) {
2142
+ async function readFileIfExists(fs17, target) {
2143
2143
  try {
2144
- return await fs16.readFile(target, "utf8");
2144
+ return await fs17.readFile(target, "utf8");
2145
2145
  } catch (error2) {
2146
2146
  if (isNotFound(error2)) {
2147
2147
  return null;
@@ -2149,9 +2149,9 @@ async function readFileIfExists(fs16, target) {
2149
2149
  throw error2;
2150
2150
  }
2151
2151
  }
2152
- async function pathExists(fs16, target) {
2152
+ async function pathExists(fs17, target) {
2153
2153
  try {
2154
- await fs16.stat(target);
2154
+ await fs17.stat(target);
2155
2155
  return true;
2156
2156
  } catch (error2) {
2157
2157
  if (isNotFound(error2)) {
@@ -2175,9 +2175,9 @@ function createInvalidDocumentBackupPath(targetPath) {
2175
2175
  const ext = targetPath.includes(".") ? targetPath.split(".").pop() : "bak";
2176
2176
  return `${targetPath}.invalid-${createTimestamp()}.${ext}`;
2177
2177
  }
2178
- async function backupInvalidDocument(fs16, targetPath, content) {
2178
+ async function backupInvalidDocument(fs17, targetPath, content) {
2179
2179
  const backupPath = createInvalidDocumentBackupPath(targetPath);
2180
- await fs16.writeFile(backupPath, content, { encoding: "utf8" });
2180
+ await fs17.writeFile(backupPath, content, { encoding: "utf8" });
2181
2181
  }
2182
2182
  function describeMutation(kind, targetPath) {
2183
2183
  const displayPath = targetPath ?? "target";
@@ -2735,12 +2735,12 @@ async function executeMutation(mutation, context, options) {
2735
2735
  }
2736
2736
 
2737
2737
  // packages/poe-code-config/src/store.ts
2738
- async function readMergedDocument(fs16, globalPath, projectPath) {
2739
- const globalDocument = await readStoredDocument(fs16, globalPath);
2738
+ async function readMergedDocument(fs17, globalPath, projectPath) {
2739
+ const globalDocument = await readStoredDocument(fs17, globalPath);
2740
2740
  if (!projectPath || projectPath === globalPath) {
2741
2741
  return globalDocument.data;
2742
2742
  }
2743
- const projectDocument = await readStoredDocument(fs16, projectPath);
2743
+ const projectDocument = await readStoredDocument(fs17, projectPath);
2744
2744
  const resolved = await resolve(
2745
2745
  [
2746
2746
  {
@@ -2754,16 +2754,16 @@ async function readMergedDocument(fs16, globalPath, projectPath) {
2754
2754
  }
2755
2755
  ],
2756
2756
  {
2757
- fs: createResolvedConfigFs(fs16, globalPath, globalDocument.content),
2757
+ fs: createResolvedConfigFs(fs17, globalPath, globalDocument.content),
2758
2758
  autoExtend: true
2759
2759
  }
2760
2760
  );
2761
2761
  return normalizeDocument(resolved.data);
2762
2762
  }
2763
- async function readStoredDocument(fs16, filePath) {
2763
+ async function readStoredDocument(fs17, filePath) {
2764
2764
  try {
2765
- const raw = await fs16.readFile(filePath, "utf8");
2766
- return await parseStoredDocument(fs16, filePath, raw);
2765
+ const raw = await fs17.readFile(filePath, "utf8");
2766
+ return await parseStoredDocument(fs17, filePath, raw);
2767
2767
  } catch (error2) {
2768
2768
  if (isNotFound(error2)) {
2769
2769
  return {
@@ -2774,7 +2774,7 @@ async function readStoredDocument(fs16, filePath) {
2774
2774
  throw error2;
2775
2775
  }
2776
2776
  }
2777
- async function parseStoredDocument(fs16, filePath, raw) {
2777
+ async function parseStoredDocument(fs17, filePath, raw) {
2778
2778
  try {
2779
2779
  return {
2780
2780
  content: raw,
@@ -2782,7 +2782,7 @@ async function parseStoredDocument(fs16, filePath, raw) {
2782
2782
  };
2783
2783
  } catch (error2) {
2784
2784
  if (error2 instanceof SyntaxError) {
2785
- await recoverInvalidDocument(fs16, filePath, raw);
2785
+ await recoverInvalidDocument(fs17, filePath, raw);
2786
2786
  return {
2787
2787
  content: EMPTY_DOCUMENT,
2788
2788
  data: {}
@@ -2816,21 +2816,21 @@ function normalizeScopeValues(value) {
2816
2816
  }
2817
2817
  return normalized;
2818
2818
  }
2819
- function createResolvedConfigFs(fs16, globalPath, globalContent) {
2819
+ function createResolvedConfigFs(fs17, globalPath, globalContent) {
2820
2820
  return {
2821
2821
  readFile(filePath, _encoding) {
2822
2822
  if (filePath === globalPath) {
2823
2823
  return Promise.resolve(globalContent);
2824
2824
  }
2825
- return fs16.readFile(filePath, "utf8");
2825
+ return fs17.readFile(filePath, "utf8");
2826
2826
  }
2827
2827
  };
2828
2828
  }
2829
- async function recoverInvalidDocument(fs16, filePath, content) {
2830
- await fs16.mkdir(path7.dirname(filePath), { recursive: true });
2829
+ async function recoverInvalidDocument(fs17, filePath, content) {
2830
+ await fs17.mkdir(path7.dirname(filePath), { recursive: true });
2831
2831
  const backupPath = createInvalidBackupPath(filePath);
2832
- await fs16.writeFile(backupPath, content, { encoding: "utf8" });
2833
- await fs16.writeFile(filePath, EMPTY_DOCUMENT, { encoding: "utf8" });
2832
+ await fs17.writeFile(backupPath, content, { encoding: "utf8" });
2833
+ await fs17.writeFile(filePath, EMPTY_DOCUMENT, { encoding: "utf8" });
2834
2834
  }
2835
2835
  function createInvalidBackupPath(filePath) {
2836
2836
  const directory = path7.dirname(filePath);
@@ -2954,7 +2954,7 @@ function mergeScope(scope, baseScope, overrideScope) {
2954
2954
  ...Object.fromEntries(scopeEntries)
2955
2955
  };
2956
2956
  }
2957
- function mergeRuntimeScope(baseScope, overrideScope, path50 = []) {
2957
+ function mergeRuntimeScope(baseScope, overrideScope, path55 = []) {
2958
2958
  const merged = {};
2959
2959
  const keys = /* @__PURE__ */ new Set([...Object.keys(baseScope), ...Object.keys(overrideScope)]);
2960
2960
  for (const key of keys) {
@@ -2966,20 +2966,20 @@ function mergeRuntimeScope(baseScope, overrideScope, path50 = []) {
2966
2966
  }
2967
2967
  continue;
2968
2968
  }
2969
- if (isRuntimeConcatenativeArray([...path50, key]) && Array.isArray(baseValue) && Array.isArray(overrideValue)) {
2969
+ if (isRuntimeConcatenativeArray([...path55, key]) && Array.isArray(baseValue) && Array.isArray(overrideValue)) {
2970
2970
  merged[key] = [...baseValue, ...overrideValue];
2971
2971
  continue;
2972
2972
  }
2973
2973
  if (isRecord3(baseValue) && isRecord3(overrideValue)) {
2974
- merged[key] = mergeRuntimeScope(baseValue, overrideValue, [...path50, key]);
2974
+ merged[key] = mergeRuntimeScope(baseValue, overrideValue, [...path55, key]);
2975
2975
  continue;
2976
2976
  }
2977
2977
  merged[key] = overrideValue;
2978
2978
  }
2979
2979
  return merged;
2980
2980
  }
2981
- function isRuntimeConcatenativeArray(path50) {
2982
- return path50.join(".") === "mounts" || path50.join(".") === "runner.workspace.exclude";
2981
+ function isRuntimeConcatenativeArray(path55) {
2982
+ return path55.join(".") === "mounts" || path55.join(".") === "runner.workspace.exclude";
2983
2983
  }
2984
2984
  function isRecord3(value) {
2985
2985
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
@@ -3088,6 +3088,24 @@ var codexAgent = {
3088
3088
  }
3089
3089
  };
3090
3090
 
3091
+ // packages/agent-defs/src/agents/gemini-cli.ts
3092
+ var geminiCliAgent = {
3093
+ id: "gemini-cli",
3094
+ name: "gemini-cli",
3095
+ aliases: ["gemini"],
3096
+ label: "Gemini CLI",
3097
+ summary: "Configure Google's Gemini CLI to use a compatible Google generations API.",
3098
+ binaryName: "gemini",
3099
+ configPath: "~/.gemini/settings.json",
3100
+ apiShapes: ["google-generations"],
3101
+ branding: {
3102
+ colors: {
3103
+ dark: "#8AB4F8",
3104
+ light: "#1A73E8"
3105
+ }
3106
+ }
3107
+ };
3108
+
3091
3109
  // packages/agent-defs/src/agents/opencode.ts
3092
3110
  var openCodeAgent = {
3093
3111
  id: "opencode",
@@ -3161,6 +3179,7 @@ var allAgents = [
3161
3179
  claudeCodeAgent,
3162
3180
  claudeDesktopAgent,
3163
3181
  codexAgent,
3182
+ geminiCliAgent,
3164
3183
  openCodeAgent,
3165
3184
  kimiAgent,
3166
3185
  gooseAgent,
@@ -3357,6 +3376,7 @@ var poeProvider = {
3357
3376
  label: "Poe",
3358
3377
  summary: "Route AI coding agents through Poe's API.",
3359
3378
  baseUrl: "https://api.poe.com",
3379
+ agentBaseUrl: "https://api.poe.com",
3360
3380
  auth: {
3361
3381
  kind: "api-key",
3362
3382
  envVar: "POE_API_KEY",
@@ -3364,6 +3384,12 @@ var poeProvider = {
3364
3384
  prompt: { title: "Poe API key" },
3365
3385
  preferredLogin: "oauth"
3366
3386
  },
3387
+ env: {
3388
+ ANTHROPIC_CUSTOM_HEADERS: {
3389
+ kind: "providerCredential",
3390
+ prefix: "Authorization: Bearer "
3391
+ }
3392
+ },
3367
3393
  apiShapes: [
3368
3394
  {
3369
3395
  id: "openai-chat-completions",
@@ -3392,6 +3418,9 @@ var anthropicProvider = {
3392
3418
  storageKey: "provider:anthropic",
3393
3419
  prompt: { title: "Anthropic API key" }
3394
3420
  },
3421
+ env: {
3422
+ ANTHROPIC_API_KEY: { kind: "providerCredential" }
3423
+ },
3395
3424
  apiShapes: [
3396
3425
  {
3397
3426
  id: "anthropic-messages",
@@ -3414,6 +3443,12 @@ var cloudflareProvider = {
3414
3443
  storageKey: "provider:cloudflare",
3415
3444
  prompt: { title: "Cloudflare AI Gateway token" }
3416
3445
  },
3446
+ env: {
3447
+ ANTHROPIC_CUSTOM_HEADERS: {
3448
+ kind: "providerCredential",
3449
+ prefix: "Authorization: Bearer "
3450
+ }
3451
+ },
3417
3452
  apiShapes: [
3418
3453
  {
3419
3454
  id: "openai-chat-completions",
@@ -3509,17 +3544,17 @@ function isPidRunning(pid) {
3509
3544
  }
3510
3545
  function createDefaultFs() {
3511
3546
  return {
3512
- open: (path50, flags) => fsPromises.open(path50, flags),
3513
- readFile: (path50, encoding) => fsPromises.readFile(path50, encoding),
3547
+ open: (path55, flags) => fsPromises.open(path55, flags),
3548
+ readFile: (path55, encoding) => fsPromises.readFile(path55, encoding),
3514
3549
  stat: fsPromises.stat,
3515
3550
  unlink: fsPromises.unlink
3516
3551
  };
3517
3552
  }
3518
- async function removeLockFile(fs16, lockPath, signal) {
3553
+ async function removeLockFile(fs17, lockPath, signal) {
3519
3554
  for (let attempt = 0; attempt <= 4; attempt += 1) {
3520
3555
  throwIfAborted(signal);
3521
3556
  try {
3522
- await fs16.unlink(lockPath);
3557
+ await fs17.unlink(lockPath);
3523
3558
  return;
3524
3559
  } catch (error2) {
3525
3560
  if (hasErrorCode(error2, "ENOENT")) {
@@ -3550,12 +3585,12 @@ function parseLockMetadata(content) {
3550
3585
  }
3551
3586
  return void 0;
3552
3587
  }
3553
- async function readLockMetadata(fs16, lockPath) {
3554
- if (!fs16.readFile) {
3588
+ async function readLockMetadata(fs17, lockPath) {
3589
+ if (!fs17.readFile) {
3555
3590
  return void 0;
3556
3591
  }
3557
3592
  try {
3558
- return parseLockMetadata(await fs16.readFile(lockPath, "utf8"));
3593
+ return parseLockMetadata(await fs17.readFile(lockPath, "utf8"));
3559
3594
  } catch (error2) {
3560
3595
  if (hasErrorCode(error2, "ENOENT")) {
3561
3596
  return null;
@@ -3589,7 +3624,7 @@ async function writeLockMetadata(handle) {
3589
3624
  }
3590
3625
  }
3591
3626
  async function acquireFileLock(filePath, options = {}) {
3592
- const fs16 = options.fs ?? createDefaultFs();
3627
+ const fs17 = options.fs ?? createDefaultFs();
3593
3628
  const retries = options.retries ?? 20;
3594
3629
  const minTimeout = options.minTimeout ?? 25;
3595
3630
  const maxTimeout = options.maxTimeout ?? 250;
@@ -3600,7 +3635,7 @@ async function acquireFileLock(filePath, options = {}) {
3600
3635
  while (attempt <= retries) {
3601
3636
  throwIfAborted(options.signal);
3602
3637
  try {
3603
- const handle = await fs16.open(lockPath, "wx");
3638
+ const handle = await fs17.open(lockPath, "wx");
3604
3639
  await writeLockMetadata(handle);
3605
3640
  let released = false;
3606
3641
  return async () => {
@@ -3608,7 +3643,7 @@ async function acquireFileLock(filePath, options = {}) {
3608
3643
  return;
3609
3644
  }
3610
3645
  released = true;
3611
- await removeLockFile(fs16, lockPath, options.signal);
3646
+ await removeLockFile(fs17, lockPath, options.signal);
3612
3647
  };
3613
3648
  } catch (error2) {
3614
3649
  if (!hasErrorCode(error2, "EEXIST")) {
@@ -3617,7 +3652,7 @@ async function acquireFileLock(filePath, options = {}) {
3617
3652
  }
3618
3653
  let stat7;
3619
3654
  try {
3620
- stat7 = await fs16.stat(lockPath);
3655
+ stat7 = await fs17.stat(lockPath);
3621
3656
  } catch (statError) {
3622
3657
  if (hasErrorCode(statError, "ENOENT")) {
3623
3658
  continue;
@@ -3625,7 +3660,7 @@ async function acquireFileLock(filePath, options = {}) {
3625
3660
  throw statError;
3626
3661
  }
3627
3662
  const reclaimLock = await shouldReclaimLock({
3628
- fs: fs16,
3663
+ fs: fs17,
3629
3664
  isPidRunning: pidIsRunning,
3630
3665
  lockPath,
3631
3666
  staleMs,
@@ -3635,7 +3670,7 @@ async function acquireFileLock(filePath, options = {}) {
3635
3670
  continue;
3636
3671
  }
3637
3672
  if (reclaimLock) {
3638
- await removeLockFile(fs16, lockPath, options.signal);
3673
+ await removeLockFile(fs17, lockPath, options.signal);
3639
3674
  continue;
3640
3675
  }
3641
3676
  if (attempt >= retries) {
@@ -3655,7 +3690,7 @@ function isNotFoundError(error2) {
3655
3690
  }
3656
3691
 
3657
3692
  // packages/poe-code-config/src/state/jobs.ts
3658
- function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3693
+ function createJobRegistry(homeDir, fs17 = defaultStateFs) {
3659
3694
  const jobsDir = path10.join(homeDir, ".poe-code", "state", "jobs");
3660
3695
  function jobPath(id) {
3661
3696
  assertSafeJobId(id);
@@ -3663,7 +3698,7 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3663
3698
  }
3664
3699
  async function get(id) {
3665
3700
  try {
3666
- return parseJobEntry(await fs16.readFile(jobPath(id), "utf8"));
3701
+ return parseJobEntry(await fs17.readFile(jobPath(id), "utf8"));
3667
3702
  } catch (error2) {
3668
3703
  if (isNotFoundError(error2)) {
3669
3704
  return null;
@@ -3674,8 +3709,8 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3674
3709
  async function put(entry) {
3675
3710
  assertJobEntry(entry);
3676
3711
  const filePath = jobPath(entry.id);
3677
- await fs16.mkdir(jobsDir, { recursive: true });
3678
- const release = await acquireFileLock(filePath, { fs: fs16 });
3712
+ await fs17.mkdir(jobsDir, { recursive: true });
3713
+ const release = await acquireFileLock(filePath, { fs: fs17 });
3679
3714
  try {
3680
3715
  await writeJobAtomically(filePath, entry);
3681
3716
  } finally {
@@ -3684,8 +3719,8 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3684
3719
  }
3685
3720
  async function update(id, patch) {
3686
3721
  const filePath = jobPath(id);
3687
- await fs16.mkdir(jobsDir, { recursive: true });
3688
- const release = await acquireFileLock(filePath, { fs: fs16 });
3722
+ await fs17.mkdir(jobsDir, { recursive: true });
3723
+ const release = await acquireFileLock(filePath, { fs: fs17 });
3689
3724
  try {
3690
3725
  const current = await get(id);
3691
3726
  if (current === null) {
@@ -3706,7 +3741,7 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3706
3741
  async function list(filter = {}) {
3707
3742
  let entries;
3708
3743
  try {
3709
- entries = await fs16.readdir(jobsDir);
3744
+ entries = await fs17.readdir(jobsDir);
3710
3745
  } catch (error2) {
3711
3746
  if (isNotFoundError(error2)) {
3712
3747
  return [];
@@ -3719,11 +3754,11 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3719
3754
  continue;
3720
3755
  }
3721
3756
  const filePath = path10.join(jobsDir, entry);
3722
- const stat7 = await fs16.stat(filePath);
3757
+ const stat7 = await fs17.stat(filePath);
3723
3758
  if (!stat7.isFile()) {
3724
3759
  continue;
3725
3760
  }
3726
- const job = parseJobEntry(await fs16.readFile(filePath, "utf8"));
3761
+ const job = parseJobEntry(await fs17.readFile(filePath, "utf8"));
3727
3762
  if (matchesFilter(job, filter)) {
3728
3763
  jobs.push(job);
3729
3764
  }
@@ -3733,16 +3768,16 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3733
3768
  async function remove2(id) {
3734
3769
  const filePath = jobPath(id);
3735
3770
  try {
3736
- await fs16.stat(jobsDir);
3771
+ await fs17.stat(jobsDir);
3737
3772
  } catch (error2) {
3738
3773
  if (isNotFoundError(error2)) {
3739
3774
  return;
3740
3775
  }
3741
3776
  throw error2;
3742
3777
  }
3743
- const release = await acquireFileLock(filePath, { fs: fs16 });
3778
+ const release = await acquireFileLock(filePath, { fs: fs17 });
3744
3779
  try {
3745
- await fs16.unlink(filePath);
3780
+ await fs17.unlink(filePath);
3746
3781
  } catch (error2) {
3747
3782
  if (!isNotFoundError(error2)) {
3748
3783
  throw error2;
@@ -3752,14 +3787,14 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3752
3787
  }
3753
3788
  }
3754
3789
  async function writeJobAtomically(filePath, entry) {
3755
- await fs16.mkdir(path10.dirname(filePath), { recursive: true });
3790
+ await fs17.mkdir(path10.dirname(filePath), { recursive: true });
3756
3791
  const tempPath = `${filePath}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
3757
3792
  try {
3758
- await fs16.writeFile(tempPath, `${JSON.stringify(entry, null, 2)}
3793
+ await fs17.writeFile(tempPath, `${JSON.stringify(entry, null, 2)}
3759
3794
  `, {
3760
3795
  encoding: "utf8"
3761
3796
  });
3762
- await fs16.rename(tempPath, filePath);
3797
+ await fs17.rename(tempPath, filePath);
3763
3798
  } catch (error2) {
3764
3799
  await removeTempFile(tempPath);
3765
3800
  throw error2;
@@ -3767,7 +3802,7 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3767
3802
  }
3768
3803
  async function removeTempFile(tempPath) {
3769
3804
  try {
3770
- await fs16.unlink(tempPath);
3805
+ await fs17.unlink(tempPath);
3771
3806
  } catch (error2) {
3772
3807
  if (!isNotFoundError(error2)) {
3773
3808
  throw error2;
@@ -3814,11 +3849,11 @@ function isRecord4(value) {
3814
3849
 
3815
3850
  // packages/poe-code-config/src/state/templates.ts
3816
3851
  import path11 from "node:path";
3817
- function createTemplateRegistry(homeDir, fs16 = defaultStateFs) {
3852
+ function createTemplateRegistry(homeDir, fs17 = defaultStateFs) {
3818
3853
  const filePath = path11.join(homeDir, ".poe-code", "state", "templates.json");
3819
3854
  async function readState() {
3820
3855
  try {
3821
- const raw = await fs16.readFile(filePath, "utf8");
3856
+ const raw = await fs17.readFile(filePath, "utf8");
3822
3857
  return normalizeTemplateState(JSON.parse(raw));
3823
3858
  } catch (error2) {
3824
3859
  if (isNotFoundError(error2)) {
@@ -3828,14 +3863,14 @@ function createTemplateRegistry(homeDir, fs16 = defaultStateFs) {
3828
3863
  }
3829
3864
  }
3830
3865
  async function writeState(state) {
3831
- await fs16.writeFile(filePath, `${JSON.stringify(state, null, 2)}
3866
+ await fs17.writeFile(filePath, `${JSON.stringify(state, null, 2)}
3832
3867
  `, {
3833
3868
  encoding: "utf8"
3834
3869
  });
3835
3870
  }
3836
3871
  async function updateState(mutator) {
3837
- await fs16.mkdir(path11.dirname(filePath), { recursive: true });
3838
- const release = await acquireFileLock(filePath, { fs: fs16 });
3872
+ await fs17.mkdir(path11.dirname(filePath), { recursive: true });
3873
+ const release = await acquireFileLock(filePath, { fs: fs17 });
3839
3874
  try {
3840
3875
  const state = await readState();
3841
3876
  mutator(state);
@@ -3905,10 +3940,10 @@ function isRecord5(value) {
3905
3940
  }
3906
3941
 
3907
3942
  // packages/poe-code-config/src/state/index.ts
3908
- function createStateManager(homeDir, fs16) {
3943
+ function createStateManager(homeDir, fs17) {
3909
3944
  return {
3910
- templates: createTemplateRegistry(homeDir, fs16),
3911
- jobs: createJobRegistry(homeDir, fs16)
3945
+ templates: createTemplateRegistry(homeDir, fs17),
3946
+ jobs: createJobRegistry(homeDir, fs17)
3912
3947
  };
3913
3948
  }
3914
3949
 
@@ -4136,10 +4171,10 @@ function parseSources(value) {
4136
4171
  if (!isRecord6(item)) {
4137
4172
  throw new Error('Invalid "sources" frontmatter. Expected each source to be a string or object.');
4138
4173
  }
4139
- const path50 = readRequiredString(item.path, "sources[].path");
4174
+ const path55 = readRequiredString(item.path, "sources[].path");
4140
4175
  const startLine = readOptionalPositiveInteger(item.startLine, "sources[].startLine");
4141
4176
  const endLine = readOptionalPositiveInteger(item.endLine, "sources[].endLine");
4142
- return parseSourceRef(serializeSourceRef({ path: path50, ...startLine === void 0 ? {} : { startLine }, ...endLine === void 0 ? {} : { endLine } }));
4177
+ return parseSourceRef(serializeSourceRef({ path: path55, ...startLine === void 0 ? {} : { startLine }, ...endLine === void 0 ? {} : { endLine } }));
4143
4178
  });
4144
4179
  }
4145
4180
  function readOptionalString(value, field) {
@@ -4381,18 +4416,18 @@ function isPidRunning2(pid) {
4381
4416
  return !hasErrorCode3(error2, "ESRCH");
4382
4417
  }
4383
4418
  }
4384
- async function removeLockFile2(fs16, lockPath) {
4419
+ async function removeLockFile2(fs17, lockPath) {
4385
4420
  try {
4386
- await fs16.unlink(lockPath);
4421
+ await fs17.unlink(lockPath);
4387
4422
  } catch (error2) {
4388
4423
  if (!hasErrorCode3(error2, "ENOENT")) {
4389
4424
  throw error2;
4390
4425
  }
4391
4426
  }
4392
4427
  }
4393
- async function readLockPid(fs16, lockPath) {
4428
+ async function readLockPid(fs17, lockPath) {
4394
4429
  try {
4395
- return parsePid(await fs16.readFile(lockPath, "utf8"));
4430
+ return parsePid(await fs17.readFile(lockPath, "utf8"));
4396
4431
  } catch (error2) {
4397
4432
  if (hasErrorCode3(error2, "ENOENT")) {
4398
4433
  return null;
@@ -4401,7 +4436,7 @@ async function readLockPid(fs16, lockPath) {
4401
4436
  }
4402
4437
  }
4403
4438
  async function withLock(root, run, options = {}) {
4404
- const fs16 = options.fs ?? createDefaultFs2();
4439
+ const fs17 = options.fs ?? createDefaultFs2();
4405
4440
  const lockPath = path17.join(root, MEMORY_LOCK_RELPATH);
4406
4441
  const pid = options.pid ?? process.pid;
4407
4442
  const retries = options.retries ?? 20;
@@ -4410,24 +4445,24 @@ async function withLock(root, run, options = {}) {
4410
4445
  const pidIsRunning = options.isPidRunning ?? isPidRunning2;
4411
4446
  for (let attempt = 0; attempt <= retries; attempt += 1) {
4412
4447
  try {
4413
- await fs16.writeFile(lockPath, `${pid}
4448
+ await fs17.writeFile(lockPath, `${pid}
4414
4449
  `, { encoding: "utf8", flag: "wx" });
4415
4450
  try {
4416
4451
  return await run();
4417
4452
  } finally {
4418
- await removeLockFile2(fs16, lockPath);
4453
+ await removeLockFile2(fs17, lockPath);
4419
4454
  }
4420
4455
  } catch (error2) {
4421
4456
  if (!hasErrorCode3(error2, "EEXIST")) {
4422
4457
  throw error2;
4423
4458
  }
4424
4459
  }
4425
- const existingPid = await readLockPid(fs16, lockPath);
4460
+ const existingPid = await readLockPid(fs17, lockPath);
4426
4461
  if (existingPid === null) {
4427
4462
  continue;
4428
4463
  }
4429
4464
  if (existingPid === void 0 || !pidIsRunning(existingPid)) {
4430
- await removeLockFile2(fs16, lockPath);
4465
+ await removeLockFile2(fs17, lockPath);
4431
4466
  continue;
4432
4467
  }
4433
4468
  if (attempt < retries) {
@@ -5194,8 +5229,8 @@ function parseOlderThan(value) {
5194
5229
  }
5195
5230
 
5196
5231
  // packages/memory/src/ingest.ts
5197
- import * as fs13 from "node:fs/promises";
5198
- import path45 from "node:path";
5232
+ import * as fs14 from "node:fs/promises";
5233
+ import path50 from "node:path";
5199
5234
 
5200
5235
  // packages/agent-spawn/src/register-factories.ts
5201
5236
  import { spawn as spawnChildProcess2 } from "node:child_process";
@@ -6031,29 +6066,29 @@ function wrapForLogTee(argv, jobId) {
6031
6066
  return ["sh", "-c", script];
6032
6067
  }
6033
6068
  async function* streamLogFile(env, jobId, opts) {
6034
- const fs16 = env.fs ?? nodeFs2;
6069
+ const fs17 = env.fs ?? nodeFs2;
6035
6070
  const file = jobLogPath(jobId);
6036
6071
  let byteOffset = opts.sinceByte ?? 0;
6037
6072
  while (true) {
6038
- if (opts.since !== void 0 && !await wasModifiedSince(fs16, file, opts.since)) {
6039
- await waitForLogChange(fs16, file);
6073
+ if (opts.since !== void 0 && !await wasModifiedSince(fs17, file, opts.since)) {
6074
+ await waitForLogChange(fs17, file);
6040
6075
  continue;
6041
6076
  }
6042
- const result = await readLogChunk(fs16, file, byteOffset);
6077
+ const result = await readLogChunk(fs17, file, byteOffset);
6043
6078
  if (result !== null) {
6044
6079
  byteOffset = result.nextByteOffset;
6045
6080
  yield result.chunk;
6046
6081
  continue;
6047
6082
  }
6048
- await waitForLogChange(fs16, file);
6083
+ await waitForLogChange(fs17, file);
6049
6084
  }
6050
6085
  }
6051
- async function wasModifiedSince(fs16, file, since) {
6052
- if (fs16.promises.stat === void 0) {
6086
+ async function wasModifiedSince(fs17, file, since) {
6087
+ if (fs17.promises.stat === void 0) {
6053
6088
  return true;
6054
6089
  }
6055
6090
  try {
6056
- const stat7 = await fs16.promises.stat(file);
6091
+ const stat7 = await fs17.promises.stat(file);
6057
6092
  return stat7.mtimeMs >= since.getTime();
6058
6093
  } catch (error2) {
6059
6094
  if (isNodeError(error2) && error2.code === "ENOENT") {
@@ -6063,11 +6098,11 @@ async function wasModifiedSince(fs16, file, since) {
6063
6098
  }
6064
6099
  }
6065
6100
  async function waitForExit(env, jobId, opts = {}) {
6066
- const fs16 = env.fs ?? nodeFs2;
6101
+ const fs17 = env.fs ?? nodeFs2;
6067
6102
  const file = jobExitPath(jobId);
6068
6103
  while (true) {
6069
6104
  throwIfAborted2(opts.signal);
6070
- const contents = await readTextFileIfExists(fs16, file);
6105
+ const contents = await readTextFileIfExists(fs17, file);
6071
6106
  if (contents !== null) {
6072
6107
  const text5 = contents.trim();
6073
6108
  const exitCode = Number(text5);
@@ -6085,8 +6120,8 @@ function jobLogPath(jobId) {
6085
6120
  function jobExitPath(jobId) {
6086
6121
  return `${JOB_DIR}/${jobId}.exit`;
6087
6122
  }
6088
- async function readLogChunk(fs16, file, byteOffset) {
6089
- const contents = await readFileIfExists2(fs16, file);
6123
+ async function readLogChunk(fs17, file, byteOffset) {
6124
+ const contents = await readFileIfExists2(fs17, file);
6090
6125
  if (contents === null || byteOffset >= contents.byteLength) {
6091
6126
  return null;
6092
6127
  }
@@ -6098,13 +6133,13 @@ async function readLogChunk(fs16, file, byteOffset) {
6098
6133
  nextByteOffset: contents.byteLength
6099
6134
  };
6100
6135
  }
6101
- async function readTextFileIfExists(fs16, file) {
6102
- const contents = await readFileIfExists2(fs16, file);
6136
+ async function readTextFileIfExists(fs17, file) {
6137
+ const contents = await readFileIfExists2(fs17, file);
6103
6138
  return contents?.toString("utf8") ?? null;
6104
6139
  }
6105
- async function readFileIfExists2(fs16, file) {
6140
+ async function readFileIfExists2(fs17, file) {
6106
6141
  try {
6107
- const contents = await fs16.promises.readFile(file);
6142
+ const contents = await fs17.promises.readFile(file);
6108
6143
  return Buffer.isBuffer(contents) ? contents : Buffer.from(contents);
6109
6144
  } catch (error2) {
6110
6145
  if (isNodeError(error2) && error2.code === "ENOENT") {
@@ -6113,8 +6148,8 @@ async function readFileIfExists2(fs16, file) {
6113
6148
  throw error2;
6114
6149
  }
6115
6150
  }
6116
- async function waitForLogChange(fs16, file) {
6117
- const watch = fs16.watch;
6151
+ async function waitForLogChange(fs17, file) {
6152
+ const watch = fs17.watch;
6118
6153
  if (typeof watch !== "function") {
6119
6154
  await sleep3(POLL_INTERVAL_MS);
6120
6155
  return;
@@ -6905,7 +6940,7 @@ import { PassThrough as PassThrough2, Writable as Writable2 } from "node:stream"
6905
6940
  import path33 from "node:path";
6906
6941
  var JOB_DIR2 = "/tmp/poe-jobs";
6907
6942
  function createE2bJobHandle(input) {
6908
- const fs16 = createE2bLogStreamFs(input.sandbox);
6943
+ const fs17 = createE2bLogStreamFs(input.sandbox);
6909
6944
  return {
6910
6945
  id: input.jobId,
6911
6946
  envId: input.envId,
@@ -6921,10 +6956,10 @@ function createE2bJobHandle(input) {
6921
6956
  return isRunning ? "running" : "lost";
6922
6957
  },
6923
6958
  stream(opts = {}) {
6924
- return streamLogFile({ fs: fs16 }, input.jobId, opts);
6959
+ return streamLogFile({ fs: fs17 }, input.jobId, opts);
6925
6960
  },
6926
6961
  async wait() {
6927
- const result = await waitForExit({ fs: fs16 }, input.jobId);
6962
+ const result = await waitForExit({ fs: fs17 }, input.jobId);
6928
6963
  const preserveMs = input.preserveAfterExitHours * 60 * 60 * 1e3;
6929
6964
  if (preserveMs > 0) {
6930
6965
  await input.sandbox.setTimeout(preserveMs);
@@ -7421,10 +7456,10 @@ var e2bAuthScope = defineScope("e2b", {
7421
7456
  });
7422
7457
  async function resolveE2bApiKey(input) {
7423
7458
  const homeDir = input.homeDir ?? os4.homedir();
7424
- const fs16 = input.fs ?? nodeFs4;
7459
+ const fs17 = input.fs ?? nodeFs4;
7425
7460
  const env = input.env ?? process.env;
7426
7461
  const document = await readMergedDocument(
7427
- fs16,
7462
+ fs17,
7428
7463
  resolveConfigPath(homeDir),
7429
7464
  resolveProjectConfigPath(input.cwd)
7430
7465
  );
@@ -7931,6 +7966,23 @@ var gooseAcpSpawnConfig = {
7931
7966
  skipAuth: true
7932
7967
  };
7933
7968
 
7969
+ // packages/agent-spawn/src/configs/gemini-cli.ts
7970
+ var geminiCliAcpSpawnConfig = {
7971
+ kind: "acp",
7972
+ agentId: "gemini-cli",
7973
+ acpArgs: ({ model, mcpServers }) => [
7974
+ "--acp",
7975
+ ...model ? ["--model", model] : [],
7976
+ ...mcpServers ? ["--allowed-mcp-server-names", Object.keys(mcpServers).join(",")] : [],
7977
+ ...mcpServers ? ["--skip-trust"] : [],
7978
+ "--yolo"
7979
+ ],
7980
+ env: {
7981
+ GEMINI_SANDBOX: "false"
7982
+ },
7983
+ skipAuth: true
7984
+ };
7985
+
7934
7986
  // packages/agent-spawn/src/configs/index.ts
7935
7987
  var allSpawnConfigs = [
7936
7988
  claudeCodeSpawnConfig,
@@ -7947,6 +7999,7 @@ var acpLookup = /* @__PURE__ */ new Map();
7947
7999
  acpLookup.set(openCodeAcpSpawnConfig.agentId, openCodeAcpSpawnConfig);
7948
8000
  acpLookup.set(kimiAcpSpawnConfig.agentId, kimiAcpSpawnConfig);
7949
8001
  acpLookup.set(gooseAcpSpawnConfig.agentId, gooseAcpSpawnConfig);
8002
+ acpLookup.set(geminiCliAcpSpawnConfig.agentId, geminiCliAcpSpawnConfig);
7950
8003
  function getSpawnConfig(input) {
7951
8004
  const resolvedId = resolveAgentId(input);
7952
8005
  if (!resolvedId) {
@@ -7966,8 +8019,8 @@ function listMcpSupportedAgents() {
7966
8019
  }
7967
8020
 
7968
8021
  // packages/agent-spawn/src/spawn.ts
7969
- import { mkdirSync as mkdirSync3, openSync, writeSync, closeSync } from "node:fs";
7970
- import path41 from "node:path";
8022
+ import { mkdirSync as mkdirSync5, openSync as openSync2, writeSync, closeSync as closeSync2 } from "node:fs";
8023
+ import path46 from "node:path";
7971
8024
 
7972
8025
  // packages/agent-spawn/src/configs/resolve-config.ts
7973
8026
  function resolveConfig(agentId) {
@@ -8368,7 +8421,7 @@ function createEventQueue() {
8368
8421
 
8369
8422
  // packages/agent-spawn/src/skill-bridge.ts
8370
8423
  import crypto from "node:crypto";
8371
- import os6 from "node:os";
8424
+ import os7 from "node:os";
8372
8425
 
8373
8426
  // packages/agent-skill-config/src/configs.ts
8374
8427
  import os5 from "node:os";
@@ -8382,6 +8435,10 @@ var agentSkillConfigs = {
8382
8435
  globalSkillDir: "~/.codex/skills",
8383
8436
  localSkillDir: ".codex/skills"
8384
8437
  },
8438
+ "gemini-cli": {
8439
+ globalSkillDir: "~/.gemini/skills",
8440
+ localSkillDir: ".gemini/skills"
8441
+ },
8385
8442
  opencode: {
8386
8443
  globalSkillDir: "~/.config/opencode/skills",
8387
8444
  localSkillDir: ".opencode/skills"
@@ -8578,7 +8635,7 @@ function resolveSkillReference(ref, cwd, homeDir) {
8578
8635
  import { execFileSync } from "node:child_process";
8579
8636
  import * as fs10 from "node:fs";
8580
8637
  import path39 from "node:path";
8581
- var markerPrefix = "# poe-code-spawn-skills:";
8638
+ var defaultMarkerPrefix = "poe-code-spawn-skills";
8582
8639
  function defaultGitDirRunner(cwd) {
8583
8640
  try {
8584
8641
  return execFileSync("git", ["rev-parse", "--git-dir"], {
@@ -8598,10 +8655,10 @@ function resolveExcludePath(cwd) {
8598
8655
  }
8599
8656
  return path39.join(path39.isAbsolute(gitDir) ? gitDir : path39.resolve(cwd, gitDir), "info/exclude");
8600
8657
  }
8601
- function markers(runId) {
8658
+ function markers(runId, markerPrefix) {
8602
8659
  return {
8603
- begin: `${markerPrefix}${runId} begin`,
8604
- end: `${markerPrefix}${runId} end`
8660
+ begin: `# ${markerPrefix}:${runId} begin`,
8661
+ end: `# ${markerPrefix}:${runId} end`
8605
8662
  };
8606
8663
  }
8607
8664
  function readExcludeFile(excludePath) {
@@ -8617,8 +8674,8 @@ function readExcludeFile(excludePath) {
8617
8674
  function isNodeError2(error2) {
8618
8675
  return error2 instanceof Error && "code" in error2;
8619
8676
  }
8620
- function removeBlock(content, runId) {
8621
- const { begin, end } = markers(runId);
8677
+ function removeBlock(content, runId, markerPrefix) {
8678
+ const { begin, end } = markers(runId, markerPrefix);
8622
8679
  const lines = content.split("\n");
8623
8680
  const result = [];
8624
8681
  for (let index = 0; index < lines.length; index += 1) {
@@ -8633,23 +8690,27 @@ function removeBlock(content, runId) {
8633
8690
  }
8634
8691
  return result.join("\n");
8635
8692
  }
8636
- function appendBlock(content, runId, entries) {
8637
- const { begin, end } = markers(runId);
8693
+ function appendBlock(content, runId, entries, markerPrefix) {
8694
+ const { begin, end } = markers(runId, markerPrefix);
8638
8695
  const existing = content ?? "";
8639
8696
  const prefix = existing.length === 0 || existing.endsWith("\n") ? existing : `${existing}
8640
8697
  `;
8641
8698
  return `${prefix}${[begin, ...entries, end, ""].join("\n")}`;
8642
8699
  }
8643
- function appendExcludeBlock(cwd, runId, entries) {
8700
+ function appendExcludeBlock(cwd, runId, entries, opts) {
8644
8701
  const excludePath = resolveExcludePath(cwd);
8645
8702
  if (excludePath === void 0) {
8646
8703
  return;
8647
8704
  }
8648
8705
  fs10.mkdirSync(path39.dirname(excludePath), { recursive: true });
8649
8706
  const content = readExcludeFile(excludePath);
8650
- fs10.writeFileSync(excludePath, appendBlock(content, runId, entries), "utf8");
8707
+ fs10.writeFileSync(
8708
+ excludePath,
8709
+ appendBlock(content, runId, entries, opts?.markerPrefix ?? defaultMarkerPrefix),
8710
+ "utf8"
8711
+ );
8651
8712
  }
8652
- function removeExcludeBlock(cwd, runId) {
8713
+ function removeExcludeBlock(cwd, runId, opts) {
8653
8714
  const excludePath = resolveExcludePath(cwd);
8654
8715
  if (excludePath === void 0) {
8655
8716
  return;
@@ -8658,7 +8719,11 @@ function removeExcludeBlock(cwd, runId) {
8658
8719
  if (content === void 0) {
8659
8720
  return;
8660
8721
  }
8661
- fs10.writeFileSync(excludePath, removeBlock(content, runId), "utf8");
8722
+ fs10.writeFileSync(
8723
+ excludePath,
8724
+ removeBlock(content, runId, opts?.markerPrefix ?? defaultMarkerPrefix),
8725
+ "utf8"
8726
+ );
8662
8727
  }
8663
8728
 
8664
8729
  // packages/agent-skill-config/src/bridge-active-skills.ts
@@ -8864,22 +8929,679 @@ function cleanupBridgedSkills(manifest) {
8864
8929
  removeExcludeBlock(manifest.cwd, manifest.runId);
8865
8930
  }
8866
8931
 
8932
+ // packages/agent-hook-config/src/configs.ts
8933
+ import os6 from "node:os";
8934
+ import path41 from "node:path";
8935
+ var agentHookConfigs = {
8936
+ "claude-code": {
8937
+ globalHookPath: "~/.claude/settings.json",
8938
+ localHookPath: ".claude/settings.json",
8939
+ format: "claude-settings-json",
8940
+ supportedEvents: [
8941
+ "SessionStart",
8942
+ "SessionEnd",
8943
+ "UserPromptSubmit",
8944
+ "PreToolUse",
8945
+ "PostToolUse",
8946
+ "PermissionRequest",
8947
+ "Stop",
8948
+ "StopFailure",
8949
+ "Notification",
8950
+ "PreCompact",
8951
+ "PostCompact",
8952
+ "SubagentStart",
8953
+ "SubagentStop"
8954
+ ],
8955
+ supportedHandlerTypes: ["command", "http", "mcp_tool", "prompt", "agent"],
8956
+ placeholders: {
8957
+ projectDir: "${CLAUDE_PROJECT_DIR}",
8958
+ pluginRoot: "${CLAUDE_PLUGIN_ROOT}",
8959
+ pluginData: "${CLAUDE_PLUGIN_DATA}"
8960
+ }
8961
+ },
8962
+ codex: {
8963
+ globalHookPath: "~/.codex/hooks.json",
8964
+ localHookPath: ".codex/hooks.json",
8965
+ format: "codex-hooks-json",
8966
+ supportedEvents: [
8967
+ "SessionStart",
8968
+ "UserPromptSubmit",
8969
+ "PreToolUse",
8970
+ "PostToolUse",
8971
+ "PermissionRequest",
8972
+ "Stop"
8973
+ ],
8974
+ supportedHandlerTypes: ["command"],
8975
+ placeholders: {
8976
+ projectDir: "$(git rev-parse --show-toplevel)",
8977
+ pluginRoot: "$PLUGIN_ROOT",
8978
+ pluginData: "$PLUGIN_DATA"
8979
+ }
8980
+ }
8981
+ };
8982
+ var supportedHookAgents = Object.keys(agentHookConfigs);
8983
+ function resolveAgentSupport2(input, registry = agentHookConfigs) {
8984
+ const resolvedId = resolveAgentId(input);
8985
+ if (!resolvedId) {
8986
+ return { status: "unknown", input };
8987
+ }
8988
+ const config = registry[resolvedId];
8989
+ if (!config) {
8990
+ return { status: "unsupported", input, id: resolvedId };
8991
+ }
8992
+ return { status: "supported", input, id: resolvedId, config };
8993
+ }
8994
+ function getAgentConfig2(agentId) {
8995
+ const support = resolveAgentSupport2(agentId);
8996
+ return support.status === "supported" ? support.config : void 0;
8997
+ }
8998
+ function expandHome3(targetPath, homeDir = os6.homedir()) {
8999
+ if (!targetPath?.startsWith("~")) {
9000
+ return targetPath;
9001
+ }
9002
+ if (targetPath === "~") {
9003
+ return homeDir;
9004
+ }
9005
+ if (targetPath.startsWith("~./")) {
9006
+ targetPath = `~/.${targetPath.slice(3)}`;
9007
+ }
9008
+ let remainder = targetPath.slice(1);
9009
+ if (remainder.startsWith("/") || remainder.startsWith("\\")) {
9010
+ remainder = remainder.slice(1);
9011
+ } else if (remainder.startsWith(".")) {
9012
+ remainder = remainder.slice(1);
9013
+ if (remainder.startsWith("/") || remainder.startsWith("\\")) {
9014
+ remainder = remainder.slice(1);
9015
+ }
9016
+ }
9017
+ return remainder.length === 0 ? homeDir : path41.join(homeDir, remainder);
9018
+ }
9019
+ function resolveHookPath(config, scope, cwd, homeDir) {
9020
+ if (scope === "global") {
9021
+ return path41.resolve(expandHome3(config.globalHookPath, homeDir));
9022
+ }
9023
+ return config.localHookPath ? path41.resolve(cwd, config.localHookPath) : void 0;
9024
+ }
9025
+
9026
+ // packages/agent-hook-config/src/read-hooks.ts
9027
+ import { readFileSync as readFileSync3 } from "node:fs";
9028
+ import path42 from "node:path";
9029
+ function readSettingsFile(filePath) {
9030
+ let content;
9031
+ try {
9032
+ content = readFileSync3(filePath, "utf8");
9033
+ } catch (error2) {
9034
+ if (error2.code === "ENOENT") {
9035
+ return void 0;
9036
+ }
9037
+ throw error2;
9038
+ }
9039
+ try {
9040
+ return JSON.parse(content);
9041
+ } catch (error2) {
9042
+ throw new Error(`Malformed JSON in ${filePath}`, { cause: error2 });
9043
+ }
9044
+ }
9045
+ function readClaudeHooks(cwd, homeDir, opts) {
9046
+ const projectPath = path42.resolve(cwd, ".claude/settings.json");
9047
+ const userPath = path42.resolve(homeDir, ".claude/settings.json");
9048
+ const scope = opts?.scope ?? "merged";
9049
+ const sourcePaths = scope === "project" ? [projectPath] : scope === "user" ? [userPath] : [userPath, projectPath];
9050
+ const result = { entries: [], readPaths: [] };
9051
+ for (const sourcePath of sourcePaths) {
9052
+ const settings = readSettingsFile(sourcePath);
9053
+ if (settings === void 0) {
9054
+ continue;
9055
+ }
9056
+ result.readPaths.push(sourcePath);
9057
+ for (const [event, groups] of Object.entries(settings.hooks ?? {})) {
9058
+ for (const group of groups) {
9059
+ for (const handler of group.hooks) {
9060
+ result.entries.push({ event, matcher: group.matcher, handler });
9061
+ }
9062
+ }
9063
+ }
9064
+ }
9065
+ return result;
9066
+ }
9067
+
9068
+ // packages/agent-hook-config/src/event-mapping.ts
9069
+ function requireAgentConfig(agentId) {
9070
+ const config = getAgentConfig2(agentId);
9071
+ if (!config) {
9072
+ throw new Error(`Unknown hook agent "${agentId}"`);
9073
+ }
9074
+ return config;
9075
+ }
9076
+ function getEventMappings(sourceAgentId, targetAgentId) {
9077
+ const source = requireAgentConfig(sourceAgentId);
9078
+ const target = requireAgentConfig(targetAgentId);
9079
+ return source.supportedEvents.map((sourceEvent) => {
9080
+ if (target.supportedEvents.includes(sourceEvent)) {
9081
+ return { sourceEvent, targetEvent: sourceEvent };
9082
+ }
9083
+ return {
9084
+ sourceEvent,
9085
+ targetEvent: null,
9086
+ dropReason: `${targetAgentId} has no ${sourceEvent} hook`
9087
+ };
9088
+ });
9089
+ }
9090
+ function getHandlerTypeRules(targetAgentId) {
9091
+ const target = requireAgentConfig(targetAgentId);
9092
+ const registeredTypes = supportedHookAgents.flatMap(
9093
+ (agentId) => requireAgentConfig(agentId).supportedHandlerTypes
9094
+ );
9095
+ const sourceTypes = [...new Set(registeredTypes)];
9096
+ const supportedTypes = target.supportedHandlerTypes.map((handlerType) => `"${handlerType}"`).join(", ");
9097
+ return sourceTypes.map((sourceType) => {
9098
+ if (target.supportedHandlerTypes.includes(sourceType)) {
9099
+ return { sourceType, allowed: true };
9100
+ }
9101
+ return {
9102
+ sourceType,
9103
+ allowed: false,
9104
+ dropReason: `${targetAgentId} only honors handlers of type ${supportedTypes}`
9105
+ };
9106
+ });
9107
+ }
9108
+ function getPlaceholderRewrites(sourceAgentId, targetAgentId) {
9109
+ const source = requireAgentConfig(sourceAgentId);
9110
+ const target = requireAgentConfig(targetAgentId);
9111
+ return Object.keys(source.placeholders).flatMap((key) => {
9112
+ const from = source.placeholders[key];
9113
+ const to = target.placeholders[key];
9114
+ if (!from || !to || from === to) {
9115
+ return [];
9116
+ }
9117
+ return [{ from, to }];
9118
+ });
9119
+ }
9120
+
9121
+ // packages/agent-hook-config/src/transform-hooks.ts
9122
+ function applyPlaceholderRewrites(value, rewrites) {
9123
+ return rewrites.reduce((rewrittenValue, rewrite) => {
9124
+ return rewrittenValue.replaceAll(rewrite.from, rewrite.to);
9125
+ }, value);
9126
+ }
9127
+ function transformHooks(source, sourceAgentId, targetAgentId, opts) {
9128
+ const eventMappings = getEventMappings(sourceAgentId, targetAgentId);
9129
+ const handlerRules = getHandlerTypeRules(targetAgentId);
9130
+ const placeholderRewrites = getPlaceholderRewrites(sourceAgentId, targetAgentId);
9131
+ const result = { entries: [], drops: [] };
9132
+ for (const sourceEntry of source) {
9133
+ const eventMapping = eventMappings.find((mapping) => mapping.sourceEvent === sourceEntry.event);
9134
+ if (!eventMapping || eventMapping.targetEvent === null) {
9135
+ result.drops.push({
9136
+ reason: "unsupported-event",
9137
+ detail: eventMapping?.dropReason ?? `${targetAgentId} has no ${sourceEntry.event} hook`,
9138
+ source: sourceEntry
9139
+ });
9140
+ continue;
9141
+ }
9142
+ const handlerRule = handlerRules.find((rule) => rule.sourceType === sourceEntry.handler.type);
9143
+ if (!handlerRule?.allowed) {
9144
+ result.drops.push({
9145
+ reason: "unsupported-handler-type",
9146
+ detail: `Unsupported handler type "${sourceEntry.handler.type}": ${handlerRule?.dropReason ?? `${targetAgentId} does not honor it`}`,
9147
+ source: sourceEntry
9148
+ });
9149
+ continue;
9150
+ }
9151
+ const handler = {
9152
+ type: "command",
9153
+ command: applyPlaceholderRewrites(sourceEntry.handler.command ?? "", placeholderRewrites),
9154
+ statusMessage: `[generated:${opts.runId}] ${sourceEntry.handler.statusMessage ?? ""}`
9155
+ };
9156
+ if (sourceEntry.handler.args !== void 0) {
9157
+ handler.args = sourceEntry.handler.args.map(
9158
+ (arg) => applyPlaceholderRewrites(arg, placeholderRewrites)
9159
+ );
9160
+ }
9161
+ if (sourceEntry.handler.timeout !== void 0) {
9162
+ handler.timeout = sourceEntry.handler.timeout;
9163
+ }
9164
+ result.entries.push({
9165
+ event: eventMapping.targetEvent,
9166
+ matcher: sourceEntry.matcher,
9167
+ handler,
9168
+ generatedId: `generated-${opts.runId}-${result.entries.length}`
9169
+ });
9170
+ }
9171
+ return result;
9172
+ }
9173
+
9174
+ // packages/agent-hook-config/src/write-hooks.ts
9175
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync, writeFileSync as writeFileSync2 } from "node:fs";
9176
+ import path43 from "node:path";
9177
+ function isGeneratedHandler(handler) {
9178
+ return handler.statusMessage?.startsWith("[generated:") ?? false;
9179
+ }
9180
+ function parseHooksFile(targetPath) {
9181
+ let content;
9182
+ try {
9183
+ content = readFileSync4(targetPath, "utf8");
9184
+ } catch (error2) {
9185
+ if (error2.code === "ENOENT") {
9186
+ return { file: { hooks: {} }, fileCreated: true };
9187
+ }
9188
+ throw error2;
9189
+ }
9190
+ try {
9191
+ return { file: JSON.parse(content), fileCreated: false };
9192
+ } catch (error2) {
9193
+ throw new Error(`Malformed JSON in ${targetPath}`, { cause: error2 });
9194
+ }
9195
+ }
9196
+ function validateEntries(entries) {
9197
+ for (const entry of entries) {
9198
+ if (!isGeneratedHandler(entry.handler)) {
9199
+ throw new Error(
9200
+ `Generated hook entry "${entry.generatedId}" has statusMessage that must start with "[generated:"`
9201
+ );
9202
+ }
9203
+ }
9204
+ }
9205
+ function removeGeneratedHandlers(file) {
9206
+ let removed = 0;
9207
+ const hooks = file.hooks ?? (file.hooks = {});
9208
+ for (const [event, groups] of Object.entries(hooks)) {
9209
+ hooks[event] = groups.filter((group) => {
9210
+ const initialCount = group.hooks.length;
9211
+ const remainingHandlers = group.hooks.filter((handler) => {
9212
+ if (isGeneratedHandler(handler)) {
9213
+ removed += 1;
9214
+ return false;
9215
+ }
9216
+ return true;
9217
+ });
9218
+ group.hooks = remainingHandlers;
9219
+ return group.hooks.length > 0 || group.hooks.length === initialCount;
9220
+ });
9221
+ }
9222
+ return removed;
9223
+ }
9224
+ function appendEntries(file, entries) {
9225
+ const hooks = file.hooks ?? (file.hooks = {});
9226
+ for (const entry of entries) {
9227
+ const groups = hooks[entry.event] ?? (hooks[entry.event] = []);
9228
+ let group = groups.find((candidate) => candidate.matcher === entry.matcher);
9229
+ if (!group) {
9230
+ group = entry.matcher === void 0 ? { hooks: [] } : { matcher: entry.matcher, hooks: [] };
9231
+ groups.push(group);
9232
+ }
9233
+ group.hooks.push(entry.handler);
9234
+ }
9235
+ }
9236
+ function writeCodexHooks(targetPath, entries, _runId) {
9237
+ const { file, fileCreated } = parseHooksFile(targetPath);
9238
+ validateEntries(entries);
9239
+ const previousGeneratedRemoved = removeGeneratedHandlers(file);
9240
+ appendEntries(file, entries);
9241
+ mkdirSync3(path43.dirname(targetPath), { recursive: true });
9242
+ const temporaryPath = `${targetPath}.tmp`;
9243
+ writeFileSync2(temporaryPath, `${JSON.stringify(file, null, 2)}
9244
+ `);
9245
+ renameSync(temporaryPath, targetPath);
9246
+ return {
9247
+ path: targetPath,
9248
+ fileCreated,
9249
+ previousGeneratedRemoved,
9250
+ generatedWritten: entries.length
9251
+ };
9252
+ }
9253
+
9254
+ // packages/agent-hook-config/src/symlink-hooks.ts
9255
+ import {
9256
+ closeSync,
9257
+ lstatSync,
9258
+ mkdirSync as mkdirSync4,
9259
+ openSync,
9260
+ readlinkSync,
9261
+ readSync,
9262
+ symlinkSync,
9263
+ unlinkSync
9264
+ } from "node:fs";
9265
+ import path44 from "node:path";
9266
+ function requireAgentConfig2(agentId) {
9267
+ const config = getAgentConfig2(agentId);
9268
+ if (!config) {
9269
+ throw new Error(`No hook configuration found for agent "${agentId}"`);
9270
+ }
9271
+ return config;
9272
+ }
9273
+ function resolveScopedPath(config, agentId, cwd, homeDir, scope) {
9274
+ const targetPath = resolveHookPath(
9275
+ config,
9276
+ scope === "project" ? "local" : "global",
9277
+ cwd,
9278
+ homeDir
9279
+ );
9280
+ if (!targetPath) {
9281
+ throw new Error(`Agent "${agentId}" has no ${scope} hook path`);
9282
+ }
9283
+ return targetPath;
9284
+ }
9285
+ function readFirstKilobyte(filePath) {
9286
+ const descriptor = openSync(filePath, "r");
9287
+ const buffer = Buffer.alloc(1024);
9288
+ try {
9289
+ const length = readSync(descriptor, buffer, 0, buffer.length, 0);
9290
+ return buffer.toString("utf8", 0, length);
9291
+ } finally {
9292
+ closeSync(descriptor);
9293
+ }
9294
+ }
9295
+ function isRecord8(value) {
9296
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9297
+ }
9298
+ function isFullyGeneratedFile(filePath) {
9299
+ let parsed;
9300
+ try {
9301
+ parsed = JSON.parse(readFirstKilobyte(filePath));
9302
+ } catch {
9303
+ return false;
9304
+ }
9305
+ if (!isRecord8(parsed)) {
9306
+ return false;
9307
+ }
9308
+ if (Object.keys(parsed).some((key) => key !== "hooks")) {
9309
+ return false;
9310
+ }
9311
+ const hooks = parsed.hooks;
9312
+ if (!isRecord8(hooks)) {
9313
+ return false;
9314
+ }
9315
+ let handlerFound = false;
9316
+ for (const groups of Object.values(hooks)) {
9317
+ if (!Array.isArray(groups)) {
9318
+ return false;
9319
+ }
9320
+ for (const group of groups) {
9321
+ if (!isRecord8(group) || !Array.isArray(group.hooks)) {
9322
+ return false;
9323
+ }
9324
+ for (const handler of group.hooks) {
9325
+ if (!isRecord8(handler)) {
9326
+ return false;
9327
+ }
9328
+ handlerFound = true;
9329
+ const statusMessage = handler.statusMessage;
9330
+ if (typeof statusMessage !== "string" || !statusMessage.startsWith("[generated:")) {
9331
+ return false;
9332
+ }
9333
+ }
9334
+ }
9335
+ }
9336
+ return handlerFound;
9337
+ }
9338
+ function symlinkHooks(sourceAgentId, targetAgentId, cwd, homeDir, scope) {
9339
+ const source = requireAgentConfig2(sourceAgentId);
9340
+ const target = requireAgentConfig2(targetAgentId);
9341
+ if (source.format !== target.format) {
9342
+ throw new Error(
9343
+ `Cannot symlink hook formats "${source.format}" and "${target.format}"; use transformation instead`
9344
+ );
9345
+ }
9346
+ const targetPath = resolveScopedPath(source, sourceAgentId, cwd, homeDir, scope);
9347
+ const symlinkPath = resolveScopedPath(target, targetAgentId, cwd, homeDir, scope);
9348
+ let replaced = "none";
9349
+ try {
9350
+ const existing = lstatSync(symlinkPath);
9351
+ if (existing.isSymbolicLink()) {
9352
+ if (readlinkSync(symlinkPath) === targetPath) {
9353
+ return { symlinkPath, targetPath, replaced };
9354
+ }
9355
+ unlinkSync(symlinkPath);
9356
+ replaced = "stale-symlink";
9357
+ } else if (existing.isFile() && isFullyGeneratedFile(symlinkPath)) {
9358
+ unlinkSync(symlinkPath);
9359
+ replaced = "generated-file";
9360
+ } else {
9361
+ throw new Error(`Refuse to replace user-authored hook file at ${symlinkPath}`);
9362
+ }
9363
+ } catch (error2) {
9364
+ if (error2.code !== "ENOENT") {
9365
+ throw error2;
9366
+ }
9367
+ }
9368
+ mkdirSync4(path44.dirname(symlinkPath), { recursive: true });
9369
+ symlinkSync(targetPath, symlinkPath);
9370
+ return { symlinkPath, targetPath, replaced };
9371
+ }
9372
+
9373
+ // packages/agent-hook-config/src/bridge-hooks.ts
9374
+ import * as fs12 from "node:fs";
9375
+ import path45 from "node:path";
9376
+ var hookExcludeMarkerPrefix = "poe-code-spawn-hooks";
9377
+ function isNodeError4(error2) {
9378
+ return error2 instanceof Error && "code" in error2;
9379
+ }
9380
+ function pathExists4(targetPath) {
9381
+ try {
9382
+ fs12.lstatSync(targetPath);
9383
+ return true;
9384
+ } catch (error2) {
9385
+ if (isNodeError4(error2) && error2.code === "ENOENT") {
9386
+ return false;
9387
+ }
9388
+ throw error2;
9389
+ }
9390
+ }
9391
+ function collectMissingParents2(targetPath) {
9392
+ const parents = [];
9393
+ let current = path45.dirname(targetPath);
9394
+ while (!pathExists4(current)) {
9395
+ parents.push(current);
9396
+ const parent = path45.dirname(current);
9397
+ if (parent === current) {
9398
+ break;
9399
+ }
9400
+ current = parent;
9401
+ }
9402
+ return parents.reverse();
9403
+ }
9404
+ function removeDirectoryIfEmpty2(targetPath) {
9405
+ try {
9406
+ fs12.rmdirSync(targetPath);
9407
+ } catch (error2) {
9408
+ if (isNodeError4(error2) && (error2.code === "ENOENT" || error2.code === "ENOTEMPTY" || error2.code === "EEXIST")) {
9409
+ return;
9410
+ }
9411
+ throw error2;
9412
+ }
9413
+ }
9414
+ function requireSupport(input, role) {
9415
+ const support = resolveAgentSupport2(input);
9416
+ if (support.status !== "supported" || !support.id || !support.config) {
9417
+ throw new Error(
9418
+ `Unsupported ${role} hook agent "${input}". Supported hook agents: ${supportedHookAgents.join(", ")}.`
9419
+ );
9420
+ }
9421
+ return { id: support.id, config: support.config };
9422
+ }
9423
+ function requireTargetPath(targetId, config, cwd, homeDir) {
9424
+ const targetPath = resolveHookPath(config, "local", cwd, homeDir);
9425
+ if (!targetPath) {
9426
+ throw new Error(`Agent "${targetId}" has no project hook path`);
9427
+ }
9428
+ return targetPath;
9429
+ }
9430
+ function readCodexFile(targetPath) {
9431
+ let content;
9432
+ try {
9433
+ content = fs12.readFileSync(targetPath, "utf8");
9434
+ } catch (error2) {
9435
+ if (isNodeError4(error2) && error2.code === "ENOENT") {
9436
+ return void 0;
9437
+ }
9438
+ throw error2;
9439
+ }
9440
+ try {
9441
+ return JSON.parse(content);
9442
+ } catch (error2) {
9443
+ throw new Error(`Malformed JSON in ${targetPath}`, { cause: error2 });
9444
+ }
9445
+ }
9446
+ function writeCodexFile(targetPath, file) {
9447
+ fs12.writeFileSync(targetPath, `${JSON.stringify(file, null, 2)}
9448
+ `, "utf8");
9449
+ }
9450
+ function hasOnlyEmptyHooks(file) {
9451
+ return Object.keys(file).every((key) => key === "hooks") && Object.values(file.hooks ?? {}).every((groups) => groups.length === 0);
9452
+ }
9453
+ function relativeToCwd(cwd, targetPath) {
9454
+ return path45.relative(cwd, targetPath);
9455
+ }
9456
+ function matcherKey(event, matcher) {
9457
+ return `${event}\0${matcher === void 0 ? "<undefined>" : matcher}`;
9458
+ }
9459
+ function bridgeHooks(sourceAgentId, targetAgentId, cwd, homeDir, runId, opts) {
9460
+ const source = requireSupport(sourceAgentId, "source");
9461
+ const target = requireSupport(targetAgentId, "target");
9462
+ const strategy = opts?.strategy ?? (source.config.format === target.config.format ? "symlink" : "transform");
9463
+ const manifest = {
9464
+ sourceAgentId,
9465
+ targetAgentId,
9466
+ cwd,
9467
+ runId,
9468
+ strategy,
9469
+ drops: []
9470
+ };
9471
+ if (strategy === "symlink") {
9472
+ const symlinkPath = requireTargetPath(target.id, target.config, cwd, homeDir);
9473
+ manifest.createdParents = collectMissingParents2(symlinkPath);
9474
+ const result = symlinkHooks(source.id, target.id, cwd, homeDir, "project");
9475
+ manifest.symlinkPath = result.symlinkPath;
9476
+ manifest.symlinkTarget = result.targetPath;
9477
+ manifest.symlinkReplaced = result.replaced;
9478
+ appendExcludeBlock(cwd, runId, [relativeToCwd(cwd, result.symlinkPath)], {
9479
+ markerPrefix: hookExcludeMarkerPrefix
9480
+ });
9481
+ return manifest;
9482
+ }
9483
+ if (source.id !== "claude-code") {
9484
+ throw new Error(`Transforming hooks from "${source.id}" is not supported yet`);
9485
+ }
9486
+ if (target.config.format !== "codex-hooks-json") {
9487
+ throw new Error(
9488
+ `Transforming hooks to "${target.id}" is not supported yet; only codex-hook targets can be written`
9489
+ );
9490
+ }
9491
+ const targetPath = requireTargetPath(target.id, target.config, cwd, homeDir);
9492
+ const priorFile = readCodexFile(targetPath);
9493
+ const sourceHooks = readClaudeHooks(cwd, homeDir, { scope: opts?.scope ?? "merged" });
9494
+ const transformed = transformHooks(sourceHooks.entries, source.id, target.id, { runId });
9495
+ const createdParents = collectMissingParents2(targetPath);
9496
+ const writeResult = writeCodexHooks(targetPath, transformed.entries, runId);
9497
+ manifest.writtenPath = targetPath;
9498
+ manifest.generatedEntryIds = transformed.entries.map((entry) => entry.generatedId);
9499
+ manifest.drops = transformed.drops;
9500
+ manifest.createdParents = createdParents;
9501
+ manifest.fileCreated = writeResult.fileCreated;
9502
+ manifest.preExistingEvents = Object.keys(priorFile?.hooks ?? {});
9503
+ manifest.preExistingMatchers = Object.entries(priorFile?.hooks ?? {}).flatMap(
9504
+ ([event, groups]) => groups.map((group) => ({
9505
+ event,
9506
+ ...group.matcher === void 0 ? {} : { matcher: group.matcher }
9507
+ }))
9508
+ );
9509
+ appendExcludeBlock(cwd, runId, [relativeToCwd(cwd, targetPath)], {
9510
+ markerPrefix: hookExcludeMarkerPrefix
9511
+ });
9512
+ return manifest;
9513
+ }
9514
+ function cleanupBridgedHooks(manifest) {
9515
+ if (manifest.strategy === "symlink" && manifest.symlinkPath && manifest.symlinkTarget) {
9516
+ try {
9517
+ if (fs12.lstatSync(manifest.symlinkPath).isSymbolicLink() && fs12.readlinkSync(manifest.symlinkPath) === manifest.symlinkTarget) {
9518
+ fs12.unlinkSync(manifest.symlinkPath);
9519
+ }
9520
+ } catch (error2) {
9521
+ if (!isNodeError4(error2) || error2.code !== "ENOENT") {
9522
+ throw error2;
9523
+ }
9524
+ }
9525
+ for (const parent of [...manifest.createdParents ?? []].reverse()) {
9526
+ removeDirectoryIfEmpty2(parent);
9527
+ }
9528
+ }
9529
+ if (manifest.strategy === "transform" && manifest.writtenPath) {
9530
+ const file = readCodexFile(manifest.writtenPath);
9531
+ if (file) {
9532
+ const generatedPrefix = `[generated:${manifest.runId}]`;
9533
+ const preExistingEvents = new Set(manifest.preExistingEvents ?? []);
9534
+ const preExistingMatchers = new Set(
9535
+ (manifest.preExistingMatchers ?? []).map((group) => matcherKey(group.event, group.matcher))
9536
+ );
9537
+ const hooks = file.hooks ?? {};
9538
+ for (const [event, groups] of Object.entries(hooks)) {
9539
+ hooks[event] = groups.filter((group) => {
9540
+ const priorLength = group.hooks.length;
9541
+ group.hooks = group.hooks.filter(
9542
+ (handler) => !handler.statusMessage?.startsWith(generatedPrefix)
9543
+ );
9544
+ return group.hooks.length > 0 || group.hooks.length === priorLength || preExistingMatchers.has(matcherKey(event, group.matcher));
9545
+ });
9546
+ if (hooks[event].length === 0 && !preExistingEvents.has(event)) {
9547
+ delete hooks[event];
9548
+ }
9549
+ }
9550
+ file.hooks = hooks;
9551
+ if (manifest.fileCreated && hasOnlyEmptyHooks(file)) {
9552
+ fs12.unlinkSync(manifest.writtenPath);
9553
+ } else {
9554
+ writeCodexFile(manifest.writtenPath, file);
9555
+ }
9556
+ }
9557
+ for (const parent of [...manifest.createdParents ?? []].reverse()) {
9558
+ removeDirectoryIfEmpty2(parent);
9559
+ }
9560
+ }
9561
+ removeExcludeBlock(manifest.cwd, manifest.runId, { markerPrefix: hookExcludeMarkerPrefix });
9562
+ }
9563
+
8867
9564
  // packages/agent-spawn/src/skill-bridge.ts
8868
- function bridgeSkillsForRun(agentId, cwd, skills) {
8869
- if (!skills || skills.length === 0) {
9565
+ function bridgeResourcesForRun(agentId, cwd, skills, hooks) {
9566
+ if ((!skills || skills.length === 0) && !hooks) {
8870
9567
  return void 0;
8871
9568
  }
8872
- const manifest = bridgeActiveSkills(agentId, cwd, skills, os6.homedir(), crypto.randomUUID());
8873
- for (const warning2 of manifest.warnings) {
8874
- logger.warn(warning2.message);
9569
+ const runId = crypto.randomUUID();
9570
+ const manifests = {};
9571
+ try {
9572
+ if (skills && skills.length > 0) {
9573
+ manifests.skills = bridgeActiveSkills(agentId, cwd, skills, os7.homedir(), runId);
9574
+ for (const warning2 of manifests.skills.warnings) {
9575
+ logger.warn(warning2.message);
9576
+ }
9577
+ }
9578
+ if (hooks) {
9579
+ manifests.hooks = bridgeHooks(hooks.from, agentId, cwd, os7.homedir(), runId, {
9580
+ strategy: hooks.strategy === "auto" ? void 0 : hooks.strategy,
9581
+ scope: hooks.scope
9582
+ });
9583
+ for (const drop of manifests.hooks.drops) {
9584
+ logger.warn(
9585
+ `Dropped bridged hook event "${drop.source.event}" with handler type "${drop.source.handler.type}": ${drop.detail}`
9586
+ );
9587
+ }
9588
+ }
9589
+ } catch (error2) {
9590
+ cleanupResourcesForRun(manifests);
9591
+ throw error2;
8875
9592
  }
8876
- return manifest;
9593
+ return manifests;
8877
9594
  }
8878
- function cleanupSkillsForRun(manifest) {
9595
+ function cleanupResourcesForRun(manifest) {
8879
9596
  if (!manifest) {
8880
9597
  return;
8881
9598
  }
8882
- cleanupBridgedSkills(manifest);
9599
+ if (manifest.hooks) {
9600
+ cleanupBridgedHooks(manifest.hooks);
9601
+ }
9602
+ if (manifest.skills) {
9603
+ cleanupBridgedSkills(manifest.skills);
9604
+ }
8883
9605
  }
8884
9606
 
8885
9607
  // packages/agent-spawn/src/adapters/utils.ts
@@ -9005,21 +9727,21 @@ async function* adaptClaude(lines) {
9005
9727
  if (blockType !== "tool_result") continue;
9006
9728
  const kind = toolKindsById.get(item.tool_use_id);
9007
9729
  toolKindsById.delete(item.tool_use_id);
9008
- let path50;
9730
+ let path55;
9009
9731
  if (typeof item.content === "string") {
9010
- path50 = item.content;
9732
+ path55 = item.content;
9011
9733
  } else {
9012
9734
  try {
9013
- path50 = JSON.stringify(item.content);
9735
+ path55 = JSON.stringify(item.content);
9014
9736
  } catch {
9015
- path50 = String(item.content);
9737
+ path55 = String(item.content);
9016
9738
  }
9017
9739
  }
9018
9740
  yield {
9019
9741
  event: "tool_complete",
9020
9742
  id: item.tool_use_id,
9021
9743
  kind,
9022
- path: path50
9744
+ path: path55
9023
9745
  };
9024
9746
  }
9025
9747
  }
@@ -9115,10 +9837,10 @@ async function* adaptCodex(lines) {
9115
9837
  const kindFromStart = toolKindById.get(item.id);
9116
9838
  const kind = kindFromStart ?? (itemType === "command_execution" ? "exec" : itemType === "file_edit" ? "edit" : "other");
9117
9839
  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;
9118
- const path50 = titleFromEvent ?? toolTitleById.get(item.id) ?? "";
9840
+ const path55 = titleFromEvent ?? toolTitleById.get(item.id) ?? "";
9119
9841
  toolTitleById.delete(item.id);
9120
9842
  toolKindById.delete(item.id);
9121
- yield { event: "tool_complete", id: item.id, kind, path: path50 };
9843
+ yield { event: "tool_complete", id: item.id, kind, path: path55 };
9122
9844
  }
9123
9845
  }
9124
9846
  }
@@ -9646,7 +10368,7 @@ function spawnStreaming(options) {
9646
10368
  };
9647
10369
  }
9648
10370
  };
9649
- const manifest = bridgeSkillsForRun(options.agentId, cwd, options.skills);
10371
+ const manifest = bridgeResourcesForRun(options.agentId, cwd, options.skills, options.hooks);
9650
10372
  void (async () => {
9651
10373
  try {
9652
10374
  for await (const output of adapter(queue.lines())) {
@@ -9697,7 +10419,7 @@ function spawnStreaming(options) {
9697
10419
  ...ctx.logFile && !result.logFile ? { logFile: ctx.logFile } : {}
9698
10420
  };
9699
10421
  } finally {
9700
- cleanupSkillsForRun(manifest);
10422
+ cleanupResourcesForRun(manifest);
9701
10423
  }
9702
10424
  })();
9703
10425
  return {
@@ -9833,7 +10555,7 @@ async function runSpawn(agentId, options, context) {
9833
10555
  return { stdout: "", stderr: "", exitCode: 0 };
9834
10556
  }
9835
10557
  const cwd = options.cwd ?? process.cwd();
9836
- const manifest = bridgeSkillsForRun(agentId, cwd, options.skills);
10558
+ const manifest = bridgeResourcesForRun(agentId, cwd, options.skills, options.hooks);
9837
10559
  let logFd;
9838
10560
  try {
9839
10561
  const logFilePath = resolveSpawnLogPath(options);
@@ -9901,7 +10623,7 @@ async function runSpawn(agentId, options, context) {
9901
10623
  };
9902
10624
  } finally {
9903
10625
  closeSpawnLog(logFd);
9904
- cleanupSkillsForRun(manifest);
10626
+ cleanupResourcesForRun(manifest);
9905
10627
  }
9906
10628
  }
9907
10629
  spawn4.retry = createSpawnRetry((service, options) => {
@@ -9923,12 +10645,12 @@ function resolveSpawnLogPath(options) {
9923
10645
  if (!options.logDir || !options.logFileName) {
9924
10646
  return void 0;
9925
10647
  }
9926
- return path41.join(options.logDir, options.logFileName);
10648
+ return path46.join(options.logDir, options.logFileName);
9927
10649
  }
9928
10650
  function openSpawnLog(filePath) {
9929
10651
  try {
9930
- mkdirSync3(path41.dirname(filePath), { recursive: true });
9931
- return openSync(filePath, "a");
10652
+ mkdirSync5(path46.dirname(filePath), { recursive: true });
10653
+ return openSync2(filePath, "a");
9932
10654
  } catch {
9933
10655
  return void 0;
9934
10656
  }
@@ -9943,7 +10665,7 @@ function appendSpawnLog(fd, chunk) {
9943
10665
  function closeSpawnLog(fd) {
9944
10666
  if (fd === void 0) return;
9945
10667
  try {
9946
- closeSync(fd);
10668
+ closeSync2(fd);
9947
10669
  } catch {
9948
10670
  }
9949
10671
  }
@@ -9952,7 +10674,7 @@ function closeSpawnLog(fd) {
9952
10674
  var DEFAULT_ACTIVITY_TIMEOUT_MS = 10 * 60 * 1e3;
9953
10675
 
9954
10676
  // packages/agent-spawn/src/acp/replay.ts
9955
- import path42 from "node:path";
10677
+ import path47 from "node:path";
9956
10678
  import { homedir as homedir2 } from "node:os";
9957
10679
  import { open as open2, readdir as readdir5 } from "node:fs/promises";
9958
10680
  import { createInterface } from "node:readline";
@@ -9971,13 +10693,13 @@ import { homedir } from "node:os";
9971
10693
  import { join } from "node:path";
9972
10694
 
9973
10695
  // packages/agent-spawn/src/acp/middlewares/spawn-log.ts
9974
- import path43 from "node:path";
10696
+ import path48 from "node:path";
9975
10697
  import { homedir as homedir3 } from "node:os";
9976
10698
  import { mkdir as mkdir5, open as open3 } from "node:fs/promises";
9977
10699
 
9978
10700
  // packages/memory/src/tokens.ts
9979
- import * as fs12 from "node:fs/promises";
9980
- import path44 from "node:path";
10701
+ import * as fs13 from "node:fs/promises";
10702
+ import path49 from "node:path";
9981
10703
 
9982
10704
  // packages/tokenfill/dist/tokenizer.js
9983
10705
  import { get_encoding } from "tiktoken";
@@ -10018,7 +10740,7 @@ function countTokens(text5) {
10018
10740
  }
10019
10741
 
10020
10742
  // packages/tokenfill/dist/corpus.js
10021
- import { readdirSync as readdirSync2, readFileSync as readFileSync3 } from "node:fs";
10743
+ import { readdirSync as readdirSync2, readFileSync as readFileSync6 } from "node:fs";
10022
10744
  import { dirname, join as join2 } from "node:path";
10023
10745
  import { fileURLToPath as fileURLToPath2 } from "node:url";
10024
10746
  var CORPUS_ARTICLE_SEPARATOR = "\n\n";
@@ -10031,7 +10753,7 @@ function loadBuiltInCorpusArticles() {
10031
10753
  if (corpusFileNames.length === 0) {
10032
10754
  throw new Error(`No built-in corpus markdown files found in ${corpusDirectoryPath}`);
10033
10755
  }
10034
- return corpusFileNames.map((fileName) => readFileSync3(join2(corpusDirectoryPath, fileName), "utf8").trim());
10756
+ return corpusFileNames.map((fileName) => readFileSync6(join2(corpusDirectoryPath, fileName), "utf8").trim());
10035
10757
  }
10036
10758
  var BUILT_IN_CORPUS_ARTICLES = loadBuiltInCorpusArticles();
10037
10759
 
@@ -10041,7 +10763,7 @@ var builtInCorpusByteLength = Buffer.byteLength(builtInCorpusText, "utf8");
10041
10763
 
10042
10764
  // packages/memory/src/tokens.ts
10043
10765
  async function computeTokenStats(root) {
10044
- if (!await pathExists4(root)) {
10766
+ if (!await pathExists5(root)) {
10045
10767
  return {
10046
10768
  memoryTokens: 0,
10047
10769
  sourceTokens: 0,
@@ -10061,13 +10783,13 @@ async function computeTokenStats(root) {
10061
10783
  }
10062
10784
  }
10063
10785
  }
10064
- const repoRoot = path44.resolve(root, "..", "..");
10786
+ const repoRoot = path49.resolve(root, "..", "..");
10065
10787
  let sourceTokens = 0;
10066
10788
  const missingSources = [];
10067
10789
  for (const sourcePath of sourcePaths) {
10068
- const absPath = path44.isAbsolute(sourcePath) ? sourcePath : path44.resolve(repoRoot, sourcePath);
10790
+ const absPath = path49.isAbsolute(sourcePath) ? sourcePath : path49.resolve(repoRoot, sourcePath);
10069
10791
  try {
10070
- const content = await fs12.readFile(absPath, "utf8");
10792
+ const content = await fs13.readFile(absPath, "utf8");
10071
10793
  sourceTokens += countTokens(content);
10072
10794
  } catch (error2) {
10073
10795
  if (isMissing4(error2)) {
@@ -10086,9 +10808,9 @@ async function computeTokenStats(root) {
10086
10808
  missingSources
10087
10809
  };
10088
10810
  }
10089
- async function pathExists4(targetPath) {
10811
+ async function pathExists5(targetPath) {
10090
10812
  try {
10091
- await fs12.stat(targetPath);
10813
+ await fs13.stat(targetPath);
10092
10814
  return true;
10093
10815
  } catch (error2) {
10094
10816
  if (isMissing4(error2)) {
@@ -10116,10 +10838,10 @@ function resolveRunners(overrides) {
10116
10838
  async function ingest(root, opts, runners) {
10117
10839
  const resolved = resolveRunners(runners);
10118
10840
  const source = await materializeSource(opts.source);
10119
- const indexMdBytes = await fs13.readFile(path45.join(root, MEMORY_INDEX_RELPATH));
10841
+ const indexMdBytes = await fs14.readFile(path50.join(root, MEMORY_INDEX_RELPATH));
10120
10842
  const configOptions = {
10121
- fs: fs13,
10122
- filePath: path45.join(inferRepoRoot(root), "poe-code.json")
10843
+ fs: fs14,
10844
+ filePath: path50.join(inferRepoRoot(root), "poe-code.json")
10123
10845
  };
10124
10846
  const agentId = await resolveAgent(configOptions, opts.agent ?? null) ?? opts.agent ?? "claude-code";
10125
10847
  const key = resolved.computeIngestKey({
@@ -10199,7 +10921,7 @@ function buildIngestPrompt(root, sourceLabel, sourceText) {
10199
10921
  }
10200
10922
  async function materializeSource(source) {
10201
10923
  if (source.kind === "file") {
10202
- const bytes = await fs13.readFile(source.absPath);
10924
+ const bytes = await fs14.readFile(source.absPath);
10203
10925
  return {
10204
10926
  label: source.absPath,
10205
10927
  bytes,
@@ -10209,7 +10931,7 @@ async function materializeSource(source) {
10209
10931
  throw new Error("URL ingest not implemented yet.");
10210
10932
  }
10211
10933
  function inferRepoRoot(root) {
10212
- return path45.resolve(root, "..", "..");
10934
+ return path50.resolve(root, "..", "..");
10213
10935
  }
10214
10936
  async function runWithTimeout(promise, timeoutMs) {
10215
10937
  return await new Promise((resolve2, reject) => {
@@ -11016,7 +11738,7 @@ var agentMcpConfigs = {
11016
11738
  }
11017
11739
  };
11018
11740
  var supportedAgents3 = Object.keys(agentMcpConfigs);
11019
- function resolveAgentSupport2(input, registry = agentMcpConfigs) {
11741
+ function resolveAgentSupport3(input, registry = agentMcpConfigs) {
11020
11742
  const resolvedId = resolveAgentId(input);
11021
11743
  if (!resolvedId) {
11022
11744
  return { status: "unknown", input };
@@ -11028,10 +11750,10 @@ function resolveAgentSupport2(input, registry = agentMcpConfigs) {
11028
11750
  return { status: "supported", input, id: resolvedId, config };
11029
11751
  }
11030
11752
  function isSupported(agentId) {
11031
- return resolveAgentSupport2(agentId).status === "supported";
11753
+ return resolveAgentSupport3(agentId).status === "supported";
11032
11754
  }
11033
- function getAgentConfig2(agentId) {
11034
- const support = resolveAgentSupport2(agentId);
11755
+ function getAgentConfig3(agentId) {
11756
+ const support = resolveAgentSupport3(agentId);
11035
11757
  return support.status === "supported" ? support.config : void 0;
11036
11758
  }
11037
11759
  function resolveConfigPath2(config, platform) {
@@ -11042,7 +11764,7 @@ function resolveConfigPath2(config, platform) {
11042
11764
  }
11043
11765
 
11044
11766
  // packages/agent-mcp-config/src/apply.ts
11045
- import path46 from "node:path";
11767
+ import path51 from "node:path";
11046
11768
  import { parse as parseYaml3, stringify as stringifyYaml2 } from "yaml";
11047
11769
 
11048
11770
  // packages/agent-mcp-config/src/shapes.ts
@@ -11134,7 +11856,7 @@ function getShapeTransformer(shape) {
11134
11856
 
11135
11857
  // packages/agent-mcp-config/src/apply.ts
11136
11858
  function getConfigDirectory(configPath) {
11137
- return path46.dirname(configPath);
11859
+ return path51.dirname(configPath);
11138
11860
  }
11139
11861
  var UnsupportedAgentError2 = class extends Error {
11140
11862
  constructor(agentId) {
@@ -11160,9 +11882,9 @@ function expandHomePath(configPath, homeDir) {
11160
11882
  return homeDir;
11161
11883
  }
11162
11884
  if (configPath.startsWith("~/")) {
11163
- return path46.join(homeDir, configPath.slice(2));
11885
+ return path51.join(homeDir, configPath.slice(2));
11164
11886
  }
11165
- return path46.join(homeDir, configPath.slice(1));
11887
+ return path51.join(homeDir, configPath.slice(1));
11166
11888
  }
11167
11889
  function parseYamlDocument(content) {
11168
11890
  if (content.trim() === "") {
@@ -11195,7 +11917,7 @@ async function writeYamlConfig(configPath, document, options) {
11195
11917
  return;
11196
11918
  }
11197
11919
  const absolutePath = expandHomePath(configPath, options.homeDir);
11198
- const configDir = path46.dirname(absolutePath);
11920
+ const configDir = path51.dirname(absolutePath);
11199
11921
  await options.fs.mkdir(configDir, { recursive: true });
11200
11922
  await options.fs.writeFile(absolutePath, serializeYamlDocument(document), {
11201
11923
  encoding: "utf8"
@@ -11222,7 +11944,7 @@ async function configure2(agentId, server, options) {
11222
11944
  if (!isSupported(agentId)) {
11223
11945
  throw new UnsupportedAgentError2(agentId);
11224
11946
  }
11225
- const config = getAgentConfig2(agentId);
11947
+ const config = getAgentConfig3(agentId);
11226
11948
  const configPath = resolveConfigPath2(config, options.platform);
11227
11949
  const shapeTransformer = getShapeTransformer(config.shape);
11228
11950
  const shaped = shapeTransformer(server);
@@ -11278,7 +12000,7 @@ async function unconfigure2(agentId, serverName, options) {
11278
12000
  if (!isSupported(agentId)) {
11279
12001
  throw new UnsupportedAgentError2(agentId);
11280
12002
  }
11281
- const config = getAgentConfig2(agentId);
12003
+ const config = getAgentConfig3(agentId);
11282
12004
  const configPath = resolveConfigPath2(config, options.platform);
11283
12005
  if (config.format === "yaml") {
11284
12006
  const document = await readYamlConfig(configPath, options);
@@ -11372,8 +12094,8 @@ async function installMemory(options) {
11372
12094
  }
11373
12095
 
11374
12096
  // packages/memory/src/query.ts
11375
- import * as fs14 from "node:fs/promises";
11376
- import path47 from "node:path";
12097
+ import * as fs15 from "node:fs/promises";
12098
+ import path52 from "node:path";
11377
12099
  async function queryMemory(root, options) {
11378
12100
  const pages = await listPages(root);
11379
12101
  if (pages.length === 0) {
@@ -11386,8 +12108,8 @@ async function queryMemory(root, options) {
11386
12108
  };
11387
12109
  }
11388
12110
  const configOptions = {
11389
- fs: fs14,
11390
- filePath: path47.join(inferRepoRoot2(root), "poe-code.json")
12111
+ fs: fs15,
12112
+ filePath: path52.join(inferRepoRoot2(root), "poe-code.json")
11391
12113
  };
11392
12114
  const agentId = await resolveAgent(configOptions, options.agent ?? null) ?? options.agent ?? "claude-code";
11393
12115
  const context = await selectQueryContext(root, options.question, options.budget);
@@ -11402,7 +12124,7 @@ async function queryMemory(root, options) {
11402
12124
  }
11403
12125
  async function selectQueryContext(root, question, budget) {
11404
12126
  const [indexText, pages] = await Promise.all([
11405
- fs14.readFile(path47.join(root, MEMORY_INDEX_RELPATH), "utf8"),
12127
+ fs15.readFile(path52.join(root, MEMORY_INDEX_RELPATH), "utf8"),
11406
12128
  listPages(root)
11407
12129
  ]);
11408
12130
  const indexTokens = countTokens(indexText);
@@ -11481,12 +12203,12 @@ function tokenize(text5) {
11481
12203
  return text5.toLowerCase().split(/[^a-z0-9]+/).filter((token) => token.length > 0);
11482
12204
  }
11483
12205
  function inferRepoRoot2(root) {
11484
- return path47.resolve(root, "..", "..");
12206
+ return path52.resolve(root, "..", "..");
11485
12207
  }
11486
12208
 
11487
12209
  // packages/memory/src/explain.ts
11488
- import * as fs15 from "node:fs/promises";
11489
- import path48 from "node:path";
12210
+ import * as fs16 from "node:fs/promises";
12211
+ import path53 from "node:path";
11490
12212
  async function explainPage(root, options) {
11491
12213
  const targetPage = await readPageIfPresent(root, options.relPath);
11492
12214
  if (targetPage === void 0) {
@@ -11508,8 +12230,8 @@ async function explainPage(root, options) {
11508
12230
  throw new Error(`budget too small; needs at least ${tokensUsed} tokens`);
11509
12231
  }
11510
12232
  const configOptions = {
11511
- fs: fs15,
11512
- filePath: path48.join(inferRepoRoot3(root), "poe-code.json")
12233
+ fs: fs16,
12234
+ filePath: path53.join(inferRepoRoot3(root), "poe-code.json")
11513
12235
  };
11514
12236
  const agentId = await resolveAgent(configOptions, options.agent ?? null) ?? options.agent ?? "claude-code";
11515
12237
  const response = await spawn4(agentId, { prompt });
@@ -11558,7 +12280,7 @@ async function readPageIfPresent(root, relPath) {
11558
12280
  }
11559
12281
  }
11560
12282
  function inferRepoRoot3(root) {
11561
- return path48.resolve(root, "..", "..");
12283
+ return path53.resolve(root, "..", "..");
11562
12284
  }
11563
12285
 
11564
12286
  // packages/memory/src/explain.cli.ts
@@ -11571,9 +12293,9 @@ async function runMemoryExplain(input) {
11571
12293
  }
11572
12294
 
11573
12295
  // packages/memory/src/handle.ts
11574
- import path49 from "node:path";
12296
+ import path54 from "node:path";
11575
12297
  function openMemory(opts) {
11576
- if (!path49.isAbsolute(opts.root)) {
12298
+ if (!path54.isAbsolute(opts.root)) {
11577
12299
  throw new Error(`openMemory: root must be absolute, got ${opts.root}`);
11578
12300
  }
11579
12301
  const root = opts.root;