poe-code 3.0.222 → 3.0.224
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/cli/commands/configure-payload.js +72 -15
- package/dist/cli/commands/configure-payload.js.map +1 -1
- package/dist/cli/commands/configure.d.ts +2 -0
- package/dist/cli/commands/configure.js +55 -15
- package/dist/cli/commands/configure.js.map +1 -1
- package/dist/cli/commands/ensure-isolated-config.js +24 -3
- package/dist/cli/commands/ensure-isolated-config.js.map +1 -1
- package/dist/cli/commands/harness.js +45 -2
- package/dist/cli/commands/harness.js.map +1 -1
- package/dist/cli/commands/login.js +11 -2
- package/dist/cli/commands/login.js.map +1 -1
- package/dist/cli/commands/plan.js +52 -20
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/provider.d.ts +2 -0
- package/dist/cli/commands/provider.js +126 -3
- package/dist/cli/commands/provider.js.map +1 -1
- package/dist/cli/commands/shared.d.ts +16 -1
- package/dist/cli/commands/shared.js +141 -18
- package/dist/cli/commands/shared.js.map +1 -1
- package/dist/cli/commands/spawn.js +24 -3
- package/dist/cli/commands/spawn.js.map +1 -1
- package/dist/cli/commands/tasks-options.d.ts +9 -1
- package/dist/cli/commands/tasks-options.js +88 -5
- package/dist/cli/commands/tasks-options.js.map +1 -1
- package/dist/cli/commands/tasks.js +250 -7
- package/dist/cli/commands/tasks.js.map +1 -1
- package/dist/cli/constants.d.ts +1 -2
- package/dist/cli/constants.js +1 -13
- package/dist/cli/constants.js.map +1 -1
- package/dist/cli/container.js +22 -9
- package/dist/cli/container.js.map +1 -1
- package/dist/cli/environment.d.ts +1 -0
- package/dist/cli/environment.js +3 -1
- package/dist/cli/environment.js.map +1 -1
- package/dist/cli/options.d.ts +1 -1
- package/dist/cli/options.js +10 -1
- package/dist/cli/options.js.map +1 -1
- package/dist/cli/program.js +127 -13
- package/dist/cli/program.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 +3 -1
- package/dist/cli/prompts.js +13 -0
- package/dist/cli/prompts.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +47146 -26676
- package/dist/index.js.map +4 -4
- package/dist/providers/claude-code.js +4547 -1202
- package/dist/providers/claude-code.js.map +4 -4
- package/dist/providers/codex.js +4558 -1210
- package/dist/providers/codex.js.map +4 -4
- package/dist/providers/goose.js +4652 -1137
- package/dist/providers/goose.js.map +4 -4
- package/dist/providers/kimi.js +4548 -1203
- package/dist/providers/kimi.js.map +4 -4
- package/dist/providers/opencode.js +4543 -1198
- package/dist/providers/opencode.js.map +4 -4
- package/dist/providers/poe-agent.js +12879 -11508
- package/dist/providers/poe-agent.js.map +4 -4
- package/dist/providers/spawn-options.d.ts +1 -0
- package/dist/sdk/container.js +22 -9
- package/dist/sdk/container.js.map +1 -1
- package/dist/sdk/pipeline.js +1 -0
- package/dist/sdk/pipeline.js.map +1 -1
- package/dist/sdk/spawn-core.d.ts +2 -0
- package/dist/sdk/spawn-core.js +2 -1
- package/dist/sdk/spawn-core.js.map +1 -1
- package/dist/sdk/spawn.d.ts +6 -1
- package/dist/sdk/spawn.js +192 -4
- package/dist/sdk/spawn.js.map +1 -1
- package/dist/sdk/types.d.ts +10 -1
- package/dist/services/config.d.ts +4 -14
- package/dist/services/config.js +12 -54
- package/dist/services/config.js.map +1 -1
- package/dist/workflow-templates/maestro-turn.yml +159 -0
- package/package.json +6 -2
- package/packages/agent-skill-config/dist/bridge-active-skills.d.ts +23 -0
- package/packages/agent-skill-config/dist/bridge-active-skills.js +194 -0
- package/packages/agent-skill-config/dist/configs.d.ts +1 -1
- package/packages/agent-skill-config/dist/configs.js +5 -5
- package/packages/agent-skill-config/dist/git-exclude.d.ts +4 -0
- package/packages/agent-skill-config/dist/git-exclude.js +93 -0
- package/packages/agent-skill-config/dist/index.d.ts +5 -0
- package/packages/agent-skill-config/dist/index.js +3 -0
- package/packages/agent-skill-config/dist/resolve-skill-reference.d.ts +22 -0
- package/packages/agent-skill-config/dist/resolve-skill-reference.js +82 -0
- package/packages/design-system/dist/components/browser.d.ts +15 -0
- package/packages/design-system/dist/components/browser.js +26 -0
- package/packages/design-system/dist/explorer/index.d.ts +1 -1
- package/packages/design-system/dist/explorer/keymap.js +6 -3
- package/packages/design-system/dist/explorer/render/footer.js +14 -0
- package/packages/design-system/dist/explorer/runtime.js +11 -4
- package/packages/design-system/dist/explorer/state.d.ts +6 -1
- package/packages/design-system/dist/index.d.ts +2 -1
- package/packages/design-system/dist/index.js +1 -0
- package/packages/memory/dist/index.js +2564 -568
- package/packages/memory/dist/index.js.map +4 -4
- package/scripts/postinstall-sync-skills.mjs +15 -2
|
@@ -35,7 +35,7 @@ function assertSafeRelPath(input) {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
// packages/memory/src/resolve-root.ts
|
|
38
|
-
import
|
|
38
|
+
import path12 from "node:path";
|
|
39
39
|
|
|
40
40
|
// packages/poe-code-config/src/runtime.ts
|
|
41
41
|
import { existsSync } from "node:fs";
|
|
@@ -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, fs16) {
|
|
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, fs14) {
|
|
|
531
531
|
checkedPaths.push(filePath);
|
|
532
532
|
try {
|
|
533
533
|
return {
|
|
534
|
-
content: await
|
|
534
|
+
content: await fs16.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, path50) {
|
|
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, path50);
|
|
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, path50) {
|
|
637
637
|
let winningSource;
|
|
638
638
|
let winningValue;
|
|
639
639
|
const objectLayers = [];
|
|
@@ -663,9 +663,9 @@ function resolveKey(layers, key, path45) {
|
|
|
663
663
|
if (winningSource === void 0) {
|
|
664
664
|
return void 0;
|
|
665
665
|
}
|
|
666
|
-
const fullPath = buildPath(
|
|
666
|
+
const fullPath = buildPath(path50, key);
|
|
667
667
|
if (isPlainObject(winningValue)) {
|
|
668
|
-
const merged = mergeObjectLayers(objectLayers, [...
|
|
668
|
+
const merged = mergeObjectLayers(objectLayers, [...path50, 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(path50, key) {
|
|
694
|
+
return [...path50, key].join(".");
|
|
695
695
|
}
|
|
696
696
|
function isPlainObject(value) {
|
|
697
697
|
if (value === null || Array.isArray(value) || typeof value !== "object") {
|
|
@@ -1445,6 +1445,10 @@ function hasProperty(value, key) {
|
|
|
1445
1445
|
return key in value;
|
|
1446
1446
|
}
|
|
1447
1447
|
|
|
1448
|
+
// packages/design-system/src/components/browser.ts
|
|
1449
|
+
import { spawn } from "node:child_process";
|
|
1450
|
+
import process2 from "node:process";
|
|
1451
|
+
|
|
1448
1452
|
// packages/design-system/src/acp/writer.ts
|
|
1449
1453
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
1450
1454
|
var storage = new AsyncLocalStorage2();
|
|
@@ -2075,16 +2079,16 @@ function getConfigFormat(pathOrFormat) {
|
|
|
2075
2079
|
}
|
|
2076
2080
|
return formatRegistry[formatName];
|
|
2077
2081
|
}
|
|
2078
|
-
function detectFormat2(
|
|
2079
|
-
const ext = getExtension(
|
|
2082
|
+
function detectFormat2(path50) {
|
|
2083
|
+
const ext = getExtension(path50);
|
|
2080
2084
|
return extensionMap[ext];
|
|
2081
2085
|
}
|
|
2082
|
-
function getExtension(
|
|
2083
|
-
const lastDot =
|
|
2086
|
+
function getExtension(path50) {
|
|
2087
|
+
const lastDot = path50.lastIndexOf(".");
|
|
2084
2088
|
if (lastDot === -1) {
|
|
2085
2089
|
return "";
|
|
2086
2090
|
}
|
|
2087
|
-
return
|
|
2091
|
+
return path50.slice(lastDot).toLowerCase();
|
|
2088
2092
|
}
|
|
2089
2093
|
|
|
2090
2094
|
// packages/config-mutations/src/execution/path-utils.ts
|
|
@@ -2135,9 +2139,9 @@ function resolvePath(rawPath, homeDir, pathMapper) {
|
|
|
2135
2139
|
function isNotFound(error2) {
|
|
2136
2140
|
return typeof error2 === "object" && error2 !== null && "code" in error2 && error2.code === "ENOENT";
|
|
2137
2141
|
}
|
|
2138
|
-
async function readFileIfExists(
|
|
2142
|
+
async function readFileIfExists(fs16, target) {
|
|
2139
2143
|
try {
|
|
2140
|
-
return await
|
|
2144
|
+
return await fs16.readFile(target, "utf8");
|
|
2141
2145
|
} catch (error2) {
|
|
2142
2146
|
if (isNotFound(error2)) {
|
|
2143
2147
|
return null;
|
|
@@ -2145,9 +2149,9 @@ async function readFileIfExists(fs14, target) {
|
|
|
2145
2149
|
throw error2;
|
|
2146
2150
|
}
|
|
2147
2151
|
}
|
|
2148
|
-
async function pathExists(
|
|
2152
|
+
async function pathExists(fs16, target) {
|
|
2149
2153
|
try {
|
|
2150
|
-
await
|
|
2154
|
+
await fs16.stat(target);
|
|
2151
2155
|
return true;
|
|
2152
2156
|
} catch (error2) {
|
|
2153
2157
|
if (isNotFound(error2)) {
|
|
@@ -2171,9 +2175,9 @@ function createInvalidDocumentBackupPath(targetPath) {
|
|
|
2171
2175
|
const ext = targetPath.includes(".") ? targetPath.split(".").pop() : "bak";
|
|
2172
2176
|
return `${targetPath}.invalid-${createTimestamp()}.${ext}`;
|
|
2173
2177
|
}
|
|
2174
|
-
async function backupInvalidDocument(
|
|
2178
|
+
async function backupInvalidDocument(fs16, targetPath, content) {
|
|
2175
2179
|
const backupPath = createInvalidDocumentBackupPath(targetPath);
|
|
2176
|
-
await
|
|
2180
|
+
await fs16.writeFile(backupPath, content, { encoding: "utf8" });
|
|
2177
2181
|
}
|
|
2178
2182
|
function describeMutation(kind, targetPath) {
|
|
2179
2183
|
const displayPath = targetPath ?? "target";
|
|
@@ -2731,12 +2735,12 @@ async function executeMutation(mutation, context, options) {
|
|
|
2731
2735
|
}
|
|
2732
2736
|
|
|
2733
2737
|
// packages/poe-code-config/src/store.ts
|
|
2734
|
-
async function readMergedDocument(
|
|
2735
|
-
const globalDocument = await readStoredDocument(
|
|
2738
|
+
async function readMergedDocument(fs16, globalPath, projectPath) {
|
|
2739
|
+
const globalDocument = await readStoredDocument(fs16, globalPath);
|
|
2736
2740
|
if (!projectPath || projectPath === globalPath) {
|
|
2737
2741
|
return globalDocument.data;
|
|
2738
2742
|
}
|
|
2739
|
-
const projectDocument = await readStoredDocument(
|
|
2743
|
+
const projectDocument = await readStoredDocument(fs16, projectPath);
|
|
2740
2744
|
const resolved = await resolve(
|
|
2741
2745
|
[
|
|
2742
2746
|
{
|
|
@@ -2750,16 +2754,16 @@ async function readMergedDocument(fs14, globalPath, projectPath) {
|
|
|
2750
2754
|
}
|
|
2751
2755
|
],
|
|
2752
2756
|
{
|
|
2753
|
-
fs: createResolvedConfigFs(
|
|
2757
|
+
fs: createResolvedConfigFs(fs16, globalPath, globalDocument.content),
|
|
2754
2758
|
autoExtend: true
|
|
2755
2759
|
}
|
|
2756
2760
|
);
|
|
2757
2761
|
return normalizeDocument(resolved.data);
|
|
2758
2762
|
}
|
|
2759
|
-
async function readStoredDocument(
|
|
2763
|
+
async function readStoredDocument(fs16, filePath) {
|
|
2760
2764
|
try {
|
|
2761
|
-
const raw = await
|
|
2762
|
-
return await parseStoredDocument(
|
|
2765
|
+
const raw = await fs16.readFile(filePath, "utf8");
|
|
2766
|
+
return await parseStoredDocument(fs16, filePath, raw);
|
|
2763
2767
|
} catch (error2) {
|
|
2764
2768
|
if (isNotFound(error2)) {
|
|
2765
2769
|
return {
|
|
@@ -2770,7 +2774,7 @@ async function readStoredDocument(fs14, filePath) {
|
|
|
2770
2774
|
throw error2;
|
|
2771
2775
|
}
|
|
2772
2776
|
}
|
|
2773
|
-
async function parseStoredDocument(
|
|
2777
|
+
async function parseStoredDocument(fs16, filePath, raw) {
|
|
2774
2778
|
try {
|
|
2775
2779
|
return {
|
|
2776
2780
|
content: raw,
|
|
@@ -2778,7 +2782,7 @@ async function parseStoredDocument(fs14, filePath, raw) {
|
|
|
2778
2782
|
};
|
|
2779
2783
|
} catch (error2) {
|
|
2780
2784
|
if (error2 instanceof SyntaxError) {
|
|
2781
|
-
await recoverInvalidDocument(
|
|
2785
|
+
await recoverInvalidDocument(fs16, filePath, raw);
|
|
2782
2786
|
return {
|
|
2783
2787
|
content: EMPTY_DOCUMENT,
|
|
2784
2788
|
data: {}
|
|
@@ -2812,21 +2816,21 @@ function normalizeScopeValues(value) {
|
|
|
2812
2816
|
}
|
|
2813
2817
|
return normalized;
|
|
2814
2818
|
}
|
|
2815
|
-
function createResolvedConfigFs(
|
|
2819
|
+
function createResolvedConfigFs(fs16, globalPath, globalContent) {
|
|
2816
2820
|
return {
|
|
2817
2821
|
readFile(filePath, _encoding) {
|
|
2818
2822
|
if (filePath === globalPath) {
|
|
2819
2823
|
return Promise.resolve(globalContent);
|
|
2820
2824
|
}
|
|
2821
|
-
return
|
|
2825
|
+
return fs16.readFile(filePath, "utf8");
|
|
2822
2826
|
}
|
|
2823
2827
|
};
|
|
2824
2828
|
}
|
|
2825
|
-
async function recoverInvalidDocument(
|
|
2826
|
-
await
|
|
2829
|
+
async function recoverInvalidDocument(fs16, filePath, content) {
|
|
2830
|
+
await fs16.mkdir(path7.dirname(filePath), { recursive: true });
|
|
2827
2831
|
const backupPath = createInvalidBackupPath(filePath);
|
|
2828
|
-
await
|
|
2829
|
-
await
|
|
2832
|
+
await fs16.writeFile(backupPath, content, { encoding: "utf8" });
|
|
2833
|
+
await fs16.writeFile(filePath, EMPTY_DOCUMENT, { encoding: "utf8" });
|
|
2830
2834
|
}
|
|
2831
2835
|
function createInvalidBackupPath(filePath) {
|
|
2832
2836
|
const directory = path7.dirname(filePath);
|
|
@@ -2950,7 +2954,7 @@ function mergeScope(scope, baseScope, overrideScope) {
|
|
|
2950
2954
|
...Object.fromEntries(scopeEntries)
|
|
2951
2955
|
};
|
|
2952
2956
|
}
|
|
2953
|
-
function mergeRuntimeScope(baseScope, overrideScope,
|
|
2957
|
+
function mergeRuntimeScope(baseScope, overrideScope, path50 = []) {
|
|
2954
2958
|
const merged = {};
|
|
2955
2959
|
const keys = /* @__PURE__ */ new Set([...Object.keys(baseScope), ...Object.keys(overrideScope)]);
|
|
2956
2960
|
for (const key of keys) {
|
|
@@ -2962,20 +2966,20 @@ function mergeRuntimeScope(baseScope, overrideScope, path45 = []) {
|
|
|
2962
2966
|
}
|
|
2963
2967
|
continue;
|
|
2964
2968
|
}
|
|
2965
|
-
if (isRuntimeConcatenativeArray([...
|
|
2969
|
+
if (isRuntimeConcatenativeArray([...path50, key]) && Array.isArray(baseValue) && Array.isArray(overrideValue)) {
|
|
2966
2970
|
merged[key] = [...baseValue, ...overrideValue];
|
|
2967
2971
|
continue;
|
|
2968
2972
|
}
|
|
2969
2973
|
if (isRecord3(baseValue) && isRecord3(overrideValue)) {
|
|
2970
|
-
merged[key] = mergeRuntimeScope(baseValue, overrideValue, [...
|
|
2974
|
+
merged[key] = mergeRuntimeScope(baseValue, overrideValue, [...path50, key]);
|
|
2971
2975
|
continue;
|
|
2972
2976
|
}
|
|
2973
2977
|
merged[key] = overrideValue;
|
|
2974
2978
|
}
|
|
2975
2979
|
return merged;
|
|
2976
2980
|
}
|
|
2977
|
-
function isRuntimeConcatenativeArray(
|
|
2978
|
-
return
|
|
2981
|
+
function isRuntimeConcatenativeArray(path50) {
|
|
2982
|
+
return path50.join(".") === "mounts" || path50.join(".") === "runner.workspace.exclude";
|
|
2979
2983
|
}
|
|
2980
2984
|
function isRecord3(value) {
|
|
2981
2985
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
@@ -3031,11 +3035,420 @@ import path8 from "node:path";
|
|
|
3031
3035
|
var EMPTY_DOCUMENT2 = `${JSON.stringify({}, null, 2)}
|
|
3032
3036
|
`;
|
|
3033
3037
|
|
|
3038
|
+
// packages/poe-code-config/src/configured-services.ts
|
|
3039
|
+
import path9 from "node:path";
|
|
3040
|
+
|
|
3041
|
+
// packages/agent-defs/src/agents/claude-code.ts
|
|
3042
|
+
var claudeCodeAgent = {
|
|
3043
|
+
id: "claude-code",
|
|
3044
|
+
name: "claude-code",
|
|
3045
|
+
label: "Claude Code",
|
|
3046
|
+
summary: "Configure Claude Code to route through Poe.",
|
|
3047
|
+
aliases: ["claude"],
|
|
3048
|
+
binaryName: "claude",
|
|
3049
|
+
apiShapes: ["anthropic-messages"],
|
|
3050
|
+
configPath: "~/.claude/settings.json",
|
|
3051
|
+
branding: {
|
|
3052
|
+
colors: {
|
|
3053
|
+
dark: "#C15F3C",
|
|
3054
|
+
light: "#C15F3C"
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
};
|
|
3058
|
+
|
|
3059
|
+
// packages/agent-defs/src/agents/claude-desktop.ts
|
|
3060
|
+
var claudeDesktopAgent = {
|
|
3061
|
+
id: "claude-desktop",
|
|
3062
|
+
name: "claude-desktop",
|
|
3063
|
+
label: "Claude Desktop",
|
|
3064
|
+
summary: "Anthropic's official desktop application for Claude",
|
|
3065
|
+
configPath: "~/.claude/settings.json",
|
|
3066
|
+
branding: {
|
|
3067
|
+
colors: {
|
|
3068
|
+
dark: "#D97757",
|
|
3069
|
+
light: "#D97757"
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
};
|
|
3073
|
+
|
|
3074
|
+
// packages/agent-defs/src/agents/codex.ts
|
|
3075
|
+
var codexAgent = {
|
|
3076
|
+
id: "codex",
|
|
3077
|
+
name: "codex",
|
|
3078
|
+
label: "Codex",
|
|
3079
|
+
summary: "Configure Codex to use Poe as the model provider.",
|
|
3080
|
+
binaryName: "codex",
|
|
3081
|
+
apiShapes: ["openai-responses"],
|
|
3082
|
+
configPath: "~/.codex/config.toml",
|
|
3083
|
+
branding: {
|
|
3084
|
+
colors: {
|
|
3085
|
+
dark: "#D5D9DF",
|
|
3086
|
+
light: "#7A7F86"
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
};
|
|
3090
|
+
|
|
3091
|
+
// packages/agent-defs/src/agents/opencode.ts
|
|
3092
|
+
var openCodeAgent = {
|
|
3093
|
+
id: "opencode",
|
|
3094
|
+
name: "opencode",
|
|
3095
|
+
label: "OpenCode CLI",
|
|
3096
|
+
summary: "Configure OpenCode CLI to use the Poe API.",
|
|
3097
|
+
binaryName: "opencode",
|
|
3098
|
+
apiShapes: ["openai-chat-completions"],
|
|
3099
|
+
configPath: "~/.config/opencode/config.json",
|
|
3100
|
+
branding: {
|
|
3101
|
+
colors: {
|
|
3102
|
+
dark: "#4A4F55",
|
|
3103
|
+
light: "#2F3338"
|
|
3104
|
+
}
|
|
3105
|
+
}
|
|
3106
|
+
};
|
|
3107
|
+
|
|
3108
|
+
// packages/agent-defs/src/agents/kimi.ts
|
|
3109
|
+
var kimiAgent = {
|
|
3110
|
+
id: "kimi",
|
|
3111
|
+
name: "kimi",
|
|
3112
|
+
label: "Kimi",
|
|
3113
|
+
summary: "Configure Kimi CLI to use Poe API",
|
|
3114
|
+
aliases: ["kimi-cli"],
|
|
3115
|
+
binaryName: "kimi",
|
|
3116
|
+
apiShapes: ["openai-chat-completions"],
|
|
3117
|
+
configPath: "~/.kimi/config.toml",
|
|
3118
|
+
branding: {
|
|
3119
|
+
colors: {
|
|
3120
|
+
dark: "#7B68EE",
|
|
3121
|
+
light: "#6A5ACD"
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
};
|
|
3125
|
+
|
|
3126
|
+
// packages/agent-defs/src/agents/goose.ts
|
|
3127
|
+
var gooseAgent = {
|
|
3128
|
+
id: "goose",
|
|
3129
|
+
name: "goose",
|
|
3130
|
+
label: "Goose",
|
|
3131
|
+
summary: "Block's open-source AI agent with ACP support.",
|
|
3132
|
+
binaryName: "goose",
|
|
3133
|
+
apiShapes: ["openai-chat-completions"],
|
|
3134
|
+
configPath: "~/.config/goose/config.yaml",
|
|
3135
|
+
branding: {
|
|
3136
|
+
colors: {
|
|
3137
|
+
dark: "#FF6B35",
|
|
3138
|
+
light: "#E85D26"
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3141
|
+
};
|
|
3142
|
+
|
|
3143
|
+
// packages/agent-defs/src/agents/poe-agent.ts
|
|
3144
|
+
var poeAgentAgent = {
|
|
3145
|
+
id: "poe-agent",
|
|
3146
|
+
name: "poe-agent",
|
|
3147
|
+
label: "Poe Agent",
|
|
3148
|
+
summary: "Run one-shot prompts with the built-in Poe agent runtime.",
|
|
3149
|
+
apiShapes: ["openai-responses", "openai-chat-completions"],
|
|
3150
|
+
configPath: "~/.poe-code/config.json",
|
|
3151
|
+
branding: {
|
|
3152
|
+
colors: {
|
|
3153
|
+
dark: "#A465F7",
|
|
3154
|
+
light: "#7A3FD3"
|
|
3155
|
+
}
|
|
3156
|
+
}
|
|
3157
|
+
};
|
|
3158
|
+
|
|
3159
|
+
// packages/agent-defs/src/registry.ts
|
|
3160
|
+
var allAgents = [
|
|
3161
|
+
claudeCodeAgent,
|
|
3162
|
+
claudeDesktopAgent,
|
|
3163
|
+
codexAgent,
|
|
3164
|
+
openCodeAgent,
|
|
3165
|
+
kimiAgent,
|
|
3166
|
+
gooseAgent,
|
|
3167
|
+
poeAgentAgent
|
|
3168
|
+
];
|
|
3169
|
+
var lookup2 = /* @__PURE__ */ new Map();
|
|
3170
|
+
for (const agent of allAgents) {
|
|
3171
|
+
const values = [agent.id, agent.name, ...agent.aliases ?? []];
|
|
3172
|
+
for (const value of values) {
|
|
3173
|
+
const normalized = value.toLowerCase();
|
|
3174
|
+
if (!lookup2.has(normalized)) {
|
|
3175
|
+
lookup2.set(normalized, agent.id);
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
3178
|
+
}
|
|
3179
|
+
function resolveAgentId(input) {
|
|
3180
|
+
if (!input) {
|
|
3181
|
+
return void 0;
|
|
3182
|
+
}
|
|
3183
|
+
return lookup2.get(input.toLowerCase());
|
|
3184
|
+
}
|
|
3185
|
+
|
|
3186
|
+
// packages/providers/src/auth/api-key.ts
|
|
3187
|
+
function requireApiKeyAuth(provider) {
|
|
3188
|
+
if (provider.auth.kind !== "api-key") {
|
|
3189
|
+
throw new Error(
|
|
3190
|
+
`Provider ${provider.id} does not use api-key auth (got ${provider.auth.kind}).`
|
|
3191
|
+
);
|
|
3192
|
+
}
|
|
3193
|
+
return provider.auth;
|
|
3194
|
+
}
|
|
3195
|
+
async function acquireApiKey(provider, options, context) {
|
|
3196
|
+
const auth = requireApiKeyAuth(provider);
|
|
3197
|
+
const candidate = options.apiKey ?? await context.promptForSecret?.(auth.prompt);
|
|
3198
|
+
const trimmed = candidate?.trim();
|
|
3199
|
+
if (!trimmed) {
|
|
3200
|
+
throw new Error(
|
|
3201
|
+
`No API key available for provider "${provider.id}". Pass --api-key or run interactively.`
|
|
3202
|
+
);
|
|
3203
|
+
}
|
|
3204
|
+
return trimmed;
|
|
3205
|
+
}
|
|
3206
|
+
var apiKeyAuthStrategy = {
|
|
3207
|
+
async login(provider, options, context) {
|
|
3208
|
+
const apiKey = await acquireApiKey(provider, options, context);
|
|
3209
|
+
await context.secretStore.set(apiKey);
|
|
3210
|
+
return apiKey;
|
|
3211
|
+
},
|
|
3212
|
+
async logout(_provider, context) {
|
|
3213
|
+
await context.secretStore.delete();
|
|
3214
|
+
},
|
|
3215
|
+
async isLoggedIn(_provider, context) {
|
|
3216
|
+
const value = await context.secretStore.get();
|
|
3217
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
3218
|
+
},
|
|
3219
|
+
async resolveCredential(provider, context) {
|
|
3220
|
+
requireApiKeyAuth(provider);
|
|
3221
|
+
const value = await context.secretStore.get();
|
|
3222
|
+
if (!value || value.trim().length === 0) {
|
|
3223
|
+
throw new Error(
|
|
3224
|
+
`No stored credential for provider "${provider.id}". Run \`poe-code provider login ${provider.id}\`.`
|
|
3225
|
+
);
|
|
3226
|
+
}
|
|
3227
|
+
return value;
|
|
3228
|
+
}
|
|
3229
|
+
};
|
|
3230
|
+
|
|
3231
|
+
// packages/providers/src/compatibility.ts
|
|
3232
|
+
function resolveApiShape(provider, agent) {
|
|
3233
|
+
if (!provider.apiShapes || !agent.apiShapes) {
|
|
3234
|
+
return void 0;
|
|
3235
|
+
}
|
|
3236
|
+
for (const shapeId of agent.apiShapes) {
|
|
3237
|
+
if (provider.apiShapes.some((shape) => shape.id === shapeId)) {
|
|
3238
|
+
return shapeId;
|
|
3239
|
+
}
|
|
3240
|
+
}
|
|
3241
|
+
return void 0;
|
|
3242
|
+
}
|
|
3243
|
+
|
|
3244
|
+
// packages/providers/src/registry.ts
|
|
3245
|
+
var ProviderRegistry = class {
|
|
3246
|
+
providers;
|
|
3247
|
+
byId;
|
|
3248
|
+
storeFactory;
|
|
3249
|
+
envVars;
|
|
3250
|
+
constructor(providers, storeFactory, options) {
|
|
3251
|
+
const byId = /* @__PURE__ */ new Map();
|
|
3252
|
+
for (const provider of providers) {
|
|
3253
|
+
if (byId.has(provider.id)) {
|
|
3254
|
+
throw new Error(`Duplicate provider id: ${provider.id}`);
|
|
3255
|
+
}
|
|
3256
|
+
byId.set(provider.id, provider);
|
|
3257
|
+
}
|
|
3258
|
+
this.providers = providers;
|
|
3259
|
+
this.byId = byId;
|
|
3260
|
+
this.storeFactory = storeFactory;
|
|
3261
|
+
this.envVars = options?.envVars ?? {};
|
|
3262
|
+
}
|
|
3263
|
+
list() {
|
|
3264
|
+
return this.providers;
|
|
3265
|
+
}
|
|
3266
|
+
get(id) {
|
|
3267
|
+
return this.byId.get(id);
|
|
3268
|
+
}
|
|
3269
|
+
forAgent(agent) {
|
|
3270
|
+
return this.providers.filter((provider) => {
|
|
3271
|
+
return resolveApiShape(provider, agent) !== void 0;
|
|
3272
|
+
});
|
|
3273
|
+
}
|
|
3274
|
+
async isLoggedIn(id) {
|
|
3275
|
+
const provider = this.requireProvider(id);
|
|
3276
|
+
if (provider.auth.kind === "api-key") {
|
|
3277
|
+
const envValue = this.envVars[provider.auth.envVar];
|
|
3278
|
+
if (typeof envValue === "string" && envValue.trim().length > 0) {
|
|
3279
|
+
return true;
|
|
3280
|
+
}
|
|
3281
|
+
}
|
|
3282
|
+
const store = this.requireStore(id);
|
|
3283
|
+
const credential = await store.get();
|
|
3284
|
+
return credential !== null;
|
|
3285
|
+
}
|
|
3286
|
+
async login(id, options, context) {
|
|
3287
|
+
const provider = this.requireProvider(id);
|
|
3288
|
+
const store = this.requireStore(id);
|
|
3289
|
+
if (provider.auth.kind !== "api-key") {
|
|
3290
|
+
throw new Error(`Provider "${id}" does not use api-key auth.`);
|
|
3291
|
+
}
|
|
3292
|
+
const auth = provider.auth;
|
|
3293
|
+
const envApiKey = context?.envVars?.[auth.envVar];
|
|
3294
|
+
const resolvedApiKey = options.apiKey ?? (typeof envApiKey === "string" && envApiKey.trim() ? envApiKey : void 0);
|
|
3295
|
+
if (auth.preferredLogin && context?.resolvePreferredLogin) {
|
|
3296
|
+
const apiKey = await context.resolvePreferredLogin({
|
|
3297
|
+
provider,
|
|
3298
|
+
apiKey: options.apiKey,
|
|
3299
|
+
envValue: typeof envApiKey === "string" ? envApiKey : void 0
|
|
3300
|
+
});
|
|
3301
|
+
await store.set(apiKey);
|
|
3302
|
+
return;
|
|
3303
|
+
}
|
|
3304
|
+
await apiKeyAuthStrategy.login(
|
|
3305
|
+
provider,
|
|
3306
|
+
{ apiKey: resolvedApiKey },
|
|
3307
|
+
{ secretStore: store, promptForSecret: context?.promptForSecret }
|
|
3308
|
+
);
|
|
3309
|
+
}
|
|
3310
|
+
async resolveCredential(id, options = {}, context) {
|
|
3311
|
+
const provider = this.requireProvider(id);
|
|
3312
|
+
if (provider.auth.kind !== "api-key") {
|
|
3313
|
+
throw new Error(`Provider "${id}" does not use api-key auth.`);
|
|
3314
|
+
}
|
|
3315
|
+
if (options.apiKey !== void 0) {
|
|
3316
|
+
return normalizeRequiredCredential(provider.id, options.apiKey);
|
|
3317
|
+
}
|
|
3318
|
+
const envVars = context?.envVars ?? this.envVars;
|
|
3319
|
+
const envApiKey = envVars[provider.auth.envVar];
|
|
3320
|
+
if (typeof envApiKey === "string" && envApiKey.trim().length > 0) {
|
|
3321
|
+
return envApiKey.trim();
|
|
3322
|
+
}
|
|
3323
|
+
const store = this.requireStore(id);
|
|
3324
|
+
return apiKeyAuthStrategy.resolveCredential(provider, { secretStore: store });
|
|
3325
|
+
}
|
|
3326
|
+
async logout(id) {
|
|
3327
|
+
this.requireProvider(id);
|
|
3328
|
+
const store = this.requireStore(id);
|
|
3329
|
+
await store.delete();
|
|
3330
|
+
}
|
|
3331
|
+
requireProvider(id) {
|
|
3332
|
+
const provider = this.byId.get(id);
|
|
3333
|
+
if (!provider) {
|
|
3334
|
+
throw new Error(`Unknown provider: "${id}".`);
|
|
3335
|
+
}
|
|
3336
|
+
return provider;
|
|
3337
|
+
}
|
|
3338
|
+
requireStore(id) {
|
|
3339
|
+
if (!this.storeFactory) {
|
|
3340
|
+
throw new Error(`No store factory configured for ProviderRegistry.`);
|
|
3341
|
+
}
|
|
3342
|
+
return this.storeFactory(id);
|
|
3343
|
+
}
|
|
3344
|
+
};
|
|
3345
|
+
function normalizeRequiredCredential(providerId, value) {
|
|
3346
|
+
const trimmed = value.trim();
|
|
3347
|
+
if (trimmed.length === 0) {
|
|
3348
|
+
throw new Error(`No API key available for provider "${providerId}".`);
|
|
3349
|
+
}
|
|
3350
|
+
return trimmed;
|
|
3351
|
+
}
|
|
3352
|
+
|
|
3353
|
+
// packages/providers/src/providers/poe.ts
|
|
3354
|
+
var POE_PROVIDER_ID = "poe";
|
|
3355
|
+
var poeProvider = {
|
|
3356
|
+
id: POE_PROVIDER_ID,
|
|
3357
|
+
label: "Poe",
|
|
3358
|
+
summary: "Route AI coding agents through Poe's API.",
|
|
3359
|
+
baseUrl: "https://api.poe.com",
|
|
3360
|
+
auth: {
|
|
3361
|
+
kind: "api-key",
|
|
3362
|
+
envVar: "POE_API_KEY",
|
|
3363
|
+
storageKey: "provider:poe",
|
|
3364
|
+
prompt: { title: "Poe API key" },
|
|
3365
|
+
preferredLogin: "oauth"
|
|
3366
|
+
},
|
|
3367
|
+
apiShapes: [
|
|
3368
|
+
{
|
|
3369
|
+
id: "openai-chat-completions",
|
|
3370
|
+
defaultBaseUrl: "https://api.poe.com/v1"
|
|
3371
|
+
},
|
|
3372
|
+
{
|
|
3373
|
+
id: "openai-responses",
|
|
3374
|
+
defaultBaseUrl: "https://api.poe.com/v1"
|
|
3375
|
+
},
|
|
3376
|
+
{
|
|
3377
|
+
id: "anthropic-messages",
|
|
3378
|
+
defaultBaseUrl: "https://api.poe.com/anthropic"
|
|
3379
|
+
}
|
|
3380
|
+
]
|
|
3381
|
+
};
|
|
3382
|
+
|
|
3383
|
+
// packages/providers/src/providers/anthropic.ts
|
|
3384
|
+
var anthropicProvider = {
|
|
3385
|
+
id: "anthropic",
|
|
3386
|
+
label: "Anthropic",
|
|
3387
|
+
summary: "Route AI coding agents through Anthropic's API.",
|
|
3388
|
+
baseUrl: "https://api.anthropic.com",
|
|
3389
|
+
auth: {
|
|
3390
|
+
kind: "api-key",
|
|
3391
|
+
envVar: "ANTHROPIC_API_KEY",
|
|
3392
|
+
storageKey: "provider:anthropic",
|
|
3393
|
+
prompt: { title: "Anthropic API key" }
|
|
3394
|
+
},
|
|
3395
|
+
apiShapes: [
|
|
3396
|
+
{
|
|
3397
|
+
id: "anthropic-messages",
|
|
3398
|
+
defaultBaseUrl: "https://api.anthropic.com"
|
|
3399
|
+
}
|
|
3400
|
+
]
|
|
3401
|
+
};
|
|
3402
|
+
|
|
3403
|
+
// packages/providers/src/providers/cloudflare.ts
|
|
3404
|
+
var cloudflareProvider = {
|
|
3405
|
+
id: "cloudflare",
|
|
3406
|
+
label: "Cloudflare AI Gateway",
|
|
3407
|
+
summary: "Route coding agents through Cloudflare AI Gateway.",
|
|
3408
|
+
baseUrlEnvVar: "CF_AIG_BASE_URL",
|
|
3409
|
+
requiresBaseUrl: true,
|
|
3410
|
+
modelInput: { kind: "freeform" },
|
|
3411
|
+
auth: {
|
|
3412
|
+
kind: "api-key",
|
|
3413
|
+
envVar: "CF_AIG_TOKEN",
|
|
3414
|
+
storageKey: "provider:cloudflare",
|
|
3415
|
+
prompt: { title: "Cloudflare AI Gateway token" }
|
|
3416
|
+
},
|
|
3417
|
+
apiShapes: [
|
|
3418
|
+
{
|
|
3419
|
+
id: "openai-chat-completions",
|
|
3420
|
+
baseUrlPath: "compat"
|
|
3421
|
+
},
|
|
3422
|
+
{
|
|
3423
|
+
id: "openai-responses",
|
|
3424
|
+
baseUrlPath: "openai"
|
|
3425
|
+
},
|
|
3426
|
+
{
|
|
3427
|
+
id: "anthropic-messages",
|
|
3428
|
+
baseUrlPath: "anthropic"
|
|
3429
|
+
},
|
|
3430
|
+
{
|
|
3431
|
+
id: "google-generations",
|
|
3432
|
+
baseUrlPath: "google-ai-studio"
|
|
3433
|
+
}
|
|
3434
|
+
]
|
|
3435
|
+
};
|
|
3436
|
+
|
|
3437
|
+
// packages/poe-code-config/src/configured-services.ts
|
|
3438
|
+
var agentsById = new Map(allAgents.map((agent) => [agent.id, agent]));
|
|
3439
|
+
var defaultProviderRegistry = new ProviderRegistry([
|
|
3440
|
+
poeProvider,
|
|
3441
|
+
anthropicProvider,
|
|
3442
|
+
cloudflareProvider
|
|
3443
|
+
]);
|
|
3444
|
+
var EMPTY_DOCUMENT3 = `${JSON.stringify({}, null, 2)}
|
|
3445
|
+
`;
|
|
3446
|
+
|
|
3034
3447
|
// packages/poe-code-config/src/state/index.ts
|
|
3035
3448
|
import os2 from "node:os";
|
|
3036
3449
|
|
|
3037
3450
|
// packages/poe-code-config/src/state/jobs.ts
|
|
3038
|
-
import
|
|
3451
|
+
import path10 from "node:path";
|
|
3039
3452
|
|
|
3040
3453
|
// packages/file-lock/src/lock.ts
|
|
3041
3454
|
import * as fsPromises from "node:fs/promises";
|
|
@@ -3096,17 +3509,17 @@ function isPidRunning(pid) {
|
|
|
3096
3509
|
}
|
|
3097
3510
|
function createDefaultFs() {
|
|
3098
3511
|
return {
|
|
3099
|
-
open: (
|
|
3100
|
-
readFile: (
|
|
3512
|
+
open: (path50, flags) => fsPromises.open(path50, flags),
|
|
3513
|
+
readFile: (path50, encoding) => fsPromises.readFile(path50, encoding),
|
|
3101
3514
|
stat: fsPromises.stat,
|
|
3102
3515
|
unlink: fsPromises.unlink
|
|
3103
3516
|
};
|
|
3104
3517
|
}
|
|
3105
|
-
async function removeLockFile(
|
|
3518
|
+
async function removeLockFile(fs16, lockPath, signal) {
|
|
3106
3519
|
for (let attempt = 0; attempt <= 4; attempt += 1) {
|
|
3107
3520
|
throwIfAborted(signal);
|
|
3108
3521
|
try {
|
|
3109
|
-
await
|
|
3522
|
+
await fs16.unlink(lockPath);
|
|
3110
3523
|
return;
|
|
3111
3524
|
} catch (error2) {
|
|
3112
3525
|
if (hasErrorCode(error2, "ENOENT")) {
|
|
@@ -3137,12 +3550,12 @@ function parseLockMetadata(content) {
|
|
|
3137
3550
|
}
|
|
3138
3551
|
return void 0;
|
|
3139
3552
|
}
|
|
3140
|
-
async function readLockMetadata(
|
|
3141
|
-
if (!
|
|
3553
|
+
async function readLockMetadata(fs16, lockPath) {
|
|
3554
|
+
if (!fs16.readFile) {
|
|
3142
3555
|
return void 0;
|
|
3143
3556
|
}
|
|
3144
3557
|
try {
|
|
3145
|
-
return parseLockMetadata(await
|
|
3558
|
+
return parseLockMetadata(await fs16.readFile(lockPath, "utf8"));
|
|
3146
3559
|
} catch (error2) {
|
|
3147
3560
|
if (hasErrorCode(error2, "ENOENT")) {
|
|
3148
3561
|
return null;
|
|
@@ -3176,7 +3589,7 @@ async function writeLockMetadata(handle) {
|
|
|
3176
3589
|
}
|
|
3177
3590
|
}
|
|
3178
3591
|
async function acquireFileLock(filePath, options = {}) {
|
|
3179
|
-
const
|
|
3592
|
+
const fs16 = options.fs ?? createDefaultFs();
|
|
3180
3593
|
const retries = options.retries ?? 20;
|
|
3181
3594
|
const minTimeout = options.minTimeout ?? 25;
|
|
3182
3595
|
const maxTimeout = options.maxTimeout ?? 250;
|
|
@@ -3187,7 +3600,7 @@ async function acquireFileLock(filePath, options = {}) {
|
|
|
3187
3600
|
while (attempt <= retries) {
|
|
3188
3601
|
throwIfAborted(options.signal);
|
|
3189
3602
|
try {
|
|
3190
|
-
const handle = await
|
|
3603
|
+
const handle = await fs16.open(lockPath, "wx");
|
|
3191
3604
|
await writeLockMetadata(handle);
|
|
3192
3605
|
let released = false;
|
|
3193
3606
|
return async () => {
|
|
@@ -3195,7 +3608,7 @@ async function acquireFileLock(filePath, options = {}) {
|
|
|
3195
3608
|
return;
|
|
3196
3609
|
}
|
|
3197
3610
|
released = true;
|
|
3198
|
-
await removeLockFile(
|
|
3611
|
+
await removeLockFile(fs16, lockPath, options.signal);
|
|
3199
3612
|
};
|
|
3200
3613
|
} catch (error2) {
|
|
3201
3614
|
if (!hasErrorCode(error2, "EEXIST")) {
|
|
@@ -3204,7 +3617,7 @@ async function acquireFileLock(filePath, options = {}) {
|
|
|
3204
3617
|
}
|
|
3205
3618
|
let stat7;
|
|
3206
3619
|
try {
|
|
3207
|
-
stat7 = await
|
|
3620
|
+
stat7 = await fs16.stat(lockPath);
|
|
3208
3621
|
} catch (statError) {
|
|
3209
3622
|
if (hasErrorCode(statError, "ENOENT")) {
|
|
3210
3623
|
continue;
|
|
@@ -3212,7 +3625,7 @@ async function acquireFileLock(filePath, options = {}) {
|
|
|
3212
3625
|
throw statError;
|
|
3213
3626
|
}
|
|
3214
3627
|
const reclaimLock = await shouldReclaimLock({
|
|
3215
|
-
fs:
|
|
3628
|
+
fs: fs16,
|
|
3216
3629
|
isPidRunning: pidIsRunning,
|
|
3217
3630
|
lockPath,
|
|
3218
3631
|
staleMs,
|
|
@@ -3222,7 +3635,7 @@ async function acquireFileLock(filePath, options = {}) {
|
|
|
3222
3635
|
continue;
|
|
3223
3636
|
}
|
|
3224
3637
|
if (reclaimLock) {
|
|
3225
|
-
await removeLockFile(
|
|
3638
|
+
await removeLockFile(fs16, lockPath, options.signal);
|
|
3226
3639
|
continue;
|
|
3227
3640
|
}
|
|
3228
3641
|
if (attempt >= retries) {
|
|
@@ -3242,15 +3655,15 @@ function isNotFoundError(error2) {
|
|
|
3242
3655
|
}
|
|
3243
3656
|
|
|
3244
3657
|
// packages/poe-code-config/src/state/jobs.ts
|
|
3245
|
-
function createJobRegistry(homeDir,
|
|
3246
|
-
const jobsDir =
|
|
3658
|
+
function createJobRegistry(homeDir, fs16 = defaultStateFs) {
|
|
3659
|
+
const jobsDir = path10.join(homeDir, ".poe-code", "state", "jobs");
|
|
3247
3660
|
function jobPath(id) {
|
|
3248
3661
|
assertSafeJobId(id);
|
|
3249
|
-
return
|
|
3662
|
+
return path10.join(jobsDir, `${id}.json`);
|
|
3250
3663
|
}
|
|
3251
3664
|
async function get(id) {
|
|
3252
3665
|
try {
|
|
3253
|
-
return parseJobEntry(await
|
|
3666
|
+
return parseJobEntry(await fs16.readFile(jobPath(id), "utf8"));
|
|
3254
3667
|
} catch (error2) {
|
|
3255
3668
|
if (isNotFoundError(error2)) {
|
|
3256
3669
|
return null;
|
|
@@ -3261,8 +3674,8 @@ function createJobRegistry(homeDir, fs14 = defaultStateFs) {
|
|
|
3261
3674
|
async function put(entry) {
|
|
3262
3675
|
assertJobEntry(entry);
|
|
3263
3676
|
const filePath = jobPath(entry.id);
|
|
3264
|
-
await
|
|
3265
|
-
const release = await acquireFileLock(filePath, { fs:
|
|
3677
|
+
await fs16.mkdir(jobsDir, { recursive: true });
|
|
3678
|
+
const release = await acquireFileLock(filePath, { fs: fs16 });
|
|
3266
3679
|
try {
|
|
3267
3680
|
await writeJobAtomically(filePath, entry);
|
|
3268
3681
|
} finally {
|
|
@@ -3271,8 +3684,8 @@ function createJobRegistry(homeDir, fs14 = defaultStateFs) {
|
|
|
3271
3684
|
}
|
|
3272
3685
|
async function update(id, patch) {
|
|
3273
3686
|
const filePath = jobPath(id);
|
|
3274
|
-
await
|
|
3275
|
-
const release = await acquireFileLock(filePath, { fs:
|
|
3687
|
+
await fs16.mkdir(jobsDir, { recursive: true });
|
|
3688
|
+
const release = await acquireFileLock(filePath, { fs: fs16 });
|
|
3276
3689
|
try {
|
|
3277
3690
|
const current = await get(id);
|
|
3278
3691
|
if (current === null) {
|
|
@@ -3293,7 +3706,7 @@ function createJobRegistry(homeDir, fs14 = defaultStateFs) {
|
|
|
3293
3706
|
async function list(filter = {}) {
|
|
3294
3707
|
let entries;
|
|
3295
3708
|
try {
|
|
3296
|
-
entries = await
|
|
3709
|
+
entries = await fs16.readdir(jobsDir);
|
|
3297
3710
|
} catch (error2) {
|
|
3298
3711
|
if (isNotFoundError(error2)) {
|
|
3299
3712
|
return [];
|
|
@@ -3305,12 +3718,12 @@ function createJobRegistry(homeDir, fs14 = defaultStateFs) {
|
|
|
3305
3718
|
if (!entry.endsWith(".json")) {
|
|
3306
3719
|
continue;
|
|
3307
3720
|
}
|
|
3308
|
-
const filePath =
|
|
3309
|
-
const stat7 = await
|
|
3721
|
+
const filePath = path10.join(jobsDir, entry);
|
|
3722
|
+
const stat7 = await fs16.stat(filePath);
|
|
3310
3723
|
if (!stat7.isFile()) {
|
|
3311
3724
|
continue;
|
|
3312
3725
|
}
|
|
3313
|
-
const job = parseJobEntry(await
|
|
3726
|
+
const job = parseJobEntry(await fs16.readFile(filePath, "utf8"));
|
|
3314
3727
|
if (matchesFilter(job, filter)) {
|
|
3315
3728
|
jobs.push(job);
|
|
3316
3729
|
}
|
|
@@ -3320,16 +3733,16 @@ function createJobRegistry(homeDir, fs14 = defaultStateFs) {
|
|
|
3320
3733
|
async function remove2(id) {
|
|
3321
3734
|
const filePath = jobPath(id);
|
|
3322
3735
|
try {
|
|
3323
|
-
await
|
|
3736
|
+
await fs16.stat(jobsDir);
|
|
3324
3737
|
} catch (error2) {
|
|
3325
3738
|
if (isNotFoundError(error2)) {
|
|
3326
3739
|
return;
|
|
3327
3740
|
}
|
|
3328
3741
|
throw error2;
|
|
3329
3742
|
}
|
|
3330
|
-
const release = await acquireFileLock(filePath, { fs:
|
|
3743
|
+
const release = await acquireFileLock(filePath, { fs: fs16 });
|
|
3331
3744
|
try {
|
|
3332
|
-
await
|
|
3745
|
+
await fs16.unlink(filePath);
|
|
3333
3746
|
} catch (error2) {
|
|
3334
3747
|
if (!isNotFoundError(error2)) {
|
|
3335
3748
|
throw error2;
|
|
@@ -3339,14 +3752,14 @@ function createJobRegistry(homeDir, fs14 = defaultStateFs) {
|
|
|
3339
3752
|
}
|
|
3340
3753
|
}
|
|
3341
3754
|
async function writeJobAtomically(filePath, entry) {
|
|
3342
|
-
await
|
|
3755
|
+
await fs16.mkdir(path10.dirname(filePath), { recursive: true });
|
|
3343
3756
|
const tempPath = `${filePath}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
3344
3757
|
try {
|
|
3345
|
-
await
|
|
3758
|
+
await fs16.writeFile(tempPath, `${JSON.stringify(entry, null, 2)}
|
|
3346
3759
|
`, {
|
|
3347
3760
|
encoding: "utf8"
|
|
3348
3761
|
});
|
|
3349
|
-
await
|
|
3762
|
+
await fs16.rename(tempPath, filePath);
|
|
3350
3763
|
} catch (error2) {
|
|
3351
3764
|
await removeTempFile(tempPath);
|
|
3352
3765
|
throw error2;
|
|
@@ -3354,7 +3767,7 @@ function createJobRegistry(homeDir, fs14 = defaultStateFs) {
|
|
|
3354
3767
|
}
|
|
3355
3768
|
async function removeTempFile(tempPath) {
|
|
3356
3769
|
try {
|
|
3357
|
-
await
|
|
3770
|
+
await fs16.unlink(tempPath);
|
|
3358
3771
|
} catch (error2) {
|
|
3359
3772
|
if (!isNotFoundError(error2)) {
|
|
3360
3773
|
throw error2;
|
|
@@ -3370,7 +3783,7 @@ function createJobRegistry(homeDir, fs14 = defaultStateFs) {
|
|
|
3370
3783
|
};
|
|
3371
3784
|
}
|
|
3372
3785
|
function assertSafeJobId(id) {
|
|
3373
|
-
if (id.length === 0 || id === "." || id === ".." ||
|
|
3786
|
+
if (id.length === 0 || id === "." || id === ".." || path10.isAbsolute(id) || id.includes("/") || id.includes("\\") || id.includes("\0")) {
|
|
3374
3787
|
throw new Error("Invalid job id.");
|
|
3375
3788
|
}
|
|
3376
3789
|
}
|
|
@@ -3400,12 +3813,12 @@ function isRecord4(value) {
|
|
|
3400
3813
|
}
|
|
3401
3814
|
|
|
3402
3815
|
// packages/poe-code-config/src/state/templates.ts
|
|
3403
|
-
import
|
|
3404
|
-
function createTemplateRegistry(homeDir,
|
|
3405
|
-
const filePath =
|
|
3816
|
+
import path11 from "node:path";
|
|
3817
|
+
function createTemplateRegistry(homeDir, fs16 = defaultStateFs) {
|
|
3818
|
+
const filePath = path11.join(homeDir, ".poe-code", "state", "templates.json");
|
|
3406
3819
|
async function readState() {
|
|
3407
3820
|
try {
|
|
3408
|
-
const raw = await
|
|
3821
|
+
const raw = await fs16.readFile(filePath, "utf8");
|
|
3409
3822
|
return normalizeTemplateState(JSON.parse(raw));
|
|
3410
3823
|
} catch (error2) {
|
|
3411
3824
|
if (isNotFoundError(error2)) {
|
|
@@ -3415,14 +3828,14 @@ function createTemplateRegistry(homeDir, fs14 = defaultStateFs) {
|
|
|
3415
3828
|
}
|
|
3416
3829
|
}
|
|
3417
3830
|
async function writeState(state) {
|
|
3418
|
-
await
|
|
3831
|
+
await fs16.writeFile(filePath, `${JSON.stringify(state, null, 2)}
|
|
3419
3832
|
`, {
|
|
3420
3833
|
encoding: "utf8"
|
|
3421
3834
|
});
|
|
3422
3835
|
}
|
|
3423
3836
|
async function updateState(mutator) {
|
|
3424
|
-
await
|
|
3425
|
-
const release = await acquireFileLock(filePath, { fs:
|
|
3837
|
+
await fs16.mkdir(path11.dirname(filePath), { recursive: true });
|
|
3838
|
+
const release = await acquireFileLock(filePath, { fs: fs16 });
|
|
3426
3839
|
try {
|
|
3427
3840
|
const state = await readState();
|
|
3428
3841
|
mutator(state);
|
|
@@ -3492,10 +3905,10 @@ function isRecord5(value) {
|
|
|
3492
3905
|
}
|
|
3493
3906
|
|
|
3494
3907
|
// packages/poe-code-config/src/state/index.ts
|
|
3495
|
-
function createStateManager(homeDir,
|
|
3908
|
+
function createStateManager(homeDir, fs16) {
|
|
3496
3909
|
return {
|
|
3497
|
-
templates: createTemplateRegistry(homeDir,
|
|
3498
|
-
jobs: createJobRegistry(homeDir,
|
|
3910
|
+
templates: createTemplateRegistry(homeDir, fs16),
|
|
3911
|
+
jobs: createJobRegistry(homeDir, fs16)
|
|
3499
3912
|
};
|
|
3500
3913
|
}
|
|
3501
3914
|
|
|
@@ -3517,16 +3930,16 @@ async function resolveConfiguredMemoryRoot(options) {
|
|
|
3517
3930
|
return resolveMemoryRoot(options.cwd);
|
|
3518
3931
|
}
|
|
3519
3932
|
function resolveAgainstCwd(cwd, value) {
|
|
3520
|
-
return
|
|
3933
|
+
return path12.isAbsolute(value) ? value : path12.resolve(cwd, value);
|
|
3521
3934
|
}
|
|
3522
3935
|
|
|
3523
3936
|
// packages/memory/src/init.ts
|
|
3524
3937
|
import * as fs from "node:fs/promises";
|
|
3525
|
-
import
|
|
3938
|
+
import path13 from "node:path";
|
|
3526
3939
|
async function initMemory(root) {
|
|
3527
|
-
await fs.mkdir(
|
|
3528
|
-
await writeFileIfMissing(
|
|
3529
|
-
await writeFileIfMissing(
|
|
3940
|
+
await fs.mkdir(path13.join(root, MEMORY_PAGES_DIR_RELPATH), { recursive: true });
|
|
3941
|
+
await writeFileIfMissing(path13.join(root, MEMORY_INDEX_RELPATH), "# Memory index\n");
|
|
3942
|
+
await writeFileIfMissing(path13.join(root, MEMORY_LOG_RELPATH), "");
|
|
3530
3943
|
}
|
|
3531
3944
|
async function writeFileIfMissing(filePath, content) {
|
|
3532
3945
|
try {
|
|
@@ -3543,7 +3956,7 @@ function hasErrorCode2(error2, code) {
|
|
|
3543
3956
|
|
|
3544
3957
|
// packages/memory/src/pages.ts
|
|
3545
3958
|
import * as fs2 from "node:fs/promises";
|
|
3546
|
-
import
|
|
3959
|
+
import path14 from "node:path";
|
|
3547
3960
|
|
|
3548
3961
|
// packages/memory/src/frontmatter.ts
|
|
3549
3962
|
import { parse as parse6, stringify } from "yaml";
|
|
@@ -3723,10 +4136,10 @@ function parseSources(value) {
|
|
|
3723
4136
|
if (!isRecord6(item)) {
|
|
3724
4137
|
throw new Error('Invalid "sources" frontmatter. Expected each source to be a string or object.');
|
|
3725
4138
|
}
|
|
3726
|
-
const
|
|
4139
|
+
const path50 = readRequiredString(item.path, "sources[].path");
|
|
3727
4140
|
const startLine = readOptionalPositiveInteger(item.startLine, "sources[].startLine");
|
|
3728
4141
|
const endLine = readOptionalPositiveInteger(item.endLine, "sources[].endLine");
|
|
3729
|
-
return parseSourceRef(serializeSourceRef({ path:
|
|
4142
|
+
return parseSourceRef(serializeSourceRef({ path: path50, ...startLine === void 0 ? {} : { startLine }, ...endLine === void 0 ? {} : { endLine } }));
|
|
3730
4143
|
});
|
|
3731
4144
|
}
|
|
3732
4145
|
function readOptionalString(value, field) {
|
|
@@ -3771,7 +4184,7 @@ async function listPages(root) {
|
|
|
3771
4184
|
}
|
|
3772
4185
|
async function readPage(root, relPath) {
|
|
3773
4186
|
const normalizedRelPath = assertMarkdownRelPath(relPath);
|
|
3774
|
-
const absPath =
|
|
4187
|
+
const absPath = path14.join(root, normalizedRelPath);
|
|
3775
4188
|
const [content, stat7] = await Promise.all([fs2.readFile(absPath, "utf8"), fs2.stat(absPath)]);
|
|
3776
4189
|
try {
|
|
3777
4190
|
const parsed = parseFrontmatter(content);
|
|
@@ -3800,7 +4213,7 @@ async function collectMarkdownRelPaths(root, startRelPath = "") {
|
|
|
3800
4213
|
return relPaths.sort((left, right) => left.localeCompare(right));
|
|
3801
4214
|
}
|
|
3802
4215
|
async function collectMarkdownRelPathsInto(root, currentRelPath, relPaths) {
|
|
3803
|
-
const absPath =
|
|
4216
|
+
const absPath = path14.join(root, currentRelPath);
|
|
3804
4217
|
let entryNames;
|
|
3805
4218
|
try {
|
|
3806
4219
|
entryNames = await fs2.readdir(absPath);
|
|
@@ -3811,8 +4224,8 @@ async function collectMarkdownRelPathsInto(root, currentRelPath, relPaths) {
|
|
|
3811
4224
|
throw error2;
|
|
3812
4225
|
}
|
|
3813
4226
|
for (const entryName of entryNames.sort((left, right) => left.localeCompare(right))) {
|
|
3814
|
-
const entryRelPath = currentRelPath.length === 0 ? entryName :
|
|
3815
|
-
const entryAbsPath =
|
|
4227
|
+
const entryRelPath = currentRelPath.length === 0 ? entryName : path14.posix.join(currentRelPath, entryName);
|
|
4228
|
+
const entryAbsPath = path14.join(root, entryRelPath);
|
|
3816
4229
|
const entryStat = await fs2.stat(entryAbsPath);
|
|
3817
4230
|
if (entryStat.isDirectory()) {
|
|
3818
4231
|
if (entryName === MEMORY_CACHE_DIR_RELPATH) {
|
|
@@ -3842,7 +4255,7 @@ function assertMarkdownRelPath(relPath) {
|
|
|
3842
4255
|
return normalizedRelPath;
|
|
3843
4256
|
}
|
|
3844
4257
|
function isMarkdownPath(relPath) {
|
|
3845
|
-
return
|
|
4258
|
+
return path14.posix.extname(relPath).toLowerCase() === ".md";
|
|
3846
4259
|
}
|
|
3847
4260
|
function isMissing(error2) {
|
|
3848
4261
|
return typeof error2 === "object" && error2 !== null && "code" in error2 && error2.code === "ENOENT";
|
|
@@ -3850,7 +4263,7 @@ function isMissing(error2) {
|
|
|
3850
4263
|
|
|
3851
4264
|
// packages/memory/src/search.ts
|
|
3852
4265
|
import * as fs3 from "node:fs/promises";
|
|
3853
|
-
import
|
|
4266
|
+
import path15 from "node:path";
|
|
3854
4267
|
async function searchMemory(root, query) {
|
|
3855
4268
|
const normalizedQuery = query.trim();
|
|
3856
4269
|
if (normalizedQuery.length === 0) {
|
|
@@ -3859,7 +4272,7 @@ async function searchMemory(root, query) {
|
|
|
3859
4272
|
const relPaths = await collectMarkdownRelPaths(root);
|
|
3860
4273
|
const hits = [];
|
|
3861
4274
|
for (const relPath of relPaths) {
|
|
3862
|
-
const content = await fs3.readFile(
|
|
4275
|
+
const content = await fs3.readFile(path15.join(root, relPath), "utf8");
|
|
3863
4276
|
if (content.length === 0) {
|
|
3864
4277
|
continue;
|
|
3865
4278
|
}
|
|
@@ -3880,7 +4293,7 @@ async function searchMemory(root, query) {
|
|
|
3880
4293
|
|
|
3881
4294
|
// packages/memory/src/status.ts
|
|
3882
4295
|
import * as fs4 from "node:fs/promises";
|
|
3883
|
-
import
|
|
4296
|
+
import path16 from "node:path";
|
|
3884
4297
|
async function statusOf(root) {
|
|
3885
4298
|
if (!await pathExists2(root)) {
|
|
3886
4299
|
return {
|
|
@@ -3897,7 +4310,7 @@ async function statusOf(root) {
|
|
|
3897
4310
|
let totalBytes = 0;
|
|
3898
4311
|
let lastWriteAtMs = Number.NEGATIVE_INFINITY;
|
|
3899
4312
|
for (const relPath of markdownRelPaths) {
|
|
3900
|
-
const stat7 = await fs4.stat(
|
|
4313
|
+
const stat7 = await fs4.stat(path16.join(root, relPath));
|
|
3901
4314
|
totalBytes += stat7.size;
|
|
3902
4315
|
lastWriteAtMs = Math.max(lastWriteAtMs, stat7.mtimeMs);
|
|
3903
4316
|
}
|
|
@@ -3922,15 +4335,15 @@ async function pathExists2(targetPath) {
|
|
|
3922
4335
|
|
|
3923
4336
|
// packages/memory/src/edit.ts
|
|
3924
4337
|
import * as fs7 from "node:fs/promises";
|
|
3925
|
-
import
|
|
4338
|
+
import path20 from "node:path";
|
|
3926
4339
|
|
|
3927
4340
|
// packages/memory/src/write.ts
|
|
3928
4341
|
import * as fs6 from "node:fs/promises";
|
|
3929
|
-
import
|
|
4342
|
+
import path19 from "node:path";
|
|
3930
4343
|
|
|
3931
4344
|
// packages/memory/src/lock.ts
|
|
3932
4345
|
import * as fsPromises2 from "node:fs/promises";
|
|
3933
|
-
import
|
|
4346
|
+
import path17 from "node:path";
|
|
3934
4347
|
function createDefaultFs2() {
|
|
3935
4348
|
return {
|
|
3936
4349
|
readFile: (filePath, encoding) => fsPromises2.readFile(filePath, encoding),
|
|
@@ -3968,18 +4381,18 @@ function isPidRunning2(pid) {
|
|
|
3968
4381
|
return !hasErrorCode3(error2, "ESRCH");
|
|
3969
4382
|
}
|
|
3970
4383
|
}
|
|
3971
|
-
async function removeLockFile2(
|
|
4384
|
+
async function removeLockFile2(fs16, lockPath) {
|
|
3972
4385
|
try {
|
|
3973
|
-
await
|
|
4386
|
+
await fs16.unlink(lockPath);
|
|
3974
4387
|
} catch (error2) {
|
|
3975
4388
|
if (!hasErrorCode3(error2, "ENOENT")) {
|
|
3976
4389
|
throw error2;
|
|
3977
4390
|
}
|
|
3978
4391
|
}
|
|
3979
4392
|
}
|
|
3980
|
-
async function readLockPid(
|
|
4393
|
+
async function readLockPid(fs16, lockPath) {
|
|
3981
4394
|
try {
|
|
3982
|
-
return parsePid(await
|
|
4395
|
+
return parsePid(await fs16.readFile(lockPath, "utf8"));
|
|
3983
4396
|
} catch (error2) {
|
|
3984
4397
|
if (hasErrorCode3(error2, "ENOENT")) {
|
|
3985
4398
|
return null;
|
|
@@ -3988,8 +4401,8 @@ async function readLockPid(fs14, lockPath) {
|
|
|
3988
4401
|
}
|
|
3989
4402
|
}
|
|
3990
4403
|
async function withLock(root, run, options = {}) {
|
|
3991
|
-
const
|
|
3992
|
-
const lockPath =
|
|
4404
|
+
const fs16 = options.fs ?? createDefaultFs2();
|
|
4405
|
+
const lockPath = path17.join(root, MEMORY_LOCK_RELPATH);
|
|
3993
4406
|
const pid = options.pid ?? process.pid;
|
|
3994
4407
|
const retries = options.retries ?? 20;
|
|
3995
4408
|
const minTimeoutMs = options.minTimeoutMs ?? 25;
|
|
@@ -3997,24 +4410,24 @@ async function withLock(root, run, options = {}) {
|
|
|
3997
4410
|
const pidIsRunning = options.isPidRunning ?? isPidRunning2;
|
|
3998
4411
|
for (let attempt = 0; attempt <= retries; attempt += 1) {
|
|
3999
4412
|
try {
|
|
4000
|
-
await
|
|
4413
|
+
await fs16.writeFile(lockPath, `${pid}
|
|
4001
4414
|
`, { encoding: "utf8", flag: "wx" });
|
|
4002
4415
|
try {
|
|
4003
4416
|
return await run();
|
|
4004
4417
|
} finally {
|
|
4005
|
-
await removeLockFile2(
|
|
4418
|
+
await removeLockFile2(fs16, lockPath);
|
|
4006
4419
|
}
|
|
4007
4420
|
} catch (error2) {
|
|
4008
4421
|
if (!hasErrorCode3(error2, "EEXIST")) {
|
|
4009
4422
|
throw error2;
|
|
4010
4423
|
}
|
|
4011
4424
|
}
|
|
4012
|
-
const existingPid = await readLockPid(
|
|
4425
|
+
const existingPid = await readLockPid(fs16, lockPath);
|
|
4013
4426
|
if (existingPid === null) {
|
|
4014
4427
|
continue;
|
|
4015
4428
|
}
|
|
4016
4429
|
if (existingPid === void 0 || !pidIsRunning(existingPid)) {
|
|
4017
|
-
await removeLockFile2(
|
|
4430
|
+
await removeLockFile2(fs16, lockPath);
|
|
4018
4431
|
continue;
|
|
4019
4432
|
}
|
|
4020
4433
|
if (attempt < retries) {
|
|
@@ -4027,7 +4440,7 @@ async function withLock(root, run, options = {}) {
|
|
|
4027
4440
|
// packages/memory/src/reconcile.ts
|
|
4028
4441
|
import { createHash } from "node:crypto";
|
|
4029
4442
|
import * as fs5 from "node:fs/promises";
|
|
4030
|
-
import
|
|
4443
|
+
import path18 from "node:path";
|
|
4031
4444
|
|
|
4032
4445
|
// packages/memory/src/confidence.ts
|
|
4033
4446
|
var TAG_RE = /^<!--\s*memory:(?<verb>extracted|inferred|ambiguous)(?<rest>[^>]*?)-->\s*$/;
|
|
@@ -4239,7 +4652,7 @@ async function snapshot(root) {
|
|
|
4239
4652
|
await Promise.all(
|
|
4240
4653
|
(await collectMarkdownRelPaths(root, MEMORY_PAGES_DIR_RELPATH)).map(async (relPath) => [
|
|
4241
4654
|
relPath,
|
|
4242
|
-
hashContent(await fs5.readFile(
|
|
4655
|
+
hashContent(await fs5.readFile(path18.join(root, relPath), "utf8"))
|
|
4243
4656
|
])
|
|
4244
4657
|
)
|
|
4245
4658
|
);
|
|
@@ -4250,7 +4663,7 @@ async function reconcile(root, before, _verb, detail) {
|
|
|
4250
4663
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
4251
4664
|
const currentPages = await Promise.all(
|
|
4252
4665
|
(await collectMarkdownRelPaths(root, MEMORY_PAGES_DIR_RELPATH)).map(async (relPath) => {
|
|
4253
|
-
const absPath =
|
|
4666
|
+
const absPath = path18.join(root, relPath);
|
|
4254
4667
|
const markdown = await fs5.readFile(absPath, "utf8");
|
|
4255
4668
|
const parsed = parsePageMarkdown(relPath, markdown);
|
|
4256
4669
|
const normalizedFrontmatter = withDenormalizedSources(parsed.frontmatter, parsed.body);
|
|
@@ -4272,7 +4685,7 @@ async function reconcile(root, before, _verb, detail) {
|
|
|
4272
4685
|
})
|
|
4273
4686
|
);
|
|
4274
4687
|
await Promise.all(
|
|
4275
|
-
currentPages.filter((page) => page.currentMarkdown !== page.nextMarkdown).map((page) => fs5.writeFile(
|
|
4688
|
+
currentPages.filter((page) => page.currentMarkdown !== page.nextMarkdown).map((page) => fs5.writeFile(path18.join(root, page.relPath), page.nextMarkdown, "utf8"))
|
|
4276
4689
|
);
|
|
4277
4690
|
const diff2 = diffSnapshots(before, await snapshot(root));
|
|
4278
4691
|
await writeIndex(root);
|
|
@@ -4302,7 +4715,7 @@ async function appendLogEntries(root, diff2, detail, timestamp = (/* @__PURE__ *
|
|
|
4302
4715
|
if (entries.length === 0) {
|
|
4303
4716
|
return;
|
|
4304
4717
|
}
|
|
4305
|
-
const logPath =
|
|
4718
|
+
const logPath = path18.join(root, MEMORY_LOG_RELPATH);
|
|
4306
4719
|
const existing = await fs5.readFile(logPath, "utf8");
|
|
4307
4720
|
const separator = existing.length === 0 || existing.endsWith("\n") ? "" : "\n";
|
|
4308
4721
|
await fs5.writeFile(logPath, `${existing}${separator}${entries.join("\n")}
|
|
@@ -4326,7 +4739,7 @@ async function writeIndex(root) {
|
|
|
4326
4739
|
description: page.frontmatter.description ?? ""
|
|
4327
4740
|
}))
|
|
4328
4741
|
);
|
|
4329
|
-
await fs5.writeFile(
|
|
4742
|
+
await fs5.writeFile(path18.join(root, MEMORY_INDEX_RELPATH), index, "utf8");
|
|
4330
4743
|
}
|
|
4331
4744
|
function parsePageMarkdown(relPath, markdown) {
|
|
4332
4745
|
try {
|
|
@@ -4371,9 +4784,9 @@ async function writePage(root, relPath, body, opts) {
|
|
|
4371
4784
|
const pageRelPath = assertPageRelPath(relPath);
|
|
4372
4785
|
return withLock(root, async () => {
|
|
4373
4786
|
const before = await snapshot(root);
|
|
4374
|
-
await fs6.mkdir(
|
|
4787
|
+
await fs6.mkdir(path19.dirname(path19.join(root, pageRelPath)), { recursive: true });
|
|
4375
4788
|
await fs6.writeFile(
|
|
4376
|
-
|
|
4789
|
+
path19.join(root, pageRelPath),
|
|
4377
4790
|
serializeFrontmatter(opts.frontmatter ?? {}, body),
|
|
4378
4791
|
"utf8"
|
|
4379
4792
|
);
|
|
@@ -4384,8 +4797,8 @@ async function appendToPage(root, relPath, content, opts) {
|
|
|
4384
4797
|
const pageRelPath = assertPageRelPath(relPath);
|
|
4385
4798
|
return withLock(root, async () => {
|
|
4386
4799
|
const before = await snapshot(root);
|
|
4387
|
-
const pagePath =
|
|
4388
|
-
await fs6.mkdir(
|
|
4800
|
+
const pagePath = path19.join(root, pageRelPath);
|
|
4801
|
+
await fs6.mkdir(path19.dirname(pagePath), { recursive: true });
|
|
4389
4802
|
const existing = await readMarkdownIfPresent(pagePath);
|
|
4390
4803
|
const parsed = existing === void 0 ? { frontmatter: {}, body: "" } : parseFrontmatter(existing);
|
|
4391
4804
|
await fs6.writeFile(
|
|
@@ -4407,7 +4820,7 @@ async function removeChildren(directoryPath) {
|
|
|
4407
4820
|
if (entryName === MEMORY_LOCK_RELPATH) {
|
|
4408
4821
|
continue;
|
|
4409
4822
|
}
|
|
4410
|
-
const entryPath =
|
|
4823
|
+
const entryPath = path19.join(directoryPath, entryName);
|
|
4411
4824
|
const stat7 = await fs6.stat(entryPath);
|
|
4412
4825
|
if (stat7.isDirectory()) {
|
|
4413
4826
|
await removeDirectory2(entryPath);
|
|
@@ -4424,7 +4837,7 @@ async function removeDirectory2(directoryPath) {
|
|
|
4424
4837
|
}
|
|
4425
4838
|
function assertPageRelPath(relPath) {
|
|
4426
4839
|
const normalizedRelPath = assertSafeRelPath(relPath);
|
|
4427
|
-
if (!normalizedRelPath.startsWith(`${MEMORY_PAGES_DIR_RELPATH}/`) ||
|
|
4840
|
+
if (!normalizedRelPath.startsWith(`${MEMORY_PAGES_DIR_RELPATH}/`) || path19.posix.extname(normalizedRelPath).toLowerCase() !== ".md") {
|
|
4428
4841
|
throw new Error(`Expected a markdown page path under "${MEMORY_PAGES_DIR_RELPATH}/".`);
|
|
4429
4842
|
}
|
|
4430
4843
|
return normalizedRelPath;
|
|
@@ -4442,12 +4855,12 @@ async function readMarkdownIfPresent(filePath) {
|
|
|
4442
4855
|
|
|
4443
4856
|
// packages/memory/src/edit.ts
|
|
4444
4857
|
async function editPage(root, relPath, opts) {
|
|
4445
|
-
const pagePath =
|
|
4858
|
+
const pagePath = path20.join(root, relPath);
|
|
4446
4859
|
const original = await readIfPresent(pagePath);
|
|
4447
|
-
const tempRoot =
|
|
4860
|
+
const tempRoot = path20.join(root, ".tmp");
|
|
4448
4861
|
await fs7.mkdir(tempRoot, { recursive: true });
|
|
4449
|
-
const tempDir = await fs7.mkdtemp(
|
|
4450
|
-
const tempPath =
|
|
4862
|
+
const tempDir = await fs7.mkdtemp(path20.join(tempRoot, "poe-code-memory-edit-"));
|
|
4863
|
+
const tempPath = path20.join(tempDir, path20.basename(relPath));
|
|
4451
4864
|
try {
|
|
4452
4865
|
await fs7.writeFile(tempPath, original ?? "", "utf8");
|
|
4453
4866
|
await opts.launchEditor(tempPath);
|
|
@@ -4481,7 +4894,7 @@ async function readIfPresent(filePath) {
|
|
|
4481
4894
|
|
|
4482
4895
|
// packages/memory/src/audit.ts
|
|
4483
4896
|
import * as fs8 from "node:fs/promises";
|
|
4484
|
-
import
|
|
4897
|
+
import path21 from "node:path";
|
|
4485
4898
|
var DEFAULT_MIN_INFERRED_CONFIDENCE = 0.3;
|
|
4486
4899
|
var DEFAULT_REJECT_UNTAGGED = false;
|
|
4487
4900
|
var DEFAULT_UNTAGGED_BODY_THRESHOLD_CHARS = 200;
|
|
@@ -4536,10 +4949,10 @@ async function auditSourceRef(source, claimLineNumber, repoRoot, sourceCache) {
|
|
|
4536
4949
|
if (isUrlLike(source.path)) {
|
|
4537
4950
|
return void 0;
|
|
4538
4951
|
}
|
|
4539
|
-
if (
|
|
4952
|
+
if (path21.isAbsolute(source.path)) {
|
|
4540
4953
|
return `Claim on line ${claimLineNumber} cites "${serializeSourceRef(source)}", but source paths must be repo-relative or URLs.`;
|
|
4541
4954
|
}
|
|
4542
|
-
const absPath =
|
|
4955
|
+
const absPath = path21.resolve(repoRoot, source.path);
|
|
4543
4956
|
if (!isWithinRoot(repoRoot, absPath)) {
|
|
4544
4957
|
return `Claim on line ${claimLineNumber} cites "${serializeSourceRef(source)}", which resolves outside the repo root.`;
|
|
4545
4958
|
}
|
|
@@ -4605,14 +5018,14 @@ function isUrlLike(value) {
|
|
|
4605
5018
|
return /^[a-z][a-z\d+.-]*:\/\//i.test(value);
|
|
4606
5019
|
}
|
|
4607
5020
|
function isWithinRoot(root, absPath) {
|
|
4608
|
-
const relative =
|
|
4609
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
5021
|
+
const relative = path21.relative(root, absPath);
|
|
5022
|
+
return relative === "" || !relative.startsWith("..") && !path21.isAbsolute(relative);
|
|
4610
5023
|
}
|
|
4611
5024
|
|
|
4612
5025
|
// packages/memory/src/cache.ts
|
|
4613
5026
|
import { createHash as createHash2 } from "node:crypto";
|
|
4614
5027
|
import * as fs9 from "node:fs/promises";
|
|
4615
|
-
import
|
|
5028
|
+
import path22 from "node:path";
|
|
4616
5029
|
function computeIngestKey(input) {
|
|
4617
5030
|
const hash = createHash2("sha256");
|
|
4618
5031
|
hash.update(input.sourceBytes);
|
|
@@ -4625,7 +5038,7 @@ function computeIngestKey(input) {
|
|
|
4625
5038
|
return hash.digest("hex");
|
|
4626
5039
|
}
|
|
4627
5040
|
async function readCacheEntry(root, key) {
|
|
4628
|
-
const cachePath =
|
|
5041
|
+
const cachePath = path22.join(root, MEMORY_INGEST_CACHE_DIR_RELPATH, `${key}.json`);
|
|
4629
5042
|
let raw;
|
|
4630
5043
|
try {
|
|
4631
5044
|
raw = await fs9.readFile(cachePath, "utf8");
|
|
@@ -4644,17 +5057,17 @@ async function readCacheEntry(root, key) {
|
|
|
4644
5057
|
}
|
|
4645
5058
|
}
|
|
4646
5059
|
async function writeCacheEntry(root, entry) {
|
|
4647
|
-
await fs9.mkdir(
|
|
5060
|
+
await fs9.mkdir(path22.join(root, MEMORY_INGEST_CACHE_DIR_RELPATH), { recursive: true });
|
|
4648
5061
|
await fs9.writeFile(
|
|
4649
|
-
|
|
5062
|
+
path22.join(root, MEMORY_INGEST_CACHE_DIR_RELPATH, `${entry.key}.json`),
|
|
4650
5063
|
`${JSON.stringify(entry)}
|
|
4651
5064
|
`,
|
|
4652
5065
|
"utf8"
|
|
4653
5066
|
);
|
|
4654
5067
|
}
|
|
4655
5068
|
async function clearCache(root, opts = {}) {
|
|
4656
|
-
const ingestDir =
|
|
4657
|
-
const cacheDir =
|
|
5069
|
+
const ingestDir = path22.join(root, MEMORY_INGEST_CACHE_DIR_RELPATH);
|
|
5070
|
+
const cacheDir = path22.join(root, MEMORY_CACHE_DIR_RELPATH);
|
|
4658
5071
|
const fileNames = await readCacheFileNames(ingestDir);
|
|
4659
5072
|
if (fileNames.length === 0) {
|
|
4660
5073
|
if (opts.olderThanMs === void 0) {
|
|
@@ -4674,7 +5087,7 @@ async function clearCache(root, opts = {}) {
|
|
|
4674
5087
|
if (entry === null || Date.parse(entry.ingestedAt) > cutoff) {
|
|
4675
5088
|
continue;
|
|
4676
5089
|
}
|
|
4677
|
-
await fs9.rm(
|
|
5090
|
+
await fs9.rm(path22.join(ingestDir, fileName), { force: true });
|
|
4678
5091
|
removed += 1;
|
|
4679
5092
|
}
|
|
4680
5093
|
await removeEmptyDirectory(ingestDir);
|
|
@@ -4730,7 +5143,7 @@ function expectStringArray(value, field) {
|
|
|
4730
5143
|
}
|
|
4731
5144
|
async function readCacheFileNames(ingestDir) {
|
|
4732
5145
|
try {
|
|
4733
|
-
return (await fs9.readdir(ingestDir)).filter((fileName) =>
|
|
5146
|
+
return (await fs9.readdir(ingestDir)).filter((fileName) => path22.posix.extname(fileName).toLowerCase() === ".json").sort((left, right) => left.localeCompare(right));
|
|
4734
5147
|
} catch (error2) {
|
|
4735
5148
|
if (isMissing3(error2)) {
|
|
4736
5149
|
return [];
|
|
@@ -4781,18 +5194,18 @@ function parseOlderThan(value) {
|
|
|
4781
5194
|
}
|
|
4782
5195
|
|
|
4783
5196
|
// packages/memory/src/ingest.ts
|
|
4784
|
-
import * as
|
|
4785
|
-
import
|
|
5197
|
+
import * as fs13 from "node:fs/promises";
|
|
5198
|
+
import path45 from "node:path";
|
|
4786
5199
|
|
|
4787
5200
|
// packages/agent-spawn/src/register-factories.ts
|
|
4788
5201
|
import { spawn as spawnChildProcess2 } from "node:child_process";
|
|
4789
5202
|
|
|
4790
5203
|
// packages/agent-harness-tools/src/paths.ts
|
|
4791
|
-
import
|
|
5204
|
+
import path23 from "node:path";
|
|
4792
5205
|
|
|
4793
5206
|
// packages/agent-harness-tools/src/plans.ts
|
|
4794
5207
|
import * as fsPromises4 from "node:fs/promises";
|
|
4795
|
-
import
|
|
5208
|
+
import path29 from "node:path";
|
|
4796
5209
|
|
|
4797
5210
|
// packages/task-list/src/open.ts
|
|
4798
5211
|
import * as fsPromises3 from "node:fs/promises";
|
|
@@ -4875,7 +5288,7 @@ import * as childProcess from "node:child_process";
|
|
|
4875
5288
|
import { randomBytes } from "node:crypto";
|
|
4876
5289
|
|
|
4877
5290
|
// packages/process-runner/src/docker/args.ts
|
|
4878
|
-
import
|
|
5291
|
+
import path24 from "node:path";
|
|
4879
5292
|
function buildDockerRunArgs(input) {
|
|
4880
5293
|
const args = [input.engine];
|
|
4881
5294
|
if (input.engine === "docker" && input.context) {
|
|
@@ -4902,7 +5315,7 @@ function buildDockerRunArgs(input) {
|
|
|
4902
5315
|
args.push("-e", `${key}=${value}`);
|
|
4903
5316
|
}
|
|
4904
5317
|
for (const mount of input.mounts) {
|
|
4905
|
-
const volume = `${
|
|
5318
|
+
const volume = `${path24.resolve(mount.source)}:${mount.target}${mount.readonly ? ":ro" : ""}`;
|
|
4906
5319
|
args.push("-v", volume);
|
|
4907
5320
|
}
|
|
4908
5321
|
for (const port of input.ports) {
|
|
@@ -4921,7 +5334,7 @@ import { createHash as createHash3, randomBytes as randomBytes2 } from "node:cry
|
|
|
4921
5334
|
import { mkdtempSync, rmSync } from "node:fs";
|
|
4922
5335
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
4923
5336
|
import { tmpdir } from "node:os";
|
|
4924
|
-
import
|
|
5337
|
+
import path25 from "node:path";
|
|
4925
5338
|
|
|
4926
5339
|
// packages/process-runner/src/host/host-runner.ts
|
|
4927
5340
|
import { spawn as spawnChildProcess } from "node:child_process";
|
|
@@ -5061,8 +5474,8 @@ function createDockerEnv(input) {
|
|
|
5061
5474
|
id: containerRef,
|
|
5062
5475
|
job: input.attachedJobId === void 0 ? null : createContainerJob(containerRef, input.runner, input.engine, input.context, input.attachedJobId),
|
|
5063
5476
|
async uploadWorkspace() {
|
|
5064
|
-
const tempDir = mkdtempSync(
|
|
5065
|
-
const archivePath =
|
|
5477
|
+
const tempDir = mkdtempSync(path25.join(tmpdir(), "poe-docker-upload-"));
|
|
5478
|
+
const archivePath = path25.join(tempDir, "workspace.tar");
|
|
5066
5479
|
try {
|
|
5067
5480
|
const excludeArgs = input.spec.uploadIgnoreFiles.flatMap((ignored) => [
|
|
5068
5481
|
"--exclude",
|
|
@@ -5105,8 +5518,8 @@ function createDockerEnv(input) {
|
|
|
5105
5518
|
}
|
|
5106
5519
|
},
|
|
5107
5520
|
async downloadWorkspace(opts) {
|
|
5108
|
-
const tempDir = mkdtempSync(
|
|
5109
|
-
const archivePath =
|
|
5521
|
+
const tempDir = mkdtempSync(path25.join(tmpdir(), "poe-docker-download-"));
|
|
5522
|
+
const archivePath = path25.join(tempDir, "workspace.tar");
|
|
5110
5523
|
try {
|
|
5111
5524
|
await runOrThrow(input.runner, {
|
|
5112
5525
|
command: input.engine,
|
|
@@ -5206,11 +5619,11 @@ async function buildDockerRuntimeTemplate(input) {
|
|
|
5206
5619
|
const runner = input.runner ?? createHostRunner();
|
|
5207
5620
|
const engine = input.runtime.engine ?? detectEngine();
|
|
5208
5621
|
const context = detectContext();
|
|
5209
|
-
const dockerfilePath =
|
|
5622
|
+
const dockerfilePath = path25.resolve(
|
|
5210
5623
|
input.cwd,
|
|
5211
|
-
input.runtime.dockerfile ??
|
|
5624
|
+
input.runtime.dockerfile ?? path25.join(".poe-code", "Dockerfile")
|
|
5212
5625
|
);
|
|
5213
|
-
const buildContext =
|
|
5626
|
+
const buildContext = path25.resolve(input.cwd, input.runtime.build_context ?? ".");
|
|
5214
5627
|
const dockerfileBytes = await readFile10(dockerfilePath);
|
|
5215
5628
|
const hash = hashDockerTemplate(dockerfileBytes, input.runtime.build_args ?? {});
|
|
5216
5629
|
const cached2 = input.force ? null : await input.state?.templates.get("docker", hash);
|
|
@@ -5472,10 +5885,10 @@ var hostExecutionEnvFactory = {
|
|
|
5472
5885
|
import { Readable, Writable } from "node:stream";
|
|
5473
5886
|
|
|
5474
5887
|
// packages/task-list/src/backends/utils.ts
|
|
5475
|
-
import
|
|
5888
|
+
import path26 from "node:path";
|
|
5476
5889
|
|
|
5477
5890
|
// packages/task-list/src/backends/markdown-dir.ts
|
|
5478
|
-
import
|
|
5891
|
+
import path27 from "node:path";
|
|
5479
5892
|
import { parseDocument as parseDocument2, stringify as stringify2 } from "yaml";
|
|
5480
5893
|
|
|
5481
5894
|
// packages/task-list/src/schema/task.schema.json
|
|
@@ -5549,6 +5962,7 @@ var defaultTransitions = deriveLegacyTransitions(defaultStateMachine);
|
|
|
5549
5962
|
var TASK_SCHEMA_ID = task_schema_default.$id;
|
|
5550
5963
|
|
|
5551
5964
|
// packages/task-list/src/backends/yaml-file.ts
|
|
5965
|
+
import path28 from "node:path";
|
|
5552
5966
|
import { isMap, parseDocument as parseDocument3 } from "yaml";
|
|
5553
5967
|
|
|
5554
5968
|
// packages/task-list/src/schema/store.schema.json
|
|
@@ -5589,145 +6003,6 @@ var store_schema_default = {
|
|
|
5589
6003
|
var STORE_SCHEMA_ID = store_schema_default.$id;
|
|
5590
6004
|
var TASK_SCHEMA_ID2 = task_schema_default.$id;
|
|
5591
6005
|
|
|
5592
|
-
// packages/agent-defs/src/agents/claude-code.ts
|
|
5593
|
-
var claudeCodeAgent = {
|
|
5594
|
-
id: "claude-code",
|
|
5595
|
-
name: "claude-code",
|
|
5596
|
-
label: "Claude Code",
|
|
5597
|
-
summary: "Configure Claude Code to route through Poe.",
|
|
5598
|
-
aliases: ["claude"],
|
|
5599
|
-
binaryName: "claude",
|
|
5600
|
-
configPath: "~/.claude/settings.json",
|
|
5601
|
-
branding: {
|
|
5602
|
-
colors: {
|
|
5603
|
-
dark: "#C15F3C",
|
|
5604
|
-
light: "#C15F3C"
|
|
5605
|
-
}
|
|
5606
|
-
}
|
|
5607
|
-
};
|
|
5608
|
-
|
|
5609
|
-
// packages/agent-defs/src/agents/claude-desktop.ts
|
|
5610
|
-
var claudeDesktopAgent = {
|
|
5611
|
-
id: "claude-desktop",
|
|
5612
|
-
name: "claude-desktop",
|
|
5613
|
-
label: "Claude Desktop",
|
|
5614
|
-
summary: "Anthropic's official desktop application for Claude",
|
|
5615
|
-
configPath: "~/.claude/settings.json",
|
|
5616
|
-
branding: {
|
|
5617
|
-
colors: {
|
|
5618
|
-
dark: "#D97757",
|
|
5619
|
-
light: "#D97757"
|
|
5620
|
-
}
|
|
5621
|
-
}
|
|
5622
|
-
};
|
|
5623
|
-
|
|
5624
|
-
// packages/agent-defs/src/agents/codex.ts
|
|
5625
|
-
var codexAgent = {
|
|
5626
|
-
id: "codex",
|
|
5627
|
-
name: "codex",
|
|
5628
|
-
label: "Codex",
|
|
5629
|
-
summary: "Configure Codex to use Poe as the model provider.",
|
|
5630
|
-
binaryName: "codex",
|
|
5631
|
-
configPath: "~/.codex/config.toml",
|
|
5632
|
-
branding: {
|
|
5633
|
-
colors: {
|
|
5634
|
-
dark: "#D5D9DF",
|
|
5635
|
-
light: "#7A7F86"
|
|
5636
|
-
}
|
|
5637
|
-
}
|
|
5638
|
-
};
|
|
5639
|
-
|
|
5640
|
-
// packages/agent-defs/src/agents/opencode.ts
|
|
5641
|
-
var openCodeAgent = {
|
|
5642
|
-
id: "opencode",
|
|
5643
|
-
name: "opencode",
|
|
5644
|
-
label: "OpenCode CLI",
|
|
5645
|
-
summary: "Configure OpenCode CLI to use the Poe API.",
|
|
5646
|
-
binaryName: "opencode",
|
|
5647
|
-
configPath: "~/.config/opencode/config.json",
|
|
5648
|
-
branding: {
|
|
5649
|
-
colors: {
|
|
5650
|
-
dark: "#4A4F55",
|
|
5651
|
-
light: "#2F3338"
|
|
5652
|
-
}
|
|
5653
|
-
}
|
|
5654
|
-
};
|
|
5655
|
-
|
|
5656
|
-
// packages/agent-defs/src/agents/kimi.ts
|
|
5657
|
-
var kimiAgent = {
|
|
5658
|
-
id: "kimi",
|
|
5659
|
-
name: "kimi",
|
|
5660
|
-
label: "Kimi",
|
|
5661
|
-
summary: "Configure Kimi CLI to use Poe API",
|
|
5662
|
-
aliases: ["kimi-cli"],
|
|
5663
|
-
binaryName: "kimi",
|
|
5664
|
-
configPath: "~/.kimi/config.toml",
|
|
5665
|
-
branding: {
|
|
5666
|
-
colors: {
|
|
5667
|
-
dark: "#7B68EE",
|
|
5668
|
-
light: "#6A5ACD"
|
|
5669
|
-
}
|
|
5670
|
-
}
|
|
5671
|
-
};
|
|
5672
|
-
|
|
5673
|
-
// packages/agent-defs/src/agents/goose.ts
|
|
5674
|
-
var gooseAgent = {
|
|
5675
|
-
id: "goose",
|
|
5676
|
-
name: "goose",
|
|
5677
|
-
label: "Goose",
|
|
5678
|
-
summary: "Block's open-source AI agent with ACP support.",
|
|
5679
|
-
binaryName: "goose",
|
|
5680
|
-
configPath: "~/.config/goose/config.yaml",
|
|
5681
|
-
branding: {
|
|
5682
|
-
colors: {
|
|
5683
|
-
dark: "#FF6B35",
|
|
5684
|
-
light: "#E85D26"
|
|
5685
|
-
}
|
|
5686
|
-
}
|
|
5687
|
-
};
|
|
5688
|
-
|
|
5689
|
-
// packages/agent-defs/src/agents/poe-agent.ts
|
|
5690
|
-
var poeAgentAgent = {
|
|
5691
|
-
id: "poe-agent",
|
|
5692
|
-
name: "poe-agent",
|
|
5693
|
-
label: "Poe Agent",
|
|
5694
|
-
summary: "Run one-shot prompts with the built-in Poe agent runtime.",
|
|
5695
|
-
configPath: "~/.poe-code/config.json",
|
|
5696
|
-
branding: {
|
|
5697
|
-
colors: {
|
|
5698
|
-
dark: "#A465F7",
|
|
5699
|
-
light: "#7A3FD3"
|
|
5700
|
-
}
|
|
5701
|
-
}
|
|
5702
|
-
};
|
|
5703
|
-
|
|
5704
|
-
// packages/agent-defs/src/registry.ts
|
|
5705
|
-
var allAgents = [
|
|
5706
|
-
claudeCodeAgent,
|
|
5707
|
-
claudeDesktopAgent,
|
|
5708
|
-
codexAgent,
|
|
5709
|
-
openCodeAgent,
|
|
5710
|
-
kimiAgent,
|
|
5711
|
-
gooseAgent,
|
|
5712
|
-
poeAgentAgent
|
|
5713
|
-
];
|
|
5714
|
-
var lookup2 = /* @__PURE__ */ new Map();
|
|
5715
|
-
for (const agent of allAgents) {
|
|
5716
|
-
const values = [agent.id, agent.name, ...agent.aliases ?? []];
|
|
5717
|
-
for (const value of values) {
|
|
5718
|
-
const normalized = value.toLowerCase();
|
|
5719
|
-
if (!lookup2.has(normalized)) {
|
|
5720
|
-
lookup2.set(normalized, agent.id);
|
|
5721
|
-
}
|
|
5722
|
-
}
|
|
5723
|
-
}
|
|
5724
|
-
function resolveAgentId(input) {
|
|
5725
|
-
if (!input) {
|
|
5726
|
-
return void 0;
|
|
5727
|
-
}
|
|
5728
|
-
return lookup2.get(input.toLowerCase());
|
|
5729
|
-
}
|
|
5730
|
-
|
|
5731
6006
|
// packages/agent-harness-tools/src/select-agent.ts
|
|
5732
6007
|
var loopAgents = allAgents.filter(
|
|
5733
6008
|
(agent) => agent.binaryName !== void 0 || agent.id === "poe-agent"
|
|
@@ -5735,7 +6010,7 @@ var loopAgents = allAgents.filter(
|
|
|
5735
6010
|
var supportedAgents = loopAgents.map((agent) => agent.id).join(", ");
|
|
5736
6011
|
|
|
5737
6012
|
// packages/agent-harness-tools/src/run-logs.ts
|
|
5738
|
-
import
|
|
6013
|
+
import path30 from "node:path";
|
|
5739
6014
|
|
|
5740
6015
|
// packages/agent-harness-tools/src/log-stream.ts
|
|
5741
6016
|
import nodeFs2 from "node:fs";
|
|
@@ -5756,29 +6031,29 @@ function wrapForLogTee(argv, jobId) {
|
|
|
5756
6031
|
return ["sh", "-c", script];
|
|
5757
6032
|
}
|
|
5758
6033
|
async function* streamLogFile(env, jobId, opts) {
|
|
5759
|
-
const
|
|
6034
|
+
const fs16 = env.fs ?? nodeFs2;
|
|
5760
6035
|
const file = jobLogPath(jobId);
|
|
5761
6036
|
let byteOffset = opts.sinceByte ?? 0;
|
|
5762
6037
|
while (true) {
|
|
5763
|
-
if (opts.since !== void 0 && !await wasModifiedSince(
|
|
5764
|
-
await waitForLogChange(
|
|
6038
|
+
if (opts.since !== void 0 && !await wasModifiedSince(fs16, file, opts.since)) {
|
|
6039
|
+
await waitForLogChange(fs16, file);
|
|
5765
6040
|
continue;
|
|
5766
6041
|
}
|
|
5767
|
-
const result = await readLogChunk(
|
|
6042
|
+
const result = await readLogChunk(fs16, file, byteOffset);
|
|
5768
6043
|
if (result !== null) {
|
|
5769
6044
|
byteOffset = result.nextByteOffset;
|
|
5770
6045
|
yield result.chunk;
|
|
5771
6046
|
continue;
|
|
5772
6047
|
}
|
|
5773
|
-
await waitForLogChange(
|
|
6048
|
+
await waitForLogChange(fs16, file);
|
|
5774
6049
|
}
|
|
5775
6050
|
}
|
|
5776
|
-
async function wasModifiedSince(
|
|
5777
|
-
if (
|
|
6051
|
+
async function wasModifiedSince(fs16, file, since) {
|
|
6052
|
+
if (fs16.promises.stat === void 0) {
|
|
5778
6053
|
return true;
|
|
5779
6054
|
}
|
|
5780
6055
|
try {
|
|
5781
|
-
const stat7 = await
|
|
6056
|
+
const stat7 = await fs16.promises.stat(file);
|
|
5782
6057
|
return stat7.mtimeMs >= since.getTime();
|
|
5783
6058
|
} catch (error2) {
|
|
5784
6059
|
if (isNodeError(error2) && error2.code === "ENOENT") {
|
|
@@ -5788,11 +6063,11 @@ async function wasModifiedSince(fs14, file, since) {
|
|
|
5788
6063
|
}
|
|
5789
6064
|
}
|
|
5790
6065
|
async function waitForExit(env, jobId, opts = {}) {
|
|
5791
|
-
const
|
|
6066
|
+
const fs16 = env.fs ?? nodeFs2;
|
|
5792
6067
|
const file = jobExitPath(jobId);
|
|
5793
6068
|
while (true) {
|
|
5794
6069
|
throwIfAborted2(opts.signal);
|
|
5795
|
-
const contents = await readTextFileIfExists(
|
|
6070
|
+
const contents = await readTextFileIfExists(fs16, file);
|
|
5796
6071
|
if (contents !== null) {
|
|
5797
6072
|
const text5 = contents.trim();
|
|
5798
6073
|
const exitCode = Number(text5);
|
|
@@ -5810,8 +6085,8 @@ function jobLogPath(jobId) {
|
|
|
5810
6085
|
function jobExitPath(jobId) {
|
|
5811
6086
|
return `${JOB_DIR}/${jobId}.exit`;
|
|
5812
6087
|
}
|
|
5813
|
-
async function readLogChunk(
|
|
5814
|
-
const contents = await readFileIfExists2(
|
|
6088
|
+
async function readLogChunk(fs16, file, byteOffset) {
|
|
6089
|
+
const contents = await readFileIfExists2(fs16, file);
|
|
5815
6090
|
if (contents === null || byteOffset >= contents.byteLength) {
|
|
5816
6091
|
return null;
|
|
5817
6092
|
}
|
|
@@ -5823,13 +6098,13 @@ async function readLogChunk(fs14, file, byteOffset) {
|
|
|
5823
6098
|
nextByteOffset: contents.byteLength
|
|
5824
6099
|
};
|
|
5825
6100
|
}
|
|
5826
|
-
async function readTextFileIfExists(
|
|
5827
|
-
const contents = await readFileIfExists2(
|
|
6101
|
+
async function readTextFileIfExists(fs16, file) {
|
|
6102
|
+
const contents = await readFileIfExists2(fs16, file);
|
|
5828
6103
|
return contents?.toString("utf8") ?? null;
|
|
5829
6104
|
}
|
|
5830
|
-
async function readFileIfExists2(
|
|
6105
|
+
async function readFileIfExists2(fs16, file) {
|
|
5831
6106
|
try {
|
|
5832
|
-
const contents = await
|
|
6107
|
+
const contents = await fs16.promises.readFile(file);
|
|
5833
6108
|
return Buffer.isBuffer(contents) ? contents : Buffer.from(contents);
|
|
5834
6109
|
} catch (error2) {
|
|
5835
6110
|
if (isNodeError(error2) && error2.code === "ENOENT") {
|
|
@@ -5838,8 +6113,8 @@ async function readFileIfExists2(fs14, file) {
|
|
|
5838
6113
|
throw error2;
|
|
5839
6114
|
}
|
|
5840
6115
|
}
|
|
5841
|
-
async function waitForLogChange(
|
|
5842
|
-
const watch =
|
|
6116
|
+
async function waitForLogChange(fs16, file) {
|
|
6117
|
+
const watch = fs16.watch;
|
|
5843
6118
|
if (typeof watch !== "function") {
|
|
5844
6119
|
await sleep3(POLL_INTERVAL_MS);
|
|
5845
6120
|
return;
|
|
@@ -5960,8 +6235,7 @@ async function runPoeCommand(opts) {
|
|
|
5960
6235
|
signal: opts.signal
|
|
5961
6236
|
});
|
|
5962
6237
|
if (execution?.input !== void 0) {
|
|
5963
|
-
handle.
|
|
5964
|
-
handle.stdin?.end(execution.input);
|
|
6238
|
+
writeExecutionInput(handle, execution.input);
|
|
5965
6239
|
}
|
|
5966
6240
|
const runningJob = opts.state.jobs.update(jobId, {
|
|
5967
6241
|
status: "running",
|
|
@@ -6271,6 +6545,19 @@ function setDetachedJobContext(env, context) {
|
|
|
6271
6545
|
const candidate = env;
|
|
6272
6546
|
candidate.setDetachedJobContext?.(context);
|
|
6273
6547
|
}
|
|
6548
|
+
function writeExecutionInput(handle, input) {
|
|
6549
|
+
const stdin = handle.stdin;
|
|
6550
|
+
if (stdin === null) {
|
|
6551
|
+
return;
|
|
6552
|
+
}
|
|
6553
|
+
stdin.on("error", (error2) => {
|
|
6554
|
+
if (error2.code !== "EPIPE") {
|
|
6555
|
+
throw error2;
|
|
6556
|
+
}
|
|
6557
|
+
});
|
|
6558
|
+
stdin.setDefaultEncoding("utf8");
|
|
6559
|
+
stdin.end(input);
|
|
6560
|
+
}
|
|
6274
6561
|
function isPromiseLike(value) {
|
|
6275
6562
|
return typeof value.then === "function";
|
|
6276
6563
|
}
|
|
@@ -6456,10 +6743,10 @@ function createMemoryStateManager() {
|
|
|
6456
6743
|
// packages/agent-harness-tools/src/workspace-transfer.ts
|
|
6457
6744
|
import { createHash as createHash4 } from "node:crypto";
|
|
6458
6745
|
import { promises as nodeFs3 } from "node:fs";
|
|
6459
|
-
import
|
|
6746
|
+
import path31 from "node:path";
|
|
6460
6747
|
|
|
6461
6748
|
// packages/runner-e2b/src/factory.ts
|
|
6462
|
-
import
|
|
6749
|
+
import path35 from "node:path";
|
|
6463
6750
|
|
|
6464
6751
|
// packages/runner-e2b/src/sdk.ts
|
|
6465
6752
|
import { Template, Sandbox } from "e2b";
|
|
@@ -6508,7 +6795,7 @@ async function readableToString(stream) {
|
|
|
6508
6795
|
// packages/runner-e2b/src/template-build.ts
|
|
6509
6796
|
import { createHash as createHash5 } from "node:crypto";
|
|
6510
6797
|
import { readdir as readdir4, readFile as readFile11 } from "node:fs/promises";
|
|
6511
|
-
import
|
|
6798
|
+
import path32 from "node:path";
|
|
6512
6799
|
var BUILD_LOG_TAIL_SIZE = 30;
|
|
6513
6800
|
async function buildE2bRuntimeTemplate(input) {
|
|
6514
6801
|
const dockerfileBytes = await readFile11(input.dockerfilePath);
|
|
@@ -6589,10 +6876,10 @@ async function readBuildContextFiles(buildContext) {
|
|
|
6589
6876
|
return files.sort((left, right) => left.relativePath.localeCompare(right.relativePath));
|
|
6590
6877
|
}
|
|
6591
6878
|
async function collectBuildContextFiles(buildContext, relativeDir, files) {
|
|
6592
|
-
const absoluteDir =
|
|
6879
|
+
const absoluteDir = path32.join(buildContext, relativeDir);
|
|
6593
6880
|
const entries = await readdir4(absoluteDir, { withFileTypes: true });
|
|
6594
6881
|
for (const entry of entries) {
|
|
6595
|
-
const relativePath =
|
|
6882
|
+
const relativePath = path32.join(relativeDir, entry.name);
|
|
6596
6883
|
if (entry.isDirectory()) {
|
|
6597
6884
|
await collectBuildContextFiles(buildContext, relativePath, files);
|
|
6598
6885
|
continue;
|
|
@@ -6601,8 +6888,8 @@ async function collectBuildContextFiles(buildContext, relativeDir, files) {
|
|
|
6601
6888
|
continue;
|
|
6602
6889
|
}
|
|
6603
6890
|
files.push({
|
|
6604
|
-
relativePath: relativePath.split(
|
|
6605
|
-
bytes: await readFile11(
|
|
6891
|
+
relativePath: relativePath.split(path32.sep).join("/"),
|
|
6892
|
+
bytes: await readFile11(path32.join(buildContext, relativePath))
|
|
6606
6893
|
});
|
|
6607
6894
|
}
|
|
6608
6895
|
}
|
|
@@ -6611,14 +6898,14 @@ async function collectBuildContextFiles(buildContext, relativeDir, files) {
|
|
|
6611
6898
|
import { mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "node:fs";
|
|
6612
6899
|
import { readFile as readFile12, writeFile as writeFile7 } from "node:fs/promises";
|
|
6613
6900
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
6614
|
-
import
|
|
6901
|
+
import path34 from "node:path";
|
|
6615
6902
|
import { PassThrough as PassThrough2, Writable as Writable2 } from "node:stream";
|
|
6616
6903
|
|
|
6617
6904
|
// packages/runner-e2b/src/job-handle.ts
|
|
6618
|
-
import
|
|
6905
|
+
import path33 from "node:path";
|
|
6619
6906
|
var JOB_DIR2 = "/tmp/poe-jobs";
|
|
6620
6907
|
function createE2bJobHandle(input) {
|
|
6621
|
-
const
|
|
6908
|
+
const fs16 = createE2bLogStreamFs(input.sandbox);
|
|
6622
6909
|
return {
|
|
6623
6910
|
id: input.jobId,
|
|
6624
6911
|
envId: input.envId,
|
|
@@ -6630,14 +6917,14 @@ function createE2bJobHandle(input) {
|
|
|
6630
6917
|
return "exited";
|
|
6631
6918
|
}
|
|
6632
6919
|
const processes = await input.sandbox.commands.list();
|
|
6633
|
-
const isRunning = input.pid === void 0 ? processes.some((
|
|
6920
|
+
const isRunning = input.pid === void 0 ? processes.some((process3) => processMentionsJob(process3, input.jobId)) : processes.some((process3) => process3.pid === input.pid);
|
|
6634
6921
|
return isRunning ? "running" : "lost";
|
|
6635
6922
|
},
|
|
6636
6923
|
stream(opts = {}) {
|
|
6637
|
-
return streamLogFile({ fs:
|
|
6924
|
+
return streamLogFile({ fs: fs16 }, input.jobId, opts);
|
|
6638
6925
|
},
|
|
6639
6926
|
async wait() {
|
|
6640
|
-
const result = await waitForExit({ fs:
|
|
6927
|
+
const result = await waitForExit({ fs: fs16 }, input.jobId);
|
|
6641
6928
|
const preserveMs = input.preserveAfterExitHours * 60 * 60 * 1e3;
|
|
6642
6929
|
if (preserveMs > 0) {
|
|
6643
6930
|
await input.sandbox.setTimeout(preserveMs);
|
|
@@ -6645,7 +6932,7 @@ function createE2bJobHandle(input) {
|
|
|
6645
6932
|
return result;
|
|
6646
6933
|
},
|
|
6647
6934
|
async kill() {
|
|
6648
|
-
const pids = input.pid === void 0 ? (await input.sandbox.commands.list()).filter((
|
|
6935
|
+
const pids = input.pid === void 0 ? (await input.sandbox.commands.list()).filter((process3) => processMentionsJob(process3, input.jobId)).map((process3) => process3.pid) : [input.pid];
|
|
6649
6936
|
await Promise.all(pids.map((pid) => input.sandbox.commands.kill(pid)));
|
|
6650
6937
|
}
|
|
6651
6938
|
};
|
|
@@ -6673,7 +6960,7 @@ function createE2bLogStreamFs(sandbox) {
|
|
|
6673
6960
|
watch(filePath, listener) {
|
|
6674
6961
|
let closed = false;
|
|
6675
6962
|
let stop = null;
|
|
6676
|
-
void sandbox.files.watchDir(
|
|
6963
|
+
void sandbox.files.watchDir(path33.dirname(filePath), listener, { recursive: false }).then((handle) => {
|
|
6677
6964
|
if (closed) {
|
|
6678
6965
|
void handle.stop();
|
|
6679
6966
|
return;
|
|
@@ -6691,9 +6978,9 @@ function createE2bLogStreamFs(sandbox) {
|
|
|
6691
6978
|
}
|
|
6692
6979
|
};
|
|
6693
6980
|
}
|
|
6694
|
-
function processMentionsJob(
|
|
6981
|
+
function processMentionsJob(process3, jobId) {
|
|
6695
6982
|
const needle = `/tmp/poe-jobs/${jobId}`;
|
|
6696
|
-
return
|
|
6983
|
+
return process3.cmd.includes(needle) || process3.args.some((arg) => arg.includes(needle));
|
|
6697
6984
|
}
|
|
6698
6985
|
function shellQuote3(value) {
|
|
6699
6986
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
@@ -6712,7 +6999,7 @@ async function readExitCode(sandbox, jobId) {
|
|
|
6712
6999
|
var REMOTE_COMMAND_STDERR_TAIL_SIZE = 30;
|
|
6713
7000
|
function createOpenedE2bEnv(input) {
|
|
6714
7001
|
const hostRunner = input.spec.hostRunner ?? createHostRunner();
|
|
6715
|
-
const hostWorkspaceDir =
|
|
7002
|
+
const hostWorkspaceDir = path34.resolve(input.spec.cwd);
|
|
6716
7003
|
const sandboxWorkspaceDir = normalizeSandboxWorkspaceDir(input.runtime.workspace_dir);
|
|
6717
7004
|
let lastProcess = null;
|
|
6718
7005
|
let detachedJobContext = null;
|
|
@@ -6720,7 +7007,7 @@ function createOpenedE2bEnv(input) {
|
|
|
6720
7007
|
if (cwd === void 0) {
|
|
6721
7008
|
return void 0;
|
|
6722
7009
|
}
|
|
6723
|
-
if (
|
|
7010
|
+
if (path34.isAbsolute(cwd) && path34.resolve(cwd) === hostWorkspaceDir) {
|
|
6724
7011
|
return sandboxWorkspaceDir;
|
|
6725
7012
|
}
|
|
6726
7013
|
return cwd;
|
|
@@ -6744,8 +7031,8 @@ function createOpenedE2bEnv(input) {
|
|
|
6744
7031
|
if (input.spec.runner?.sync === "none") {
|
|
6745
7032
|
return { files: 0, bytes: 0, skipped: [] };
|
|
6746
7033
|
}
|
|
6747
|
-
const tempDir = mkdtempSync2(
|
|
6748
|
-
const archivePath =
|
|
7034
|
+
const tempDir = mkdtempSync2(path34.join(tmpdir2(), "poe-e2b-upload-"));
|
|
7035
|
+
const archivePath = path34.join(tempDir, "workspace.tar");
|
|
6749
7036
|
try {
|
|
6750
7037
|
await runOrThrow2(hostRunner, {
|
|
6751
7038
|
command: "tar",
|
|
@@ -6777,8 +7064,8 @@ function createOpenedE2bEnv(input) {
|
|
|
6777
7064
|
if (input.spec.runner?.sync === "upload" || input.spec.runner?.sync === "none") {
|
|
6778
7065
|
return { files: 0, bytes: 0, conflicts: [] };
|
|
6779
7066
|
}
|
|
6780
|
-
const tempDir = mkdtempSync2(
|
|
6781
|
-
const archivePath =
|
|
7067
|
+
const tempDir = mkdtempSync2(path34.join(tmpdir2(), "poe-e2b-download-"));
|
|
7068
|
+
const archivePath = path34.join(tempDir, "workspace.tar");
|
|
6782
7069
|
try {
|
|
6783
7070
|
await runRemoteOrThrow(
|
|
6784
7071
|
input.sandbox,
|
|
@@ -7101,10 +7388,10 @@ function resolveSandboxCommandEnv(env) {
|
|
|
7101
7388
|
}
|
|
7102
7389
|
function normalizeSandboxWorkspaceDir(workspaceDir) {
|
|
7103
7390
|
const resolvedWorkspaceDir = workspaceDir ?? "/workspace";
|
|
7104
|
-
if (!
|
|
7391
|
+
if (!path34.posix.isAbsolute(resolvedWorkspaceDir)) {
|
|
7105
7392
|
throw new Error("E2B runtime workspace_dir must be an absolute sandbox path.");
|
|
7106
7393
|
}
|
|
7107
|
-
let normalized =
|
|
7394
|
+
let normalized = path34.posix.normalize(resolvedWorkspaceDir);
|
|
7108
7395
|
while (normalized.length > 1 && normalized.endsWith("/")) {
|
|
7109
7396
|
normalized = normalized.slice(0, -1);
|
|
7110
7397
|
}
|
|
@@ -7134,10 +7421,10 @@ var e2bAuthScope = defineScope("e2b", {
|
|
|
7134
7421
|
});
|
|
7135
7422
|
async function resolveE2bApiKey(input) {
|
|
7136
7423
|
const homeDir = input.homeDir ?? os4.homedir();
|
|
7137
|
-
const
|
|
7424
|
+
const fs16 = input.fs ?? nodeFs4;
|
|
7138
7425
|
const env = input.env ?? process.env;
|
|
7139
7426
|
const document = await readMergedDocument(
|
|
7140
|
-
|
|
7427
|
+
fs16,
|
|
7141
7428
|
resolveConfigPath(homeDir),
|
|
7142
7429
|
resolveProjectConfigPath(input.cwd)
|
|
7143
7430
|
);
|
|
@@ -7160,11 +7447,11 @@ var e2bExecutionEnvFactory = {
|
|
|
7160
7447
|
const apiKey = await resolveE2bApiKey({ cwd: runtimeCwd });
|
|
7161
7448
|
const templateId = runtime.template_id ?? (await buildE2bRuntimeTemplate({
|
|
7162
7449
|
runtime,
|
|
7163
|
-
dockerfilePath:
|
|
7450
|
+
dockerfilePath: path35.resolve(
|
|
7164
7451
|
runtimeCwd,
|
|
7165
|
-
runtime.dockerfile ??
|
|
7452
|
+
runtime.dockerfile ?? path35.join(".poe-code", "Dockerfile")
|
|
7166
7453
|
),
|
|
7167
|
-
buildContext:
|
|
7454
|
+
buildContext: path35.resolve(runtimeCwd, runtime.build_context ?? "."),
|
|
7168
7455
|
state: spec.state,
|
|
7169
7456
|
apiKey
|
|
7170
7457
|
})).templateId;
|
|
@@ -7309,8 +7596,83 @@ function runHost(spawnProcess, spec) {
|
|
|
7309
7596
|
};
|
|
7310
7597
|
}
|
|
7311
7598
|
|
|
7599
|
+
// packages/agent-spawn/src/observability/otel.ts
|
|
7600
|
+
var noopOtelSpan = {
|
|
7601
|
+
setAttribute: () => void 0,
|
|
7602
|
+
addEvent: () => void 0,
|
|
7603
|
+
end: () => void 0
|
|
7604
|
+
};
|
|
7605
|
+
function observeAgentSpawn(input, operation) {
|
|
7606
|
+
const span = safeStartSpan(input.otelSink, "agent.spawn", {
|
|
7607
|
+
agent: input.agent,
|
|
7608
|
+
mode: input.mode ?? "yolo",
|
|
7609
|
+
cwd: input.cwd ?? process.cwd()
|
|
7610
|
+
});
|
|
7611
|
+
safeAddEvent(span, "prompt", { prompt: input.prompt });
|
|
7612
|
+
return (async () => {
|
|
7613
|
+
try {
|
|
7614
|
+
const result = await operation();
|
|
7615
|
+
safeAddEvent(span, "summary", { summary: readSummary(result) });
|
|
7616
|
+
safeAddEvent(span, "exit", { exitCode: result.exitCode });
|
|
7617
|
+
return result;
|
|
7618
|
+
} catch (error2) {
|
|
7619
|
+
safeRecordException(input.otelSink, span, error2);
|
|
7620
|
+
throw error2;
|
|
7621
|
+
} finally {
|
|
7622
|
+
safeEndSpan(span);
|
|
7623
|
+
}
|
|
7624
|
+
})();
|
|
7625
|
+
}
|
|
7626
|
+
function safeStartSpan(sink, name, attrs) {
|
|
7627
|
+
if (sink === void 0) {
|
|
7628
|
+
return noopOtelSpan;
|
|
7629
|
+
}
|
|
7630
|
+
try {
|
|
7631
|
+
return sink.startSpan(name, attrs);
|
|
7632
|
+
} catch (error2) {
|
|
7633
|
+
warnOtelSinkFailure("startSpan", error2);
|
|
7634
|
+
return noopOtelSpan;
|
|
7635
|
+
}
|
|
7636
|
+
}
|
|
7637
|
+
function safeAddEvent(span, name, attrs) {
|
|
7638
|
+
if (span === void 0) {
|
|
7639
|
+
return;
|
|
7640
|
+
}
|
|
7641
|
+
try {
|
|
7642
|
+
span.addEvent(name, attrs);
|
|
7643
|
+
} catch (error2) {
|
|
7644
|
+
warnOtelSinkFailure("addEvent", error2);
|
|
7645
|
+
}
|
|
7646
|
+
}
|
|
7647
|
+
function safeRecordException(sink, span, error2) {
|
|
7648
|
+
if (sink === void 0) {
|
|
7649
|
+
return;
|
|
7650
|
+
}
|
|
7651
|
+
try {
|
|
7652
|
+
sink.recordException(span, error2);
|
|
7653
|
+
} catch (recordError) {
|
|
7654
|
+
warnOtelSinkFailure("recordException", recordError);
|
|
7655
|
+
}
|
|
7656
|
+
}
|
|
7657
|
+
function safeEndSpan(span) {
|
|
7658
|
+
try {
|
|
7659
|
+
span.end();
|
|
7660
|
+
} catch (error2) {
|
|
7661
|
+
warnOtelSinkFailure("end", error2);
|
|
7662
|
+
}
|
|
7663
|
+
}
|
|
7664
|
+
function readSummary(result) {
|
|
7665
|
+
return result.stdout.trim() || result.stderr.trim();
|
|
7666
|
+
}
|
|
7667
|
+
function warnOtelSinkFailure(method, error2) {
|
|
7668
|
+
console.warn(`OpenTelemetry sink ${method} failed: ${readErrorMessage(error2)}`);
|
|
7669
|
+
}
|
|
7670
|
+
function readErrorMessage(error2) {
|
|
7671
|
+
return error2 instanceof Error ? error2.message : String(error2);
|
|
7672
|
+
}
|
|
7673
|
+
|
|
7312
7674
|
// packages/agent-spawn/src/run-command.ts
|
|
7313
|
-
import { spawn as
|
|
7675
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
7314
7676
|
|
|
7315
7677
|
// packages/agent-spawn/src/types.ts
|
|
7316
7678
|
function resolveModeConfig(modeConfig) {
|
|
@@ -7604,8 +7966,8 @@ function listMcpSupportedAgents() {
|
|
|
7604
7966
|
}
|
|
7605
7967
|
|
|
7606
7968
|
// packages/agent-spawn/src/spawn.ts
|
|
7607
|
-
import { mkdirSync, openSync, writeSync, closeSync } from "node:fs";
|
|
7608
|
-
import
|
|
7969
|
+
import { mkdirSync as mkdirSync3, openSync, writeSync, closeSync } from "node:fs";
|
|
7970
|
+
import path41 from "node:path";
|
|
7609
7971
|
|
|
7610
7972
|
// packages/agent-spawn/src/configs/resolve-config.ts
|
|
7611
7973
|
function resolveConfig(agentId) {
|
|
@@ -7641,6 +8003,12 @@ function getMcpArgs(config, servers) {
|
|
|
7641
8003
|
}
|
|
7642
8004
|
return config.mcpArgs(servers);
|
|
7643
8005
|
}
|
|
8006
|
+
function getMcpEnv(config, servers) {
|
|
8007
|
+
if (!hasMcpServers(servers) || !config.mcpEnv) {
|
|
8008
|
+
return {};
|
|
8009
|
+
}
|
|
8010
|
+
return config.mcpEnv(servers);
|
|
8011
|
+
}
|
|
7644
8012
|
function formatUnsupportedMcpSpawnMessage(agentId) {
|
|
7645
8013
|
const supported = listMcpSupportedAgents();
|
|
7646
8014
|
const supportedText = supported.length > 0 ? supported.join(", ") : "(none)";
|
|
@@ -7654,50 +8022,1743 @@ function stripModelNamespace(model) {
|
|
|
7654
8022
|
return slashIndex === -1 ? model : model.slice(slashIndex + 1);
|
|
7655
8023
|
}
|
|
7656
8024
|
|
|
7657
|
-
// packages/agent-spawn/src/
|
|
7658
|
-
|
|
7659
|
-
|
|
7660
|
-
|
|
7661
|
-
|
|
8025
|
+
// packages/agent-spawn/src/parallel.ts
|
|
8026
|
+
var SpawnParallelError = class extends Error {
|
|
8027
|
+
index;
|
|
8028
|
+
result;
|
|
8029
|
+
results;
|
|
8030
|
+
constructor(index, result, results) {
|
|
8031
|
+
super(`spawn.parallel call ${index} failed with exit code ${result.exitCode}.`);
|
|
8032
|
+
this.name = "SpawnParallelError";
|
|
8033
|
+
this.index = index;
|
|
8034
|
+
this.result = result;
|
|
8035
|
+
this.results = results;
|
|
8036
|
+
}
|
|
8037
|
+
};
|
|
8038
|
+
function createSpawnParallel(spawnOnce) {
|
|
8039
|
+
return async function parallel(calls, options = {}) {
|
|
8040
|
+
if (calls.length === 0) {
|
|
8041
|
+
return [];
|
|
8042
|
+
}
|
|
8043
|
+
const maxConcurrent = normalizeMaxConcurrent(options.maxConcurrent);
|
|
8044
|
+
const failFast = options.failFast ?? true;
|
|
8045
|
+
const group = new AbortController();
|
|
8046
|
+
const results = new Array(calls.length);
|
|
8047
|
+
const errors = [];
|
|
8048
|
+
let nextIndex = 0;
|
|
8049
|
+
let primaryFailure;
|
|
8050
|
+
const removeParentAbort = linkParentAbort(options.signal, group, (error2) => {
|
|
8051
|
+
primaryFailure ??= error2;
|
|
8052
|
+
});
|
|
8053
|
+
const worker = async () => {
|
|
8054
|
+
while (!primaryFailure) {
|
|
8055
|
+
const index = nextIndex;
|
|
8056
|
+
nextIndex += 1;
|
|
8057
|
+
if (index >= calls.length) {
|
|
8058
|
+
return;
|
|
8059
|
+
}
|
|
8060
|
+
try {
|
|
8061
|
+
const result = await runParallelCall(calls[index], spawnOnce, group.signal);
|
|
8062
|
+
results[index] = result;
|
|
8063
|
+
if (failFast && result.exitCode !== 0) {
|
|
8064
|
+
const error2 = new SpawnParallelError(index, result, results);
|
|
8065
|
+
primaryFailure ??= error2;
|
|
8066
|
+
group.abort(error2);
|
|
8067
|
+
return;
|
|
8068
|
+
}
|
|
8069
|
+
} catch (error2) {
|
|
8070
|
+
if (failFast || group.signal.aborted) {
|
|
8071
|
+
primaryFailure ??= error2;
|
|
8072
|
+
group.abort(error2);
|
|
8073
|
+
return;
|
|
8074
|
+
}
|
|
8075
|
+
errors.push(error2);
|
|
8076
|
+
}
|
|
8077
|
+
}
|
|
8078
|
+
};
|
|
8079
|
+
try {
|
|
8080
|
+
await Promise.allSettled(
|
|
8081
|
+
Array.from({ length: Math.min(maxConcurrent, calls.length) }, () => worker())
|
|
8082
|
+
);
|
|
8083
|
+
} finally {
|
|
8084
|
+
removeParentAbort();
|
|
8085
|
+
}
|
|
8086
|
+
if (primaryFailure) {
|
|
8087
|
+
throw primaryFailure;
|
|
8088
|
+
}
|
|
8089
|
+
if (errors.length > 0) {
|
|
8090
|
+
throw new AggregateError(errors, "spawn.parallel failed before every call returned a result.");
|
|
8091
|
+
}
|
|
8092
|
+
return results;
|
|
8093
|
+
};
|
|
7662
8094
|
}
|
|
7663
|
-
function
|
|
7664
|
-
|
|
7665
|
-
if (
|
|
7666
|
-
|
|
8095
|
+
async function runParallelCall(call, spawnOnce, signal) {
|
|
8096
|
+
throwIfAborted3(signal);
|
|
8097
|
+
if (typeof call === "function") {
|
|
8098
|
+
const handle = call(signal);
|
|
8099
|
+
const [result] = await Promise.all([handle.result, drainEvents(handle.events)]);
|
|
8100
|
+
return result;
|
|
7667
8101
|
}
|
|
7668
|
-
if (
|
|
7669
|
-
throw new Error(
|
|
8102
|
+
if (!isSpawnTuple(call)) {
|
|
8103
|
+
throw new Error("spawn.parallel calls must be [service, options] tuples or spawn thunks.");
|
|
7670
8104
|
}
|
|
7671
|
-
|
|
7672
|
-
|
|
8105
|
+
const { options, cleanup } = withAbortSignal(call[1], signal);
|
|
8106
|
+
try {
|
|
8107
|
+
const handle = spawnOnce(call[0], options);
|
|
8108
|
+
const [result] = await Promise.all([handle.result, drainEvents(handle.events)]);
|
|
8109
|
+
return result;
|
|
8110
|
+
} finally {
|
|
8111
|
+
cleanup();
|
|
7673
8112
|
}
|
|
7674
|
-
return {
|
|
7675
|
-
agentId: resolved.agentId,
|
|
7676
|
-
binaryName: resolved.binaryName,
|
|
7677
|
-
spawnConfig: resolved.spawnConfig
|
|
7678
|
-
};
|
|
7679
|
-
}
|
|
7680
|
-
function getDefaultArgsPosition(config) {
|
|
7681
|
-
return config.defaultArgsPosition ?? "afterPrompt";
|
|
7682
8113
|
}
|
|
7683
|
-
function
|
|
7684
|
-
|
|
7685
|
-
|
|
8114
|
+
async function drainEvents(events) {
|
|
8115
|
+
for await (const ignoredEvent of events) {
|
|
8116
|
+
void ignoredEvent;
|
|
7686
8117
|
}
|
|
7687
|
-
return config.mcpArgsBeforeCommand ? "beforeCommand" : "afterCommand";
|
|
7688
8118
|
}
|
|
7689
|
-
function
|
|
7690
|
-
const
|
|
7691
|
-
|
|
7692
|
-
|
|
7693
|
-
const mcpArgsPosition = getMcpArgsPosition(config);
|
|
7694
|
-
const resumeArgsPosition = config.resume?.position ?? "afterPrompt";
|
|
7695
|
-
const args = [];
|
|
7696
|
-
if (mcpArgsPosition === "beforeCommand") {
|
|
7697
|
-
args.push(...mcpArgs);
|
|
8119
|
+
function normalizeMaxConcurrent(maxConcurrent) {
|
|
8120
|
+
const value = maxConcurrent ?? 4;
|
|
8121
|
+
if (!Number.isInteger(value) || value < 1) {
|
|
8122
|
+
throw new Error("spawn.parallel maxConcurrent must be an integer greater than or equal to 1.");
|
|
7698
8123
|
}
|
|
7699
|
-
|
|
7700
|
-
|
|
8124
|
+
return value;
|
|
8125
|
+
}
|
|
8126
|
+
function isSpawnTuple(call) {
|
|
8127
|
+
return Array.isArray(call) && call.length === 2;
|
|
8128
|
+
}
|
|
8129
|
+
function withAbortSignal(options, signal) {
|
|
8130
|
+
if (!options.signal) {
|
|
8131
|
+
return {
|
|
8132
|
+
options: { ...options, signal },
|
|
8133
|
+
cleanup() {
|
|
8134
|
+
}
|
|
8135
|
+
};
|
|
8136
|
+
}
|
|
8137
|
+
const controller = new AbortController();
|
|
8138
|
+
const abort = () => {
|
|
8139
|
+
controller.abort();
|
|
8140
|
+
};
|
|
8141
|
+
if (signal.aborted || options.signal.aborted) {
|
|
8142
|
+
controller.abort();
|
|
8143
|
+
} else {
|
|
8144
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
8145
|
+
options.signal.addEventListener("abort", abort, { once: true });
|
|
8146
|
+
}
|
|
8147
|
+
return {
|
|
8148
|
+
options: { ...options, signal: controller.signal },
|
|
8149
|
+
cleanup() {
|
|
8150
|
+
signal.removeEventListener("abort", abort);
|
|
8151
|
+
options.signal?.removeEventListener("abort", abort);
|
|
8152
|
+
}
|
|
8153
|
+
};
|
|
8154
|
+
}
|
|
8155
|
+
function linkParentAbort(parentSignal, group, setFailure) {
|
|
8156
|
+
if (!parentSignal) {
|
|
8157
|
+
return () => {
|
|
8158
|
+
};
|
|
8159
|
+
}
|
|
8160
|
+
const abort = () => {
|
|
8161
|
+
const error2 = createAbortError3();
|
|
8162
|
+
setFailure(error2);
|
|
8163
|
+
group.abort(error2);
|
|
8164
|
+
};
|
|
8165
|
+
if (parentSignal.aborted) {
|
|
8166
|
+
abort();
|
|
8167
|
+
return () => {
|
|
8168
|
+
};
|
|
8169
|
+
}
|
|
8170
|
+
parentSignal.addEventListener("abort", abort, { once: true });
|
|
8171
|
+
return () => parentSignal.removeEventListener("abort", abort);
|
|
8172
|
+
}
|
|
8173
|
+
function throwIfAborted3(signal) {
|
|
8174
|
+
if (signal.aborted) {
|
|
8175
|
+
throw createAbortError3();
|
|
8176
|
+
}
|
|
8177
|
+
}
|
|
8178
|
+
function createAbortError3() {
|
|
8179
|
+
const error2 = new Error("Agent spawn parallel aborted");
|
|
8180
|
+
error2.name = "AbortError";
|
|
8181
|
+
return error2;
|
|
8182
|
+
}
|
|
8183
|
+
|
|
8184
|
+
// packages/agent-spawn/src/prompt-transport.ts
|
|
8185
|
+
function shouldSendPromptViaStdin(config, options) {
|
|
8186
|
+
return !!config.stdinMode && (options.useStdin === true || options.prompt.includes("\0"));
|
|
8187
|
+
}
|
|
8188
|
+
|
|
8189
|
+
// packages/agent-spawn/src/retry.ts
|
|
8190
|
+
var retryableExitCodes = /* @__PURE__ */ new Set([1, 124, 125, 137]);
|
|
8191
|
+
var maxBackoffMs = 3e4;
|
|
8192
|
+
function createSpawnRetry(spawnOnce) {
|
|
8193
|
+
return (service, options, retryOptions) => {
|
|
8194
|
+
const normalizedRetryOptions = normalizeRetryOptions(retryOptions);
|
|
8195
|
+
const queue = createEventQueue();
|
|
8196
|
+
const result = runRetryingSpawn({
|
|
8197
|
+
service,
|
|
8198
|
+
options,
|
|
8199
|
+
retryOptions: normalizedRetryOptions,
|
|
8200
|
+
spawnOnce,
|
|
8201
|
+
emit: queue.push
|
|
8202
|
+
}).then((value) => {
|
|
8203
|
+
queue.close();
|
|
8204
|
+
return value;
|
|
8205
|
+
}).catch((error2) => {
|
|
8206
|
+
queue.fail(error2);
|
|
8207
|
+
throw error2;
|
|
8208
|
+
});
|
|
8209
|
+
return {
|
|
8210
|
+
events: queue,
|
|
8211
|
+
result
|
|
8212
|
+
};
|
|
8213
|
+
};
|
|
8214
|
+
}
|
|
8215
|
+
function defaultIsRetryable(result) {
|
|
8216
|
+
return retryableExitCodes.has(result.exitCode);
|
|
8217
|
+
}
|
|
8218
|
+
function calculateBackoffMs(baseBackoffMs, completedAttempt) {
|
|
8219
|
+
return Math.min(baseBackoffMs * 2 ** (completedAttempt - 1), maxBackoffMs);
|
|
8220
|
+
}
|
|
8221
|
+
function normalizeRetryOptions(retryOptions) {
|
|
8222
|
+
if (!Number.isInteger(retryOptions.maxAttempts) || retryOptions.maxAttempts < 1) {
|
|
8223
|
+
throw new Error("spawn.retry maxAttempts must be an integer greater than or equal to 1.");
|
|
8224
|
+
}
|
|
8225
|
+
if (!Number.isFinite(retryOptions.backoffMs) || retryOptions.backoffMs < 0) {
|
|
8226
|
+
throw new Error("spawn.retry backoffMs must be a non-negative finite number.");
|
|
8227
|
+
}
|
|
8228
|
+
return {
|
|
8229
|
+
maxAttempts: retryOptions.maxAttempts,
|
|
8230
|
+
backoffMs: retryOptions.backoffMs,
|
|
8231
|
+
isRetryable: retryOptions.isRetryable ?? defaultIsRetryable
|
|
8232
|
+
};
|
|
8233
|
+
}
|
|
8234
|
+
async function runRetryingSpawn(input) {
|
|
8235
|
+
for (let attempt = 1; attempt <= input.retryOptions.maxAttempts; attempt += 1) {
|
|
8236
|
+
throwIfAborted4(input.options.signal);
|
|
8237
|
+
const handle = input.spawnOnce(input.service, input.options);
|
|
8238
|
+
const events = forwardAttemptEvents(handle.events, attempt, input.emit);
|
|
8239
|
+
const result = await handle.result;
|
|
8240
|
+
await events;
|
|
8241
|
+
const isLastAttempt = attempt >= input.retryOptions.maxAttempts;
|
|
8242
|
+
if (result.exitCode === 0 || isLastAttempt || !input.retryOptions.isRetryable(result)) {
|
|
8243
|
+
return result;
|
|
8244
|
+
}
|
|
8245
|
+
const delayMs = calculateBackoffMs(input.retryOptions.backoffMs, attempt);
|
|
8246
|
+
input.emit(createWaitEvent(attempt, delayMs));
|
|
8247
|
+
await sleep4(delayMs, input.options.signal);
|
|
8248
|
+
}
|
|
8249
|
+
throw new Error("spawn.retry reached an unreachable retry state.");
|
|
8250
|
+
}
|
|
8251
|
+
async function forwardAttemptEvents(events, attempt, emit) {
|
|
8252
|
+
for await (const event of events) {
|
|
8253
|
+
emit(prefixEvent(event, attempt));
|
|
8254
|
+
}
|
|
8255
|
+
}
|
|
8256
|
+
function prefixEvent(event, attempt) {
|
|
8257
|
+
const prefix = `attempt: ${attempt}`;
|
|
8258
|
+
if (event.event === "agent_message" || event.event === "reasoning") {
|
|
8259
|
+
return { ...event, text: `${prefix} ${event.text}` };
|
|
8260
|
+
}
|
|
8261
|
+
if (event.event === "error") {
|
|
8262
|
+
return { ...event, message: `${prefix} ${event.message}` };
|
|
8263
|
+
}
|
|
8264
|
+
if (event.event === "tool_start") {
|
|
8265
|
+
return { ...event, title: `${prefix} ${event.title}` };
|
|
8266
|
+
}
|
|
8267
|
+
if (event.event === "tool_complete") {
|
|
8268
|
+
return { ...event, path: `${prefix} ${event.path}` };
|
|
8269
|
+
}
|
|
8270
|
+
return {
|
|
8271
|
+
...event,
|
|
8272
|
+
_meta: {
|
|
8273
|
+
...typeof event._meta === "object" && event._meta !== null ? event._meta : {},
|
|
8274
|
+
attempt
|
|
8275
|
+
}
|
|
8276
|
+
};
|
|
8277
|
+
}
|
|
8278
|
+
function createWaitEvent(attempt, delayMs) {
|
|
8279
|
+
return {
|
|
8280
|
+
event: "agent_message",
|
|
8281
|
+
text: `attempt: ${attempt} wait ${delayMs}ms before retry`
|
|
8282
|
+
};
|
|
8283
|
+
}
|
|
8284
|
+
function sleep4(delayMs, signal) {
|
|
8285
|
+
throwIfAborted4(signal);
|
|
8286
|
+
return new Promise((resolve2, reject) => {
|
|
8287
|
+
const timeout = setTimeout(() => {
|
|
8288
|
+
signal?.removeEventListener("abort", onAbort);
|
|
8289
|
+
resolve2();
|
|
8290
|
+
}, delayMs);
|
|
8291
|
+
const onAbort = () => {
|
|
8292
|
+
clearTimeout(timeout);
|
|
8293
|
+
reject(createAbortError4());
|
|
8294
|
+
};
|
|
8295
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
8296
|
+
});
|
|
8297
|
+
}
|
|
8298
|
+
function throwIfAborted4(signal) {
|
|
8299
|
+
if (signal?.aborted) {
|
|
8300
|
+
throw createAbortError4();
|
|
8301
|
+
}
|
|
8302
|
+
}
|
|
8303
|
+
function createAbortError4() {
|
|
8304
|
+
const error2 = new Error("Agent spawn retry aborted");
|
|
8305
|
+
error2.name = "AbortError";
|
|
8306
|
+
return error2;
|
|
8307
|
+
}
|
|
8308
|
+
function createEventQueue() {
|
|
8309
|
+
const values = [];
|
|
8310
|
+
const waiters = [];
|
|
8311
|
+
let closed = false;
|
|
8312
|
+
let failure;
|
|
8313
|
+
const next = () => {
|
|
8314
|
+
if (values.length > 0) {
|
|
8315
|
+
return Promise.resolve({ value: values.shift(), done: false });
|
|
8316
|
+
}
|
|
8317
|
+
if (failure !== void 0) {
|
|
8318
|
+
return Promise.reject(failure);
|
|
8319
|
+
}
|
|
8320
|
+
if (closed) {
|
|
8321
|
+
return Promise.resolve({ value: void 0, done: true });
|
|
8322
|
+
}
|
|
8323
|
+
return new Promise((resolve2, reject) => {
|
|
8324
|
+
waiters.push({ resolve: resolve2, reject });
|
|
8325
|
+
});
|
|
8326
|
+
};
|
|
8327
|
+
return {
|
|
8328
|
+
push(value) {
|
|
8329
|
+
if (closed || failure !== void 0) {
|
|
8330
|
+
return;
|
|
8331
|
+
}
|
|
8332
|
+
const waiter = waiters.shift();
|
|
8333
|
+
if (waiter) {
|
|
8334
|
+
waiter.resolve({ value, done: false });
|
|
8335
|
+
return;
|
|
8336
|
+
}
|
|
8337
|
+
values.push(value);
|
|
8338
|
+
},
|
|
8339
|
+
close() {
|
|
8340
|
+
if (closed || failure !== void 0) {
|
|
8341
|
+
return;
|
|
8342
|
+
}
|
|
8343
|
+
closed = true;
|
|
8344
|
+
for (const waiter of waiters.splice(0)) {
|
|
8345
|
+
waiter.resolve({ value: void 0, done: true });
|
|
8346
|
+
}
|
|
8347
|
+
},
|
|
8348
|
+
fail(error2) {
|
|
8349
|
+
if (closed || failure !== void 0) {
|
|
8350
|
+
return;
|
|
8351
|
+
}
|
|
8352
|
+
failure = error2;
|
|
8353
|
+
for (const waiter of waiters.splice(0)) {
|
|
8354
|
+
waiter.reject(error2);
|
|
8355
|
+
}
|
|
8356
|
+
},
|
|
8357
|
+
async *[Symbol.asyncIterator]() {
|
|
8358
|
+
while (true) {
|
|
8359
|
+
const item = await next();
|
|
8360
|
+
if (item.done) {
|
|
8361
|
+
return;
|
|
8362
|
+
}
|
|
8363
|
+
yield item.value;
|
|
8364
|
+
}
|
|
8365
|
+
}
|
|
8366
|
+
};
|
|
8367
|
+
}
|
|
8368
|
+
|
|
8369
|
+
// packages/agent-spawn/src/skill-bridge.ts
|
|
8370
|
+
import crypto from "node:crypto";
|
|
8371
|
+
import os6 from "node:os";
|
|
8372
|
+
|
|
8373
|
+
// packages/agent-skill-config/src/configs.ts
|
|
8374
|
+
import os5 from "node:os";
|
|
8375
|
+
import path36 from "node:path";
|
|
8376
|
+
var agentSkillConfigs = {
|
|
8377
|
+
"claude-code": {
|
|
8378
|
+
globalSkillDir: "~/.claude/skills",
|
|
8379
|
+
localSkillDir: ".claude/skills"
|
|
8380
|
+
},
|
|
8381
|
+
codex: {
|
|
8382
|
+
globalSkillDir: "~/.codex/skills",
|
|
8383
|
+
localSkillDir: ".codex/skills"
|
|
8384
|
+
},
|
|
8385
|
+
opencode: {
|
|
8386
|
+
globalSkillDir: "~/.config/opencode/skills",
|
|
8387
|
+
localSkillDir: ".opencode/skills"
|
|
8388
|
+
},
|
|
8389
|
+
goose: {
|
|
8390
|
+
globalSkillDir: "~/.agents/skills",
|
|
8391
|
+
localSkillDir: ".agents/skills"
|
|
8392
|
+
}
|
|
8393
|
+
};
|
|
8394
|
+
var supportedAgents2 = Object.keys(agentSkillConfigs);
|
|
8395
|
+
function resolveAgentSupport(input, registry = agentSkillConfigs) {
|
|
8396
|
+
const resolvedId = resolveAgentId(input);
|
|
8397
|
+
if (!resolvedId) {
|
|
8398
|
+
return { status: "unknown", input };
|
|
8399
|
+
}
|
|
8400
|
+
const config = registry[resolvedId];
|
|
8401
|
+
if (!config) {
|
|
8402
|
+
return { status: "unsupported", input, id: resolvedId };
|
|
8403
|
+
}
|
|
8404
|
+
return { status: "supported", input, id: resolvedId, config };
|
|
8405
|
+
}
|
|
8406
|
+
function getAgentConfig(agentId) {
|
|
8407
|
+
const support = resolveAgentSupport(agentId);
|
|
8408
|
+
return support.status === "supported" ? support.config : void 0;
|
|
8409
|
+
}
|
|
8410
|
+
function expandHome2(targetPath, homeDir = os5.homedir()) {
|
|
8411
|
+
if (!targetPath?.startsWith("~")) {
|
|
8412
|
+
return targetPath;
|
|
8413
|
+
}
|
|
8414
|
+
if (targetPath === "~") {
|
|
8415
|
+
return homeDir;
|
|
8416
|
+
}
|
|
8417
|
+
if (targetPath.startsWith("~./")) {
|
|
8418
|
+
targetPath = `~/.${targetPath.slice(3)}`;
|
|
8419
|
+
}
|
|
8420
|
+
let remainder = targetPath.slice(1);
|
|
8421
|
+
if (remainder.startsWith("/") || remainder.startsWith("\\")) {
|
|
8422
|
+
remainder = remainder.slice(1);
|
|
8423
|
+
} else if (remainder.startsWith(".")) {
|
|
8424
|
+
remainder = remainder.slice(1);
|
|
8425
|
+
if (remainder.startsWith("/") || remainder.startsWith("\\")) {
|
|
8426
|
+
remainder = remainder.slice(1);
|
|
8427
|
+
}
|
|
8428
|
+
}
|
|
8429
|
+
return remainder.length === 0 ? homeDir : path36.join(homeDir, remainder);
|
|
8430
|
+
}
|
|
8431
|
+
function resolveSkillDir(config, scope, cwd, homeDir) {
|
|
8432
|
+
if (scope === "global") {
|
|
8433
|
+
return path36.resolve(expandHome2(config.globalSkillDir, homeDir));
|
|
8434
|
+
}
|
|
8435
|
+
return path36.resolve(cwd, config.localSkillDir);
|
|
8436
|
+
}
|
|
8437
|
+
|
|
8438
|
+
// packages/agent-skill-config/src/templates.ts
|
|
8439
|
+
import { readFile as readFile13, stat as stat5 } from "node:fs/promises";
|
|
8440
|
+
import path37 from "node:path";
|
|
8441
|
+
import { fileURLToPath } from "node:url";
|
|
8442
|
+
|
|
8443
|
+
// packages/agent-skill-config/src/apply.ts
|
|
8444
|
+
var UnsupportedAgentError = class extends Error {
|
|
8445
|
+
constructor(agentId) {
|
|
8446
|
+
super(`Unsupported agent: ${agentId}`);
|
|
8447
|
+
this.name = "UnsupportedAgentError";
|
|
8448
|
+
}
|
|
8449
|
+
};
|
|
8450
|
+
function toHomeRelative(localSkillDir) {
|
|
8451
|
+
if (localSkillDir.startsWith("~/") || localSkillDir === "~") {
|
|
8452
|
+
return localSkillDir;
|
|
8453
|
+
}
|
|
8454
|
+
const normalized = localSkillDir.startsWith("./") ? localSkillDir.slice(2) : localSkillDir;
|
|
8455
|
+
return `~/${normalized}`;
|
|
8456
|
+
}
|
|
8457
|
+
var SKILL_TEMPLATE_ID = "__skill_content__";
|
|
8458
|
+
async function installSkill(agentId, skill, options) {
|
|
8459
|
+
const support = resolveAgentSupport(agentId);
|
|
8460
|
+
if (support.status !== "supported") {
|
|
8461
|
+
throw new UnsupportedAgentError(agentId);
|
|
8462
|
+
}
|
|
8463
|
+
const scope = options.scope ?? "local";
|
|
8464
|
+
const config = support.config;
|
|
8465
|
+
const skillDir = scope === "global" ? config.globalSkillDir : toHomeRelative(config.localSkillDir);
|
|
8466
|
+
const skillFolderPath = `${skillDir}/${skill.name}`;
|
|
8467
|
+
const skillFilePath = `${skillFolderPath}/SKILL.md`;
|
|
8468
|
+
const displayPath = `${scope === "global" ? config.globalSkillDir : config.localSkillDir}/${skill.name}/SKILL.md`;
|
|
8469
|
+
await runMutations(
|
|
8470
|
+
[
|
|
8471
|
+
fileMutation.ensureDirectory({
|
|
8472
|
+
path: skillFolderPath,
|
|
8473
|
+
label: `Ensure skill directory ${skill.name}`
|
|
8474
|
+
}),
|
|
8475
|
+
templateMutation.write({
|
|
8476
|
+
target: skillFilePath,
|
|
8477
|
+
templateId: SKILL_TEMPLATE_ID,
|
|
8478
|
+
label: `Write skill ${skill.name}`
|
|
8479
|
+
})
|
|
8480
|
+
],
|
|
8481
|
+
{
|
|
8482
|
+
fs: options.fs,
|
|
8483
|
+
homeDir: scope === "global" ? options.homeDir : options.cwd,
|
|
8484
|
+
dryRun: options.dryRun,
|
|
8485
|
+
observers: options.observers,
|
|
8486
|
+
templates: async (templateId) => {
|
|
8487
|
+
if (templateId === SKILL_TEMPLATE_ID) {
|
|
8488
|
+
return skill.content;
|
|
8489
|
+
}
|
|
8490
|
+
throw new Error(`Unknown template: ${templateId}`);
|
|
8491
|
+
}
|
|
8492
|
+
}
|
|
8493
|
+
);
|
|
8494
|
+
return { skillPath: skillFilePath, displayPath };
|
|
8495
|
+
}
|
|
8496
|
+
|
|
8497
|
+
// packages/agent-skill-config/src/resolve-skill-reference.ts
|
|
8498
|
+
import { statSync } from "node:fs";
|
|
8499
|
+
import path38 from "node:path";
|
|
8500
|
+
function isMalformedSegment(segment) {
|
|
8501
|
+
return segment.length === 0 || segment !== segment.trim();
|
|
8502
|
+
}
|
|
8503
|
+
function isDirectory(targetPath) {
|
|
8504
|
+
try {
|
|
8505
|
+
return statSync(targetPath).isDirectory();
|
|
8506
|
+
} catch {
|
|
8507
|
+
return false;
|
|
8508
|
+
}
|
|
8509
|
+
}
|
|
8510
|
+
function findSkill(ref, name, tiers, sourceAgentId) {
|
|
8511
|
+
for (const tier of tiers) {
|
|
8512
|
+
if (isDirectory(tier.sourcePath)) {
|
|
8513
|
+
return {
|
|
8514
|
+
kind: "resolved",
|
|
8515
|
+
ref,
|
|
8516
|
+
name,
|
|
8517
|
+
...sourceAgentId ? { sourceAgentId } : {},
|
|
8518
|
+
sourcePath: tier.sourcePath,
|
|
8519
|
+
scope: tier.scope
|
|
8520
|
+
};
|
|
8521
|
+
}
|
|
8522
|
+
}
|
|
8523
|
+
return {
|
|
8524
|
+
kind: "not-found",
|
|
8525
|
+
ref,
|
|
8526
|
+
searchedPaths: tiers.map((tier) => tier.sourcePath)
|
|
8527
|
+
};
|
|
8528
|
+
}
|
|
8529
|
+
function resolveSkillReference(ref, cwd, homeDir) {
|
|
8530
|
+
const slashIndex = ref.indexOf("/");
|
|
8531
|
+
const hasPrefix = slashIndex !== -1;
|
|
8532
|
+
if (ref.length === 0 || ref !== ref.trim() || hasPrefix && ref.indexOf("/", slashIndex + 1) !== -1) {
|
|
8533
|
+
return { kind: "malformed", ref };
|
|
8534
|
+
}
|
|
8535
|
+
if (!hasPrefix) {
|
|
8536
|
+
if (isMalformedSegment(ref)) {
|
|
8537
|
+
return { kind: "malformed", ref };
|
|
8538
|
+
}
|
|
8539
|
+
const tiers2 = [
|
|
8540
|
+
{
|
|
8541
|
+
scope: "project",
|
|
8542
|
+
sourcePath: path38.resolve(cwd, ".poe-code/skills", ref)
|
|
8543
|
+
},
|
|
8544
|
+
{
|
|
8545
|
+
scope: "user",
|
|
8546
|
+
sourcePath: path38.resolve(homeDir, ".poe-code/skills", ref)
|
|
8547
|
+
}
|
|
8548
|
+
];
|
|
8549
|
+
return findSkill(ref, ref, tiers2);
|
|
8550
|
+
}
|
|
8551
|
+
const agentInput = ref.slice(0, slashIndex);
|
|
8552
|
+
const name = ref.slice(slashIndex + 1);
|
|
8553
|
+
if (isMalformedSegment(agentInput) || isMalformedSegment(name)) {
|
|
8554
|
+
return { kind: "malformed", ref };
|
|
8555
|
+
}
|
|
8556
|
+
const support = resolveAgentSupport(agentInput);
|
|
8557
|
+
if (support.status !== "supported" || !support.id) {
|
|
8558
|
+
return { kind: "unknown-agent", ref, agentInput };
|
|
8559
|
+
}
|
|
8560
|
+
const config = getAgentConfig(support.id);
|
|
8561
|
+
if (!config) {
|
|
8562
|
+
return { kind: "unknown-agent", ref, agentInput };
|
|
8563
|
+
}
|
|
8564
|
+
const tiers = [
|
|
8565
|
+
{
|
|
8566
|
+
scope: "project",
|
|
8567
|
+
sourcePath: path38.resolve(resolveSkillDir(config, "local", cwd), name)
|
|
8568
|
+
},
|
|
8569
|
+
{
|
|
8570
|
+
scope: "user",
|
|
8571
|
+
sourcePath: path38.resolve(resolveSkillDir(config, "global", cwd, homeDir), name)
|
|
8572
|
+
}
|
|
8573
|
+
];
|
|
8574
|
+
return findSkill(ref, name, tiers, support.id);
|
|
8575
|
+
}
|
|
8576
|
+
|
|
8577
|
+
// packages/agent-skill-config/src/git-exclude.ts
|
|
8578
|
+
import { execFileSync } from "node:child_process";
|
|
8579
|
+
import * as fs10 from "node:fs";
|
|
8580
|
+
import path39 from "node:path";
|
|
8581
|
+
var markerPrefix = "# poe-code-spawn-skills:";
|
|
8582
|
+
function defaultGitDirRunner(cwd) {
|
|
8583
|
+
try {
|
|
8584
|
+
return execFileSync("git", ["rev-parse", "--git-dir"], {
|
|
8585
|
+
cwd,
|
|
8586
|
+
encoding: "utf8",
|
|
8587
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
8588
|
+
}).trim();
|
|
8589
|
+
} catch {
|
|
8590
|
+
return void 0;
|
|
8591
|
+
}
|
|
8592
|
+
}
|
|
8593
|
+
var gitDirRunner = defaultGitDirRunner;
|
|
8594
|
+
function resolveExcludePath(cwd) {
|
|
8595
|
+
const gitDir = gitDirRunner(cwd);
|
|
8596
|
+
if (gitDir === void 0 || gitDir.length === 0) {
|
|
8597
|
+
return void 0;
|
|
8598
|
+
}
|
|
8599
|
+
return path39.join(path39.isAbsolute(gitDir) ? gitDir : path39.resolve(cwd, gitDir), "info/exclude");
|
|
8600
|
+
}
|
|
8601
|
+
function markers(runId) {
|
|
8602
|
+
return {
|
|
8603
|
+
begin: `${markerPrefix}${runId} begin`,
|
|
8604
|
+
end: `${markerPrefix}${runId} end`
|
|
8605
|
+
};
|
|
8606
|
+
}
|
|
8607
|
+
function readExcludeFile(excludePath) {
|
|
8608
|
+
try {
|
|
8609
|
+
return fs10.readFileSync(excludePath, "utf8");
|
|
8610
|
+
} catch (error2) {
|
|
8611
|
+
if (isNodeError2(error2) && error2.code === "ENOENT") {
|
|
8612
|
+
return void 0;
|
|
8613
|
+
}
|
|
8614
|
+
throw error2;
|
|
8615
|
+
}
|
|
8616
|
+
}
|
|
8617
|
+
function isNodeError2(error2) {
|
|
8618
|
+
return error2 instanceof Error && "code" in error2;
|
|
8619
|
+
}
|
|
8620
|
+
function removeBlock(content, runId) {
|
|
8621
|
+
const { begin, end } = markers(runId);
|
|
8622
|
+
const lines = content.split("\n");
|
|
8623
|
+
const result = [];
|
|
8624
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
8625
|
+
if (lines[index] === begin) {
|
|
8626
|
+
const endIndex = lines.indexOf(end, index + 1);
|
|
8627
|
+
if (endIndex !== -1) {
|
|
8628
|
+
index = endIndex;
|
|
8629
|
+
continue;
|
|
8630
|
+
}
|
|
8631
|
+
}
|
|
8632
|
+
result.push(lines[index]);
|
|
8633
|
+
}
|
|
8634
|
+
return result.join("\n");
|
|
8635
|
+
}
|
|
8636
|
+
function appendBlock(content, runId, entries) {
|
|
8637
|
+
const { begin, end } = markers(runId);
|
|
8638
|
+
const existing = content ?? "";
|
|
8639
|
+
const prefix = existing.length === 0 || existing.endsWith("\n") ? existing : `${existing}
|
|
8640
|
+
`;
|
|
8641
|
+
return `${prefix}${[begin, ...entries, end, ""].join("\n")}`;
|
|
8642
|
+
}
|
|
8643
|
+
function appendExcludeBlock(cwd, runId, entries) {
|
|
8644
|
+
const excludePath = resolveExcludePath(cwd);
|
|
8645
|
+
if (excludePath === void 0) {
|
|
8646
|
+
return;
|
|
8647
|
+
}
|
|
8648
|
+
fs10.mkdirSync(path39.dirname(excludePath), { recursive: true });
|
|
8649
|
+
const content = readExcludeFile(excludePath);
|
|
8650
|
+
fs10.writeFileSync(excludePath, appendBlock(content, runId, entries), "utf8");
|
|
8651
|
+
}
|
|
8652
|
+
function removeExcludeBlock(cwd, runId) {
|
|
8653
|
+
const excludePath = resolveExcludePath(cwd);
|
|
8654
|
+
if (excludePath === void 0) {
|
|
8655
|
+
return;
|
|
8656
|
+
}
|
|
8657
|
+
const content = readExcludeFile(excludePath);
|
|
8658
|
+
if (content === void 0) {
|
|
8659
|
+
return;
|
|
8660
|
+
}
|
|
8661
|
+
fs10.writeFileSync(excludePath, removeBlock(content, runId), "utf8");
|
|
8662
|
+
}
|
|
8663
|
+
|
|
8664
|
+
// packages/agent-skill-config/src/bridge-active-skills.ts
|
|
8665
|
+
import * as fs11 from "node:fs";
|
|
8666
|
+
import path40 from "node:path";
|
|
8667
|
+
function isNodeError3(error2) {
|
|
8668
|
+
return error2 instanceof Error && "code" in error2;
|
|
8669
|
+
}
|
|
8670
|
+
function pathExists3(targetPath) {
|
|
8671
|
+
try {
|
|
8672
|
+
fs11.statSync(targetPath);
|
|
8673
|
+
return true;
|
|
8674
|
+
} catch (error2) {
|
|
8675
|
+
if (isNodeError3(error2) && error2.code === "ENOENT") {
|
|
8676
|
+
return false;
|
|
8677
|
+
}
|
|
8678
|
+
throw error2;
|
|
8679
|
+
}
|
|
8680
|
+
}
|
|
8681
|
+
function isDirectory2(targetPath) {
|
|
8682
|
+
try {
|
|
8683
|
+
return fs11.statSync(targetPath).isDirectory();
|
|
8684
|
+
} catch (error2) {
|
|
8685
|
+
if (isNodeError3(error2) && error2.code === "ENOENT") {
|
|
8686
|
+
return false;
|
|
8687
|
+
}
|
|
8688
|
+
throw error2;
|
|
8689
|
+
}
|
|
8690
|
+
}
|
|
8691
|
+
function formatResolutionFailureError(failures) {
|
|
8692
|
+
const malformed = failures.filter((failure) => failure.kind === "malformed");
|
|
8693
|
+
const unknownAgent = failures.filter((failure) => failure.kind === "unknown-agent");
|
|
8694
|
+
const notFound = failures.filter((failure) => failure.kind === "not-found");
|
|
8695
|
+
const lines = [
|
|
8696
|
+
`Failed to bridge active skills: ${failures.length} skill reference(s) could not be resolved.`
|
|
8697
|
+
];
|
|
8698
|
+
if (malformed.length > 0) {
|
|
8699
|
+
lines.push("", "Malformed skill references:");
|
|
8700
|
+
for (const failure of malformed) {
|
|
8701
|
+
lines.push(`- ${failure.ref}`);
|
|
8702
|
+
}
|
|
8703
|
+
lines.push('Expected syntax: "<name>" or "<agentId>/<name>".');
|
|
8704
|
+
}
|
|
8705
|
+
if (unknownAgent.length > 0) {
|
|
8706
|
+
lines.push("", "Unknown agent references:");
|
|
8707
|
+
for (const failure of unknownAgent) {
|
|
8708
|
+
lines.push(`- ${failure.ref} (agent token: ${failure.agentInput})`);
|
|
8709
|
+
}
|
|
8710
|
+
lines.push(`Supported agents: ${supportedAgents2.join(", ")}.`);
|
|
8711
|
+
}
|
|
8712
|
+
if (notFound.length > 0) {
|
|
8713
|
+
lines.push("", "Not found skill references.");
|
|
8714
|
+
for (const failure of notFound) {
|
|
8715
|
+
lines.push(`- ${failure.ref}`);
|
|
8716
|
+
lines.push(" searched paths:");
|
|
8717
|
+
for (const searchedPath of failure.searchedPaths) {
|
|
8718
|
+
lines.push(` - ${searchedPath}`);
|
|
8719
|
+
}
|
|
8720
|
+
}
|
|
8721
|
+
}
|
|
8722
|
+
return new Error(lines.join("\n"));
|
|
8723
|
+
}
|
|
8724
|
+
function copyDirectory(sourcePath, targetPath) {
|
|
8725
|
+
fs11.mkdirSync(targetPath, { recursive: true });
|
|
8726
|
+
for (const dirent of fs11.readdirSync(sourcePath, { withFileTypes: true })) {
|
|
8727
|
+
const childSource = path40.join(sourcePath, dirent.name);
|
|
8728
|
+
const childTarget = path40.join(targetPath, dirent.name);
|
|
8729
|
+
if (dirent.isDirectory()) {
|
|
8730
|
+
copyDirectory(childSource, childTarget);
|
|
8731
|
+
continue;
|
|
8732
|
+
}
|
|
8733
|
+
if (dirent.isFile()) {
|
|
8734
|
+
fs11.copyFileSync(childSource, childTarget);
|
|
8735
|
+
}
|
|
8736
|
+
}
|
|
8737
|
+
}
|
|
8738
|
+
function collectMissingParents(targetPath) {
|
|
8739
|
+
const parents = [];
|
|
8740
|
+
let current = path40.dirname(targetPath);
|
|
8741
|
+
while (!pathExists3(current)) {
|
|
8742
|
+
parents.push(current);
|
|
8743
|
+
const parent = path40.dirname(current);
|
|
8744
|
+
if (parent === current) {
|
|
8745
|
+
break;
|
|
8746
|
+
}
|
|
8747
|
+
current = parent;
|
|
8748
|
+
}
|
|
8749
|
+
return parents.reverse();
|
|
8750
|
+
}
|
|
8751
|
+
function removeDirectoryIfEmpty(targetPath) {
|
|
8752
|
+
try {
|
|
8753
|
+
fs11.rmdirSync(targetPath);
|
|
8754
|
+
} catch (error2) {
|
|
8755
|
+
if (isNodeError3(error2) && (error2.code === "ENOENT" || error2.code === "ENOTEMPTY" || error2.code === "EEXIST")) {
|
|
8756
|
+
return;
|
|
8757
|
+
}
|
|
8758
|
+
throw error2;
|
|
8759
|
+
}
|
|
8760
|
+
}
|
|
8761
|
+
function removeTarget(targetPath) {
|
|
8762
|
+
fs11.rmSync(targetPath, { recursive: true, force: true });
|
|
8763
|
+
}
|
|
8764
|
+
function toCwdRelative(cwd, targetPath) {
|
|
8765
|
+
return path40.relative(cwd, targetPath);
|
|
8766
|
+
}
|
|
8767
|
+
function warning(kind, ref, sourcePath, conflictingPath) {
|
|
8768
|
+
const messages = {
|
|
8769
|
+
"intra-batch-collision": `Skipping ${ref}: an earlier bridged skill already targets ${conflictingPath}.`,
|
|
8770
|
+
"local-collision": `Skipping ${ref}: local skill already exists at ${conflictingPath}.`,
|
|
8771
|
+
"global-collision": `Skipping ${ref}: global skill already exists at ${conflictingPath}.`,
|
|
8772
|
+
"self-reference": `Skipping ${ref}: spawning agent already sees this native skill at ${conflictingPath}.`
|
|
8773
|
+
};
|
|
8774
|
+
return {
|
|
8775
|
+
kind,
|
|
8776
|
+
ref,
|
|
8777
|
+
sourcePath,
|
|
8778
|
+
conflictingPath,
|
|
8779
|
+
message: messages[kind]
|
|
8780
|
+
};
|
|
8781
|
+
}
|
|
8782
|
+
function bridgeActiveSkills(spawnAgentId, cwd, refs, homeDir, runId) {
|
|
8783
|
+
const spawnConfig = getAgentConfig(spawnAgentId);
|
|
8784
|
+
const spawnSupport = resolveAgentSupport(spawnAgentId);
|
|
8785
|
+
if (!spawnConfig || spawnSupport.status !== "supported" || !spawnSupport.id) {
|
|
8786
|
+
throw new Error(
|
|
8787
|
+
`Unsupported spawn agent "${spawnAgentId}". Supported agents: ${supportedAgents2.join(", ")}.`
|
|
8788
|
+
);
|
|
8789
|
+
}
|
|
8790
|
+
const targetDir = resolveSkillDir(spawnConfig, "local", cwd);
|
|
8791
|
+
const globalTargetDir = resolveSkillDir(spawnConfig, "global", cwd, homeDir);
|
|
8792
|
+
const resolutions = refs.map((ref) => resolveSkillReference(ref, cwd, homeDir));
|
|
8793
|
+
const failures = resolutions.filter(
|
|
8794
|
+
(resolution) => resolution.kind !== "resolved"
|
|
8795
|
+
);
|
|
8796
|
+
if (failures.length > 0) {
|
|
8797
|
+
throw formatResolutionFailureError(failures);
|
|
8798
|
+
}
|
|
8799
|
+
const sources = resolutions.map((source, index) => ({
|
|
8800
|
+
ref: refs[index],
|
|
8801
|
+
source,
|
|
8802
|
+
targetPath: path40.resolve(targetDir, source.name),
|
|
8803
|
+
globalTargetPath: path40.resolve(globalTargetDir, source.name)
|
|
8804
|
+
}));
|
|
8805
|
+
const entries = [];
|
|
8806
|
+
const warnings = [];
|
|
8807
|
+
const claimedTargets = /* @__PURE__ */ new Set();
|
|
8808
|
+
for (const item of sources) {
|
|
8809
|
+
if (claimedTargets.has(item.targetPath)) {
|
|
8810
|
+
warnings.push(
|
|
8811
|
+
warning("intra-batch-collision", item.ref, item.source.sourcePath, item.targetPath)
|
|
8812
|
+
);
|
|
8813
|
+
continue;
|
|
8814
|
+
}
|
|
8815
|
+
if (item.source.sourceAgentId === spawnSupport.id) {
|
|
8816
|
+
warnings.push(
|
|
8817
|
+
warning("self-reference", item.ref, item.source.sourcePath, item.source.sourcePath)
|
|
8818
|
+
);
|
|
8819
|
+
continue;
|
|
8820
|
+
}
|
|
8821
|
+
if (pathExists3(item.targetPath)) {
|
|
8822
|
+
warnings.push(warning("local-collision", item.ref, item.source.sourcePath, item.targetPath));
|
|
8823
|
+
continue;
|
|
8824
|
+
}
|
|
8825
|
+
if (isDirectory2(item.globalTargetPath)) {
|
|
8826
|
+
warnings.push(
|
|
8827
|
+
warning("global-collision", item.ref, item.source.sourcePath, item.globalTargetPath)
|
|
8828
|
+
);
|
|
8829
|
+
continue;
|
|
8830
|
+
}
|
|
8831
|
+
const createdParents = collectMissingParents(item.targetPath);
|
|
8832
|
+
fs11.mkdirSync(path40.dirname(item.targetPath), { recursive: true });
|
|
8833
|
+
copyDirectory(item.source.sourcePath, item.targetPath);
|
|
8834
|
+
claimedTargets.add(item.targetPath);
|
|
8835
|
+
entries.push({
|
|
8836
|
+
ref: item.ref,
|
|
8837
|
+
sourcePath: item.source.sourcePath,
|
|
8838
|
+
targetPath: item.targetPath,
|
|
8839
|
+
createdParents
|
|
8840
|
+
});
|
|
8841
|
+
}
|
|
8842
|
+
if (entries.length > 0) {
|
|
8843
|
+
appendExcludeBlock(
|
|
8844
|
+
cwd,
|
|
8845
|
+
runId,
|
|
8846
|
+
entries.map((entry) => toCwdRelative(cwd, entry.targetPath))
|
|
8847
|
+
);
|
|
8848
|
+
}
|
|
8849
|
+
return {
|
|
8850
|
+
spawnAgentId,
|
|
8851
|
+
cwd,
|
|
8852
|
+
runId,
|
|
8853
|
+
entries,
|
|
8854
|
+
warnings
|
|
8855
|
+
};
|
|
8856
|
+
}
|
|
8857
|
+
function cleanupBridgedSkills(manifest) {
|
|
8858
|
+
for (const entry of manifest.entries) {
|
|
8859
|
+
removeTarget(entry.targetPath);
|
|
8860
|
+
for (const parent of [...entry.createdParents].reverse()) {
|
|
8861
|
+
removeDirectoryIfEmpty(parent);
|
|
8862
|
+
}
|
|
8863
|
+
}
|
|
8864
|
+
removeExcludeBlock(manifest.cwd, manifest.runId);
|
|
8865
|
+
}
|
|
8866
|
+
|
|
8867
|
+
// packages/agent-spawn/src/skill-bridge.ts
|
|
8868
|
+
function bridgeSkillsForRun(agentId, cwd, skills) {
|
|
8869
|
+
if (!skills || skills.length === 0) {
|
|
8870
|
+
return void 0;
|
|
8871
|
+
}
|
|
8872
|
+
const manifest = bridgeActiveSkills(agentId, cwd, skills, os6.homedir(), crypto.randomUUID());
|
|
8873
|
+
for (const warning2 of manifest.warnings) {
|
|
8874
|
+
logger.warn(warning2.message);
|
|
8875
|
+
}
|
|
8876
|
+
return manifest;
|
|
8877
|
+
}
|
|
8878
|
+
function cleanupSkillsForRun(manifest) {
|
|
8879
|
+
if (!manifest) {
|
|
8880
|
+
return;
|
|
8881
|
+
}
|
|
8882
|
+
cleanupBridgedSkills(manifest);
|
|
8883
|
+
}
|
|
8884
|
+
|
|
8885
|
+
// packages/agent-spawn/src/adapters/utils.ts
|
|
8886
|
+
function truncate(text5, maxLength) {
|
|
8887
|
+
if (text5.length <= maxLength) return text5;
|
|
8888
|
+
if (maxLength <= 3) return text5.slice(0, maxLength);
|
|
8889
|
+
return `${text5.slice(0, maxLength - 3)}...`;
|
|
8890
|
+
}
|
|
8891
|
+
function isNonEmptyString(value) {
|
|
8892
|
+
return typeof value === "string" && value.length > 0;
|
|
8893
|
+
}
|
|
8894
|
+
function extractThreadId(value) {
|
|
8895
|
+
if (!value || typeof value !== "object") return;
|
|
8896
|
+
const obj = value;
|
|
8897
|
+
const maybeThreadId = isNonEmptyString(obj.thread_id) && obj.thread_id || isNonEmptyString(obj.threadId) && obj.threadId || isNonEmptyString(obj.threadID) && obj.threadID || isNonEmptyString(obj.session_id) && obj.session_id || isNonEmptyString(obj.sessionId) && obj.sessionId || isNonEmptyString(obj.sessionID) && obj.sessionID;
|
|
8898
|
+
return maybeThreadId || void 0;
|
|
8899
|
+
}
|
|
8900
|
+
|
|
8901
|
+
// packages/agent-spawn/src/adapters/claude.ts
|
|
8902
|
+
var TOOL_KIND_MAP = {
|
|
8903
|
+
Read: "read",
|
|
8904
|
+
Write: "edit",
|
|
8905
|
+
Edit: "edit",
|
|
8906
|
+
NotebookEdit: "edit",
|
|
8907
|
+
Bash: "exec",
|
|
8908
|
+
Glob: "search",
|
|
8909
|
+
Grep: "search",
|
|
8910
|
+
Task: "think"
|
|
8911
|
+
};
|
|
8912
|
+
var TITLE_KEYS = {
|
|
8913
|
+
Bash: ["command"],
|
|
8914
|
+
Read: ["file_path"],
|
|
8915
|
+
Write: ["file_path"],
|
|
8916
|
+
Edit: ["file_path"],
|
|
8917
|
+
NotebookEdit: ["notebook_path"],
|
|
8918
|
+
Glob: ["pattern"],
|
|
8919
|
+
Grep: ["pattern"],
|
|
8920
|
+
Task: ["description", "prompt"]
|
|
8921
|
+
};
|
|
8922
|
+
function extractTitle(name, input) {
|
|
8923
|
+
const keys = TITLE_KEYS[name];
|
|
8924
|
+
if (keys && input && typeof input === "object") {
|
|
8925
|
+
const obj = input;
|
|
8926
|
+
for (const key of keys) {
|
|
8927
|
+
const value = obj[key];
|
|
8928
|
+
if (typeof value === "string" && value.length > 0) {
|
|
8929
|
+
return truncate(value, 80);
|
|
8930
|
+
}
|
|
8931
|
+
}
|
|
8932
|
+
}
|
|
8933
|
+
return name;
|
|
8934
|
+
}
|
|
8935
|
+
async function* adaptClaude(lines) {
|
|
8936
|
+
const toolKindsById = /* @__PURE__ */ new Map();
|
|
8937
|
+
let emittedSessionStart = false;
|
|
8938
|
+
for await (const rawLine of lines) {
|
|
8939
|
+
const line = rawLine.trim();
|
|
8940
|
+
if (!line) continue;
|
|
8941
|
+
const firstChar = line[0];
|
|
8942
|
+
if (firstChar !== "{" && firstChar !== "[") {
|
|
8943
|
+
continue;
|
|
8944
|
+
}
|
|
8945
|
+
let event;
|
|
8946
|
+
try {
|
|
8947
|
+
event = JSON.parse(line);
|
|
8948
|
+
} catch (error2) {
|
|
8949
|
+
const stack = error2 instanceof Error ? error2.stack : void 0;
|
|
8950
|
+
yield {
|
|
8951
|
+
event: "error",
|
|
8952
|
+
message: `[adaptClaude] Malformed JSON line: ${truncate(line, 200)}`,
|
|
8953
|
+
stack
|
|
8954
|
+
};
|
|
8955
|
+
continue;
|
|
8956
|
+
}
|
|
8957
|
+
const eventType = event.type;
|
|
8958
|
+
if (!isNonEmptyString(eventType)) continue;
|
|
8959
|
+
if (!emittedSessionStart) {
|
|
8960
|
+
const threadId = extractThreadId(event);
|
|
8961
|
+
emittedSessionStart = true;
|
|
8962
|
+
yield { event: "session_start", threadId };
|
|
8963
|
+
}
|
|
8964
|
+
if (eventType === "result") {
|
|
8965
|
+
const usage = event.usage ?? {};
|
|
8966
|
+
const inputTokens = typeof usage.input_tokens === "number" ? usage.input_tokens : typeof event.input_tokens === "number" ? event.input_tokens : typeof event.num_input_tokens === "number" ? event.num_input_tokens : 0;
|
|
8967
|
+
const outputTokens = typeof usage.output_tokens === "number" ? usage.output_tokens : typeof event.output_tokens === "number" ? event.output_tokens : typeof event.num_output_tokens === "number" ? event.num_output_tokens : 0;
|
|
8968
|
+
const costUsd = typeof usage.cost_usd === "number" ? usage.cost_usd : typeof event.cost_usd === "number" ? event.cost_usd : void 0;
|
|
8969
|
+
yield { event: "usage", inputTokens, outputTokens, costUsd };
|
|
8970
|
+
continue;
|
|
8971
|
+
}
|
|
8972
|
+
if (eventType !== "assistant" && eventType !== "user") continue;
|
|
8973
|
+
const message2 = event.message ?? null;
|
|
8974
|
+
if (!message2 || typeof message2 !== "object") continue;
|
|
8975
|
+
const content = message2.content ?? null;
|
|
8976
|
+
if (!Array.isArray(content)) continue;
|
|
8977
|
+
for (const block of content) {
|
|
8978
|
+
const item = block;
|
|
8979
|
+
if (!item || typeof item !== "object") continue;
|
|
8980
|
+
const blockType = item.type;
|
|
8981
|
+
if (!isNonEmptyString(blockType)) continue;
|
|
8982
|
+
if (eventType === "assistant") {
|
|
8983
|
+
if (blockType === "text" && isNonEmptyString(item.text)) {
|
|
8984
|
+
yield {
|
|
8985
|
+
event: "agent_message",
|
|
8986
|
+
text: item.text
|
|
8987
|
+
};
|
|
8988
|
+
continue;
|
|
8989
|
+
}
|
|
8990
|
+
if (blockType === "tool_use" && isNonEmptyString(item.id) && isNonEmptyString(item.name)) {
|
|
8991
|
+
const kind = TOOL_KIND_MAP[item.name] ?? "other";
|
|
8992
|
+
toolKindsById.set(item.id, kind);
|
|
8993
|
+
yield {
|
|
8994
|
+
event: "tool_start",
|
|
8995
|
+
id: item.id,
|
|
8996
|
+
kind,
|
|
8997
|
+
title: extractTitle(item.name, item.input),
|
|
8998
|
+
input: item.input
|
|
8999
|
+
};
|
|
9000
|
+
}
|
|
9001
|
+
continue;
|
|
9002
|
+
}
|
|
9003
|
+
if (eventType === "user") {
|
|
9004
|
+
if (!isNonEmptyString(item.tool_use_id)) continue;
|
|
9005
|
+
if (blockType !== "tool_result") continue;
|
|
9006
|
+
const kind = toolKindsById.get(item.tool_use_id);
|
|
9007
|
+
toolKindsById.delete(item.tool_use_id);
|
|
9008
|
+
let path50;
|
|
9009
|
+
if (typeof item.content === "string") {
|
|
9010
|
+
path50 = item.content;
|
|
9011
|
+
} else {
|
|
9012
|
+
try {
|
|
9013
|
+
path50 = JSON.stringify(item.content);
|
|
9014
|
+
} catch {
|
|
9015
|
+
path50 = String(item.content);
|
|
9016
|
+
}
|
|
9017
|
+
}
|
|
9018
|
+
yield {
|
|
9019
|
+
event: "tool_complete",
|
|
9020
|
+
id: item.tool_use_id,
|
|
9021
|
+
kind,
|
|
9022
|
+
path: path50
|
|
9023
|
+
};
|
|
9024
|
+
}
|
|
9025
|
+
}
|
|
9026
|
+
}
|
|
9027
|
+
}
|
|
9028
|
+
|
|
9029
|
+
// packages/agent-spawn/src/adapters/codex.ts
|
|
9030
|
+
async function* adaptCodex(lines) {
|
|
9031
|
+
const toolTitleById = /* @__PURE__ */ new Map();
|
|
9032
|
+
const toolKindById = /* @__PURE__ */ new Map();
|
|
9033
|
+
for await (const rawLine of lines) {
|
|
9034
|
+
const line = rawLine.trim();
|
|
9035
|
+
if (!line) continue;
|
|
9036
|
+
let event;
|
|
9037
|
+
try {
|
|
9038
|
+
event = JSON.parse(line);
|
|
9039
|
+
} catch (error2) {
|
|
9040
|
+
const stack = error2 instanceof Error ? error2.stack : void 0;
|
|
9041
|
+
yield {
|
|
9042
|
+
event: "error",
|
|
9043
|
+
message: `[adaptCodex] Malformed JSON line: ${truncate(line, 200)}`,
|
|
9044
|
+
stack
|
|
9045
|
+
};
|
|
9046
|
+
continue;
|
|
9047
|
+
}
|
|
9048
|
+
const eventType = event.type;
|
|
9049
|
+
if (!isNonEmptyString(eventType)) continue;
|
|
9050
|
+
if (eventType === "thread.started") {
|
|
9051
|
+
const maybeThreadId = extractThreadId(event);
|
|
9052
|
+
yield { event: "session_start", threadId: maybeThreadId };
|
|
9053
|
+
continue;
|
|
9054
|
+
}
|
|
9055
|
+
if (eventType === "turn.started") {
|
|
9056
|
+
continue;
|
|
9057
|
+
}
|
|
9058
|
+
if (eventType === "turn.completed") {
|
|
9059
|
+
const usage = event.usage ?? {};
|
|
9060
|
+
const inputTokens = typeof usage.input_tokens === "number" ? usage.input_tokens : 0;
|
|
9061
|
+
const outputTokens = typeof usage.output_tokens === "number" ? usage.output_tokens : 0;
|
|
9062
|
+
const cachedTokens = typeof usage.cached_input_tokens === "number" ? usage.cached_input_tokens : 0;
|
|
9063
|
+
yield { event: "usage", inputTokens, outputTokens, cachedTokens };
|
|
9064
|
+
continue;
|
|
9065
|
+
}
|
|
9066
|
+
if (eventType === "turn.failed") {
|
|
9067
|
+
const message2 = extractErrorMessage(event) ?? "Turn failed";
|
|
9068
|
+
yield { event: "error", message: message2 };
|
|
9069
|
+
continue;
|
|
9070
|
+
}
|
|
9071
|
+
const item = event.item ?? null;
|
|
9072
|
+
if (!item || typeof item !== "object") continue;
|
|
9073
|
+
const itemType = item.type;
|
|
9074
|
+
if (!isNonEmptyString(itemType)) continue;
|
|
9075
|
+
if (eventType === "item.started") {
|
|
9076
|
+
if (!isNonEmptyString(item.id)) continue;
|
|
9077
|
+
let kind;
|
|
9078
|
+
let title;
|
|
9079
|
+
if (itemType === "command_execution") {
|
|
9080
|
+
kind = "exec";
|
|
9081
|
+
title = truncate(isNonEmptyString(item.command) ? item.command : "", 80);
|
|
9082
|
+
} else if (itemType === "file_edit") {
|
|
9083
|
+
kind = "edit";
|
|
9084
|
+
title = isNonEmptyString(item.path) ? item.path : "";
|
|
9085
|
+
} else if (itemType === "thinking") {
|
|
9086
|
+
kind = "think";
|
|
9087
|
+
title = "thinking...";
|
|
9088
|
+
} else if (itemType === "mcp_tool_call") {
|
|
9089
|
+
const server = isNonEmptyString(item.server) ? item.server : "unknown";
|
|
9090
|
+
const tool = isNonEmptyString(item.tool) ? item.tool : "unknown";
|
|
9091
|
+
kind = "other";
|
|
9092
|
+
title = `${server}.${tool}`;
|
|
9093
|
+
}
|
|
9094
|
+
if (kind && title !== void 0) {
|
|
9095
|
+
toolTitleById.set(item.id, title);
|
|
9096
|
+
toolKindById.set(item.id, kind);
|
|
9097
|
+
yield { event: "tool_start", id: item.id, kind, title };
|
|
9098
|
+
}
|
|
9099
|
+
continue;
|
|
9100
|
+
}
|
|
9101
|
+
if (eventType === "item.completed") {
|
|
9102
|
+
if (itemType === "agent_message") {
|
|
9103
|
+
if (!isNonEmptyString(item.text)) continue;
|
|
9104
|
+
yield { event: "agent_message", text: item.text };
|
|
9105
|
+
continue;
|
|
9106
|
+
}
|
|
9107
|
+
if (itemType === "reasoning") {
|
|
9108
|
+
const text5 = isNonEmptyString(item.text) ? item.text : isNonEmptyString(item.content) ? item.content : isNonEmptyString(item.summary) ? item.summary : void 0;
|
|
9109
|
+
if (!text5) continue;
|
|
9110
|
+
yield { event: "reasoning", text: text5 };
|
|
9111
|
+
continue;
|
|
9112
|
+
}
|
|
9113
|
+
if (!isNonEmptyString(item.id)) continue;
|
|
9114
|
+
if (itemType === "command_execution" || itemType === "file_edit" || itemType === "mcp_tool_call") {
|
|
9115
|
+
const kindFromStart = toolKindById.get(item.id);
|
|
9116
|
+
const kind = kindFromStart ?? (itemType === "command_execution" ? "exec" : itemType === "file_edit" ? "edit" : "other");
|
|
9117
|
+
const titleFromEvent = isNonEmptyString(item.path) ? item.path : itemType === "mcp_tool_call" ? `${isNonEmptyString(item.server) ? item.server : "unknown"}.${isNonEmptyString(item.tool) ? item.tool : "unknown"}` : void 0;
|
|
9118
|
+
const path50 = titleFromEvent ?? toolTitleById.get(item.id) ?? "";
|
|
9119
|
+
toolTitleById.delete(item.id);
|
|
9120
|
+
toolKindById.delete(item.id);
|
|
9121
|
+
yield { event: "tool_complete", id: item.id, kind, path: path50 };
|
|
9122
|
+
}
|
|
9123
|
+
}
|
|
9124
|
+
}
|
|
9125
|
+
}
|
|
9126
|
+
function extractErrorMessage(event) {
|
|
9127
|
+
if (isNonEmptyString(event.message)) return event.message;
|
|
9128
|
+
const error2 = event.error;
|
|
9129
|
+
if (isNonEmptyString(error2)) return error2;
|
|
9130
|
+
if (typeof error2 === "object" && error2 !== null) {
|
|
9131
|
+
const errorObj = error2;
|
|
9132
|
+
if (isNonEmptyString(errorObj.message)) return errorObj.message;
|
|
9133
|
+
}
|
|
9134
|
+
if (isNonEmptyString(event.reason)) return event.reason;
|
|
9135
|
+
return void 0;
|
|
9136
|
+
}
|
|
9137
|
+
|
|
9138
|
+
// packages/agent-spawn/src/adapters/kimi.ts
|
|
9139
|
+
async function* adaptKimi(lines) {
|
|
9140
|
+
let emittedSessionStart = false;
|
|
9141
|
+
for await (const rawLine of lines) {
|
|
9142
|
+
const line = rawLine.trim();
|
|
9143
|
+
if (!line) continue;
|
|
9144
|
+
let event;
|
|
9145
|
+
try {
|
|
9146
|
+
event = JSON.parse(line);
|
|
9147
|
+
} catch (error2) {
|
|
9148
|
+
const stack = error2 instanceof Error ? error2.stack : void 0;
|
|
9149
|
+
yield {
|
|
9150
|
+
event: "error",
|
|
9151
|
+
message: `[adaptKimi] Malformed JSON line: ${truncate(line, 200)}`,
|
|
9152
|
+
stack
|
|
9153
|
+
};
|
|
9154
|
+
continue;
|
|
9155
|
+
}
|
|
9156
|
+
if (!event || typeof event !== "object") continue;
|
|
9157
|
+
if (!emittedSessionStart) {
|
|
9158
|
+
const threadId = extractThreadId(event);
|
|
9159
|
+
if (threadId) {
|
|
9160
|
+
emittedSessionStart = true;
|
|
9161
|
+
yield { event: "session_start", threadId };
|
|
9162
|
+
}
|
|
9163
|
+
}
|
|
9164
|
+
const role = event.role;
|
|
9165
|
+
if (!isNonEmptyString(role) || role !== "assistant") continue;
|
|
9166
|
+
const content = event.content;
|
|
9167
|
+
if (!isNonEmptyString(content)) continue;
|
|
9168
|
+
yield { event: "agent_message", text: content };
|
|
9169
|
+
}
|
|
9170
|
+
}
|
|
9171
|
+
|
|
9172
|
+
// packages/agent-spawn/src/adapters/native.ts
|
|
9173
|
+
async function* adaptNative(lines) {
|
|
9174
|
+
for await (const rawLine of lines) {
|
|
9175
|
+
const line = rawLine.trim();
|
|
9176
|
+
if (!line) continue;
|
|
9177
|
+
let event;
|
|
9178
|
+
try {
|
|
9179
|
+
event = JSON.parse(line);
|
|
9180
|
+
} catch (error2) {
|
|
9181
|
+
const stack = error2 instanceof Error ? error2.stack : void 0;
|
|
9182
|
+
yield {
|
|
9183
|
+
event: "error",
|
|
9184
|
+
message: `[adaptNative] Malformed JSON line: ${truncate(line, 200)}`,
|
|
9185
|
+
stack
|
|
9186
|
+
};
|
|
9187
|
+
continue;
|
|
9188
|
+
}
|
|
9189
|
+
const maybeEventType = event?.event;
|
|
9190
|
+
if (!isNonEmptyString(maybeEventType)) {
|
|
9191
|
+
yield {
|
|
9192
|
+
event: "error",
|
|
9193
|
+
message: `[adaptNative] Line missing string "event" field: ${truncate(line, 200)}`
|
|
9194
|
+
};
|
|
9195
|
+
continue;
|
|
9196
|
+
}
|
|
9197
|
+
yield event;
|
|
9198
|
+
}
|
|
9199
|
+
}
|
|
9200
|
+
|
|
9201
|
+
// packages/agent-spawn/src/adapters/opencode.ts
|
|
9202
|
+
function guessToolKind(toolName) {
|
|
9203
|
+
const normalized = toolName.toLowerCase();
|
|
9204
|
+
if (normalized === "bash" || normalized === "shell" || normalized === "sh") return "exec";
|
|
9205
|
+
if (normalized.includes("read")) return "read";
|
|
9206
|
+
if (normalized.includes("write") || normalized.includes("edit") || normalized.includes("patch")) {
|
|
9207
|
+
return "edit";
|
|
9208
|
+
}
|
|
9209
|
+
if (normalized.includes("search") || normalized.includes("grep") || normalized.includes("glob") || normalized.includes("find")) {
|
|
9210
|
+
return "search";
|
|
9211
|
+
}
|
|
9212
|
+
if (normalized.includes("think") || normalized.includes("task")) return "think";
|
|
9213
|
+
return "other";
|
|
9214
|
+
}
|
|
9215
|
+
function safeStringify(value) {
|
|
9216
|
+
if (typeof value === "string") return value;
|
|
9217
|
+
try {
|
|
9218
|
+
return JSON.stringify(value);
|
|
9219
|
+
} catch {
|
|
9220
|
+
return String(value);
|
|
9221
|
+
}
|
|
9222
|
+
}
|
|
9223
|
+
async function* adaptOpenCode(lines) {
|
|
9224
|
+
let emittedSessionStart = false;
|
|
9225
|
+
const toolKindById = /* @__PURE__ */ new Map();
|
|
9226
|
+
for await (const rawLine of lines) {
|
|
9227
|
+
const line = rawLine.trim();
|
|
9228
|
+
if (!line) continue;
|
|
9229
|
+
let event;
|
|
9230
|
+
try {
|
|
9231
|
+
event = JSON.parse(line);
|
|
9232
|
+
} catch (error2) {
|
|
9233
|
+
const stack = error2 instanceof Error ? error2.stack : void 0;
|
|
9234
|
+
yield {
|
|
9235
|
+
event: "error",
|
|
9236
|
+
message: `[adaptOpenCode] Malformed JSON line: ${truncate(line, 200)}`,
|
|
9237
|
+
stack
|
|
9238
|
+
};
|
|
9239
|
+
continue;
|
|
9240
|
+
}
|
|
9241
|
+
if (!event || typeof event !== "object") continue;
|
|
9242
|
+
const sessionID = extractThreadId(event);
|
|
9243
|
+
if (!emittedSessionStart && isNonEmptyString(sessionID)) {
|
|
9244
|
+
emittedSessionStart = true;
|
|
9245
|
+
yield { event: "session_start", threadId: sessionID };
|
|
9246
|
+
}
|
|
9247
|
+
const eventType = event.type;
|
|
9248
|
+
if (!isNonEmptyString(eventType)) continue;
|
|
9249
|
+
if (eventType === "text") {
|
|
9250
|
+
const part = event.part ?? null;
|
|
9251
|
+
if (!part || typeof part !== "object") continue;
|
|
9252
|
+
if (!isNonEmptyString(part.text)) continue;
|
|
9253
|
+
yield { event: "agent_message", text: part.text };
|
|
9254
|
+
continue;
|
|
9255
|
+
}
|
|
9256
|
+
if (eventType === "tool_use") {
|
|
9257
|
+
const part = event.part ?? null;
|
|
9258
|
+
if (!part || typeof part !== "object") continue;
|
|
9259
|
+
if (!isNonEmptyString(part.callID) || !isNonEmptyString(part.tool)) continue;
|
|
9260
|
+
const state = part.state ?? null;
|
|
9261
|
+
if (!state || typeof state !== "object") continue;
|
|
9262
|
+
const kind = guessToolKind(part.tool);
|
|
9263
|
+
const status = state.status;
|
|
9264
|
+
const terminal = status === "completed" || status === "failed";
|
|
9265
|
+
if (!toolKindById.has(part.callID)) {
|
|
9266
|
+
toolKindById.set(part.callID, kind);
|
|
9267
|
+
let title = part.tool;
|
|
9268
|
+
const maybeInput = state.input;
|
|
9269
|
+
if (kind === "exec" && maybeInput && typeof maybeInput === "object") {
|
|
9270
|
+
const command = maybeInput.command;
|
|
9271
|
+
if (isNonEmptyString(command)) {
|
|
9272
|
+
title = truncate(command, 80);
|
|
9273
|
+
}
|
|
9274
|
+
}
|
|
9275
|
+
yield {
|
|
9276
|
+
event: "tool_start",
|
|
9277
|
+
id: part.callID,
|
|
9278
|
+
kind,
|
|
9279
|
+
title,
|
|
9280
|
+
input: state.input
|
|
9281
|
+
};
|
|
9282
|
+
}
|
|
9283
|
+
if (terminal) {
|
|
9284
|
+
const kindFromStart = toolKindById.get(part.callID) ?? kind;
|
|
9285
|
+
toolKindById.delete(part.callID);
|
|
9286
|
+
yield {
|
|
9287
|
+
event: "tool_complete",
|
|
9288
|
+
id: part.callID,
|
|
9289
|
+
kind: kindFromStart,
|
|
9290
|
+
path: safeStringify(state.output)
|
|
9291
|
+
};
|
|
9292
|
+
}
|
|
9293
|
+
continue;
|
|
9294
|
+
}
|
|
9295
|
+
if (eventType === "step_finish") {
|
|
9296
|
+
const part = event.part ?? null;
|
|
9297
|
+
if (!part || typeof part !== "object") continue;
|
|
9298
|
+
const tokens = part.tokens ?? null;
|
|
9299
|
+
if (!tokens || typeof tokens !== "object") continue;
|
|
9300
|
+
const inputTokens = typeof tokens.input === "number" ? tokens.input : 0;
|
|
9301
|
+
const outputTokens = typeof tokens.output === "number" ? tokens.output : 0;
|
|
9302
|
+
const cache = tokens.cache ?? null;
|
|
9303
|
+
const cachedTokens = cache && typeof cache === "object" && typeof cache.read === "number" ? cache.read : void 0;
|
|
9304
|
+
if (inputTokens === 0 && outputTokens === 0 && cachedTokens === void 0) continue;
|
|
9305
|
+
yield { event: "usage", inputTokens, outputTokens, cachedTokens };
|
|
9306
|
+
continue;
|
|
9307
|
+
}
|
|
9308
|
+
}
|
|
9309
|
+
}
|
|
9310
|
+
|
|
9311
|
+
// packages/agent-spawn/src/adapters/index.ts
|
|
9312
|
+
var adapters = {
|
|
9313
|
+
codex: adaptCodex,
|
|
9314
|
+
claude: adaptClaude,
|
|
9315
|
+
kimi: adaptKimi,
|
|
9316
|
+
native: adaptNative,
|
|
9317
|
+
opencode: adaptOpenCode
|
|
9318
|
+
};
|
|
9319
|
+
function getAdapter(type) {
|
|
9320
|
+
const adapter = adapters[type];
|
|
9321
|
+
if (!adapter) {
|
|
9322
|
+
throw new Error(`Unknown adapter "${String(type)}".`);
|
|
9323
|
+
}
|
|
9324
|
+
return adapter;
|
|
9325
|
+
}
|
|
9326
|
+
|
|
9327
|
+
// packages/agent-spawn/src/acp/meta.ts
|
|
9328
|
+
function stampReceiveTime(event, ts) {
|
|
9329
|
+
if (event === null || typeof event !== "object") {
|
|
9330
|
+
return event;
|
|
9331
|
+
}
|
|
9332
|
+
const target = event;
|
|
9333
|
+
const existing = target._meta;
|
|
9334
|
+
if (existing && typeof existing.ts === "number") {
|
|
9335
|
+
return event;
|
|
9336
|
+
}
|
|
9337
|
+
target._meta = existing ? { ...existing, ts } : { ts };
|
|
9338
|
+
return event;
|
|
9339
|
+
}
|
|
9340
|
+
|
|
9341
|
+
// packages/agent-spawn/src/acp/middleware.ts
|
|
9342
|
+
async function applyMiddlewares(middlewares, ctx) {
|
|
9343
|
+
let index = -1;
|
|
9344
|
+
async function dispatch(position) {
|
|
9345
|
+
if (position <= index) {
|
|
9346
|
+
throw new Error("next() called multiple times");
|
|
9347
|
+
}
|
|
9348
|
+
index = position;
|
|
9349
|
+
if (position === middlewares.length) {
|
|
9350
|
+
return;
|
|
9351
|
+
}
|
|
9352
|
+
const middleware = middlewares[position];
|
|
9353
|
+
if (typeof middleware !== "function") {
|
|
9354
|
+
throw new Error(`Invalid ACP middleware at index ${position}`);
|
|
9355
|
+
}
|
|
9356
|
+
await middleware(ctx, () => dispatch(position + 1));
|
|
9357
|
+
}
|
|
9358
|
+
await dispatch(0);
|
|
9359
|
+
}
|
|
9360
|
+
|
|
9361
|
+
// packages/agent-spawn/src/acp/spawn.ts
|
|
9362
|
+
function createAbortError5() {
|
|
9363
|
+
const error2 = new Error("Agent spawn aborted");
|
|
9364
|
+
error2.name = "AbortError";
|
|
9365
|
+
return error2;
|
|
9366
|
+
}
|
|
9367
|
+
function isAcpEvent(value) {
|
|
9368
|
+
return !!value && typeof value === "object" && "event" in value;
|
|
9369
|
+
}
|
|
9370
|
+
function accumulateUsage(ctx, event) {
|
|
9371
|
+
if (event.event !== "usage") {
|
|
9372
|
+
return;
|
|
9373
|
+
}
|
|
9374
|
+
const usage = event;
|
|
9375
|
+
if (typeof usage.inputTokens === "number" && Number.isFinite(usage.inputTokens)) {
|
|
9376
|
+
ctx.usage.inputTokens += usage.inputTokens;
|
|
9377
|
+
}
|
|
9378
|
+
if (typeof usage.outputTokens === "number" && Number.isFinite(usage.outputTokens)) {
|
|
9379
|
+
ctx.usage.outputTokens += usage.outputTokens;
|
|
9380
|
+
}
|
|
9381
|
+
if (typeof usage.cachedTokens === "number" && Number.isFinite(usage.cachedTokens)) {
|
|
9382
|
+
ctx.usage.cachedTokens = (ctx.usage.cachedTokens ?? 0) + usage.cachedTokens;
|
|
9383
|
+
}
|
|
9384
|
+
if (typeof usage.costUsd === "number" && Number.isFinite(usage.costUsd)) {
|
|
9385
|
+
ctx.usage.costUsd = (ctx.usage.costUsd ?? 0) + usage.costUsd;
|
|
9386
|
+
}
|
|
9387
|
+
}
|
|
9388
|
+
function createLineQueue() {
|
|
9389
|
+
const lines = [];
|
|
9390
|
+
const waiters = [];
|
|
9391
|
+
let pending = "";
|
|
9392
|
+
let closed = false;
|
|
9393
|
+
const emit = (line) => {
|
|
9394
|
+
const waiter = waiters.shift();
|
|
9395
|
+
if (waiter) {
|
|
9396
|
+
waiter.resolve({ done: false, value: line });
|
|
9397
|
+
return;
|
|
9398
|
+
}
|
|
9399
|
+
lines.push(line);
|
|
9400
|
+
};
|
|
9401
|
+
const finishWaiters = () => {
|
|
9402
|
+
while (waiters.length > 0) {
|
|
9403
|
+
const waiter = waiters.shift();
|
|
9404
|
+
waiter.resolve({ done: true, value: void 0 });
|
|
9405
|
+
}
|
|
9406
|
+
};
|
|
9407
|
+
return {
|
|
9408
|
+
push(chunk) {
|
|
9409
|
+
if (closed) return;
|
|
9410
|
+
pending += chunk;
|
|
9411
|
+
let newlineIndex = pending.indexOf("\n");
|
|
9412
|
+
while (newlineIndex !== -1) {
|
|
9413
|
+
const raw = pending.slice(0, newlineIndex);
|
|
9414
|
+
emit(raw.endsWith("\r") ? raw.slice(0, -1) : raw);
|
|
9415
|
+
pending = pending.slice(newlineIndex + 1);
|
|
9416
|
+
newlineIndex = pending.indexOf("\n");
|
|
9417
|
+
}
|
|
9418
|
+
},
|
|
9419
|
+
close() {
|
|
9420
|
+
if (closed) return;
|
|
9421
|
+
if (pending.length > 0) {
|
|
9422
|
+
emit(pending.endsWith("\r") ? pending.slice(0, -1) : pending);
|
|
9423
|
+
pending = "";
|
|
9424
|
+
}
|
|
9425
|
+
closed = true;
|
|
9426
|
+
finishWaiters();
|
|
9427
|
+
},
|
|
9428
|
+
lines() {
|
|
9429
|
+
return {
|
|
9430
|
+
[Symbol.asyncIterator]() {
|
|
9431
|
+
return {
|
|
9432
|
+
next() {
|
|
9433
|
+
if (lines.length > 0) {
|
|
9434
|
+
return Promise.resolve({ done: false, value: lines.shift() });
|
|
9435
|
+
}
|
|
9436
|
+
if (closed) {
|
|
9437
|
+
return Promise.resolve({ done: true, value: void 0 });
|
|
9438
|
+
}
|
|
9439
|
+
return new Promise((resolve2) => {
|
|
9440
|
+
waiters.push({ resolve: resolve2 });
|
|
9441
|
+
});
|
|
9442
|
+
}
|
|
9443
|
+
};
|
|
9444
|
+
}
|
|
9445
|
+
};
|
|
9446
|
+
}
|
|
9447
|
+
};
|
|
9448
|
+
}
|
|
9449
|
+
function getDefaultArgsPosition(config) {
|
|
9450
|
+
return config.defaultArgsPosition ?? "afterPrompt";
|
|
9451
|
+
}
|
|
9452
|
+
function getMcpArgsPosition(config) {
|
|
9453
|
+
if (config.mcpArgsPosition) {
|
|
9454
|
+
return config.mcpArgsPosition;
|
|
9455
|
+
}
|
|
9456
|
+
return config.mcpArgsBeforeCommand ? "beforeCommand" : "afterCommand";
|
|
9457
|
+
}
|
|
9458
|
+
function getResumeArgs(config, options) {
|
|
9459
|
+
if (!options.resumeThreadId) {
|
|
9460
|
+
return [];
|
|
9461
|
+
}
|
|
9462
|
+
if (!config.resume) {
|
|
9463
|
+
throw new Error(`Agent "${config.agentId}" does not support resumeThreadId.`);
|
|
9464
|
+
}
|
|
9465
|
+
return config.resume.args(options.resumeThreadId, options.cwd ?? process.cwd());
|
|
9466
|
+
}
|
|
9467
|
+
function spawnStreaming(options) {
|
|
9468
|
+
if (options.signal?.aborted) {
|
|
9469
|
+
throw createAbortError5();
|
|
9470
|
+
}
|
|
9471
|
+
const { agentId, binaryName, spawnConfig } = resolveConfig(options.agentId);
|
|
9472
|
+
if (spawnConfig === void 0) {
|
|
9473
|
+
throw new Error(`Agent "${agentId}" has no spawn config.`);
|
|
9474
|
+
}
|
|
9475
|
+
if (spawnConfig.kind !== "cli") {
|
|
9476
|
+
throw new Error(`Agent "${agentId}" does not support CLI spawn.`);
|
|
9477
|
+
}
|
|
9478
|
+
if (!binaryName) {
|
|
9479
|
+
throw new Error(`Agent "${agentId}" has no binaryName.`);
|
|
9480
|
+
}
|
|
9481
|
+
const mcpArgs = getMcpArgs(spawnConfig, options.mcpServers);
|
|
9482
|
+
const mcpEnvVars = getMcpEnv(spawnConfig, options.mcpServers);
|
|
9483
|
+
const resumeArgs = getResumeArgs(spawnConfig, options);
|
|
9484
|
+
const defaultArgsPosition = getDefaultArgsPosition(spawnConfig);
|
|
9485
|
+
const mcpArgsPosition = getMcpArgsPosition(spawnConfig);
|
|
9486
|
+
const resumeArgsPosition = spawnConfig.resume?.position ?? "afterPrompt";
|
|
9487
|
+
const args = [];
|
|
9488
|
+
if (mcpArgsPosition === "beforeCommand") {
|
|
9489
|
+
args.push(...mcpArgs);
|
|
9490
|
+
}
|
|
9491
|
+
if (defaultArgsPosition === "beforePrompt") {
|
|
9492
|
+
args.push(...spawnConfig.defaultArgs);
|
|
9493
|
+
}
|
|
9494
|
+
if (mcpArgsPosition === "beforePrompt") {
|
|
9495
|
+
args.push(...mcpArgs);
|
|
9496
|
+
}
|
|
9497
|
+
args.push(spawnConfig.promptFlag);
|
|
9498
|
+
if (resumeArgsPosition === "beforePrompt") {
|
|
9499
|
+
args.push(...resumeArgs);
|
|
9500
|
+
}
|
|
9501
|
+
const useStdin = shouldSendPromptViaStdin(spawnConfig, options);
|
|
9502
|
+
if (!useStdin || !spawnConfig.stdinMode?.omitPrompt) {
|
|
9503
|
+
args.push(options.prompt);
|
|
9504
|
+
}
|
|
9505
|
+
if (options.model && spawnConfig.modelFlag) {
|
|
9506
|
+
let model = spawnConfig.modelStripProviderPrefix ? stripModelNamespace(options.model) : options.model;
|
|
9507
|
+
if (spawnConfig.modelTransform) model = spawnConfig.modelTransform(model);
|
|
9508
|
+
args.push(spawnConfig.modelFlag, model);
|
|
9509
|
+
}
|
|
9510
|
+
if (defaultArgsPosition === "afterPrompt") {
|
|
9511
|
+
args.push(...spawnConfig.defaultArgs);
|
|
9512
|
+
}
|
|
9513
|
+
if (mcpArgsPosition === "afterCommand") {
|
|
9514
|
+
args.push(...mcpArgs);
|
|
9515
|
+
}
|
|
9516
|
+
const modeResolved = resolveModeConfig(spawnConfig.modes[options.mode ?? "yolo"]);
|
|
9517
|
+
args.push(...modeResolved.args);
|
|
9518
|
+
if (useStdin) {
|
|
9519
|
+
args.push(...spawnConfig.stdinMode.extraArgs);
|
|
9520
|
+
}
|
|
9521
|
+
if (options.args && options.args.length > 0) {
|
|
9522
|
+
if (resumeArgsPosition === "afterPrompt") {
|
|
9523
|
+
args.push(...resumeArgs);
|
|
9524
|
+
}
|
|
9525
|
+
args.push(...options.args);
|
|
9526
|
+
} else if (resumeArgsPosition === "afterPrompt") {
|
|
9527
|
+
args.push(...resumeArgs);
|
|
9528
|
+
}
|
|
9529
|
+
const envOverrides = { ...mcpEnvVars, ...modeResolved.env };
|
|
9530
|
+
const processEnv = Object.keys(envOverrides).length > 0 ? { ...process.env, ...envOverrides } : void 0;
|
|
9531
|
+
const cwd = options.cwd ?? process.cwd();
|
|
9532
|
+
const queue = createLineQueue();
|
|
9533
|
+
const argv = [binaryName, ...args];
|
|
9534
|
+
const execution = resolvePoeCommandExecution({
|
|
9535
|
+
cwd,
|
|
9536
|
+
runtimeConfigCwd: options.runtimeConfigCwd,
|
|
9537
|
+
env: processEnv ?? process.env,
|
|
9538
|
+
argv,
|
|
9539
|
+
tool: agentId,
|
|
9540
|
+
runtime: {
|
|
9541
|
+
runtime: options.runtime,
|
|
9542
|
+
runtimeImage: options.runtimeImage,
|
|
9543
|
+
runtimeTemplate: options.runtimeTemplate,
|
|
9544
|
+
detach: options.detach,
|
|
9545
|
+
mountPoeCode: options.mountPoeCode,
|
|
9546
|
+
runnerSync: options.runnerSync
|
|
9547
|
+
},
|
|
9548
|
+
openSpec: {
|
|
9549
|
+
execution: {
|
|
9550
|
+
wrapForLogTee: false,
|
|
9551
|
+
stdin: "pipe",
|
|
9552
|
+
stdout: "pipe",
|
|
9553
|
+
stderr: "pipe",
|
|
9554
|
+
env: processEnv,
|
|
9555
|
+
input: useStdin ? options.prompt : "",
|
|
9556
|
+
captureOutput: true,
|
|
9557
|
+
activityTimeoutMs: options.activityTimeoutMs,
|
|
9558
|
+
onStdout(chunk) {
|
|
9559
|
+
queue.push(chunk);
|
|
9560
|
+
},
|
|
9561
|
+
onStderr(chunk) {
|
|
9562
|
+
if (options.tee?.stderr) options.tee.stderr.write(chunk);
|
|
9563
|
+
}
|
|
9564
|
+
}
|
|
9565
|
+
}
|
|
9566
|
+
});
|
|
9567
|
+
const result = { stdout: "", stderr: "", exitCode: 1 };
|
|
9568
|
+
const adapter = getAdapter(spawnConfig.adapter);
|
|
9569
|
+
let resolveEventStreamDone;
|
|
9570
|
+
let rejectEventStreamDone;
|
|
9571
|
+
const eventStreamDone = new Promise((resolve2, reject) => {
|
|
9572
|
+
resolveEventStreamDone = resolve2;
|
|
9573
|
+
rejectEventStreamDone = reject;
|
|
9574
|
+
});
|
|
9575
|
+
const eventQueue = [];
|
|
9576
|
+
const waiters = [];
|
|
9577
|
+
let eventsDone = false;
|
|
9578
|
+
let eventStreamError;
|
|
9579
|
+
const ctx = {
|
|
9580
|
+
sessionId: "unknown",
|
|
9581
|
+
agent: agentId,
|
|
9582
|
+
...options.logPath !== void 0 ? { logPath: options.logPath } : {},
|
|
9583
|
+
...options.logDir !== void 0 ? { logDir: options.logDir } : {},
|
|
9584
|
+
...options.logFileName !== void 0 ? { logFileName: options.logFileName } : {},
|
|
9585
|
+
events: [],
|
|
9586
|
+
usage: {
|
|
9587
|
+
inputTokens: 0,
|
|
9588
|
+
outputTokens: 0
|
|
9589
|
+
},
|
|
9590
|
+
prompt: options.prompt,
|
|
9591
|
+
model: options.model,
|
|
9592
|
+
mode: options.mode,
|
|
9593
|
+
cwd: options.cwd ?? process.cwd(),
|
|
9594
|
+
startedAt: /* @__PURE__ */ new Date()
|
|
9595
|
+
};
|
|
9596
|
+
const pushEvent = (event) => {
|
|
9597
|
+
if (eventsDone) return;
|
|
9598
|
+
if (event.event === "session_start") {
|
|
9599
|
+
const threadId = event.threadId;
|
|
9600
|
+
if (typeof threadId === "string" && threadId.length > 0) {
|
|
9601
|
+
ctx.threadId = threadId;
|
|
9602
|
+
ctx.sessionId = threadId;
|
|
9603
|
+
}
|
|
9604
|
+
}
|
|
9605
|
+
ctx.events.push(event);
|
|
9606
|
+
accumulateUsage(ctx, event);
|
|
9607
|
+
const waiter = waiters.shift();
|
|
9608
|
+
if (waiter) {
|
|
9609
|
+
waiter.resolve({ done: false, value: event });
|
|
9610
|
+
return;
|
|
9611
|
+
}
|
|
9612
|
+
eventQueue.push(event);
|
|
9613
|
+
};
|
|
9614
|
+
const completeEventStream = () => {
|
|
9615
|
+
if (eventsDone) return;
|
|
9616
|
+
eventsDone = true;
|
|
9617
|
+
while (waiters.length > 0) {
|
|
9618
|
+
waiters.shift()?.resolve({ done: true, value: void 0 });
|
|
9619
|
+
}
|
|
9620
|
+
};
|
|
9621
|
+
const failEventStream = (error2) => {
|
|
9622
|
+
if (eventsDone) return;
|
|
9623
|
+
eventStreamError = error2;
|
|
9624
|
+
eventsDone = true;
|
|
9625
|
+
while (waiters.length > 0) {
|
|
9626
|
+
waiters.shift()?.reject(error2);
|
|
9627
|
+
}
|
|
9628
|
+
};
|
|
9629
|
+
ctx.eventStream = {
|
|
9630
|
+
[Symbol.asyncIterator]() {
|
|
9631
|
+
return {
|
|
9632
|
+
next() {
|
|
9633
|
+
if (eventQueue.length > 0) {
|
|
9634
|
+
return Promise.resolve({ done: false, value: eventQueue.shift() });
|
|
9635
|
+
}
|
|
9636
|
+
if (eventStreamError) {
|
|
9637
|
+
return Promise.reject(eventStreamError);
|
|
9638
|
+
}
|
|
9639
|
+
if (eventsDone) {
|
|
9640
|
+
return Promise.resolve({ done: true, value: void 0 });
|
|
9641
|
+
}
|
|
9642
|
+
return new Promise((resolve2, reject) => {
|
|
9643
|
+
waiters.push({ resolve: resolve2, reject });
|
|
9644
|
+
});
|
|
9645
|
+
}
|
|
9646
|
+
};
|
|
9647
|
+
}
|
|
9648
|
+
};
|
|
9649
|
+
const manifest = bridgeSkillsForRun(options.agentId, cwd, options.skills);
|
|
9650
|
+
void (async () => {
|
|
9651
|
+
try {
|
|
9652
|
+
for await (const output of adapter(queue.lines())) {
|
|
9653
|
+
if (!isAcpEvent(output)) continue;
|
|
9654
|
+
pushEvent(stampReceiveTime(output, Date.now()));
|
|
9655
|
+
}
|
|
9656
|
+
completeEventStream();
|
|
9657
|
+
resolveEventStreamDone?.();
|
|
9658
|
+
} catch (error2) {
|
|
9659
|
+
failEventStream(error2);
|
|
9660
|
+
rejectEventStreamDone?.(error2);
|
|
9661
|
+
}
|
|
9662
|
+
})();
|
|
9663
|
+
const done = (async () => {
|
|
9664
|
+
try {
|
|
9665
|
+
await applyMiddlewares(
|
|
9666
|
+
[
|
|
9667
|
+
...options.middlewares ?? [],
|
|
9668
|
+
async (_ctx, next) => {
|
|
9669
|
+
try {
|
|
9670
|
+
const runResult = await runPoeCommand({
|
|
9671
|
+
factory: execution.factory,
|
|
9672
|
+
openSpec: execution.openSpec,
|
|
9673
|
+
detach: execution.detach,
|
|
9674
|
+
state: execution.state,
|
|
9675
|
+
signal: options.signal
|
|
9676
|
+
});
|
|
9677
|
+
if (runResult.kind === "detached") {
|
|
9678
|
+
result.stdout = "";
|
|
9679
|
+
result.stderr = "";
|
|
9680
|
+
result.exitCode = 0;
|
|
9681
|
+
result.detached = { jobId: runResult.jobId, envId: runResult.envId };
|
|
9682
|
+
} else {
|
|
9683
|
+
result.stderr = runResult.stderr ?? "";
|
|
9684
|
+
result.exitCode = runResult.exitCode;
|
|
9685
|
+
}
|
|
9686
|
+
} finally {
|
|
9687
|
+
queue.close();
|
|
9688
|
+
}
|
|
9689
|
+
await eventStreamDone;
|
|
9690
|
+
await next();
|
|
9691
|
+
}
|
|
9692
|
+
],
|
|
9693
|
+
ctx
|
|
9694
|
+
);
|
|
9695
|
+
return {
|
|
9696
|
+
...result,
|
|
9697
|
+
...ctx.logFile && !result.logFile ? { logFile: ctx.logFile } : {}
|
|
9698
|
+
};
|
|
9699
|
+
} finally {
|
|
9700
|
+
cleanupSkillsForRun(manifest);
|
|
9701
|
+
}
|
|
9702
|
+
})();
|
|
9703
|
+
return {
|
|
9704
|
+
events: ctx.eventStream,
|
|
9705
|
+
done: observeAgentSpawn(
|
|
9706
|
+
{
|
|
9707
|
+
agent: agentId,
|
|
9708
|
+
cwd: options.cwd,
|
|
9709
|
+
mode: options.mode,
|
|
9710
|
+
otelSink: options.otelSink,
|
|
9711
|
+
prompt: options.prompt
|
|
9712
|
+
},
|
|
9713
|
+
() => done
|
|
9714
|
+
)
|
|
9715
|
+
};
|
|
9716
|
+
}
|
|
9717
|
+
|
|
9718
|
+
// packages/agent-spawn/src/spawn.ts
|
|
9719
|
+
function createAbortError6() {
|
|
9720
|
+
const error2 = new Error("Agent spawn aborted");
|
|
9721
|
+
error2.name = "AbortError";
|
|
9722
|
+
return error2;
|
|
9723
|
+
}
|
|
9724
|
+
function resolveCliConfig(agentId) {
|
|
9725
|
+
const resolved = resolveConfig(agentId);
|
|
9726
|
+
if (!resolved.spawnConfig) {
|
|
9727
|
+
throw new Error(`Agent "${resolved.agentId}" has no spawn config.`);
|
|
9728
|
+
}
|
|
9729
|
+
if (resolved.spawnConfig.kind !== "cli") {
|
|
9730
|
+
throw new Error(`Agent "${resolved.agentId}" does not support CLI spawn.`);
|
|
9731
|
+
}
|
|
9732
|
+
if (!resolved.binaryName) {
|
|
9733
|
+
throw new Error(`Agent "${resolved.agentId}" has no binaryName.`);
|
|
9734
|
+
}
|
|
9735
|
+
return {
|
|
9736
|
+
agentId: resolved.agentId,
|
|
9737
|
+
binaryName: resolved.binaryName,
|
|
9738
|
+
spawnConfig: resolved.spawnConfig
|
|
9739
|
+
};
|
|
9740
|
+
}
|
|
9741
|
+
function getDefaultArgsPosition2(config) {
|
|
9742
|
+
return config.defaultArgsPosition ?? "afterPrompt";
|
|
9743
|
+
}
|
|
9744
|
+
function getMcpArgsPosition2(config) {
|
|
9745
|
+
if (config.mcpArgsPosition) {
|
|
9746
|
+
return config.mcpArgsPosition;
|
|
9747
|
+
}
|
|
9748
|
+
return config.mcpArgsBeforeCommand ? "beforeCommand" : "afterCommand";
|
|
9749
|
+
}
|
|
9750
|
+
function buildCliArgs(config, options, stdinMode) {
|
|
9751
|
+
const mcpArgs = getMcpArgs(config, options.mcpServers);
|
|
9752
|
+
const resumeArgs = getResumeArgs2(config, options);
|
|
9753
|
+
const defaultArgsPosition = getDefaultArgsPosition2(config);
|
|
9754
|
+
const mcpArgsPosition = getMcpArgsPosition2(config);
|
|
9755
|
+
const resumeArgsPosition = config.resume?.position ?? "afterPrompt";
|
|
9756
|
+
const args = [];
|
|
9757
|
+
if (mcpArgsPosition === "beforeCommand") {
|
|
9758
|
+
args.push(...mcpArgs);
|
|
9759
|
+
}
|
|
9760
|
+
if (defaultArgsPosition === "beforePrompt") {
|
|
9761
|
+
args.push(...config.defaultArgs);
|
|
7701
9762
|
}
|
|
7702
9763
|
if (mcpArgsPosition === "beforePrompt") {
|
|
7703
9764
|
args.push(...mcpArgs);
|
|
@@ -7738,7 +9799,7 @@ function buildCliArgs(config, options, stdinMode) {
|
|
|
7738
9799
|
}
|
|
7739
9800
|
return { args, env: mode.env };
|
|
7740
9801
|
}
|
|
7741
|
-
function
|
|
9802
|
+
function getResumeArgs2(config, options) {
|
|
7742
9803
|
if (!options.resumeThreadId) {
|
|
7743
9804
|
return [];
|
|
7744
9805
|
}
|
|
@@ -7747,59 +9808,74 @@ function getResumeArgs(config, options) {
|
|
|
7747
9808
|
}
|
|
7748
9809
|
return config.resume.args(options.resumeThreadId, options.cwd ?? process.cwd());
|
|
7749
9810
|
}
|
|
7750
|
-
async function
|
|
9811
|
+
async function spawn4(agentId, options, context) {
|
|
9812
|
+
return observeAgentSpawn(
|
|
9813
|
+
{
|
|
9814
|
+
agent: agentId,
|
|
9815
|
+
cwd: options.cwd,
|
|
9816
|
+
mode: options.mode,
|
|
9817
|
+
otelSink: options.otelSink,
|
|
9818
|
+
prompt: options.prompt
|
|
9819
|
+
},
|
|
9820
|
+
() => runSpawn(agentId, options, context)
|
|
9821
|
+
);
|
|
9822
|
+
}
|
|
9823
|
+
async function runSpawn(agentId, options, context) {
|
|
7751
9824
|
if (options.signal?.aborted) {
|
|
7752
|
-
throw
|
|
9825
|
+
throw createAbortError6();
|
|
7753
9826
|
}
|
|
7754
9827
|
const { agentId: resolvedId, binaryName, spawnConfig } = resolveCliConfig(agentId);
|
|
7755
|
-
const stdinMode = options
|
|
9828
|
+
const stdinMode = shouldSendPromptViaStdin(spawnConfig, options) ? spawnConfig.stdinMode : void 0;
|
|
7756
9829
|
const { args: spawnArgs, env: modeEnv } = buildCliArgs(spawnConfig, options, stdinMode);
|
|
7757
9830
|
if (context?.dryRun) {
|
|
7758
9831
|
const rendered = [binaryName, ...spawnArgs].join(" ");
|
|
7759
9832
|
context.logger?.dryRun(rendered);
|
|
7760
9833
|
return { stdout: "", stderr: "", exitCode: 0 };
|
|
7761
9834
|
}
|
|
7762
|
-
const
|
|
7763
|
-
const
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
|
|
7773
|
-
|
|
7774
|
-
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
7785
|
-
|
|
7786
|
-
|
|
7787
|
-
|
|
7788
|
-
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
options.
|
|
7793
|
-
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
|
|
9835
|
+
const cwd = options.cwd ?? process.cwd();
|
|
9836
|
+
const manifest = bridgeSkillsForRun(agentId, cwd, options.skills);
|
|
9837
|
+
let logFd;
|
|
9838
|
+
try {
|
|
9839
|
+
const logFilePath = resolveSpawnLogPath(options);
|
|
9840
|
+
logFd = logFilePath ? openSpawnLog(logFilePath) : void 0;
|
|
9841
|
+
const processEnv = modeEnv ? { ...process.env, ...modeEnv } : void 0;
|
|
9842
|
+
const argv = [binaryName, ...spawnArgs];
|
|
9843
|
+
const execution = resolvePoeCommandExecution({
|
|
9844
|
+
cwd,
|
|
9845
|
+
runtimeConfigCwd: options.runtimeConfigCwd,
|
|
9846
|
+
env: processEnv ?? process.env,
|
|
9847
|
+
argv,
|
|
9848
|
+
tool: resolvedId,
|
|
9849
|
+
runtime: {
|
|
9850
|
+
runtime: options.runtime,
|
|
9851
|
+
runtimeImage: options.runtimeImage,
|
|
9852
|
+
runtimeTemplate: options.runtimeTemplate,
|
|
9853
|
+
detach: options.detach,
|
|
9854
|
+
mountPoeCode: options.mountPoeCode,
|
|
9855
|
+
runnerSync: options.runnerSync
|
|
9856
|
+
},
|
|
9857
|
+
context,
|
|
9858
|
+
openSpec: {
|
|
9859
|
+
execution: {
|
|
9860
|
+
wrapForLogTee: false,
|
|
9861
|
+
stdin: stdinMode ? "pipe" : "inherit",
|
|
9862
|
+
stdout: "pipe",
|
|
9863
|
+
stderr: "pipe",
|
|
9864
|
+
env: processEnv,
|
|
9865
|
+
input: stdinMode ? options.prompt : void 0,
|
|
9866
|
+
captureOutput: true,
|
|
9867
|
+
activityTimeoutMs: options.activityTimeoutMs,
|
|
9868
|
+
onStdout(chunk) {
|
|
9869
|
+
options.tee?.stdout?.write(chunk);
|
|
9870
|
+
appendSpawnLog(logFd, chunk);
|
|
9871
|
+
},
|
|
9872
|
+
onStderr(chunk) {
|
|
9873
|
+
options.tee?.stderr?.write(chunk);
|
|
9874
|
+
appendSpawnLog(logFd, chunk);
|
|
9875
|
+
}
|
|
7798
9876
|
}
|
|
7799
9877
|
}
|
|
7800
|
-
}
|
|
7801
|
-
});
|
|
7802
|
-
try {
|
|
9878
|
+
});
|
|
7803
9879
|
const result = await runPoeCommand({
|
|
7804
9880
|
factory: execution.factory,
|
|
7805
9881
|
openSpec: execution.openSpec,
|
|
@@ -7825,8 +9901,21 @@ async function spawn3(agentId, options, context) {
|
|
|
7825
9901
|
};
|
|
7826
9902
|
} finally {
|
|
7827
9903
|
closeSpawnLog(logFd);
|
|
9904
|
+
cleanupSkillsForRun(manifest);
|
|
7828
9905
|
}
|
|
7829
9906
|
}
|
|
9907
|
+
spawn4.retry = createSpawnRetry((service, options) => {
|
|
9908
|
+
const handle = spawnStreaming({ ...options, agentId: service });
|
|
9909
|
+
return {
|
|
9910
|
+
events: handle.events,
|
|
9911
|
+
result: handle.done
|
|
9912
|
+
};
|
|
9913
|
+
});
|
|
9914
|
+
spawn4.parallel = createSpawnParallel((service, options) => ({
|
|
9915
|
+
events: (async function* () {
|
|
9916
|
+
})(),
|
|
9917
|
+
result: spawn4(service, options)
|
|
9918
|
+
}));
|
|
7830
9919
|
function resolveSpawnLogPath(options) {
|
|
7831
9920
|
if (options.logPath) {
|
|
7832
9921
|
return options.logPath;
|
|
@@ -7834,11 +9923,11 @@ function resolveSpawnLogPath(options) {
|
|
|
7834
9923
|
if (!options.logDir || !options.logFileName) {
|
|
7835
9924
|
return void 0;
|
|
7836
9925
|
}
|
|
7837
|
-
return
|
|
9926
|
+
return path41.join(options.logDir, options.logFileName);
|
|
7838
9927
|
}
|
|
7839
9928
|
function openSpawnLog(filePath) {
|
|
7840
9929
|
try {
|
|
7841
|
-
|
|
9930
|
+
mkdirSync3(path41.dirname(filePath), { recursive: true });
|
|
7842
9931
|
return openSync(filePath, "a");
|
|
7843
9932
|
} catch {
|
|
7844
9933
|
return void 0;
|
|
@@ -7863,7 +9952,7 @@ function closeSpawnLog(fd) {
|
|
|
7863
9952
|
var DEFAULT_ACTIVITY_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
7864
9953
|
|
|
7865
9954
|
// packages/agent-spawn/src/acp/replay.ts
|
|
7866
|
-
import
|
|
9955
|
+
import path42 from "node:path";
|
|
7867
9956
|
import { homedir as homedir2 } from "node:os";
|
|
7868
9957
|
import { open as open2, readdir as readdir5 } from "node:fs/promises";
|
|
7869
9958
|
import { createInterface } from "node:readline";
|
|
@@ -7882,13 +9971,13 @@ import { homedir } from "node:os";
|
|
|
7882
9971
|
import { join } from "node:path";
|
|
7883
9972
|
|
|
7884
9973
|
// packages/agent-spawn/src/acp/middlewares/spawn-log.ts
|
|
7885
|
-
import
|
|
9974
|
+
import path43 from "node:path";
|
|
7886
9975
|
import { homedir as homedir3 } from "node:os";
|
|
7887
9976
|
import { mkdir as mkdir5, open as open3 } from "node:fs/promises";
|
|
7888
9977
|
|
|
7889
9978
|
// packages/memory/src/tokens.ts
|
|
7890
|
-
import * as
|
|
7891
|
-
import
|
|
9979
|
+
import * as fs12 from "node:fs/promises";
|
|
9980
|
+
import path44 from "node:path";
|
|
7892
9981
|
|
|
7893
9982
|
// packages/tokenfill/dist/tokenizer.js
|
|
7894
9983
|
import { get_encoding } from "tiktoken";
|
|
@@ -7929,20 +10018,20 @@ function countTokens(text5) {
|
|
|
7929
10018
|
}
|
|
7930
10019
|
|
|
7931
10020
|
// packages/tokenfill/dist/corpus.js
|
|
7932
|
-
import { readdirSync, readFileSync as
|
|
10021
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync3 } from "node:fs";
|
|
7933
10022
|
import { dirname, join as join2 } from "node:path";
|
|
7934
|
-
import { fileURLToPath } from "node:url";
|
|
10023
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
7935
10024
|
var CORPUS_ARTICLE_SEPARATOR = "\n\n";
|
|
7936
|
-
var corpusDirectoryPath = join2(dirname(
|
|
10025
|
+
var corpusDirectoryPath = join2(dirname(fileURLToPath2(import.meta.url)), "corpus");
|
|
7937
10026
|
function getCorpusFileNames() {
|
|
7938
|
-
return
|
|
10027
|
+
return readdirSync2(corpusDirectoryPath, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".md")).map((entry) => entry.name).sort((left, right) => left.localeCompare(right));
|
|
7939
10028
|
}
|
|
7940
10029
|
function loadBuiltInCorpusArticles() {
|
|
7941
10030
|
const corpusFileNames = getCorpusFileNames();
|
|
7942
10031
|
if (corpusFileNames.length === 0) {
|
|
7943
10032
|
throw new Error(`No built-in corpus markdown files found in ${corpusDirectoryPath}`);
|
|
7944
10033
|
}
|
|
7945
|
-
return corpusFileNames.map((fileName) =>
|
|
10034
|
+
return corpusFileNames.map((fileName) => readFileSync3(join2(corpusDirectoryPath, fileName), "utf8").trim());
|
|
7946
10035
|
}
|
|
7947
10036
|
var BUILT_IN_CORPUS_ARTICLES = loadBuiltInCorpusArticles();
|
|
7948
10037
|
|
|
@@ -7952,7 +10041,7 @@ var builtInCorpusByteLength = Buffer.byteLength(builtInCorpusText, "utf8");
|
|
|
7952
10041
|
|
|
7953
10042
|
// packages/memory/src/tokens.ts
|
|
7954
10043
|
async function computeTokenStats(root) {
|
|
7955
|
-
if (!await
|
|
10044
|
+
if (!await pathExists4(root)) {
|
|
7956
10045
|
return {
|
|
7957
10046
|
memoryTokens: 0,
|
|
7958
10047
|
sourceTokens: 0,
|
|
@@ -7972,13 +10061,13 @@ async function computeTokenStats(root) {
|
|
|
7972
10061
|
}
|
|
7973
10062
|
}
|
|
7974
10063
|
}
|
|
7975
|
-
const repoRoot =
|
|
10064
|
+
const repoRoot = path44.resolve(root, "..", "..");
|
|
7976
10065
|
let sourceTokens = 0;
|
|
7977
10066
|
const missingSources = [];
|
|
7978
10067
|
for (const sourcePath of sourcePaths) {
|
|
7979
|
-
const absPath =
|
|
10068
|
+
const absPath = path44.isAbsolute(sourcePath) ? sourcePath : path44.resolve(repoRoot, sourcePath);
|
|
7980
10069
|
try {
|
|
7981
|
-
const content = await
|
|
10070
|
+
const content = await fs12.readFile(absPath, "utf8");
|
|
7982
10071
|
sourceTokens += countTokens(content);
|
|
7983
10072
|
} catch (error2) {
|
|
7984
10073
|
if (isMissing4(error2)) {
|
|
@@ -7997,9 +10086,9 @@ async function computeTokenStats(root) {
|
|
|
7997
10086
|
missingSources
|
|
7998
10087
|
};
|
|
7999
10088
|
}
|
|
8000
|
-
async function
|
|
10089
|
+
async function pathExists4(targetPath) {
|
|
8001
10090
|
try {
|
|
8002
|
-
await
|
|
10091
|
+
await fs12.stat(targetPath);
|
|
8003
10092
|
return true;
|
|
8004
10093
|
} catch (error2) {
|
|
8005
10094
|
if (isMissing4(error2)) {
|
|
@@ -8027,10 +10116,10 @@ function resolveRunners(overrides) {
|
|
|
8027
10116
|
async function ingest(root, opts, runners) {
|
|
8028
10117
|
const resolved = resolveRunners(runners);
|
|
8029
10118
|
const source = await materializeSource(opts.source);
|
|
8030
|
-
const indexMdBytes = await
|
|
10119
|
+
const indexMdBytes = await fs13.readFile(path45.join(root, MEMORY_INDEX_RELPATH));
|
|
8031
10120
|
const configOptions = {
|
|
8032
|
-
fs:
|
|
8033
|
-
filePath:
|
|
10121
|
+
fs: fs13,
|
|
10122
|
+
filePath: path45.join(inferRepoRoot(root), "poe-code.json")
|
|
8034
10123
|
};
|
|
8035
10124
|
const agentId = await resolveAgent(configOptions, opts.agent ?? null) ?? opts.agent ?? "claude-code";
|
|
8036
10125
|
const key = resolved.computeIngestKey({
|
|
@@ -8068,7 +10157,7 @@ async function ingest(root, opts, runners) {
|
|
|
8068
10157
|
let timeoutError;
|
|
8069
10158
|
try {
|
|
8070
10159
|
const result = await runWithTimeout(
|
|
8071
|
-
|
|
10160
|
+
spawn4(agentId, { prompt }),
|
|
8072
10161
|
opts.timeoutMs ?? await configuredTimeout(configOptions)
|
|
8073
10162
|
);
|
|
8074
10163
|
exitCode = result.exitCode;
|
|
@@ -8110,7 +10199,7 @@ function buildIngestPrompt(root, sourceLabel, sourceText) {
|
|
|
8110
10199
|
}
|
|
8111
10200
|
async function materializeSource(source) {
|
|
8112
10201
|
if (source.kind === "file") {
|
|
8113
|
-
const bytes = await
|
|
10202
|
+
const bytes = await fs13.readFile(source.absPath);
|
|
8114
10203
|
return {
|
|
8115
10204
|
label: source.absPath,
|
|
8116
10205
|
bytes,
|
|
@@ -8120,7 +10209,7 @@ async function materializeSource(source) {
|
|
|
8120
10209
|
throw new Error("URL ingest not implemented yet.");
|
|
8121
10210
|
}
|
|
8122
10211
|
function inferRepoRoot(root) {
|
|
8123
|
-
return
|
|
10212
|
+
return path45.resolve(root, "..", "..");
|
|
8124
10213
|
}
|
|
8125
10214
|
async function runWithTimeout(promise, timeoutMs) {
|
|
8126
10215
|
return await new Promise((resolve2, reject) => {
|
|
@@ -8877,99 +10966,6 @@ function printMcpConfig() {
|
|
|
8877
10966
|
);
|
|
8878
10967
|
}
|
|
8879
10968
|
|
|
8880
|
-
// packages/agent-skill-config/src/configs.ts
|
|
8881
|
-
import os5 from "node:os";
|
|
8882
|
-
import path39 from "node:path";
|
|
8883
|
-
var agentSkillConfigs = {
|
|
8884
|
-
"claude-code": {
|
|
8885
|
-
globalSkillDir: "~/.claude/skills",
|
|
8886
|
-
localSkillDir: ".claude/skills"
|
|
8887
|
-
},
|
|
8888
|
-
codex: {
|
|
8889
|
-
globalSkillDir: "~/.codex/skills",
|
|
8890
|
-
localSkillDir: ".codex/skills"
|
|
8891
|
-
},
|
|
8892
|
-
opencode: {
|
|
8893
|
-
globalSkillDir: "~/.config/opencode/skills",
|
|
8894
|
-
localSkillDir: ".opencode/skills"
|
|
8895
|
-
},
|
|
8896
|
-
goose: {
|
|
8897
|
-
globalSkillDir: "~/.agents/skills",
|
|
8898
|
-
localSkillDir: ".agents/skills"
|
|
8899
|
-
}
|
|
8900
|
-
};
|
|
8901
|
-
var supportedAgents2 = Object.keys(agentSkillConfigs);
|
|
8902
|
-
function resolveAgentSupport(input, registry = agentSkillConfigs) {
|
|
8903
|
-
const resolvedId = resolveAgentId(input);
|
|
8904
|
-
if (!resolvedId) {
|
|
8905
|
-
return { status: "unknown", input };
|
|
8906
|
-
}
|
|
8907
|
-
const config = registry[resolvedId];
|
|
8908
|
-
if (!config) {
|
|
8909
|
-
return { status: "unsupported", input, id: resolvedId };
|
|
8910
|
-
}
|
|
8911
|
-
return { status: "supported", input, id: resolvedId, config };
|
|
8912
|
-
}
|
|
8913
|
-
|
|
8914
|
-
// packages/agent-skill-config/src/templates.ts
|
|
8915
|
-
import { readFile as readFile15, stat as stat6 } from "node:fs/promises";
|
|
8916
|
-
import path40 from "node:path";
|
|
8917
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
8918
|
-
|
|
8919
|
-
// packages/agent-skill-config/src/apply.ts
|
|
8920
|
-
var UnsupportedAgentError = class extends Error {
|
|
8921
|
-
constructor(agentId) {
|
|
8922
|
-
super(`Unsupported agent: ${agentId}`);
|
|
8923
|
-
this.name = "UnsupportedAgentError";
|
|
8924
|
-
}
|
|
8925
|
-
};
|
|
8926
|
-
function toHomeRelative(localSkillDir) {
|
|
8927
|
-
if (localSkillDir.startsWith("~/") || localSkillDir === "~") {
|
|
8928
|
-
return localSkillDir;
|
|
8929
|
-
}
|
|
8930
|
-
const normalized = localSkillDir.startsWith("./") ? localSkillDir.slice(2) : localSkillDir;
|
|
8931
|
-
return `~/${normalized}`;
|
|
8932
|
-
}
|
|
8933
|
-
var SKILL_TEMPLATE_ID = "__skill_content__";
|
|
8934
|
-
async function installSkill(agentId, skill, options) {
|
|
8935
|
-
const support = resolveAgentSupport(agentId);
|
|
8936
|
-
if (support.status !== "supported") {
|
|
8937
|
-
throw new UnsupportedAgentError(agentId);
|
|
8938
|
-
}
|
|
8939
|
-
const scope = options.scope ?? "local";
|
|
8940
|
-
const config = support.config;
|
|
8941
|
-
const skillDir = scope === "global" ? config.globalSkillDir : toHomeRelative(config.localSkillDir);
|
|
8942
|
-
const skillFolderPath = `${skillDir}/${skill.name}`;
|
|
8943
|
-
const skillFilePath = `${skillFolderPath}/SKILL.md`;
|
|
8944
|
-
const displayPath = `${scope === "global" ? config.globalSkillDir : config.localSkillDir}/${skill.name}/SKILL.md`;
|
|
8945
|
-
await runMutations(
|
|
8946
|
-
[
|
|
8947
|
-
fileMutation.ensureDirectory({
|
|
8948
|
-
path: skillFolderPath,
|
|
8949
|
-
label: `Ensure skill directory ${skill.name}`
|
|
8950
|
-
}),
|
|
8951
|
-
templateMutation.write({
|
|
8952
|
-
target: skillFilePath,
|
|
8953
|
-
templateId: SKILL_TEMPLATE_ID,
|
|
8954
|
-
label: `Write skill ${skill.name}`
|
|
8955
|
-
})
|
|
8956
|
-
],
|
|
8957
|
-
{
|
|
8958
|
-
fs: options.fs,
|
|
8959
|
-
homeDir: scope === "global" ? options.homeDir : options.cwd,
|
|
8960
|
-
dryRun: options.dryRun,
|
|
8961
|
-
observers: options.observers,
|
|
8962
|
-
templates: async (templateId) => {
|
|
8963
|
-
if (templateId === SKILL_TEMPLATE_ID) {
|
|
8964
|
-
return skill.content;
|
|
8965
|
-
}
|
|
8966
|
-
throw new Error(`Unknown template: ${templateId}`);
|
|
8967
|
-
}
|
|
8968
|
-
}
|
|
8969
|
-
);
|
|
8970
|
-
return { skillPath: skillFilePath, displayPath };
|
|
8971
|
-
}
|
|
8972
|
-
|
|
8973
10969
|
// packages/agent-mcp-config/src/configs.ts
|
|
8974
10970
|
var agentMcpConfigs = {
|
|
8975
10971
|
"claude-code": {
|
|
@@ -9046,7 +11042,7 @@ function resolveConfigPath2(config, platform) {
|
|
|
9046
11042
|
}
|
|
9047
11043
|
|
|
9048
11044
|
// packages/agent-mcp-config/src/apply.ts
|
|
9049
|
-
import
|
|
11045
|
+
import path46 from "node:path";
|
|
9050
11046
|
import { parse as parseYaml3, stringify as stringifyYaml2 } from "yaml";
|
|
9051
11047
|
|
|
9052
11048
|
// packages/agent-mcp-config/src/shapes.ts
|
|
@@ -9138,7 +11134,7 @@ function getShapeTransformer(shape) {
|
|
|
9138
11134
|
|
|
9139
11135
|
// packages/agent-mcp-config/src/apply.ts
|
|
9140
11136
|
function getConfigDirectory(configPath) {
|
|
9141
|
-
return
|
|
11137
|
+
return path46.dirname(configPath);
|
|
9142
11138
|
}
|
|
9143
11139
|
var UnsupportedAgentError2 = class extends Error {
|
|
9144
11140
|
constructor(agentId) {
|
|
@@ -9164,9 +11160,9 @@ function expandHomePath(configPath, homeDir) {
|
|
|
9164
11160
|
return homeDir;
|
|
9165
11161
|
}
|
|
9166
11162
|
if (configPath.startsWith("~/")) {
|
|
9167
|
-
return
|
|
11163
|
+
return path46.join(homeDir, configPath.slice(2));
|
|
9168
11164
|
}
|
|
9169
|
-
return
|
|
11165
|
+
return path46.join(homeDir, configPath.slice(1));
|
|
9170
11166
|
}
|
|
9171
11167
|
function parseYamlDocument(content) {
|
|
9172
11168
|
if (content.trim() === "") {
|
|
@@ -9199,7 +11195,7 @@ async function writeYamlConfig(configPath, document, options) {
|
|
|
9199
11195
|
return;
|
|
9200
11196
|
}
|
|
9201
11197
|
const absolutePath = expandHomePath(configPath, options.homeDir);
|
|
9202
|
-
const configDir =
|
|
11198
|
+
const configDir = path46.dirname(absolutePath);
|
|
9203
11199
|
await options.fs.mkdir(configDir, { recursive: true });
|
|
9204
11200
|
await options.fs.writeFile(absolutePath, serializeYamlDocument(document), {
|
|
9205
11201
|
encoding: "utf8"
|
|
@@ -9376,8 +11372,8 @@ async function installMemory(options) {
|
|
|
9376
11372
|
}
|
|
9377
11373
|
|
|
9378
11374
|
// packages/memory/src/query.ts
|
|
9379
|
-
import * as
|
|
9380
|
-
import
|
|
11375
|
+
import * as fs14 from "node:fs/promises";
|
|
11376
|
+
import path47 from "node:path";
|
|
9381
11377
|
async function queryMemory(root, options) {
|
|
9382
11378
|
const pages = await listPages(root);
|
|
9383
11379
|
if (pages.length === 0) {
|
|
@@ -9390,12 +11386,12 @@ async function queryMemory(root, options) {
|
|
|
9390
11386
|
};
|
|
9391
11387
|
}
|
|
9392
11388
|
const configOptions = {
|
|
9393
|
-
fs:
|
|
9394
|
-
filePath:
|
|
11389
|
+
fs: fs14,
|
|
11390
|
+
filePath: path47.join(inferRepoRoot2(root), "poe-code.json")
|
|
9395
11391
|
};
|
|
9396
11392
|
const agentId = await resolveAgent(configOptions, options.agent ?? null) ?? options.agent ?? "claude-code";
|
|
9397
11393
|
const context = await selectQueryContext(root, options.question, options.budget);
|
|
9398
|
-
const result = await
|
|
11394
|
+
const result = await spawn4(agentId, { prompt: context.prompt });
|
|
9399
11395
|
return {
|
|
9400
11396
|
answer: result.answer,
|
|
9401
11397
|
citations: result.citations,
|
|
@@ -9406,7 +11402,7 @@ async function queryMemory(root, options) {
|
|
|
9406
11402
|
}
|
|
9407
11403
|
async function selectQueryContext(root, question, budget) {
|
|
9408
11404
|
const [indexText, pages] = await Promise.all([
|
|
9409
|
-
|
|
11405
|
+
fs14.readFile(path47.join(root, MEMORY_INDEX_RELPATH), "utf8"),
|
|
9410
11406
|
listPages(root)
|
|
9411
11407
|
]);
|
|
9412
11408
|
const indexTokens = countTokens(indexText);
|
|
@@ -9485,12 +11481,12 @@ function tokenize(text5) {
|
|
|
9485
11481
|
return text5.toLowerCase().split(/[^a-z0-9]+/).filter((token) => token.length > 0);
|
|
9486
11482
|
}
|
|
9487
11483
|
function inferRepoRoot2(root) {
|
|
9488
|
-
return
|
|
11484
|
+
return path47.resolve(root, "..", "..");
|
|
9489
11485
|
}
|
|
9490
11486
|
|
|
9491
11487
|
// packages/memory/src/explain.ts
|
|
9492
|
-
import * as
|
|
9493
|
-
import
|
|
11488
|
+
import * as fs15 from "node:fs/promises";
|
|
11489
|
+
import path48 from "node:path";
|
|
9494
11490
|
async function explainPage(root, options) {
|
|
9495
11491
|
const targetPage = await readPageIfPresent(root, options.relPath);
|
|
9496
11492
|
if (targetPage === void 0) {
|
|
@@ -9512,11 +11508,11 @@ async function explainPage(root, options) {
|
|
|
9512
11508
|
throw new Error(`budget too small; needs at least ${tokensUsed} tokens`);
|
|
9513
11509
|
}
|
|
9514
11510
|
const configOptions = {
|
|
9515
|
-
fs:
|
|
9516
|
-
filePath:
|
|
11511
|
+
fs: fs15,
|
|
11512
|
+
filePath: path48.join(inferRepoRoot3(root), "poe-code.json")
|
|
9517
11513
|
};
|
|
9518
11514
|
const agentId = await resolveAgent(configOptions, options.agent ?? null) ?? options.agent ?? "claude-code";
|
|
9519
|
-
const response = await
|
|
11515
|
+
const response = await spawn4(agentId, { prompt });
|
|
9520
11516
|
return {
|
|
9521
11517
|
answer: response.answer,
|
|
9522
11518
|
citations: response.citations,
|
|
@@ -9562,7 +11558,7 @@ async function readPageIfPresent(root, relPath) {
|
|
|
9562
11558
|
}
|
|
9563
11559
|
}
|
|
9564
11560
|
function inferRepoRoot3(root) {
|
|
9565
|
-
return
|
|
11561
|
+
return path48.resolve(root, "..", "..");
|
|
9566
11562
|
}
|
|
9567
11563
|
|
|
9568
11564
|
// packages/memory/src/explain.cli.ts
|
|
@@ -9575,9 +11571,9 @@ async function runMemoryExplain(input) {
|
|
|
9575
11571
|
}
|
|
9576
11572
|
|
|
9577
11573
|
// packages/memory/src/handle.ts
|
|
9578
|
-
import
|
|
11574
|
+
import path49 from "node:path";
|
|
9579
11575
|
function openMemory(opts) {
|
|
9580
|
-
if (!
|
|
11576
|
+
if (!path49.isAbsolute(opts.root)) {
|
|
9581
11577
|
throw new Error(`openMemory: root must be absolute, got ${opts.root}`);
|
|
9582
11578
|
}
|
|
9583
11579
|
const root = opts.root;
|