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.
- package/dist/bin/poe-gemini.js +23 -0
- package/dist/cli/commands/configure-payload.js +100 -13
- package/dist/cli/commands/configure-payload.js.map +1 -1
- package/dist/cli/commands/configure.js +2 -2
- package/dist/cli/commands/configure.js.map +1 -1
- package/dist/cli/commands/pipeline.js +4 -2
- package/dist/cli/commands/pipeline.js.map +1 -1
- package/dist/cli/commands/provider.d.ts +1 -0
- package/dist/cli/commands/provider.js +94 -3
- package/dist/cli/commands/provider.js.map +1 -1
- package/dist/cli/commands/ralph.js +1 -0
- package/dist/cli/commands/ralph.js.map +1 -1
- package/dist/cli/commands/shared.d.ts +8 -1
- package/dist/cli/commands/shared.js +88 -7
- package/dist/cli/commands/shared.js.map +1 -1
- package/dist/cli/commands/spawn.js +20 -0
- package/dist/cli/commands/spawn.js.map +1 -1
- package/dist/cli/commands/test.d.ts +5 -1
- package/dist/cli/commands/test.js +58 -6
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/constants.d.ts +2 -2
- package/dist/cli/constants.js +3 -14
- package/dist/cli/constants.js.map +1 -1
- package/dist/cli/isolated-env.d.ts +2 -1
- package/dist/cli/isolated-env.js +20 -2
- package/dist/cli/isolated-env.js.map +1 -1
- package/dist/cli/options.d.ts +2 -5
- package/dist/cli/options.js +10 -1
- package/dist/cli/options.js.map +1 -1
- package/dist/cli/poe-code-command-runner.js +7 -2
- package/dist/cli/poe-code-command-runner.js.map +1 -1
- package/dist/cli/prompt-runner.js +4 -2
- package/dist/cli/prompt-runner.js.map +1 -1
- package/dist/cli/prompts.d.ts +23 -13
- package/dist/cli/prompts.js +13 -0
- package/dist/cli/prompts.js.map +1 -1
- package/dist/cli/service-registry.d.ts +12 -3
- package/dist/cli/service-registry.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +4936 -2415
- package/dist/index.js.map +4 -4
- package/dist/providers/claude-code.js +924 -174
- package/dist/providers/claude-code.js.map +4 -4
- package/dist/providers/codex.js +916 -178
- package/dist/providers/codex.js.map +4 -4
- package/dist/providers/create-provider.d.ts +1 -0
- package/dist/providers/create-provider.js +1 -0
- package/dist/providers/create-provider.js.map +1 -1
- package/dist/providers/gemini-cli.d.ts +16 -0
- package/dist/providers/gemini-cli.js +11349 -0
- package/dist/providers/gemini-cli.js.map +7 -0
- package/dist/providers/goose.js +881 -183
- package/dist/providers/goose.js.map +4 -4
- package/dist/providers/kimi.js +905 -165
- package/dist/providers/kimi.js.map +4 -4
- package/dist/providers/opencode.js +905 -165
- package/dist/providers/opencode.js.map +4 -4
- package/dist/providers/poe-agent.js +1155 -357
- package/dist/providers/poe-agent.js.map +4 -4
- package/dist/providers/spawn-options.d.ts +3 -0
- package/dist/sdk/pipeline.d.ts +1 -1
- package/dist/sdk/pipeline.js +22 -19
- package/dist/sdk/pipeline.js.map +1 -1
- package/dist/sdk/ralph.js +5 -0
- package/dist/sdk/ralph.js.map +1 -1
- package/dist/sdk/spawn-core.d.ts +3 -0
- package/dist/sdk/spawn-core.js +6 -8
- package/dist/sdk/spawn-core.js.map +1 -1
- package/dist/sdk/spawn.d.ts +8 -8
- package/dist/sdk/spawn.js +26 -3
- package/dist/sdk/spawn.js.map +1 -1
- package/dist/sdk/types.d.ts +7 -0
- package/dist/utils/command-checks.d.ts +8 -0
- package/dist/utils/command-checks.js +35 -9
- package/dist/utils/command-checks.js.map +1 -1
- package/dist/utils/dry-run.js +7 -1
- package/dist/utils/dry-run.js.map +1 -1
- package/dist/workflow-templates/github-issue-opened.caller.yml +2 -1
- package/dist/workflow-templates/github-issue-opened.ejected.yml +2 -1
- package/package.json +2 -1
- package/packages/agent-skill-config/dist/configs.js +4 -0
- package/packages/agent-skill-config/dist/git-exclude.d.ts +6 -2
- package/packages/agent-skill-config/dist/git-exclude.js +12 -12
- package/packages/memory/dist/index.js +924 -200
- package/packages/memory/dist/index.js.map +4 -4
- package/packages/superintendent/dist/index.d.ts +2 -1
- package/packages/superintendent/dist/runtime/loop.d.ts +1 -0
- 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,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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(
|
|
666
|
+
const fullPath = buildPath(path55, key);
|
|
667
667
|
if (isPlainObject(winningValue)) {
|
|
668
|
-
const merged = mergeObjectLayers(objectLayers, [...
|
|
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(
|
|
694
|
-
return [...
|
|
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(
|
|
2083
|
-
const ext = getExtension(
|
|
2082
|
+
function detectFormat2(path55) {
|
|
2083
|
+
const ext = getExtension(path55);
|
|
2084
2084
|
return extensionMap[ext];
|
|
2085
2085
|
}
|
|
2086
|
-
function getExtension(
|
|
2087
|
-
const lastDot =
|
|
2086
|
+
function getExtension(path55) {
|
|
2087
|
+
const lastDot = path55.lastIndexOf(".");
|
|
2088
2088
|
if (lastDot === -1) {
|
|
2089
2089
|
return "";
|
|
2090
2090
|
}
|
|
2091
|
-
return
|
|
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(
|
|
2142
|
+
async function readFileIfExists(fs17, target) {
|
|
2143
2143
|
try {
|
|
2144
|
-
return await
|
|
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(
|
|
2152
|
+
async function pathExists(fs17, target) {
|
|
2153
2153
|
try {
|
|
2154
|
-
await
|
|
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(
|
|
2178
|
+
async function backupInvalidDocument(fs17, targetPath, content) {
|
|
2179
2179
|
const backupPath = createInvalidDocumentBackupPath(targetPath);
|
|
2180
|
-
await
|
|
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(
|
|
2739
|
-
const globalDocument = await readStoredDocument(
|
|
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(
|
|
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(
|
|
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(
|
|
2763
|
+
async function readStoredDocument(fs17, filePath) {
|
|
2764
2764
|
try {
|
|
2765
|
-
const raw = await
|
|
2766
|
-
return await parseStoredDocument(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
2825
|
+
return fs17.readFile(filePath, "utf8");
|
|
2826
2826
|
}
|
|
2827
2827
|
};
|
|
2828
2828
|
}
|
|
2829
|
-
async function recoverInvalidDocument(
|
|
2830
|
-
await
|
|
2829
|
+
async function recoverInvalidDocument(fs17, filePath, content) {
|
|
2830
|
+
await fs17.mkdir(path7.dirname(filePath), { recursive: true });
|
|
2831
2831
|
const backupPath = createInvalidBackupPath(filePath);
|
|
2832
|
-
await
|
|
2833
|
-
await
|
|
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,
|
|
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([...
|
|
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, [...
|
|
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(
|
|
2982
|
-
return
|
|
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
|
|
3408
|
-
|
|
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: "
|
|
3442
|
+
envVar: "CF_AIG_TOKEN",
|
|
3412
3443
|
storageKey: "provider:cloudflare",
|
|
3413
|
-
prompt: { title: "Cloudflare
|
|
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
|
-
|
|
3455
|
+
baseUrlPath: "compat"
|
|
3419
3456
|
},
|
|
3420
3457
|
{
|
|
3421
3458
|
id: "openai-responses",
|
|
3422
|
-
|
|
3459
|
+
baseUrlPath: "openai"
|
|
3423
3460
|
},
|
|
3424
3461
|
{
|
|
3425
3462
|
id: "anthropic-messages",
|
|
3426
|
-
|
|
3463
|
+
baseUrlPath: "anthropic"
|
|
3427
3464
|
},
|
|
3428
3465
|
{
|
|
3429
3466
|
id: "google-generations",
|
|
3430
|
-
|
|
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: (
|
|
3511
|
-
readFile: (
|
|
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(
|
|
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
|
|
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(
|
|
3552
|
-
if (!
|
|
3588
|
+
async function readLockMetadata(fs17, lockPath) {
|
|
3589
|
+
if (!fs17.readFile) {
|
|
3553
3590
|
return void 0;
|
|
3554
3591
|
}
|
|
3555
3592
|
try {
|
|
3556
|
-
return parseLockMetadata(await
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
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:
|
|
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(
|
|
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,
|
|
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
|
|
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
|
|
3676
|
-
const release = await acquireFileLock(filePath, { fs:
|
|
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
|
|
3686
|
-
const release = await acquireFileLock(filePath, { fs:
|
|
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
|
|
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
|
|
3757
|
+
const stat7 = await fs17.stat(filePath);
|
|
3721
3758
|
if (!stat7.isFile()) {
|
|
3722
3759
|
continue;
|
|
3723
3760
|
}
|
|
3724
|
-
const job = parseJobEntry(await
|
|
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
|
|
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:
|
|
3778
|
+
const release = await acquireFileLock(filePath, { fs: fs17 });
|
|
3742
3779
|
try {
|
|
3743
|
-
await
|
|
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
|
|
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
|
|
3793
|
+
await fs17.writeFile(tempPath, `${JSON.stringify(entry, null, 2)}
|
|
3757
3794
|
`, {
|
|
3758
3795
|
encoding: "utf8"
|
|
3759
3796
|
});
|
|
3760
|
-
await
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
3836
|
-
const release = await acquireFileLock(filePath, { fs:
|
|
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,
|
|
3943
|
+
function createStateManager(homeDir, fs17) {
|
|
3907
3944
|
return {
|
|
3908
|
-
templates: createTemplateRegistry(homeDir,
|
|
3909
|
-
jobs: createJobRegistry(homeDir,
|
|
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
|
|
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:
|
|
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(
|
|
4419
|
+
async function removeLockFile2(fs17, lockPath) {
|
|
4383
4420
|
try {
|
|
4384
|
-
await
|
|
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(
|
|
4428
|
+
async function readLockPid(fs17, lockPath) {
|
|
4392
4429
|
try {
|
|
4393
|
-
return parsePid(await
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
5196
|
-
import
|
|
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
|
|
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(
|
|
6037
|
-
await waitForLogChange(
|
|
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(
|
|
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(
|
|
6083
|
+
await waitForLogChange(fs17, file);
|
|
6047
6084
|
}
|
|
6048
6085
|
}
|
|
6049
|
-
async function wasModifiedSince(
|
|
6050
|
-
if (
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
6087
|
-
const contents = await readFileIfExists2(
|
|
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(
|
|
6100
|
-
const contents = await readFileIfExists2(
|
|
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(
|
|
6140
|
+
async function readFileIfExists2(fs17, file) {
|
|
6104
6141
|
try {
|
|
6105
|
-
const contents = await
|
|
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(
|
|
6115
|
-
const 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
|
|
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:
|
|
6959
|
+
return streamLogFile({ fs: fs17 }, input.jobId, opts);
|
|
6923
6960
|
},
|
|
6924
6961
|
async wait() {
|
|
6925
|
-
const result = await waitForExit({ fs:
|
|
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
|
|
7459
|
+
const fs17 = input.fs ?? nodeFs4;
|
|
7423
7460
|
const env = input.env ?? process.env;
|
|
7424
7461
|
const document = await readMergedDocument(
|
|
7425
|
-
|
|
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
|
|
7968
|
-
import
|
|
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
|
|
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
|
|
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:
|
|
8602
|
-
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(
|
|
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(
|
|
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
|
|
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
|
|
8871
|
-
|
|
8872
|
-
|
|
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
|
|
9593
|
+
return manifests;
|
|
8875
9594
|
}
|
|
8876
|
-
function
|
|
9595
|
+
function cleanupResourcesForRun(manifest) {
|
|
8877
9596
|
if (!manifest) {
|
|
8878
9597
|
return;
|
|
8879
9598
|
}
|
|
8880
|
-
|
|
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
|
|
9730
|
+
let path55;
|
|
9007
9731
|
if (typeof item.content === "string") {
|
|
9008
|
-
|
|
9732
|
+
path55 = item.content;
|
|
9009
9733
|
} else {
|
|
9010
9734
|
try {
|
|
9011
|
-
|
|
9735
|
+
path55 = JSON.stringify(item.content);
|
|
9012
9736
|
} catch {
|
|
9013
|
-
|
|
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:
|
|
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
|
|
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:
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
|
10648
|
+
return path46.join(options.logDir, options.logFileName);
|
|
9925
10649
|
}
|
|
9926
10650
|
function openSpawnLog(filePath) {
|
|
9927
10651
|
try {
|
|
9928
|
-
|
|
9929
|
-
return
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
9978
|
-
import
|
|
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
|
|
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) =>
|
|
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
|
|
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 =
|
|
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 =
|
|
10790
|
+
const absPath = path49.isAbsolute(sourcePath) ? sourcePath : path49.resolve(repoRoot, sourcePath);
|
|
10067
10791
|
try {
|
|
10068
|
-
const content = await
|
|
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
|
|
10811
|
+
async function pathExists5(targetPath) {
|
|
10088
10812
|
try {
|
|
10089
|
-
await
|
|
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
|
|
10841
|
+
const indexMdBytes = await fs14.readFile(path50.join(root, MEMORY_INDEX_RELPATH));
|
|
10118
10842
|
const configOptions = {
|
|
10119
|
-
fs:
|
|
10120
|
-
filePath:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
11753
|
+
return resolveAgentSupport3(agentId).status === "supported";
|
|
11030
11754
|
}
|
|
11031
|
-
function
|
|
11032
|
-
const support =
|
|
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
|
|
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
|
|
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
|
|
11885
|
+
return path51.join(homeDir, configPath.slice(2));
|
|
11162
11886
|
}
|
|
11163
|
-
return
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
11374
|
-
import
|
|
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:
|
|
11388
|
-
filePath:
|
|
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
|
-
|
|
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
|
|
12206
|
+
return path52.resolve(root, "..", "..");
|
|
11483
12207
|
}
|
|
11484
12208
|
|
|
11485
12209
|
// packages/memory/src/explain.ts
|
|
11486
|
-
import * as
|
|
11487
|
-
import
|
|
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:
|
|
11510
|
-
filePath:
|
|
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
|
|
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
|
|
12296
|
+
import path54 from "node:path";
|
|
11573
12297
|
function openMemory(opts) {
|
|
11574
|
-
if (!
|
|
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;
|