poe-code 3.0.223 → 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 (88) hide show
  1. package/dist/bin/poe-gemini.js +23 -0
  2. package/dist/cli/commands/configure-payload.js +100 -13
  3. package/dist/cli/commands/configure-payload.js.map +1 -1
  4. package/dist/cli/commands/configure.js +2 -2
  5. package/dist/cli/commands/configure.js.map +1 -1
  6. package/dist/cli/commands/pipeline.js +4 -2
  7. package/dist/cli/commands/pipeline.js.map +1 -1
  8. package/dist/cli/commands/provider.d.ts +1 -0
  9. package/dist/cli/commands/provider.js +94 -3
  10. package/dist/cli/commands/provider.js.map +1 -1
  11. package/dist/cli/commands/ralph.js +1 -0
  12. package/dist/cli/commands/ralph.js.map +1 -1
  13. package/dist/cli/commands/shared.d.ts +8 -1
  14. package/dist/cli/commands/shared.js +88 -7
  15. package/dist/cli/commands/shared.js.map +1 -1
  16. package/dist/cli/commands/spawn.js +20 -0
  17. package/dist/cli/commands/spawn.js.map +1 -1
  18. package/dist/cli/commands/test.d.ts +5 -1
  19. package/dist/cli/commands/test.js +58 -6
  20. package/dist/cli/commands/test.js.map +1 -1
  21. package/dist/cli/constants.d.ts +2 -2
  22. package/dist/cli/constants.js +3 -14
  23. package/dist/cli/constants.js.map +1 -1
  24. package/dist/cli/isolated-env.d.ts +2 -1
  25. package/dist/cli/isolated-env.js +20 -2
  26. package/dist/cli/isolated-env.js.map +1 -1
  27. package/dist/cli/options.d.ts +2 -5
  28. package/dist/cli/options.js +10 -1
  29. package/dist/cli/options.js.map +1 -1
  30. package/dist/cli/poe-code-command-runner.js +7 -2
  31. package/dist/cli/poe-code-command-runner.js.map +1 -1
  32. package/dist/cli/prompt-runner.js +4 -2
  33. package/dist/cli/prompt-runner.js.map +1 -1
  34. package/dist/cli/prompts.d.ts +23 -13
  35. package/dist/cli/prompts.js +13 -0
  36. package/dist/cli/prompts.js.map +1 -1
  37. package/dist/cli/service-registry.d.ts +12 -3
  38. package/dist/cli/service-registry.js.map +1 -1
  39. package/dist/index.d.ts +3 -1
  40. package/dist/index.js +4936 -2415
  41. package/dist/index.js.map +4 -4
  42. package/dist/providers/claude-code.js +924 -174
  43. package/dist/providers/claude-code.js.map +4 -4
  44. package/dist/providers/codex.js +916 -178
  45. package/dist/providers/codex.js.map +4 -4
  46. package/dist/providers/create-provider.d.ts +1 -0
  47. package/dist/providers/create-provider.js +1 -0
  48. package/dist/providers/create-provider.js.map +1 -1
  49. package/dist/providers/gemini-cli.d.ts +16 -0
  50. package/dist/providers/gemini-cli.js +11349 -0
  51. package/dist/providers/gemini-cli.js.map +7 -0
  52. package/dist/providers/goose.js +881 -183
  53. package/dist/providers/goose.js.map +4 -4
  54. package/dist/providers/kimi.js +905 -165
  55. package/dist/providers/kimi.js.map +4 -4
  56. package/dist/providers/opencode.js +905 -165
  57. package/dist/providers/opencode.js.map +4 -4
  58. package/dist/providers/poe-agent.js +1155 -357
  59. package/dist/providers/poe-agent.js.map +4 -4
  60. package/dist/providers/spawn-options.d.ts +3 -0
  61. package/dist/sdk/pipeline.d.ts +1 -1
  62. package/dist/sdk/pipeline.js +22 -19
  63. package/dist/sdk/pipeline.js.map +1 -1
  64. package/dist/sdk/ralph.js +5 -0
  65. package/dist/sdk/ralph.js.map +1 -1
  66. package/dist/sdk/spawn-core.d.ts +3 -0
  67. package/dist/sdk/spawn-core.js +6 -8
  68. package/dist/sdk/spawn-core.js.map +1 -1
  69. package/dist/sdk/spawn.d.ts +8 -8
  70. package/dist/sdk/spawn.js +26 -3
  71. package/dist/sdk/spawn.js.map +1 -1
  72. package/dist/sdk/types.d.ts +7 -0
  73. package/dist/utils/command-checks.d.ts +8 -0
  74. package/dist/utils/command-checks.js +35 -9
  75. package/dist/utils/command-checks.js.map +1 -1
  76. package/dist/utils/dry-run.js +7 -1
  77. package/dist/utils/dry-run.js.map +1 -1
  78. package/dist/workflow-templates/github-issue-opened.caller.yml +2 -1
  79. package/dist/workflow-templates/github-issue-opened.ejected.yml +2 -1
  80. package/package.json +2 -1
  81. package/packages/agent-skill-config/dist/configs.js +4 -0
  82. package/packages/agent-skill-config/dist/git-exclude.d.ts +6 -2
  83. package/packages/agent-skill-config/dist/git-exclude.js +12 -12
  84. package/packages/memory/dist/index.js +924 -200
  85. package/packages/memory/dist/index.js.map +4 -4
  86. package/packages/superintendent/dist/index.d.ts +2 -1
  87. package/packages/superintendent/dist/runtime/loop.d.ts +1 -0
  88. 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",
@@ -3404,30 +3433,38 @@ var anthropicProvider = {
3404
3433
  var cloudflareProvider = {
3405
3434
  id: "cloudflare",
3406
3435
  label: "Cloudflare AI Gateway",
3407
- summary: "Route through the Poe Cloudflare gateway with BYOK keys.",
3408
- baseUrl: "https://poe-ai-gateway.poe-dev.workers.dev",
3436
+ summary: "Route coding agents through Cloudflare AI Gateway.",
3437
+ baseUrlEnvVar: "CF_AIG_BASE_URL",
3438
+ requiresBaseUrl: true,
3439
+ modelInput: { kind: "freeform" },
3409
3440
  auth: {
3410
3441
  kind: "api-key",
3411
- envVar: "CLOUDFLARE_API_KEY",
3442
+ envVar: "CF_AIG_TOKEN",
3412
3443
  storageKey: "provider:cloudflare",
3413
- prompt: { title: "Cloudflare API key" }
3444
+ prompt: { title: "Cloudflare AI Gateway token" }
3445
+ },
3446
+ env: {
3447
+ ANTHROPIC_CUSTOM_HEADERS: {
3448
+ kind: "providerCredential",
3449
+ prefix: "Authorization: Bearer "
3450
+ }
3414
3451
  },
3415
3452
  apiShapes: [
3416
3453
  {
3417
3454
  id: "openai-chat-completions",
3418
- defaultBaseUrl: "https://poe-ai-gateway.poe-dev.workers.dev/openai/v1"
3455
+ baseUrlPath: "compat"
3419
3456
  },
3420
3457
  {
3421
3458
  id: "openai-responses",
3422
- defaultBaseUrl: "https://poe-ai-gateway.poe-dev.workers.dev/openai/v1"
3459
+ baseUrlPath: "openai"
3423
3460
  },
3424
3461
  {
3425
3462
  id: "anthropic-messages",
3426
- defaultBaseUrl: "https://poe-ai-gateway.poe-dev.workers.dev/anthropic"
3463
+ baseUrlPath: "anthropic"
3427
3464
  },
3428
3465
  {
3429
3466
  id: "google-generations",
3430
- defaultBaseUrl: "https://poe-ai-gateway.poe-dev.workers.dev/google-ai-studio"
3467
+ baseUrlPath: "google-ai-studio"
3431
3468
  }
3432
3469
  ]
3433
3470
  };
@@ -3507,17 +3544,17 @@ function isPidRunning(pid) {
3507
3544
  }
3508
3545
  function createDefaultFs() {
3509
3546
  return {
3510
- open: (path50, flags) => fsPromises.open(path50, flags),
3511
- readFile: (path50, encoding) => fsPromises.readFile(path50, encoding),
3547
+ open: (path55, flags) => fsPromises.open(path55, flags),
3548
+ readFile: (path55, encoding) => fsPromises.readFile(path55, encoding),
3512
3549
  stat: fsPromises.stat,
3513
3550
  unlink: fsPromises.unlink
3514
3551
  };
3515
3552
  }
3516
- async function removeLockFile(fs16, lockPath, signal) {
3553
+ async function removeLockFile(fs17, lockPath, signal) {
3517
3554
  for (let attempt = 0; attempt <= 4; attempt += 1) {
3518
3555
  throwIfAborted(signal);
3519
3556
  try {
3520
- await fs16.unlink(lockPath);
3557
+ await fs17.unlink(lockPath);
3521
3558
  return;
3522
3559
  } catch (error2) {
3523
3560
  if (hasErrorCode(error2, "ENOENT")) {
@@ -3548,12 +3585,12 @@ function parseLockMetadata(content) {
3548
3585
  }
3549
3586
  return void 0;
3550
3587
  }
3551
- async function readLockMetadata(fs16, lockPath) {
3552
- if (!fs16.readFile) {
3588
+ async function readLockMetadata(fs17, lockPath) {
3589
+ if (!fs17.readFile) {
3553
3590
  return void 0;
3554
3591
  }
3555
3592
  try {
3556
- return parseLockMetadata(await fs16.readFile(lockPath, "utf8"));
3593
+ return parseLockMetadata(await fs17.readFile(lockPath, "utf8"));
3557
3594
  } catch (error2) {
3558
3595
  if (hasErrorCode(error2, "ENOENT")) {
3559
3596
  return null;
@@ -3587,7 +3624,7 @@ async function writeLockMetadata(handle) {
3587
3624
  }
3588
3625
  }
3589
3626
  async function acquireFileLock(filePath, options = {}) {
3590
- const fs16 = options.fs ?? createDefaultFs();
3627
+ const fs17 = options.fs ?? createDefaultFs();
3591
3628
  const retries = options.retries ?? 20;
3592
3629
  const minTimeout = options.minTimeout ?? 25;
3593
3630
  const maxTimeout = options.maxTimeout ?? 250;
@@ -3598,7 +3635,7 @@ async function acquireFileLock(filePath, options = {}) {
3598
3635
  while (attempt <= retries) {
3599
3636
  throwIfAborted(options.signal);
3600
3637
  try {
3601
- const handle = await fs16.open(lockPath, "wx");
3638
+ const handle = await fs17.open(lockPath, "wx");
3602
3639
  await writeLockMetadata(handle);
3603
3640
  let released = false;
3604
3641
  return async () => {
@@ -3606,7 +3643,7 @@ async function acquireFileLock(filePath, options = {}) {
3606
3643
  return;
3607
3644
  }
3608
3645
  released = true;
3609
- await removeLockFile(fs16, lockPath, options.signal);
3646
+ await removeLockFile(fs17, lockPath, options.signal);
3610
3647
  };
3611
3648
  } catch (error2) {
3612
3649
  if (!hasErrorCode(error2, "EEXIST")) {
@@ -3615,7 +3652,7 @@ async function acquireFileLock(filePath, options = {}) {
3615
3652
  }
3616
3653
  let stat7;
3617
3654
  try {
3618
- stat7 = await fs16.stat(lockPath);
3655
+ stat7 = await fs17.stat(lockPath);
3619
3656
  } catch (statError) {
3620
3657
  if (hasErrorCode(statError, "ENOENT")) {
3621
3658
  continue;
@@ -3623,7 +3660,7 @@ async function acquireFileLock(filePath, options = {}) {
3623
3660
  throw statError;
3624
3661
  }
3625
3662
  const reclaimLock = await shouldReclaimLock({
3626
- fs: fs16,
3663
+ fs: fs17,
3627
3664
  isPidRunning: pidIsRunning,
3628
3665
  lockPath,
3629
3666
  staleMs,
@@ -3633,7 +3670,7 @@ async function acquireFileLock(filePath, options = {}) {
3633
3670
  continue;
3634
3671
  }
3635
3672
  if (reclaimLock) {
3636
- await removeLockFile(fs16, lockPath, options.signal);
3673
+ await removeLockFile(fs17, lockPath, options.signal);
3637
3674
  continue;
3638
3675
  }
3639
3676
  if (attempt >= retries) {
@@ -3653,7 +3690,7 @@ function isNotFoundError(error2) {
3653
3690
  }
3654
3691
 
3655
3692
  // packages/poe-code-config/src/state/jobs.ts
3656
- function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3693
+ function createJobRegistry(homeDir, fs17 = defaultStateFs) {
3657
3694
  const jobsDir = path10.join(homeDir, ".poe-code", "state", "jobs");
3658
3695
  function jobPath(id) {
3659
3696
  assertSafeJobId(id);
@@ -3661,7 +3698,7 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3661
3698
  }
3662
3699
  async function get(id) {
3663
3700
  try {
3664
- return parseJobEntry(await fs16.readFile(jobPath(id), "utf8"));
3701
+ return parseJobEntry(await fs17.readFile(jobPath(id), "utf8"));
3665
3702
  } catch (error2) {
3666
3703
  if (isNotFoundError(error2)) {
3667
3704
  return null;
@@ -3672,8 +3709,8 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3672
3709
  async function put(entry) {
3673
3710
  assertJobEntry(entry);
3674
3711
  const filePath = jobPath(entry.id);
3675
- await fs16.mkdir(jobsDir, { recursive: true });
3676
- const release = await acquireFileLock(filePath, { fs: fs16 });
3712
+ await fs17.mkdir(jobsDir, { recursive: true });
3713
+ const release = await acquireFileLock(filePath, { fs: fs17 });
3677
3714
  try {
3678
3715
  await writeJobAtomically(filePath, entry);
3679
3716
  } finally {
@@ -3682,8 +3719,8 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3682
3719
  }
3683
3720
  async function update(id, patch) {
3684
3721
  const filePath = jobPath(id);
3685
- await fs16.mkdir(jobsDir, { recursive: true });
3686
- const release = await acquireFileLock(filePath, { fs: fs16 });
3722
+ await fs17.mkdir(jobsDir, { recursive: true });
3723
+ const release = await acquireFileLock(filePath, { fs: fs17 });
3687
3724
  try {
3688
3725
  const current = await get(id);
3689
3726
  if (current === null) {
@@ -3704,7 +3741,7 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3704
3741
  async function list(filter = {}) {
3705
3742
  let entries;
3706
3743
  try {
3707
- entries = await fs16.readdir(jobsDir);
3744
+ entries = await fs17.readdir(jobsDir);
3708
3745
  } catch (error2) {
3709
3746
  if (isNotFoundError(error2)) {
3710
3747
  return [];
@@ -3717,11 +3754,11 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3717
3754
  continue;
3718
3755
  }
3719
3756
  const filePath = path10.join(jobsDir, entry);
3720
- const stat7 = await fs16.stat(filePath);
3757
+ const stat7 = await fs17.stat(filePath);
3721
3758
  if (!stat7.isFile()) {
3722
3759
  continue;
3723
3760
  }
3724
- const job = parseJobEntry(await fs16.readFile(filePath, "utf8"));
3761
+ const job = parseJobEntry(await fs17.readFile(filePath, "utf8"));
3725
3762
  if (matchesFilter(job, filter)) {
3726
3763
  jobs.push(job);
3727
3764
  }
@@ -3731,16 +3768,16 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3731
3768
  async function remove2(id) {
3732
3769
  const filePath = jobPath(id);
3733
3770
  try {
3734
- await fs16.stat(jobsDir);
3771
+ await fs17.stat(jobsDir);
3735
3772
  } catch (error2) {
3736
3773
  if (isNotFoundError(error2)) {
3737
3774
  return;
3738
3775
  }
3739
3776
  throw error2;
3740
3777
  }
3741
- const release = await acquireFileLock(filePath, { fs: fs16 });
3778
+ const release = await acquireFileLock(filePath, { fs: fs17 });
3742
3779
  try {
3743
- await fs16.unlink(filePath);
3780
+ await fs17.unlink(filePath);
3744
3781
  } catch (error2) {
3745
3782
  if (!isNotFoundError(error2)) {
3746
3783
  throw error2;
@@ -3750,14 +3787,14 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3750
3787
  }
3751
3788
  }
3752
3789
  async function writeJobAtomically(filePath, entry) {
3753
- await fs16.mkdir(path10.dirname(filePath), { recursive: true });
3790
+ await fs17.mkdir(path10.dirname(filePath), { recursive: true });
3754
3791
  const tempPath = `${filePath}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
3755
3792
  try {
3756
- await fs16.writeFile(tempPath, `${JSON.stringify(entry, null, 2)}
3793
+ await fs17.writeFile(tempPath, `${JSON.stringify(entry, null, 2)}
3757
3794
  `, {
3758
3795
  encoding: "utf8"
3759
3796
  });
3760
- await fs16.rename(tempPath, filePath);
3797
+ await fs17.rename(tempPath, filePath);
3761
3798
  } catch (error2) {
3762
3799
  await removeTempFile(tempPath);
3763
3800
  throw error2;
@@ -3765,7 +3802,7 @@ function createJobRegistry(homeDir, fs16 = defaultStateFs) {
3765
3802
  }
3766
3803
  async function removeTempFile(tempPath) {
3767
3804
  try {
3768
- await fs16.unlink(tempPath);
3805
+ await fs17.unlink(tempPath);
3769
3806
  } catch (error2) {
3770
3807
  if (!isNotFoundError(error2)) {
3771
3808
  throw error2;
@@ -3812,11 +3849,11 @@ function isRecord4(value) {
3812
3849
 
3813
3850
  // packages/poe-code-config/src/state/templates.ts
3814
3851
  import path11 from "node:path";
3815
- function createTemplateRegistry(homeDir, fs16 = defaultStateFs) {
3852
+ function createTemplateRegistry(homeDir, fs17 = defaultStateFs) {
3816
3853
  const filePath = path11.join(homeDir, ".poe-code", "state", "templates.json");
3817
3854
  async function readState() {
3818
3855
  try {
3819
- const raw = await fs16.readFile(filePath, "utf8");
3856
+ const raw = await fs17.readFile(filePath, "utf8");
3820
3857
  return normalizeTemplateState(JSON.parse(raw));
3821
3858
  } catch (error2) {
3822
3859
  if (isNotFoundError(error2)) {
@@ -3826,14 +3863,14 @@ function createTemplateRegistry(homeDir, fs16 = defaultStateFs) {
3826
3863
  }
3827
3864
  }
3828
3865
  async function writeState(state) {
3829
- await fs16.writeFile(filePath, `${JSON.stringify(state, null, 2)}
3866
+ await fs17.writeFile(filePath, `${JSON.stringify(state, null, 2)}
3830
3867
  `, {
3831
3868
  encoding: "utf8"
3832
3869
  });
3833
3870
  }
3834
3871
  async function updateState(mutator) {
3835
- await fs16.mkdir(path11.dirname(filePath), { recursive: true });
3836
- const release = await acquireFileLock(filePath, { fs: fs16 });
3872
+ await fs17.mkdir(path11.dirname(filePath), { recursive: true });
3873
+ const release = await acquireFileLock(filePath, { fs: fs17 });
3837
3874
  try {
3838
3875
  const state = await readState();
3839
3876
  mutator(state);
@@ -3903,10 +3940,10 @@ function isRecord5(value) {
3903
3940
  }
3904
3941
 
3905
3942
  // packages/poe-code-config/src/state/index.ts
3906
- function createStateManager(homeDir, fs16) {
3943
+ function createStateManager(homeDir, fs17) {
3907
3944
  return {
3908
- templates: createTemplateRegistry(homeDir, fs16),
3909
- jobs: createJobRegistry(homeDir, fs16)
3945
+ templates: createTemplateRegistry(homeDir, fs17),
3946
+ jobs: createJobRegistry(homeDir, fs17)
3910
3947
  };
3911
3948
  }
3912
3949
 
@@ -4134,10 +4171,10 @@ function parseSources(value) {
4134
4171
  if (!isRecord6(item)) {
4135
4172
  throw new Error('Invalid "sources" frontmatter. Expected each source to be a string or object.');
4136
4173
  }
4137
- const path50 = readRequiredString(item.path, "sources[].path");
4174
+ const path55 = readRequiredString(item.path, "sources[].path");
4138
4175
  const startLine = readOptionalPositiveInteger(item.startLine, "sources[].startLine");
4139
4176
  const endLine = readOptionalPositiveInteger(item.endLine, "sources[].endLine");
4140
- 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 } }));
4141
4178
  });
4142
4179
  }
4143
4180
  function readOptionalString(value, field) {
@@ -4379,18 +4416,18 @@ function isPidRunning2(pid) {
4379
4416
  return !hasErrorCode3(error2, "ESRCH");
4380
4417
  }
4381
4418
  }
4382
- async function removeLockFile2(fs16, lockPath) {
4419
+ async function removeLockFile2(fs17, lockPath) {
4383
4420
  try {
4384
- await fs16.unlink(lockPath);
4421
+ await fs17.unlink(lockPath);
4385
4422
  } catch (error2) {
4386
4423
  if (!hasErrorCode3(error2, "ENOENT")) {
4387
4424
  throw error2;
4388
4425
  }
4389
4426
  }
4390
4427
  }
4391
- async function readLockPid(fs16, lockPath) {
4428
+ async function readLockPid(fs17, lockPath) {
4392
4429
  try {
4393
- return parsePid(await fs16.readFile(lockPath, "utf8"));
4430
+ return parsePid(await fs17.readFile(lockPath, "utf8"));
4394
4431
  } catch (error2) {
4395
4432
  if (hasErrorCode3(error2, "ENOENT")) {
4396
4433
  return null;
@@ -4399,7 +4436,7 @@ async function readLockPid(fs16, lockPath) {
4399
4436
  }
4400
4437
  }
4401
4438
  async function withLock(root, run, options = {}) {
4402
- const fs16 = options.fs ?? createDefaultFs2();
4439
+ const fs17 = options.fs ?? createDefaultFs2();
4403
4440
  const lockPath = path17.join(root, MEMORY_LOCK_RELPATH);
4404
4441
  const pid = options.pid ?? process.pid;
4405
4442
  const retries = options.retries ?? 20;
@@ -4408,24 +4445,24 @@ async function withLock(root, run, options = {}) {
4408
4445
  const pidIsRunning = options.isPidRunning ?? isPidRunning2;
4409
4446
  for (let attempt = 0; attempt <= retries; attempt += 1) {
4410
4447
  try {
4411
- await fs16.writeFile(lockPath, `${pid}
4448
+ await fs17.writeFile(lockPath, `${pid}
4412
4449
  `, { encoding: "utf8", flag: "wx" });
4413
4450
  try {
4414
4451
  return await run();
4415
4452
  } finally {
4416
- await removeLockFile2(fs16, lockPath);
4453
+ await removeLockFile2(fs17, lockPath);
4417
4454
  }
4418
4455
  } catch (error2) {
4419
4456
  if (!hasErrorCode3(error2, "EEXIST")) {
4420
4457
  throw error2;
4421
4458
  }
4422
4459
  }
4423
- const existingPid = await readLockPid(fs16, lockPath);
4460
+ const existingPid = await readLockPid(fs17, lockPath);
4424
4461
  if (existingPid === null) {
4425
4462
  continue;
4426
4463
  }
4427
4464
  if (existingPid === void 0 || !pidIsRunning(existingPid)) {
4428
- await removeLockFile2(fs16, lockPath);
4465
+ await removeLockFile2(fs17, lockPath);
4429
4466
  continue;
4430
4467
  }
4431
4468
  if (attempt < retries) {
@@ -5192,8 +5229,8 @@ function parseOlderThan(value) {
5192
5229
  }
5193
5230
 
5194
5231
  // packages/memory/src/ingest.ts
5195
- import * as fs13 from "node:fs/promises";
5196
- import path45 from "node:path";
5232
+ import * as fs14 from "node:fs/promises";
5233
+ import path50 from "node:path";
5197
5234
 
5198
5235
  // packages/agent-spawn/src/register-factories.ts
5199
5236
  import { spawn as spawnChildProcess2 } from "node:child_process";
@@ -6029,29 +6066,29 @@ function wrapForLogTee(argv, jobId) {
6029
6066
  return ["sh", "-c", script];
6030
6067
  }
6031
6068
  async function* streamLogFile(env, jobId, opts) {
6032
- const fs16 = env.fs ?? nodeFs2;
6069
+ const fs17 = env.fs ?? nodeFs2;
6033
6070
  const file = jobLogPath(jobId);
6034
6071
  let byteOffset = opts.sinceByte ?? 0;
6035
6072
  while (true) {
6036
- if (opts.since !== void 0 && !await wasModifiedSince(fs16, file, opts.since)) {
6037
- await waitForLogChange(fs16, file);
6073
+ if (opts.since !== void 0 && !await wasModifiedSince(fs17, file, opts.since)) {
6074
+ await waitForLogChange(fs17, file);
6038
6075
  continue;
6039
6076
  }
6040
- const result = await readLogChunk(fs16, file, byteOffset);
6077
+ const result = await readLogChunk(fs17, file, byteOffset);
6041
6078
  if (result !== null) {
6042
6079
  byteOffset = result.nextByteOffset;
6043
6080
  yield result.chunk;
6044
6081
  continue;
6045
6082
  }
6046
- await waitForLogChange(fs16, file);
6083
+ await waitForLogChange(fs17, file);
6047
6084
  }
6048
6085
  }
6049
- async function wasModifiedSince(fs16, file, since) {
6050
- if (fs16.promises.stat === void 0) {
6086
+ async function wasModifiedSince(fs17, file, since) {
6087
+ if (fs17.promises.stat === void 0) {
6051
6088
  return true;
6052
6089
  }
6053
6090
  try {
6054
- const stat7 = await fs16.promises.stat(file);
6091
+ const stat7 = await fs17.promises.stat(file);
6055
6092
  return stat7.mtimeMs >= since.getTime();
6056
6093
  } catch (error2) {
6057
6094
  if (isNodeError(error2) && error2.code === "ENOENT") {
@@ -6061,11 +6098,11 @@ async function wasModifiedSince(fs16, file, since) {
6061
6098
  }
6062
6099
  }
6063
6100
  async function waitForExit(env, jobId, opts = {}) {
6064
- const fs16 = env.fs ?? nodeFs2;
6101
+ const fs17 = env.fs ?? nodeFs2;
6065
6102
  const file = jobExitPath(jobId);
6066
6103
  while (true) {
6067
6104
  throwIfAborted2(opts.signal);
6068
- const contents = await readTextFileIfExists(fs16, file);
6105
+ const contents = await readTextFileIfExists(fs17, file);
6069
6106
  if (contents !== null) {
6070
6107
  const text5 = contents.trim();
6071
6108
  const exitCode = Number(text5);
@@ -6083,8 +6120,8 @@ function jobLogPath(jobId) {
6083
6120
  function jobExitPath(jobId) {
6084
6121
  return `${JOB_DIR}/${jobId}.exit`;
6085
6122
  }
6086
- async function readLogChunk(fs16, file, byteOffset) {
6087
- const contents = await readFileIfExists2(fs16, file);
6123
+ async function readLogChunk(fs17, file, byteOffset) {
6124
+ const contents = await readFileIfExists2(fs17, file);
6088
6125
  if (contents === null || byteOffset >= contents.byteLength) {
6089
6126
  return null;
6090
6127
  }
@@ -6096,13 +6133,13 @@ async function readLogChunk(fs16, file, byteOffset) {
6096
6133
  nextByteOffset: contents.byteLength
6097
6134
  };
6098
6135
  }
6099
- async function readTextFileIfExists(fs16, file) {
6100
- const contents = await readFileIfExists2(fs16, file);
6136
+ async function readTextFileIfExists(fs17, file) {
6137
+ const contents = await readFileIfExists2(fs17, file);
6101
6138
  return contents?.toString("utf8") ?? null;
6102
6139
  }
6103
- async function readFileIfExists2(fs16, file) {
6140
+ async function readFileIfExists2(fs17, file) {
6104
6141
  try {
6105
- const contents = await fs16.promises.readFile(file);
6142
+ const contents = await fs17.promises.readFile(file);
6106
6143
  return Buffer.isBuffer(contents) ? contents : Buffer.from(contents);
6107
6144
  } catch (error2) {
6108
6145
  if (isNodeError(error2) && error2.code === "ENOENT") {
@@ -6111,8 +6148,8 @@ async function readFileIfExists2(fs16, file) {
6111
6148
  throw error2;
6112
6149
  }
6113
6150
  }
6114
- async function waitForLogChange(fs16, file) {
6115
- const watch = fs16.watch;
6151
+ async function waitForLogChange(fs17, file) {
6152
+ const watch = fs17.watch;
6116
6153
  if (typeof watch !== "function") {
6117
6154
  await sleep3(POLL_INTERVAL_MS);
6118
6155
  return;
@@ -6903,7 +6940,7 @@ import { PassThrough as PassThrough2, Writable as Writable2 } from "node:stream"
6903
6940
  import path33 from "node:path";
6904
6941
  var JOB_DIR2 = "/tmp/poe-jobs";
6905
6942
  function createE2bJobHandle(input) {
6906
- const fs16 = createE2bLogStreamFs(input.sandbox);
6943
+ const fs17 = createE2bLogStreamFs(input.sandbox);
6907
6944
  return {
6908
6945
  id: input.jobId,
6909
6946
  envId: input.envId,
@@ -6919,10 +6956,10 @@ function createE2bJobHandle(input) {
6919
6956
  return isRunning ? "running" : "lost";
6920
6957
  },
6921
6958
  stream(opts = {}) {
6922
- return streamLogFile({ fs: fs16 }, input.jobId, opts);
6959
+ return streamLogFile({ fs: fs17 }, input.jobId, opts);
6923
6960
  },
6924
6961
  async wait() {
6925
- const result = await waitForExit({ fs: fs16 }, input.jobId);
6962
+ const result = await waitForExit({ fs: fs17 }, input.jobId);
6926
6963
  const preserveMs = input.preserveAfterExitHours * 60 * 60 * 1e3;
6927
6964
  if (preserveMs > 0) {
6928
6965
  await input.sandbox.setTimeout(preserveMs);
@@ -7419,10 +7456,10 @@ var e2bAuthScope = defineScope("e2b", {
7419
7456
  });
7420
7457
  async function resolveE2bApiKey(input) {
7421
7458
  const homeDir = input.homeDir ?? os4.homedir();
7422
- const fs16 = input.fs ?? nodeFs4;
7459
+ const fs17 = input.fs ?? nodeFs4;
7423
7460
  const env = input.env ?? process.env;
7424
7461
  const document = await readMergedDocument(
7425
- fs16,
7462
+ fs17,
7426
7463
  resolveConfigPath(homeDir),
7427
7464
  resolveProjectConfigPath(input.cwd)
7428
7465
  );
@@ -7929,6 +7966,23 @@ var gooseAcpSpawnConfig = {
7929
7966
  skipAuth: true
7930
7967
  };
7931
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
+
7932
7986
  // packages/agent-spawn/src/configs/index.ts
7933
7987
  var allSpawnConfigs = [
7934
7988
  claudeCodeSpawnConfig,
@@ -7945,6 +7999,7 @@ var acpLookup = /* @__PURE__ */ new Map();
7945
7999
  acpLookup.set(openCodeAcpSpawnConfig.agentId, openCodeAcpSpawnConfig);
7946
8000
  acpLookup.set(kimiAcpSpawnConfig.agentId, kimiAcpSpawnConfig);
7947
8001
  acpLookup.set(gooseAcpSpawnConfig.agentId, gooseAcpSpawnConfig);
8002
+ acpLookup.set(geminiCliAcpSpawnConfig.agentId, geminiCliAcpSpawnConfig);
7948
8003
  function getSpawnConfig(input) {
7949
8004
  const resolvedId = resolveAgentId(input);
7950
8005
  if (!resolvedId) {
@@ -7964,8 +8019,8 @@ function listMcpSupportedAgents() {
7964
8019
  }
7965
8020
 
7966
8021
  // packages/agent-spawn/src/spawn.ts
7967
- import { mkdirSync as mkdirSync3, openSync, writeSync, closeSync } from "node:fs";
7968
- 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";
7969
8024
 
7970
8025
  // packages/agent-spawn/src/configs/resolve-config.ts
7971
8026
  function resolveConfig(agentId) {
@@ -8366,7 +8421,7 @@ function createEventQueue() {
8366
8421
 
8367
8422
  // packages/agent-spawn/src/skill-bridge.ts
8368
8423
  import crypto from "node:crypto";
8369
- import os6 from "node:os";
8424
+ import os7 from "node:os";
8370
8425
 
8371
8426
  // packages/agent-skill-config/src/configs.ts
8372
8427
  import os5 from "node:os";
@@ -8380,6 +8435,10 @@ var agentSkillConfigs = {
8380
8435
  globalSkillDir: "~/.codex/skills",
8381
8436
  localSkillDir: ".codex/skills"
8382
8437
  },
8438
+ "gemini-cli": {
8439
+ globalSkillDir: "~/.gemini/skills",
8440
+ localSkillDir: ".gemini/skills"
8441
+ },
8383
8442
  opencode: {
8384
8443
  globalSkillDir: "~/.config/opencode/skills",
8385
8444
  localSkillDir: ".opencode/skills"
@@ -8576,7 +8635,7 @@ function resolveSkillReference(ref, cwd, homeDir) {
8576
8635
  import { execFileSync } from "node:child_process";
8577
8636
  import * as fs10 from "node:fs";
8578
8637
  import path39 from "node:path";
8579
- var markerPrefix = "# poe-code-spawn-skills:";
8638
+ var defaultMarkerPrefix = "poe-code-spawn-skills";
8580
8639
  function defaultGitDirRunner(cwd) {
8581
8640
  try {
8582
8641
  return execFileSync("git", ["rev-parse", "--git-dir"], {
@@ -8596,10 +8655,10 @@ function resolveExcludePath(cwd) {
8596
8655
  }
8597
8656
  return path39.join(path39.isAbsolute(gitDir) ? gitDir : path39.resolve(cwd, gitDir), "info/exclude");
8598
8657
  }
8599
- function markers(runId) {
8658
+ function markers(runId, markerPrefix) {
8600
8659
  return {
8601
- begin: `${markerPrefix}${runId} begin`,
8602
- end: `${markerPrefix}${runId} end`
8660
+ begin: `# ${markerPrefix}:${runId} begin`,
8661
+ end: `# ${markerPrefix}:${runId} end`
8603
8662
  };
8604
8663
  }
8605
8664
  function readExcludeFile(excludePath) {
@@ -8615,8 +8674,8 @@ function readExcludeFile(excludePath) {
8615
8674
  function isNodeError2(error2) {
8616
8675
  return error2 instanceof Error && "code" in error2;
8617
8676
  }
8618
- function removeBlock(content, runId) {
8619
- const { begin, end } = markers(runId);
8677
+ function removeBlock(content, runId, markerPrefix) {
8678
+ const { begin, end } = markers(runId, markerPrefix);
8620
8679
  const lines = content.split("\n");
8621
8680
  const result = [];
8622
8681
  for (let index = 0; index < lines.length; index += 1) {
@@ -8631,23 +8690,27 @@ function removeBlock(content, runId) {
8631
8690
  }
8632
8691
  return result.join("\n");
8633
8692
  }
8634
- function appendBlock(content, runId, entries) {
8635
- const { begin, end } = markers(runId);
8693
+ function appendBlock(content, runId, entries, markerPrefix) {
8694
+ const { begin, end } = markers(runId, markerPrefix);
8636
8695
  const existing = content ?? "";
8637
8696
  const prefix = existing.length === 0 || existing.endsWith("\n") ? existing : `${existing}
8638
8697
  `;
8639
8698
  return `${prefix}${[begin, ...entries, end, ""].join("\n")}`;
8640
8699
  }
8641
- function appendExcludeBlock(cwd, runId, entries) {
8700
+ function appendExcludeBlock(cwd, runId, entries, opts) {
8642
8701
  const excludePath = resolveExcludePath(cwd);
8643
8702
  if (excludePath === void 0) {
8644
8703
  return;
8645
8704
  }
8646
8705
  fs10.mkdirSync(path39.dirname(excludePath), { recursive: true });
8647
8706
  const content = readExcludeFile(excludePath);
8648
- fs10.writeFileSync(excludePath, appendBlock(content, runId, entries), "utf8");
8707
+ fs10.writeFileSync(
8708
+ excludePath,
8709
+ appendBlock(content, runId, entries, opts?.markerPrefix ?? defaultMarkerPrefix),
8710
+ "utf8"
8711
+ );
8649
8712
  }
8650
- function removeExcludeBlock(cwd, runId) {
8713
+ function removeExcludeBlock(cwd, runId, opts) {
8651
8714
  const excludePath = resolveExcludePath(cwd);
8652
8715
  if (excludePath === void 0) {
8653
8716
  return;
@@ -8656,7 +8719,11 @@ function removeExcludeBlock(cwd, runId) {
8656
8719
  if (content === void 0) {
8657
8720
  return;
8658
8721
  }
8659
- fs10.writeFileSync(excludePath, removeBlock(content, runId), "utf8");
8722
+ fs10.writeFileSync(
8723
+ excludePath,
8724
+ removeBlock(content, runId, opts?.markerPrefix ?? defaultMarkerPrefix),
8725
+ "utf8"
8726
+ );
8660
8727
  }
8661
8728
 
8662
8729
  // packages/agent-skill-config/src/bridge-active-skills.ts
@@ -8862,22 +8929,679 @@ function cleanupBridgedSkills(manifest) {
8862
8929
  removeExcludeBlock(manifest.cwd, manifest.runId);
8863
8930
  }
8864
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
+
8865
9564
  // packages/agent-spawn/src/skill-bridge.ts
8866
- function bridgeSkillsForRun(agentId, cwd, skills) {
8867
- if (!skills || skills.length === 0) {
9565
+ function bridgeResourcesForRun(agentId, cwd, skills, hooks) {
9566
+ if ((!skills || skills.length === 0) && !hooks) {
8868
9567
  return void 0;
8869
9568
  }
8870
- const manifest = bridgeActiveSkills(agentId, cwd, skills, os6.homedir(), crypto.randomUUID());
8871
- for (const warning2 of manifest.warnings) {
8872
- 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;
8873
9592
  }
8874
- return manifest;
9593
+ return manifests;
8875
9594
  }
8876
- function cleanupSkillsForRun(manifest) {
9595
+ function cleanupResourcesForRun(manifest) {
8877
9596
  if (!manifest) {
8878
9597
  return;
8879
9598
  }
8880
- cleanupBridgedSkills(manifest);
9599
+ if (manifest.hooks) {
9600
+ cleanupBridgedHooks(manifest.hooks);
9601
+ }
9602
+ if (manifest.skills) {
9603
+ cleanupBridgedSkills(manifest.skills);
9604
+ }
8881
9605
  }
8882
9606
 
8883
9607
  // packages/agent-spawn/src/adapters/utils.ts
@@ -9003,21 +9727,21 @@ async function* adaptClaude(lines) {
9003
9727
  if (blockType !== "tool_result") continue;
9004
9728
  const kind = toolKindsById.get(item.tool_use_id);
9005
9729
  toolKindsById.delete(item.tool_use_id);
9006
- let path50;
9730
+ let path55;
9007
9731
  if (typeof item.content === "string") {
9008
- path50 = item.content;
9732
+ path55 = item.content;
9009
9733
  } else {
9010
9734
  try {
9011
- path50 = JSON.stringify(item.content);
9735
+ path55 = JSON.stringify(item.content);
9012
9736
  } catch {
9013
- path50 = String(item.content);
9737
+ path55 = String(item.content);
9014
9738
  }
9015
9739
  }
9016
9740
  yield {
9017
9741
  event: "tool_complete",
9018
9742
  id: item.tool_use_id,
9019
9743
  kind,
9020
- path: path50
9744
+ path: path55
9021
9745
  };
9022
9746
  }
9023
9747
  }
@@ -9113,10 +9837,10 @@ async function* adaptCodex(lines) {
9113
9837
  const kindFromStart = toolKindById.get(item.id);
9114
9838
  const kind = kindFromStart ?? (itemType === "command_execution" ? "exec" : itemType === "file_edit" ? "edit" : "other");
9115
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;
9116
- const path50 = titleFromEvent ?? toolTitleById.get(item.id) ?? "";
9840
+ const path55 = titleFromEvent ?? toolTitleById.get(item.id) ?? "";
9117
9841
  toolTitleById.delete(item.id);
9118
9842
  toolKindById.delete(item.id);
9119
- yield { event: "tool_complete", id: item.id, kind, path: path50 };
9843
+ yield { event: "tool_complete", id: item.id, kind, path: path55 };
9120
9844
  }
9121
9845
  }
9122
9846
  }
@@ -9644,7 +10368,7 @@ function spawnStreaming(options) {
9644
10368
  };
9645
10369
  }
9646
10370
  };
9647
- const manifest = bridgeSkillsForRun(options.agentId, cwd, options.skills);
10371
+ const manifest = bridgeResourcesForRun(options.agentId, cwd, options.skills, options.hooks);
9648
10372
  void (async () => {
9649
10373
  try {
9650
10374
  for await (const output of adapter(queue.lines())) {
@@ -9695,7 +10419,7 @@ function spawnStreaming(options) {
9695
10419
  ...ctx.logFile && !result.logFile ? { logFile: ctx.logFile } : {}
9696
10420
  };
9697
10421
  } finally {
9698
- cleanupSkillsForRun(manifest);
10422
+ cleanupResourcesForRun(manifest);
9699
10423
  }
9700
10424
  })();
9701
10425
  return {
@@ -9831,7 +10555,7 @@ async function runSpawn(agentId, options, context) {
9831
10555
  return { stdout: "", stderr: "", exitCode: 0 };
9832
10556
  }
9833
10557
  const cwd = options.cwd ?? process.cwd();
9834
- const manifest = bridgeSkillsForRun(agentId, cwd, options.skills);
10558
+ const manifest = bridgeResourcesForRun(agentId, cwd, options.skills, options.hooks);
9835
10559
  let logFd;
9836
10560
  try {
9837
10561
  const logFilePath = resolveSpawnLogPath(options);
@@ -9899,7 +10623,7 @@ async function runSpawn(agentId, options, context) {
9899
10623
  };
9900
10624
  } finally {
9901
10625
  closeSpawnLog(logFd);
9902
- cleanupSkillsForRun(manifest);
10626
+ cleanupResourcesForRun(manifest);
9903
10627
  }
9904
10628
  }
9905
10629
  spawn4.retry = createSpawnRetry((service, options) => {
@@ -9921,12 +10645,12 @@ function resolveSpawnLogPath(options) {
9921
10645
  if (!options.logDir || !options.logFileName) {
9922
10646
  return void 0;
9923
10647
  }
9924
- return path41.join(options.logDir, options.logFileName);
10648
+ return path46.join(options.logDir, options.logFileName);
9925
10649
  }
9926
10650
  function openSpawnLog(filePath) {
9927
10651
  try {
9928
- mkdirSync3(path41.dirname(filePath), { recursive: true });
9929
- return openSync(filePath, "a");
10652
+ mkdirSync5(path46.dirname(filePath), { recursive: true });
10653
+ return openSync2(filePath, "a");
9930
10654
  } catch {
9931
10655
  return void 0;
9932
10656
  }
@@ -9941,7 +10665,7 @@ function appendSpawnLog(fd, chunk) {
9941
10665
  function closeSpawnLog(fd) {
9942
10666
  if (fd === void 0) return;
9943
10667
  try {
9944
- closeSync(fd);
10668
+ closeSync2(fd);
9945
10669
  } catch {
9946
10670
  }
9947
10671
  }
@@ -9950,7 +10674,7 @@ function closeSpawnLog(fd) {
9950
10674
  var DEFAULT_ACTIVITY_TIMEOUT_MS = 10 * 60 * 1e3;
9951
10675
 
9952
10676
  // packages/agent-spawn/src/acp/replay.ts
9953
- import path42 from "node:path";
10677
+ import path47 from "node:path";
9954
10678
  import { homedir as homedir2 } from "node:os";
9955
10679
  import { open as open2, readdir as readdir5 } from "node:fs/promises";
9956
10680
  import { createInterface } from "node:readline";
@@ -9969,13 +10693,13 @@ import { homedir } from "node:os";
9969
10693
  import { join } from "node:path";
9970
10694
 
9971
10695
  // packages/agent-spawn/src/acp/middlewares/spawn-log.ts
9972
- import path43 from "node:path";
10696
+ import path48 from "node:path";
9973
10697
  import { homedir as homedir3 } from "node:os";
9974
10698
  import { mkdir as mkdir5, open as open3 } from "node:fs/promises";
9975
10699
 
9976
10700
  // packages/memory/src/tokens.ts
9977
- import * as fs12 from "node:fs/promises";
9978
- import path44 from "node:path";
10701
+ import * as fs13 from "node:fs/promises";
10702
+ import path49 from "node:path";
9979
10703
 
9980
10704
  // packages/tokenfill/dist/tokenizer.js
9981
10705
  import { get_encoding } from "tiktoken";
@@ -10016,7 +10740,7 @@ function countTokens(text5) {
10016
10740
  }
10017
10741
 
10018
10742
  // packages/tokenfill/dist/corpus.js
10019
- import { readdirSync as readdirSync2, readFileSync as readFileSync3 } from "node:fs";
10743
+ import { readdirSync as readdirSync2, readFileSync as readFileSync6 } from "node:fs";
10020
10744
  import { dirname, join as join2 } from "node:path";
10021
10745
  import { fileURLToPath as fileURLToPath2 } from "node:url";
10022
10746
  var CORPUS_ARTICLE_SEPARATOR = "\n\n";
@@ -10029,7 +10753,7 @@ function loadBuiltInCorpusArticles() {
10029
10753
  if (corpusFileNames.length === 0) {
10030
10754
  throw new Error(`No built-in corpus markdown files found in ${corpusDirectoryPath}`);
10031
10755
  }
10032
- return corpusFileNames.map((fileName) => readFileSync3(join2(corpusDirectoryPath, fileName), "utf8").trim());
10756
+ return corpusFileNames.map((fileName) => readFileSync6(join2(corpusDirectoryPath, fileName), "utf8").trim());
10033
10757
  }
10034
10758
  var BUILT_IN_CORPUS_ARTICLES = loadBuiltInCorpusArticles();
10035
10759
 
@@ -10039,7 +10763,7 @@ var builtInCorpusByteLength = Buffer.byteLength(builtInCorpusText, "utf8");
10039
10763
 
10040
10764
  // packages/memory/src/tokens.ts
10041
10765
  async function computeTokenStats(root) {
10042
- if (!await pathExists4(root)) {
10766
+ if (!await pathExists5(root)) {
10043
10767
  return {
10044
10768
  memoryTokens: 0,
10045
10769
  sourceTokens: 0,
@@ -10059,13 +10783,13 @@ async function computeTokenStats(root) {
10059
10783
  }
10060
10784
  }
10061
10785
  }
10062
- const repoRoot = path44.resolve(root, "..", "..");
10786
+ const repoRoot = path49.resolve(root, "..", "..");
10063
10787
  let sourceTokens = 0;
10064
10788
  const missingSources = [];
10065
10789
  for (const sourcePath of sourcePaths) {
10066
- const absPath = path44.isAbsolute(sourcePath) ? sourcePath : path44.resolve(repoRoot, sourcePath);
10790
+ const absPath = path49.isAbsolute(sourcePath) ? sourcePath : path49.resolve(repoRoot, sourcePath);
10067
10791
  try {
10068
- const content = await fs12.readFile(absPath, "utf8");
10792
+ const content = await fs13.readFile(absPath, "utf8");
10069
10793
  sourceTokens += countTokens(content);
10070
10794
  } catch (error2) {
10071
10795
  if (isMissing4(error2)) {
@@ -10084,9 +10808,9 @@ async function computeTokenStats(root) {
10084
10808
  missingSources
10085
10809
  };
10086
10810
  }
10087
- async function pathExists4(targetPath) {
10811
+ async function pathExists5(targetPath) {
10088
10812
  try {
10089
- await fs12.stat(targetPath);
10813
+ await fs13.stat(targetPath);
10090
10814
  return true;
10091
10815
  } catch (error2) {
10092
10816
  if (isMissing4(error2)) {
@@ -10114,10 +10838,10 @@ function resolveRunners(overrides) {
10114
10838
  async function ingest(root, opts, runners) {
10115
10839
  const resolved = resolveRunners(runners);
10116
10840
  const source = await materializeSource(opts.source);
10117
- const indexMdBytes = await fs13.readFile(path45.join(root, MEMORY_INDEX_RELPATH));
10841
+ const indexMdBytes = await fs14.readFile(path50.join(root, MEMORY_INDEX_RELPATH));
10118
10842
  const configOptions = {
10119
- fs: fs13,
10120
- filePath: path45.join(inferRepoRoot(root), "poe-code.json")
10843
+ fs: fs14,
10844
+ filePath: path50.join(inferRepoRoot(root), "poe-code.json")
10121
10845
  };
10122
10846
  const agentId = await resolveAgent(configOptions, opts.agent ?? null) ?? opts.agent ?? "claude-code";
10123
10847
  const key = resolved.computeIngestKey({
@@ -10197,7 +10921,7 @@ function buildIngestPrompt(root, sourceLabel, sourceText) {
10197
10921
  }
10198
10922
  async function materializeSource(source) {
10199
10923
  if (source.kind === "file") {
10200
- const bytes = await fs13.readFile(source.absPath);
10924
+ const bytes = await fs14.readFile(source.absPath);
10201
10925
  return {
10202
10926
  label: source.absPath,
10203
10927
  bytes,
@@ -10207,7 +10931,7 @@ async function materializeSource(source) {
10207
10931
  throw new Error("URL ingest not implemented yet.");
10208
10932
  }
10209
10933
  function inferRepoRoot(root) {
10210
- return path45.resolve(root, "..", "..");
10934
+ return path50.resolve(root, "..", "..");
10211
10935
  }
10212
10936
  async function runWithTimeout(promise, timeoutMs) {
10213
10937
  return await new Promise((resolve2, reject) => {
@@ -11014,7 +11738,7 @@ var agentMcpConfigs = {
11014
11738
  }
11015
11739
  };
11016
11740
  var supportedAgents3 = Object.keys(agentMcpConfigs);
11017
- function resolveAgentSupport2(input, registry = agentMcpConfigs) {
11741
+ function resolveAgentSupport3(input, registry = agentMcpConfigs) {
11018
11742
  const resolvedId = resolveAgentId(input);
11019
11743
  if (!resolvedId) {
11020
11744
  return { status: "unknown", input };
@@ -11026,10 +11750,10 @@ function resolveAgentSupport2(input, registry = agentMcpConfigs) {
11026
11750
  return { status: "supported", input, id: resolvedId, config };
11027
11751
  }
11028
11752
  function isSupported(agentId) {
11029
- return resolveAgentSupport2(agentId).status === "supported";
11753
+ return resolveAgentSupport3(agentId).status === "supported";
11030
11754
  }
11031
- function getAgentConfig2(agentId) {
11032
- const support = resolveAgentSupport2(agentId);
11755
+ function getAgentConfig3(agentId) {
11756
+ const support = resolveAgentSupport3(agentId);
11033
11757
  return support.status === "supported" ? support.config : void 0;
11034
11758
  }
11035
11759
  function resolveConfigPath2(config, platform) {
@@ -11040,7 +11764,7 @@ function resolveConfigPath2(config, platform) {
11040
11764
  }
11041
11765
 
11042
11766
  // packages/agent-mcp-config/src/apply.ts
11043
- import path46 from "node:path";
11767
+ import path51 from "node:path";
11044
11768
  import { parse as parseYaml3, stringify as stringifyYaml2 } from "yaml";
11045
11769
 
11046
11770
  // packages/agent-mcp-config/src/shapes.ts
@@ -11132,7 +11856,7 @@ function getShapeTransformer(shape) {
11132
11856
 
11133
11857
  // packages/agent-mcp-config/src/apply.ts
11134
11858
  function getConfigDirectory(configPath) {
11135
- return path46.dirname(configPath);
11859
+ return path51.dirname(configPath);
11136
11860
  }
11137
11861
  var UnsupportedAgentError2 = class extends Error {
11138
11862
  constructor(agentId) {
@@ -11158,9 +11882,9 @@ function expandHomePath(configPath, homeDir) {
11158
11882
  return homeDir;
11159
11883
  }
11160
11884
  if (configPath.startsWith("~/")) {
11161
- return path46.join(homeDir, configPath.slice(2));
11885
+ return path51.join(homeDir, configPath.slice(2));
11162
11886
  }
11163
- return path46.join(homeDir, configPath.slice(1));
11887
+ return path51.join(homeDir, configPath.slice(1));
11164
11888
  }
11165
11889
  function parseYamlDocument(content) {
11166
11890
  if (content.trim() === "") {
@@ -11193,7 +11917,7 @@ async function writeYamlConfig(configPath, document, options) {
11193
11917
  return;
11194
11918
  }
11195
11919
  const absolutePath = expandHomePath(configPath, options.homeDir);
11196
- const configDir = path46.dirname(absolutePath);
11920
+ const configDir = path51.dirname(absolutePath);
11197
11921
  await options.fs.mkdir(configDir, { recursive: true });
11198
11922
  await options.fs.writeFile(absolutePath, serializeYamlDocument(document), {
11199
11923
  encoding: "utf8"
@@ -11220,7 +11944,7 @@ async function configure2(agentId, server, options) {
11220
11944
  if (!isSupported(agentId)) {
11221
11945
  throw new UnsupportedAgentError2(agentId);
11222
11946
  }
11223
- const config = getAgentConfig2(agentId);
11947
+ const config = getAgentConfig3(agentId);
11224
11948
  const configPath = resolveConfigPath2(config, options.platform);
11225
11949
  const shapeTransformer = getShapeTransformer(config.shape);
11226
11950
  const shaped = shapeTransformer(server);
@@ -11276,7 +12000,7 @@ async function unconfigure2(agentId, serverName, options) {
11276
12000
  if (!isSupported(agentId)) {
11277
12001
  throw new UnsupportedAgentError2(agentId);
11278
12002
  }
11279
- const config = getAgentConfig2(agentId);
12003
+ const config = getAgentConfig3(agentId);
11280
12004
  const configPath = resolveConfigPath2(config, options.platform);
11281
12005
  if (config.format === "yaml") {
11282
12006
  const document = await readYamlConfig(configPath, options);
@@ -11370,8 +12094,8 @@ async function installMemory(options) {
11370
12094
  }
11371
12095
 
11372
12096
  // packages/memory/src/query.ts
11373
- import * as fs14 from "node:fs/promises";
11374
- import path47 from "node:path";
12097
+ import * as fs15 from "node:fs/promises";
12098
+ import path52 from "node:path";
11375
12099
  async function queryMemory(root, options) {
11376
12100
  const pages = await listPages(root);
11377
12101
  if (pages.length === 0) {
@@ -11384,8 +12108,8 @@ async function queryMemory(root, options) {
11384
12108
  };
11385
12109
  }
11386
12110
  const configOptions = {
11387
- fs: fs14,
11388
- filePath: path47.join(inferRepoRoot2(root), "poe-code.json")
12111
+ fs: fs15,
12112
+ filePath: path52.join(inferRepoRoot2(root), "poe-code.json")
11389
12113
  };
11390
12114
  const agentId = await resolveAgent(configOptions, options.agent ?? null) ?? options.agent ?? "claude-code";
11391
12115
  const context = await selectQueryContext(root, options.question, options.budget);
@@ -11400,7 +12124,7 @@ async function queryMemory(root, options) {
11400
12124
  }
11401
12125
  async function selectQueryContext(root, question, budget) {
11402
12126
  const [indexText, pages] = await Promise.all([
11403
- fs14.readFile(path47.join(root, MEMORY_INDEX_RELPATH), "utf8"),
12127
+ fs15.readFile(path52.join(root, MEMORY_INDEX_RELPATH), "utf8"),
11404
12128
  listPages(root)
11405
12129
  ]);
11406
12130
  const indexTokens = countTokens(indexText);
@@ -11479,12 +12203,12 @@ function tokenize(text5) {
11479
12203
  return text5.toLowerCase().split(/[^a-z0-9]+/).filter((token) => token.length > 0);
11480
12204
  }
11481
12205
  function inferRepoRoot2(root) {
11482
- return path47.resolve(root, "..", "..");
12206
+ return path52.resolve(root, "..", "..");
11483
12207
  }
11484
12208
 
11485
12209
  // packages/memory/src/explain.ts
11486
- import * as fs15 from "node:fs/promises";
11487
- import path48 from "node:path";
12210
+ import * as fs16 from "node:fs/promises";
12211
+ import path53 from "node:path";
11488
12212
  async function explainPage(root, options) {
11489
12213
  const targetPage = await readPageIfPresent(root, options.relPath);
11490
12214
  if (targetPage === void 0) {
@@ -11506,8 +12230,8 @@ async function explainPage(root, options) {
11506
12230
  throw new Error(`budget too small; needs at least ${tokensUsed} tokens`);
11507
12231
  }
11508
12232
  const configOptions = {
11509
- fs: fs15,
11510
- filePath: path48.join(inferRepoRoot3(root), "poe-code.json")
12233
+ fs: fs16,
12234
+ filePath: path53.join(inferRepoRoot3(root), "poe-code.json")
11511
12235
  };
11512
12236
  const agentId = await resolveAgent(configOptions, options.agent ?? null) ?? options.agent ?? "claude-code";
11513
12237
  const response = await spawn4(agentId, { prompt });
@@ -11556,7 +12280,7 @@ async function readPageIfPresent(root, relPath) {
11556
12280
  }
11557
12281
  }
11558
12282
  function inferRepoRoot3(root) {
11559
- return path48.resolve(root, "..", "..");
12283
+ return path53.resolve(root, "..", "..");
11560
12284
  }
11561
12285
 
11562
12286
  // packages/memory/src/explain.cli.ts
@@ -11569,9 +12293,9 @@ async function runMemoryExplain(input) {
11569
12293
  }
11570
12294
 
11571
12295
  // packages/memory/src/handle.ts
11572
- import path49 from "node:path";
12296
+ import path54 from "node:path";
11573
12297
  function openMemory(opts) {
11574
- if (!path49.isAbsolute(opts.root)) {
12298
+ if (!path54.isAbsolute(opts.root)) {
11575
12299
  throw new Error(`openMemory: root must be absolute, got ${opts.root}`);
11576
12300
  }
11577
12301
  const root = opts.root;