poe-code 3.0.183 → 3.0.184
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/pipeline-init.d.ts +0 -1
- package/dist/cli/commands/pipeline-init.js +3 -1
- package/dist/cli/commands/pipeline-init.js.map +1 -1
- package/dist/cli/commands/pipeline.js +134 -90
- package/dist/cli/commands/pipeline.js.map +1 -1
- package/dist/index.js +1116 -699
- package/dist/index.js.map +4 -4
- package/dist/providers/poe-agent.js +33 -4
- package/dist/providers/poe-agent.js.map +3 -3
- package/dist/sdk/pipeline.d.ts +3 -3
- package/dist/sdk/pipeline.js +126 -9
- package/dist/sdk/pipeline.js.map +1 -1
- package/dist/templates/pipeline/SKILL_plan.md +26 -13
- package/dist/templates/pipeline/steps.yaml.mustache +5 -2
- package/package.json +1 -1
- package/packages/design-system/dist/dashboard/components/stats-pane.js +2 -1
- package/packages/design-system/dist/dashboard/types.d.ts +1 -0
package/dist/index.js
CHANGED
|
@@ -777,11 +777,11 @@ var init_parse = __esm({
|
|
|
777
777
|
function mergeLayers(layers) {
|
|
778
778
|
return mergeObjectLayers(layers, []);
|
|
779
779
|
}
|
|
780
|
-
function mergeObjectLayers(layers,
|
|
780
|
+
function mergeObjectLayers(layers, path84) {
|
|
781
781
|
const data = {};
|
|
782
782
|
const sources = {};
|
|
783
783
|
for (const key of collectKeys(layers)) {
|
|
784
|
-
const resolved = resolveKey(layers, key,
|
|
784
|
+
const resolved = resolveKey(layers, key, path84);
|
|
785
785
|
if (resolved === void 0) {
|
|
786
786
|
continue;
|
|
787
787
|
}
|
|
@@ -799,7 +799,7 @@ function collectKeys(layers) {
|
|
|
799
799
|
}
|
|
800
800
|
return [...keys];
|
|
801
801
|
}
|
|
802
|
-
function resolveKey(layers, key,
|
|
802
|
+
function resolveKey(layers, key, path84) {
|
|
803
803
|
let winningSource;
|
|
804
804
|
let winningValue;
|
|
805
805
|
const objectLayers = [];
|
|
@@ -829,9 +829,9 @@ function resolveKey(layers, key, path82) {
|
|
|
829
829
|
if (winningSource === void 0) {
|
|
830
830
|
return void 0;
|
|
831
831
|
}
|
|
832
|
-
const fullPath = buildPath(
|
|
832
|
+
const fullPath = buildPath(path84, key);
|
|
833
833
|
if (isPlainObject(winningValue)) {
|
|
834
|
-
const merged = mergeObjectLayers(objectLayers, [...
|
|
834
|
+
const merged = mergeObjectLayers(objectLayers, [...path84, key]);
|
|
835
835
|
return {
|
|
836
836
|
value: merged.data,
|
|
837
837
|
sources: {
|
|
@@ -856,8 +856,8 @@ function isWinningCandidate(key, value) {
|
|
|
856
856
|
}
|
|
857
857
|
return true;
|
|
858
858
|
}
|
|
859
|
-
function buildPath(
|
|
860
|
-
return [...
|
|
859
|
+
function buildPath(path84, key) {
|
|
860
|
+
return [...path84, key].join(".");
|
|
861
861
|
}
|
|
862
862
|
function isPlainObject(value) {
|
|
863
863
|
if (value === null || Array.isArray(value) || typeof value !== "object") {
|
|
@@ -1535,16 +1535,16 @@ function getConfigFormat(pathOrFormat) {
|
|
|
1535
1535
|
}
|
|
1536
1536
|
return formatRegistry[formatName];
|
|
1537
1537
|
}
|
|
1538
|
-
function detectFormat2(
|
|
1539
|
-
const ext = getExtension(
|
|
1538
|
+
function detectFormat2(path84) {
|
|
1539
|
+
const ext = getExtension(path84);
|
|
1540
1540
|
return extensionMap[ext];
|
|
1541
1541
|
}
|
|
1542
|
-
function getExtension(
|
|
1543
|
-
const lastDot =
|
|
1542
|
+
function getExtension(path84) {
|
|
1543
|
+
const lastDot = path84.lastIndexOf(".");
|
|
1544
1544
|
if (lastDot === -1) {
|
|
1545
1545
|
return "";
|
|
1546
1546
|
}
|
|
1547
|
-
return
|
|
1547
|
+
return path84.slice(lastDot).toLowerCase();
|
|
1548
1548
|
}
|
|
1549
1549
|
var formatRegistry, extensionMap;
|
|
1550
1550
|
var init_formats = __esm({
|
|
@@ -1880,8 +1880,8 @@ async function applyChmod(mutation, context, options) {
|
|
|
1880
1880
|
};
|
|
1881
1881
|
}
|
|
1882
1882
|
try {
|
|
1883
|
-
const
|
|
1884
|
-
const currentMode = typeof
|
|
1883
|
+
const stat24 = await context.fs.stat(targetPath);
|
|
1884
|
+
const currentMode = typeof stat24.mode === "number" ? stat24.mode & 511 : null;
|
|
1885
1885
|
if (currentMode === mutation.mode) {
|
|
1886
1886
|
return {
|
|
1887
1887
|
outcome: { changed: false, effect: "none", detail: "noop" },
|
|
@@ -2713,50 +2713,50 @@ import { createTwoFilesPatch } from "diff";
|
|
|
2713
2713
|
import chalk from "chalk";
|
|
2714
2714
|
function createDryRunFileSystem(base, recorder) {
|
|
2715
2715
|
const proxy = {
|
|
2716
|
-
async readFile(
|
|
2716
|
+
async readFile(path84, encoding) {
|
|
2717
2717
|
if (encoding) {
|
|
2718
|
-
return base.readFile(
|
|
2718
|
+
return base.readFile(path84, encoding);
|
|
2719
2719
|
}
|
|
2720
|
-
return base.readFile(
|
|
2720
|
+
return base.readFile(path84);
|
|
2721
2721
|
},
|
|
2722
|
-
async writeFile(
|
|
2723
|
-
const previousContent = await tryReadText(base,
|
|
2722
|
+
async writeFile(path84, data, options) {
|
|
2723
|
+
const previousContent = await tryReadText(base, path84);
|
|
2724
2724
|
const nextContent = formatData(data, options?.encoding);
|
|
2725
2725
|
recorder.record({
|
|
2726
2726
|
type: "writeFile",
|
|
2727
|
-
path:
|
|
2727
|
+
path: path84,
|
|
2728
2728
|
nextContent,
|
|
2729
2729
|
previousContent
|
|
2730
2730
|
});
|
|
2731
2731
|
},
|
|
2732
|
-
async symlink(target,
|
|
2733
|
-
recorder.record({ type: "symlink", target, path:
|
|
2732
|
+
async symlink(target, path84) {
|
|
2733
|
+
recorder.record({ type: "symlink", target, path: path84 });
|
|
2734
2734
|
},
|
|
2735
|
-
async readlink(
|
|
2736
|
-
return base.readlink(
|
|
2735
|
+
async readlink(path84) {
|
|
2736
|
+
return base.readlink(path84);
|
|
2737
2737
|
},
|
|
2738
|
-
async mkdir(
|
|
2739
|
-
recorder.record({ type: "mkdir", path:
|
|
2738
|
+
async mkdir(path84, options) {
|
|
2739
|
+
recorder.record({ type: "mkdir", path: path84, options });
|
|
2740
2740
|
},
|
|
2741
|
-
async stat(
|
|
2742
|
-
return base.stat(
|
|
2741
|
+
async stat(path84) {
|
|
2742
|
+
return base.stat(path84);
|
|
2743
2743
|
},
|
|
2744
|
-
async lstat(
|
|
2745
|
-
return base.lstat(
|
|
2744
|
+
async lstat(path84) {
|
|
2745
|
+
return base.lstat(path84);
|
|
2746
2746
|
},
|
|
2747
2747
|
async rename(from, to) {
|
|
2748
2748
|
recorder.record({ type: "rename", from, to });
|
|
2749
2749
|
},
|
|
2750
|
-
async unlink(
|
|
2751
|
-
recorder.record({ type: "unlink", path:
|
|
2750
|
+
async unlink(path84) {
|
|
2751
|
+
recorder.record({ type: "unlink", path: path84 });
|
|
2752
2752
|
},
|
|
2753
|
-
async readdir(
|
|
2754
|
-
return base.readdir(
|
|
2753
|
+
async readdir(path84) {
|
|
2754
|
+
return base.readdir(path84);
|
|
2755
2755
|
}
|
|
2756
2756
|
};
|
|
2757
2757
|
if (typeof base.rm === "function") {
|
|
2758
|
-
proxy.rm = async (
|
|
2759
|
-
recorder.record({ type: "rm", path:
|
|
2758
|
+
proxy.rm = async (path84, options) => {
|
|
2759
|
+
recorder.record({ type: "rm", path: path84, options });
|
|
2760
2760
|
};
|
|
2761
2761
|
}
|
|
2762
2762
|
if (typeof base.copyFile === "function") {
|
|
@@ -2858,8 +2858,8 @@ function describeWriteChange(previous, next) {
|
|
|
2858
2858
|
}
|
|
2859
2859
|
return "update";
|
|
2860
2860
|
}
|
|
2861
|
-
function renderWriteCommand(
|
|
2862
|
-
const command = `cat > ${
|
|
2861
|
+
function renderWriteCommand(path84, change) {
|
|
2862
|
+
const command = `cat > ${path84}`;
|
|
2863
2863
|
if (change === "create") {
|
|
2864
2864
|
return renderOperationCommand(command, chalk.green, "# create");
|
|
2865
2865
|
}
|
|
@@ -3021,9 +3021,9 @@ function redactTomlLine(line) {
|
|
|
3021
3021
|
}
|
|
3022
3022
|
return line;
|
|
3023
3023
|
}
|
|
3024
|
-
async function tryReadText(base,
|
|
3024
|
+
async function tryReadText(base, path84) {
|
|
3025
3025
|
try {
|
|
3026
|
-
return await base.readFile(
|
|
3026
|
+
return await base.readFile(path84, "utf8");
|
|
3027
3027
|
} catch (error2) {
|
|
3028
3028
|
if (isNotFound(error2)) {
|
|
3029
3029
|
return null;
|
|
@@ -9823,9 +9823,10 @@ function statsToLines(stats, width) {
|
|
|
9823
9823
|
}
|
|
9824
9824
|
const mutedStyle = getToneStyle("muted");
|
|
9825
9825
|
const totalTokens = stats.tokensIn + stats.tokensOut;
|
|
9826
|
+
const iterationsLabel = stats.iterationsLabel ?? "Iteration";
|
|
9826
9827
|
const lines = [
|
|
9827
9828
|
createKeyValueLine("Status", formatStatus(stats.status), width, getStatusStyle(stats.status)),
|
|
9828
|
-
createKeyValueLine(
|
|
9829
|
+
createKeyValueLine(iterationsLabel, formatNumber(stats.iterations), width),
|
|
9829
9830
|
createKeyValueLine("Elapsed", formatElapsed(stats.elapsedMs), width),
|
|
9830
9831
|
createBlankLine(),
|
|
9831
9832
|
createKeyValueLine("Tokens In", formatNumber(stats.tokensIn), width),
|
|
@@ -11936,8 +11937,8 @@ function resourceNotFound(resource) {
|
|
|
11936
11937
|
`Resource not found: ${resource}`
|
|
11937
11938
|
);
|
|
11938
11939
|
}
|
|
11939
|
-
function assertAbsolutePath(
|
|
11940
|
-
if (!isAbsolute(
|
|
11940
|
+
function assertAbsolutePath(path84) {
|
|
11941
|
+
if (!isAbsolute(path84)) {
|
|
11941
11942
|
throw invalidParams('"path" must be an absolute path');
|
|
11942
11943
|
}
|
|
11943
11944
|
}
|
|
@@ -12812,21 +12813,21 @@ async function* adaptClaude(lines) {
|
|
|
12812
12813
|
if (blockType !== "tool_result") continue;
|
|
12813
12814
|
const kind = toolKindsById.get(item.tool_use_id);
|
|
12814
12815
|
toolKindsById.delete(item.tool_use_id);
|
|
12815
|
-
let
|
|
12816
|
+
let path84;
|
|
12816
12817
|
if (typeof item.content === "string") {
|
|
12817
|
-
|
|
12818
|
+
path84 = item.content;
|
|
12818
12819
|
} else {
|
|
12819
12820
|
try {
|
|
12820
|
-
|
|
12821
|
+
path84 = JSON.stringify(item.content);
|
|
12821
12822
|
} catch {
|
|
12822
|
-
|
|
12823
|
+
path84 = String(item.content);
|
|
12823
12824
|
}
|
|
12824
12825
|
}
|
|
12825
12826
|
yield {
|
|
12826
12827
|
event: "tool_complete",
|
|
12827
12828
|
id: item.tool_use_id,
|
|
12828
12829
|
kind,
|
|
12829
|
-
path:
|
|
12830
|
+
path: path84
|
|
12830
12831
|
};
|
|
12831
12832
|
}
|
|
12832
12833
|
}
|
|
@@ -12949,10 +12950,10 @@ async function* adaptCodex(lines) {
|
|
|
12949
12950
|
const kindFromStart = toolKindById.get(item.id);
|
|
12950
12951
|
const kind = kindFromStart ?? (itemType === "command_execution" ? "exec" : itemType === "file_edit" ? "edit" : "other");
|
|
12951
12952
|
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;
|
|
12952
|
-
const
|
|
12953
|
+
const path84 = titleFromEvent ?? toolTitleById.get(item.id) ?? "";
|
|
12953
12954
|
toolTitleById.delete(item.id);
|
|
12954
12955
|
toolKindById.delete(item.id);
|
|
12955
|
-
yield { event: "tool_complete", id: item.id, kind, path:
|
|
12956
|
+
yield { event: "tool_complete", id: item.id, kind, path: path84 };
|
|
12956
12957
|
}
|
|
12957
12958
|
}
|
|
12958
12959
|
}
|
|
@@ -13636,7 +13637,7 @@ function updateSessionFromEvent(ctx, event, toolCallsById) {
|
|
|
13636
13637
|
}
|
|
13637
13638
|
const id = readString(event.id);
|
|
13638
13639
|
const kind = readString(event.kind);
|
|
13639
|
-
const
|
|
13640
|
+
const path84 = readString(event.path);
|
|
13640
13641
|
let toolCall = id ? toolCallsById.get(id) : void 0;
|
|
13641
13642
|
if (!toolCall) {
|
|
13642
13643
|
toolCall = {};
|
|
@@ -13651,8 +13652,8 @@ function updateSessionFromEvent(ctx, event, toolCallsById) {
|
|
|
13651
13652
|
if (kind) {
|
|
13652
13653
|
toolCall.kind = kind;
|
|
13653
13654
|
}
|
|
13654
|
-
if (
|
|
13655
|
-
toolCall.path =
|
|
13655
|
+
if (path84) {
|
|
13656
|
+
toolCall.path = path84;
|
|
13656
13657
|
}
|
|
13657
13658
|
}
|
|
13658
13659
|
var sessionCapture;
|
|
@@ -22016,8 +22017,35 @@ var init_stage = __esm({
|
|
|
22016
22017
|
|
|
22017
22018
|
// packages/agent-kit/src/lock.ts
|
|
22018
22019
|
import * as fsPromises4 from "node:fs/promises";
|
|
22019
|
-
function
|
|
22020
|
-
|
|
22020
|
+
function createAbortError4() {
|
|
22021
|
+
const error2 = new Error("The operation was aborted.");
|
|
22022
|
+
error2.name = "AbortError";
|
|
22023
|
+
return error2;
|
|
22024
|
+
}
|
|
22025
|
+
function throwIfAborted(signal) {
|
|
22026
|
+
if (signal?.aborted) {
|
|
22027
|
+
throw createAbortError4();
|
|
22028
|
+
}
|
|
22029
|
+
}
|
|
22030
|
+
function sleep(ms, signal) {
|
|
22031
|
+
if (!signal) {
|
|
22032
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
22033
|
+
}
|
|
22034
|
+
if (signal.aborted) {
|
|
22035
|
+
return Promise.reject(createAbortError4());
|
|
22036
|
+
}
|
|
22037
|
+
return new Promise((resolve2, reject) => {
|
|
22038
|
+
const timeoutId = setTimeout(() => {
|
|
22039
|
+
signal.removeEventListener("abort", onAbort);
|
|
22040
|
+
resolve2();
|
|
22041
|
+
}, ms);
|
|
22042
|
+
const onAbort = () => {
|
|
22043
|
+
clearTimeout(timeoutId);
|
|
22044
|
+
signal.removeEventListener("abort", onAbort);
|
|
22045
|
+
reject(createAbortError4());
|
|
22046
|
+
};
|
|
22047
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
22048
|
+
});
|
|
22021
22049
|
}
|
|
22022
22050
|
function backoff(attempt, minTimeout, maxTimeout) {
|
|
22023
22051
|
const delay2 = Math.min(maxTimeout, minTimeout * Math.pow(2, attempt));
|
|
@@ -22028,16 +22056,16 @@ function hasErrorCode(error2, code) {
|
|
|
22028
22056
|
}
|
|
22029
22057
|
function createDefaultFs() {
|
|
22030
22058
|
return {
|
|
22031
|
-
mkdir: async (
|
|
22032
|
-
await fsPromises4.mkdir(
|
|
22059
|
+
mkdir: async (path84, options) => {
|
|
22060
|
+
await fsPromises4.mkdir(path84, options);
|
|
22033
22061
|
},
|
|
22034
22062
|
rmdir: fsPromises4.rmdir,
|
|
22035
|
-
stat: async (
|
|
22036
|
-
const
|
|
22063
|
+
stat: async (path84) => {
|
|
22064
|
+
const stat24 = await fsPromises4.stat(path84);
|
|
22037
22065
|
return {
|
|
22038
|
-
isFile: () =>
|
|
22039
|
-
isDirectory: () =>
|
|
22040
|
-
mtimeMs:
|
|
22066
|
+
isFile: () => stat24.isFile(),
|
|
22067
|
+
isDirectory: () => stat24.isDirectory(),
|
|
22068
|
+
mtimeMs: stat24.mtimeMs
|
|
22041
22069
|
};
|
|
22042
22070
|
}
|
|
22043
22071
|
};
|
|
@@ -22059,6 +22087,7 @@ async function lockWorkflow(docPath, options = {}) {
|
|
|
22059
22087
|
const staleMs = options.staleMs ?? 3e4;
|
|
22060
22088
|
const lockPath = `${docPath}.lock`;
|
|
22061
22089
|
for (let attempt = 0; attempt <= retries; attempt += 1) {
|
|
22090
|
+
throwIfAborted(options.signal);
|
|
22062
22091
|
try {
|
|
22063
22092
|
await fs17.mkdir(lockPath);
|
|
22064
22093
|
let released = false;
|
|
@@ -22073,21 +22102,21 @@ async function lockWorkflow(docPath, options = {}) {
|
|
|
22073
22102
|
if (!hasErrorCode(error2, "EEXIST")) {
|
|
22074
22103
|
throw error2;
|
|
22075
22104
|
}
|
|
22076
|
-
let
|
|
22105
|
+
let stat24;
|
|
22077
22106
|
try {
|
|
22078
|
-
|
|
22107
|
+
stat24 = await fs17.stat(lockPath);
|
|
22079
22108
|
} catch (statError) {
|
|
22080
22109
|
if (hasErrorCode(statError, "ENOENT")) {
|
|
22081
22110
|
continue;
|
|
22082
22111
|
}
|
|
22083
22112
|
throw statError;
|
|
22084
22113
|
}
|
|
22085
|
-
if (Date.now() -
|
|
22114
|
+
if (Date.now() - stat24.mtimeMs > staleMs) {
|
|
22086
22115
|
await removeLockDirectory(fs17, lockPath);
|
|
22087
22116
|
continue;
|
|
22088
22117
|
}
|
|
22089
22118
|
if (attempt < retries) {
|
|
22090
|
-
await sleep(backoff(attempt, minTimeout, maxTimeout));
|
|
22119
|
+
await sleep(backoff(attempt, minTimeout, maxTimeout), options.signal);
|
|
22091
22120
|
}
|
|
22092
22121
|
}
|
|
22093
22122
|
}
|
|
@@ -22115,7 +22144,7 @@ function toAbortError2(reason) {
|
|
|
22115
22144
|
}
|
|
22116
22145
|
return new Error(reason === void 0 ? "This operation was aborted." : String(reason));
|
|
22117
22146
|
}
|
|
22118
|
-
function
|
|
22147
|
+
function throwIfAborted2(signal) {
|
|
22119
22148
|
if (!signal?.aborted) {
|
|
22120
22149
|
return;
|
|
22121
22150
|
}
|
|
@@ -22248,7 +22277,7 @@ async function runDocumentWorkflow(options) {
|
|
|
22248
22277
|
let pendingError;
|
|
22249
22278
|
let currentWorkflow = initialWorkflow;
|
|
22250
22279
|
try {
|
|
22251
|
-
|
|
22280
|
+
throwIfAborted2(options.signal);
|
|
22252
22281
|
if (initialWorkflow.setup) {
|
|
22253
22282
|
await runWorkflowHook(initialWorkflow.setup, {
|
|
22254
22283
|
cwd: options.cwd,
|
|
@@ -22264,12 +22293,12 @@ async function runDocumentWorkflow(options) {
|
|
|
22264
22293
|
}
|
|
22265
22294
|
let shouldStop = false;
|
|
22266
22295
|
for (let iteration = 0; iteration < initialWorkflow.maxIterations; iteration += 1) {
|
|
22267
|
-
|
|
22296
|
+
throwIfAborted2(options.signal);
|
|
22268
22297
|
currentWorkflow = iteration === 0 ? initialWorkflow : await readWorkflow();
|
|
22269
22298
|
await options.onIterationStart?.(iteration);
|
|
22270
22299
|
let iterationResult = "completed";
|
|
22271
22300
|
for (const stage of currentWorkflow.stages) {
|
|
22272
|
-
|
|
22301
|
+
throwIfAborted2(options.signal);
|
|
22273
22302
|
try {
|
|
22274
22303
|
const stageResult = await runWorkflowStage(stage, {
|
|
22275
22304
|
cwd: options.cwd,
|
|
@@ -23536,11 +23565,11 @@ function createDefaultFs2() {
|
|
|
23536
23565
|
writeFile: fsPromises5.writeFile,
|
|
23537
23566
|
readdir: fsPromises5.readdir,
|
|
23538
23567
|
stat: async (filePath) => {
|
|
23539
|
-
const
|
|
23568
|
+
const stat24 = await fsPromises5.stat(filePath);
|
|
23540
23569
|
return {
|
|
23541
|
-
isFile: () =>
|
|
23542
|
-
isDirectory: () =>
|
|
23543
|
-
mtimeMs:
|
|
23570
|
+
isFile: () => stat24.isFile(),
|
|
23571
|
+
isDirectory: () => stat24.isDirectory(),
|
|
23572
|
+
mtimeMs: stat24.mtimeMs
|
|
23544
23573
|
};
|
|
23545
23574
|
},
|
|
23546
23575
|
mkdir: async (filePath, options) => {
|
|
@@ -25971,11 +26000,11 @@ function createDefaultFs3() {
|
|
|
25971
26000
|
writeFile: fsPromises6.writeFile,
|
|
25972
26001
|
readdir: fsPromises6.readdir,
|
|
25973
26002
|
stat: async (filePath) => {
|
|
25974
|
-
const
|
|
26003
|
+
const stat24 = await fsPromises6.stat(filePath);
|
|
25975
26004
|
return {
|
|
25976
|
-
isFile: () =>
|
|
25977
|
-
isDirectory: () =>
|
|
25978
|
-
mtimeMs:
|
|
26005
|
+
isFile: () => stat24.isFile(),
|
|
26006
|
+
isDirectory: () => stat24.isDirectory(),
|
|
26007
|
+
mtimeMs: stat24.mtimeMs
|
|
25979
26008
|
};
|
|
25980
26009
|
},
|
|
25981
26010
|
mkdir: async (filePath, mkdirOptions) => {
|
|
@@ -26099,8 +26128,8 @@ var init_run = __esm({
|
|
|
26099
26128
|
},
|
|
26100
26129
|
unlink: (filePath) => fsPromises6.unlink(filePath),
|
|
26101
26130
|
stat: async (filePath) => {
|
|
26102
|
-
const
|
|
26103
|
-
return { mode:
|
|
26131
|
+
const stat24 = await fsPromises6.stat(filePath);
|
|
26132
|
+
return { mode: stat24.mode };
|
|
26104
26133
|
},
|
|
26105
26134
|
readdir: (filePath) => fsPromises6.readdir(filePath)
|
|
26106
26135
|
};
|
|
@@ -26964,14 +26993,14 @@ function parseDockerLocator(input) {
|
|
|
26964
26993
|
throw new Error(`Invalid docker workspace locator "${input}".`);
|
|
26965
26994
|
}
|
|
26966
26995
|
const container = input.slice(0, slashIndex);
|
|
26967
|
-
const
|
|
26968
|
-
if (container.length === 0 ||
|
|
26996
|
+
const path84 = input.slice(slashIndex);
|
|
26997
|
+
if (container.length === 0 || path84.length === 0) {
|
|
26969
26998
|
throw new Error(`Invalid docker workspace locator "${input}".`);
|
|
26970
26999
|
}
|
|
26971
27000
|
return {
|
|
26972
27001
|
scheme: "docker",
|
|
26973
27002
|
container,
|
|
26974
|
-
path:
|
|
27003
|
+
path: path84
|
|
26975
27004
|
};
|
|
26976
27005
|
}
|
|
26977
27006
|
function splitOnce(input, separator) {
|
|
@@ -28795,25 +28824,25 @@ function createSdkContainer(options) {
|
|
|
28795
28824
|
});
|
|
28796
28825
|
loggerFactory.setErrorLogger(errorLogger);
|
|
28797
28826
|
const asyncFs = {
|
|
28798
|
-
readFile: ((
|
|
28827
|
+
readFile: ((path84, encoding) => {
|
|
28799
28828
|
if (encoding) {
|
|
28800
|
-
return fs3.readFile(
|
|
28829
|
+
return fs3.readFile(path84, encoding);
|
|
28801
28830
|
}
|
|
28802
|
-
return fs3.readFile(
|
|
28831
|
+
return fs3.readFile(path84);
|
|
28803
28832
|
}),
|
|
28804
|
-
symlink: (target,
|
|
28805
|
-
readlink: (
|
|
28806
|
-
writeFile: (
|
|
28807
|
-
mkdir: (
|
|
28833
|
+
symlink: (target, path84) => fs3.symlink(target, path84),
|
|
28834
|
+
readlink: (path84) => fs3.readlink(path84, { encoding: "utf8" }),
|
|
28835
|
+
writeFile: (path84, data, opts) => fs3.writeFile(path84, data, opts),
|
|
28836
|
+
mkdir: (path84, opts) => fs3.mkdir(path84, opts).then(() => {
|
|
28808
28837
|
}),
|
|
28809
|
-
stat: (
|
|
28810
|
-
lstat: (
|
|
28838
|
+
stat: (path84) => fs3.stat(path84),
|
|
28839
|
+
lstat: (path84) => fs3.lstat(path84),
|
|
28811
28840
|
rename: (oldPath, newPath) => fs3.rename(oldPath, newPath),
|
|
28812
|
-
rm: (
|
|
28813
|
-
unlink: (
|
|
28814
|
-
readdir: (
|
|
28841
|
+
rm: (path84, opts) => fs3.rm(path84, opts),
|
|
28842
|
+
unlink: (path84) => fs3.unlink(path84),
|
|
28843
|
+
readdir: (path84) => fs3.readdir(path84),
|
|
28815
28844
|
copyFile: (src, dest) => fs3.copyFile(src, dest),
|
|
28816
|
-
chmod: (
|
|
28845
|
+
chmod: (path84, mode) => fs3.chmod(path84, mode)
|
|
28817
28846
|
};
|
|
28818
28847
|
const contextFactory = createCommandContextFactory({ fs: asyncFs });
|
|
28819
28848
|
const authFs = {
|
|
@@ -29180,9 +29209,9 @@ function assertNotAborted4(signal) {
|
|
|
29180
29209
|
if (!signal?.aborted) {
|
|
29181
29210
|
return;
|
|
29182
29211
|
}
|
|
29183
|
-
throw
|
|
29212
|
+
throw createAbortError5();
|
|
29184
29213
|
}
|
|
29185
|
-
function
|
|
29214
|
+
function createAbortError5() {
|
|
29186
29215
|
const error2 = new Error("Pipeline run cancelled");
|
|
29187
29216
|
error2.name = "AbortError";
|
|
29188
29217
|
return error2;
|
|
@@ -29195,7 +29224,7 @@ var init_utils2 = __esm({
|
|
|
29195
29224
|
|
|
29196
29225
|
// packages/pipeline/src/config/loader.ts
|
|
29197
29226
|
import path34 from "node:path";
|
|
29198
|
-
import { parse as parse6
|
|
29227
|
+
import { parse as parse6 } from "yaml";
|
|
29199
29228
|
function asStepMode(value) {
|
|
29200
29229
|
if (value === void 0 || value === null) {
|
|
29201
29230
|
return "yolo";
|
|
@@ -29213,13 +29242,6 @@ function parseYamlDocument(filePath, content) {
|
|
|
29213
29242
|
throw new Error(`Invalid pipeline step config YAML in "${filePath}": ${message2}`);
|
|
29214
29243
|
}
|
|
29215
29244
|
}
|
|
29216
|
-
function parseStepConfigSource(filePath, content) {
|
|
29217
|
-
const document = parseYamlDocument(filePath, content);
|
|
29218
|
-
return {
|
|
29219
|
-
config: parseStepConfigData(filePath, document),
|
|
29220
|
-
extendsBase: isRecord11(document) && document.extends === true
|
|
29221
|
-
};
|
|
29222
|
-
}
|
|
29223
29245
|
function parseStepConfigData(filePath, document) {
|
|
29224
29246
|
if (document === null || document === void 0) {
|
|
29225
29247
|
return { steps: {} };
|
|
@@ -29261,102 +29283,72 @@ function parseStepConfigData(filePath, document) {
|
|
|
29261
29283
|
}
|
|
29262
29284
|
return result;
|
|
29263
29285
|
}
|
|
29264
|
-
function
|
|
29265
|
-
const
|
|
29266
|
-
if (
|
|
29267
|
-
|
|
29268
|
-
Object.entries(config.steps).map(([stepName, definition]) => [
|
|
29269
|
-
stepName,
|
|
29270
|
-
JSON.stringify(definition)
|
|
29271
|
-
])
|
|
29272
|
-
);
|
|
29273
|
-
}
|
|
29274
|
-
if (config.setup !== void 0) {
|
|
29275
|
-
data.setup = JSON.stringify(config.setup);
|
|
29276
|
-
}
|
|
29277
|
-
if (config.teardown !== void 0) {
|
|
29278
|
-
data.teardown = JSON.stringify(config.teardown);
|
|
29286
|
+
function mergeStepDefinition(base, override, context) {
|
|
29287
|
+
const prompt = override.prompt ?? base?.prompt;
|
|
29288
|
+
if (typeof prompt !== "string" || prompt.length === 0) {
|
|
29289
|
+
throw new Error(`Missing prompt for ${context}.`);
|
|
29279
29290
|
}
|
|
29280
|
-
|
|
29291
|
+
const agent2 = override.agent ?? base?.agent;
|
|
29292
|
+
const model = override.model ?? base?.model;
|
|
29293
|
+
return {
|
|
29294
|
+
mode: override.mode ?? base?.mode ?? "yolo",
|
|
29295
|
+
prompt,
|
|
29296
|
+
...agent2 ? { agent: agent2 } : {},
|
|
29297
|
+
...model ? { model } : {}
|
|
29298
|
+
};
|
|
29281
29299
|
}
|
|
29282
|
-
function
|
|
29283
|
-
|
|
29284
|
-
|
|
29285
|
-
if (!isRecord11(document.steps)) {
|
|
29286
|
-
throw new Error(`Invalid pipeline step config in "${filePath}": "steps" must be an object.`);
|
|
29287
|
-
}
|
|
29288
|
-
decoded.steps = Object.fromEntries(
|
|
29289
|
-
Object.entries(document.steps).map(([stepName, definition]) => [
|
|
29290
|
-
stepName,
|
|
29291
|
-
decodeEncodedDefinition(filePath, definition, `step "${stepName}"`)
|
|
29292
|
-
])
|
|
29293
|
-
);
|
|
29300
|
+
function applyStepOverrides(config, stepOverrides) {
|
|
29301
|
+
if (!stepOverrides || Object.keys(stepOverrides).length === 0) {
|
|
29302
|
+
return config;
|
|
29294
29303
|
}
|
|
29295
|
-
|
|
29296
|
-
|
|
29304
|
+
const steps = { ...config.steps };
|
|
29305
|
+
for (const [stepName, override] of Object.entries(stepOverrides)) {
|
|
29306
|
+
steps[stepName] = mergeStepDefinition(steps[stepName], override, `plan step "${stepName}"`);
|
|
29297
29307
|
}
|
|
29298
|
-
|
|
29299
|
-
|
|
29300
|
-
|
|
29301
|
-
|
|
29308
|
+
return {
|
|
29309
|
+
...config,
|
|
29310
|
+
steps
|
|
29311
|
+
};
|
|
29302
29312
|
}
|
|
29303
|
-
function
|
|
29304
|
-
if (typeof value !== "string") {
|
|
29305
|
-
throw new Error(`Invalid ${context} in "${filePath}": expected an object.`);
|
|
29306
|
-
}
|
|
29307
|
-
let decoded;
|
|
29313
|
+
async function directoryExists(fs17, targetPath) {
|
|
29308
29314
|
try {
|
|
29309
|
-
|
|
29315
|
+
return (await fs17.stat(targetPath)).isDirectory();
|
|
29310
29316
|
} catch (error2) {
|
|
29311
|
-
|
|
29312
|
-
|
|
29313
|
-
|
|
29314
|
-
|
|
29315
|
-
throw new Error(`Invalid ${context} in "${filePath}": expected an object.`);
|
|
29317
|
+
if (isNotFound2(error2)) {
|
|
29318
|
+
return false;
|
|
29319
|
+
}
|
|
29320
|
+
throw error2;
|
|
29316
29321
|
}
|
|
29317
|
-
return decoded;
|
|
29318
29322
|
}
|
|
29319
|
-
async function
|
|
29320
|
-
const
|
|
29321
|
-
|
|
29322
|
-
|
|
29323
|
-
const [globalContent, projectContent] = await Promise.all([
|
|
29324
|
-
readOptionalFile2(options.fs, globalPath),
|
|
29325
|
-
readOptionalFile2(options.fs, projectPath)
|
|
29326
|
-
]);
|
|
29327
|
-
const globalSource = globalContent == null ? void 0 : parseStepConfigSource(globalPath, globalContent);
|
|
29328
|
-
if (projectContent == null) {
|
|
29329
|
-
return globalSource?.config ?? { steps: {} };
|
|
29323
|
+
async function resolveStepsDirectory(options) {
|
|
29324
|
+
const projectDir = path34.join(options.cwd, ".poe-code", "pipeline", "steps");
|
|
29325
|
+
if (await directoryExists(options.fs, projectDir)) {
|
|
29326
|
+
return projectDir;
|
|
29330
29327
|
}
|
|
29331
|
-
const
|
|
29332
|
-
if (
|
|
29333
|
-
|
|
29334
|
-
[
|
|
29335
|
-
{ source: "document", filePath: projectPath, content: projectContent },
|
|
29336
|
-
{ source: "base", path: globalDir }
|
|
29337
|
-
],
|
|
29338
|
-
{ fs: options.fs }
|
|
29339
|
-
);
|
|
29340
|
-
return parseStepConfigData(projectPath, resolved2.data);
|
|
29328
|
+
const globalDir = path34.join(options.homeDir, ".poe-code", "pipeline", "steps");
|
|
29329
|
+
if (await directoryExists(options.fs, globalDir)) {
|
|
29330
|
+
return globalDir;
|
|
29341
29331
|
}
|
|
29342
|
-
|
|
29343
|
-
|
|
29344
|
-
|
|
29345
|
-
const
|
|
29346
|
-
|
|
29347
|
-
|
|
29348
|
-
|
|
29349
|
-
|
|
29350
|
-
|
|
29351
|
-
|
|
29352
|
-
|
|
29353
|
-
|
|
29354
|
-
|
|
29355
|
-
|
|
29356
|
-
|
|
29357
|
-
|
|
29332
|
+
return null;
|
|
29333
|
+
}
|
|
29334
|
+
async function loadResolvedSteps(options) {
|
|
29335
|
+
const name = options.name?.trim() || "default";
|
|
29336
|
+
const stepsDir = await resolveStepsDirectory(options);
|
|
29337
|
+
if (!stepsDir) {
|
|
29338
|
+
if (name !== "default") {
|
|
29339
|
+
throw new Error(`Unknown pipeline step config "${name}": no pipeline steps directory found.`);
|
|
29340
|
+
}
|
|
29341
|
+
return applyStepOverrides({ steps: {} }, options.stepOverrides);
|
|
29342
|
+
}
|
|
29343
|
+
const filePath = path34.join(stepsDir, `${name}.yaml`);
|
|
29344
|
+
const content = await readOptionalFile2(options.fs, filePath);
|
|
29345
|
+
if (content == null) {
|
|
29346
|
+
throw new Error(`Unknown pipeline step config "${name}" in "${stepsDir}".`);
|
|
29347
|
+
}
|
|
29348
|
+
return applyStepOverrides(
|
|
29349
|
+
parseStepConfigData(filePath, parseYamlDocument(filePath, content)),
|
|
29350
|
+
options.stepOverrides
|
|
29358
29351
|
);
|
|
29359
|
-
return parseStepConfigData(projectPath, decodeShallowStepsConfig(projectPath, resolved.data));
|
|
29360
29352
|
}
|
|
29361
29353
|
var init_loader = __esm({
|
|
29362
29354
|
"packages/pipeline/src/config/loader.ts"() {
|
|
@@ -29420,23 +29412,60 @@ function parseTaskStatus(value, availableSteps, taskId) {
|
|
|
29420
29412
|
}
|
|
29421
29413
|
return statusMap;
|
|
29422
29414
|
}
|
|
29423
|
-
function
|
|
29424
|
-
if (value ===
|
|
29425
|
-
|
|
29415
|
+
function parseStepMode(value, label) {
|
|
29416
|
+
if (value === void 0 || value === null) {
|
|
29417
|
+
return void 0;
|
|
29418
|
+
}
|
|
29419
|
+
if (value === "yolo" || value === "edit" || value === "read") {
|
|
29420
|
+
return value;
|
|
29421
|
+
}
|
|
29422
|
+
throw new Error(`Invalid plan YAML: "${label}.mode" must be "yolo", "edit", or "read".`);
|
|
29426
29423
|
}
|
|
29427
|
-
function
|
|
29424
|
+
function parseOptionalAgentFields(value, label) {
|
|
29425
|
+
const result = {};
|
|
29426
|
+
if (value.agent !== void 0) {
|
|
29427
|
+
if (typeof value.agent !== "string" || value.agent.length === 0) {
|
|
29428
|
+
throw new Error(`Invalid plan YAML: "${label}.agent" must be a non-empty string.`);
|
|
29429
|
+
}
|
|
29430
|
+
result.agent = value.agent;
|
|
29431
|
+
}
|
|
29432
|
+
if (value.model !== void 0) {
|
|
29433
|
+
if (typeof value.model !== "string" || value.model.length === 0) {
|
|
29434
|
+
throw new Error(`Invalid plan YAML: "${label}.model" must be a non-empty string.`);
|
|
29435
|
+
}
|
|
29436
|
+
result.model = value.model;
|
|
29437
|
+
}
|
|
29438
|
+
return result;
|
|
29439
|
+
}
|
|
29440
|
+
function parseStepOverride(value, label) {
|
|
29428
29441
|
if (!isRecord11(value)) {
|
|
29429
29442
|
throw new Error(`Invalid plan YAML: "${label}" must be an object.`);
|
|
29430
29443
|
}
|
|
29431
|
-
const
|
|
29432
|
-
|
|
29444
|
+
const result = {
|
|
29445
|
+
...parseOptionalAgentFields(value, label)
|
|
29446
|
+
};
|
|
29447
|
+
const mode = parseStepMode(value.mode, label);
|
|
29448
|
+
if (mode !== void 0) {
|
|
29449
|
+
result.mode = mode;
|
|
29450
|
+
}
|
|
29451
|
+
if (value.prompt !== void 0) {
|
|
29452
|
+
if (typeof value.prompt !== "string" || value.prompt.length === 0) {
|
|
29453
|
+
throw new Error(`Invalid plan YAML: "${label}.prompt" must be a non-empty string.`);
|
|
29454
|
+
}
|
|
29455
|
+
result.prompt = value.prompt;
|
|
29456
|
+
}
|
|
29457
|
+
return result;
|
|
29458
|
+
}
|
|
29459
|
+
function parseStepDef(value, label) {
|
|
29460
|
+
const override = parseStepOverride(value, label);
|
|
29461
|
+
if (override.prompt === void 0) {
|
|
29433
29462
|
throw new Error(`Invalid plan YAML: "${label}" is missing a prompt.`);
|
|
29434
29463
|
}
|
|
29435
29464
|
return {
|
|
29436
|
-
mode:
|
|
29437
|
-
prompt,
|
|
29438
|
-
...
|
|
29439
|
-
...
|
|
29465
|
+
mode: override.mode ?? "yolo",
|
|
29466
|
+
prompt: override.prompt,
|
|
29467
|
+
...override.agent ? { agent: override.agent } : {},
|
|
29468
|
+
...override.model ? { model: override.model } : {}
|
|
29440
29469
|
};
|
|
29441
29470
|
}
|
|
29442
29471
|
function parseMcpConfig2(value) {
|
|
@@ -29480,6 +29509,23 @@ function parsePlan(planContent, options = {}) {
|
|
|
29480
29509
|
if (!isRecord11(document)) {
|
|
29481
29510
|
throw new Error("Invalid plan YAML: expected a top-level object.");
|
|
29482
29511
|
}
|
|
29512
|
+
let extendsName = "default";
|
|
29513
|
+
if (document.extends !== void 0) {
|
|
29514
|
+
if (typeof document.extends !== "string" || document.extends.trim().length === 0) {
|
|
29515
|
+
throw new Error('Invalid plan YAML: "extends" must be a non-empty string.');
|
|
29516
|
+
}
|
|
29517
|
+
extendsName = document.extends.trim();
|
|
29518
|
+
}
|
|
29519
|
+
let stepOverrides;
|
|
29520
|
+
if (document.steps !== void 0) {
|
|
29521
|
+
if (!isRecord11(document.steps)) {
|
|
29522
|
+
throw new Error('Invalid plan YAML: "steps" must be an object.');
|
|
29523
|
+
}
|
|
29524
|
+
stepOverrides = {};
|
|
29525
|
+
for (const [stepName, value] of Object.entries(document.steps)) {
|
|
29526
|
+
stepOverrides[stepName] = parseStepOverride(value, `steps.${stepName}`);
|
|
29527
|
+
}
|
|
29528
|
+
}
|
|
29483
29529
|
const tasksValue = document.tasks;
|
|
29484
29530
|
if (!Array.isArray(tasksValue)) {
|
|
29485
29531
|
throw new Error('Invalid plan YAML: expected "tasks" to be an array.');
|
|
@@ -29519,6 +29565,8 @@ function parsePlan(planContent, options = {}) {
|
|
|
29519
29565
|
}
|
|
29520
29566
|
}
|
|
29521
29567
|
return {
|
|
29568
|
+
extends: extendsName,
|
|
29569
|
+
...stepOverrides !== void 0 ? { stepOverrides } : {},
|
|
29522
29570
|
tasks,
|
|
29523
29571
|
...vars !== void 0 ? { vars } : {},
|
|
29524
29572
|
...setup !== void 0 ? { setup } : {},
|
|
@@ -29543,11 +29591,11 @@ function createDefaultFs4() {
|
|
|
29543
29591
|
readFile: fsPromises7.readFile,
|
|
29544
29592
|
readdir: fsPromises7.readdir,
|
|
29545
29593
|
stat: async (filePath) => {
|
|
29546
|
-
const
|
|
29594
|
+
const stat24 = await fsPromises7.stat(filePath);
|
|
29547
29595
|
return {
|
|
29548
|
-
isFile: () =>
|
|
29549
|
-
isDirectory: () =>
|
|
29550
|
-
mtimeMs:
|
|
29596
|
+
isFile: () => stat24.isFile(),
|
|
29597
|
+
isDirectory: () => stat24.isDirectory(),
|
|
29598
|
+
mtimeMs: stat24.mtimeMs
|
|
29551
29599
|
};
|
|
29552
29600
|
}
|
|
29553
29601
|
};
|
|
@@ -29574,8 +29622,8 @@ function countCompletedTasks(planPath, content) {
|
|
|
29574
29622
|
async function ensurePlanExists(fs17, cwd, planPath) {
|
|
29575
29623
|
const absolutePath = path35.isAbsolute(planPath) ? planPath : path35.resolve(cwd, planPath);
|
|
29576
29624
|
try {
|
|
29577
|
-
const
|
|
29578
|
-
if (!
|
|
29625
|
+
const stat24 = await fs17.stat(absolutePath);
|
|
29626
|
+
if (!stat24.isFile()) {
|
|
29579
29627
|
throw new Error(`Plan not found at "${planPath}".`);
|
|
29580
29628
|
}
|
|
29581
29629
|
} catch (error2) {
|
|
@@ -29601,8 +29649,8 @@ async function scanPlansDir(fs17, plansDir, displayPrefix) {
|
|
|
29601
29649
|
continue;
|
|
29602
29650
|
}
|
|
29603
29651
|
const absolutePath = path35.join(plansDir, entry);
|
|
29604
|
-
const
|
|
29605
|
-
if (!
|
|
29652
|
+
const stat24 = await fs17.stat(absolutePath);
|
|
29653
|
+
if (!stat24.isFile()) {
|
|
29606
29654
|
continue;
|
|
29607
29655
|
}
|
|
29608
29656
|
const displayPath2 = path35.join(displayPrefix, entry);
|
|
@@ -29875,6 +29923,23 @@ var init_writer2 = __esm({
|
|
|
29875
29923
|
}
|
|
29876
29924
|
});
|
|
29877
29925
|
|
|
29926
|
+
// packages/pipeline/src/vars/interpolate.ts
|
|
29927
|
+
function interpolatePipelineVars(template, values, context = "template") {
|
|
29928
|
+
return template.replace(PLACEHOLDER_PATTERN, (_match, key) => {
|
|
29929
|
+
if (!Object.prototype.hasOwnProperty.call(values, key)) {
|
|
29930
|
+
throw new Error(`Missing pipeline variable "${key}" in ${context}.`);
|
|
29931
|
+
}
|
|
29932
|
+
return values[key];
|
|
29933
|
+
});
|
|
29934
|
+
}
|
|
29935
|
+
var PLACEHOLDER_PATTERN;
|
|
29936
|
+
var init_interpolate = __esm({
|
|
29937
|
+
"packages/pipeline/src/vars/interpolate.ts"() {
|
|
29938
|
+
"use strict";
|
|
29939
|
+
PLACEHOLDER_PATTERN = /\{\{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}/g;
|
|
29940
|
+
}
|
|
29941
|
+
});
|
|
29942
|
+
|
|
29878
29943
|
// packages/pipeline/src/run/runner.ts
|
|
29879
29944
|
import path36 from "node:path";
|
|
29880
29945
|
function selectFromTask(task) {
|
|
@@ -29897,12 +29962,8 @@ function selectNextExecution(plan, taskId) {
|
|
|
29897
29962
|
}
|
|
29898
29963
|
return { kind: "completed" };
|
|
29899
29964
|
}
|
|
29900
|
-
function
|
|
29901
|
-
|
|
29902
|
-
for (const [key, value] of Object.entries(values)) {
|
|
29903
|
-
output = output.split(`{{${key}}}`).join(value);
|
|
29904
|
-
}
|
|
29905
|
-
return output;
|
|
29965
|
+
function describeExecutionContext(selection) {
|
|
29966
|
+
return selection.stepName ? `task "${selection.task.id}" step "${selection.stepName}"` : `task "${selection.task.id}"`;
|
|
29906
29967
|
}
|
|
29907
29968
|
async function resolveFileIncludes(template, cwd, readFile34) {
|
|
29908
29969
|
const matches2 = [...template.matchAll(FILE_INCLUDE_PATTERN)];
|
|
@@ -29918,31 +29979,128 @@ async function resolveFileIncludes(template, cwd, readFile34) {
|
|
|
29918
29979
|
return result;
|
|
29919
29980
|
}
|
|
29920
29981
|
function buildExecutionPrompt(input) {
|
|
29982
|
+
const context = describeExecutionContext(input.selection);
|
|
29983
|
+
const resolvedTaskPrompt = interpolatePipelineVars(
|
|
29984
|
+
input.selection.task.prompt,
|
|
29985
|
+
input.vars ?? {},
|
|
29986
|
+
context
|
|
29987
|
+
);
|
|
29921
29988
|
if (!input.selection.stepName) {
|
|
29922
|
-
return
|
|
29989
|
+
return resolvedTaskPrompt;
|
|
29923
29990
|
}
|
|
29924
29991
|
const step = input.steps[input.selection.stepName];
|
|
29925
29992
|
if (!step) {
|
|
29926
29993
|
throw new Error(`Missing step definition for "${input.selection.stepName}".`);
|
|
29927
29994
|
}
|
|
29928
|
-
return
|
|
29929
|
-
|
|
29930
|
-
|
|
29931
|
-
|
|
29932
|
-
|
|
29933
|
-
|
|
29934
|
-
|
|
29995
|
+
return interpolatePipelineVars(
|
|
29996
|
+
step.prompt,
|
|
29997
|
+
{
|
|
29998
|
+
...input.vars ?? {},
|
|
29999
|
+
id: input.selection.task.id,
|
|
30000
|
+
title: input.selection.task.title,
|
|
30001
|
+
prompt: resolvedTaskPrompt,
|
|
30002
|
+
plan_path: input.planPath
|
|
30003
|
+
},
|
|
30004
|
+
context
|
|
30005
|
+
);
|
|
29935
30006
|
}
|
|
29936
30007
|
var FILE_INCLUDE_PATTERN;
|
|
29937
30008
|
var init_runner2 = __esm({
|
|
29938
30009
|
"packages/pipeline/src/run/runner.ts"() {
|
|
29939
30010
|
"use strict";
|
|
30011
|
+
init_interpolate();
|
|
29940
30012
|
FILE_INCLUDE_PATTERN = /\{\{file\s+['"]([^'"]+)['"]\s*\}\}/g;
|
|
29941
30013
|
}
|
|
29942
30014
|
});
|
|
29943
30015
|
|
|
29944
|
-
// packages/pipeline/src/
|
|
30016
|
+
// packages/pipeline/src/vars/resolve.ts
|
|
29945
30017
|
import path37 from "node:path";
|
|
30018
|
+
function looksLikeDocPath(value) {
|
|
30019
|
+
const trimmed = value.trim();
|
|
30020
|
+
if (trimmed.length === 0) return false;
|
|
30021
|
+
if (trimmed.includes("\n")) return false;
|
|
30022
|
+
if (trimmed.includes("{{")) return false;
|
|
30023
|
+
if (trimmed.startsWith("/") || trimmed.startsWith("./") || trimmed.startsWith("../")) {
|
|
30024
|
+
return true;
|
|
30025
|
+
}
|
|
30026
|
+
if (trimmed.includes("/")) return true;
|
|
30027
|
+
if (trimmed.endsWith(".md") || trimmed.endsWith(".markdown") || trimmed.endsWith(".txt")) {
|
|
30028
|
+
return true;
|
|
30029
|
+
}
|
|
30030
|
+
return false;
|
|
30031
|
+
}
|
|
30032
|
+
async function resolveDocVarFromPath(options) {
|
|
30033
|
+
const trimmed = options.value.trim();
|
|
30034
|
+
const absolutePath = path37.isAbsolute(trimmed) ? trimmed : path37.join(options.cwd, trimmed);
|
|
30035
|
+
try {
|
|
30036
|
+
return await options.readFile(absolutePath, "utf8");
|
|
30037
|
+
} catch (error2) {
|
|
30038
|
+
throw new Error(
|
|
30039
|
+
`Failed to read doc var "${options.key}" from "${trimmed}" (resolved to ${absolutePath}).`,
|
|
30040
|
+
{ cause: error2 }
|
|
30041
|
+
);
|
|
30042
|
+
}
|
|
30043
|
+
}
|
|
30044
|
+
async function resolvePipelineVars(vars, cwd, readFile34) {
|
|
30045
|
+
const resolved = {};
|
|
30046
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
30047
|
+
if (key.endsWith("_doc") && looksLikeDocPath(value)) {
|
|
30048
|
+
const docContent = await resolveDocVarFromPath({ key, value, cwd, readFile: readFile34 });
|
|
30049
|
+
resolved[key] = await resolveFileIncludes(docContent, cwd, readFile34);
|
|
30050
|
+
continue;
|
|
30051
|
+
}
|
|
30052
|
+
resolved[key] = await resolveFileIncludes(value, cwd, readFile34);
|
|
30053
|
+
}
|
|
30054
|
+
return resolved;
|
|
30055
|
+
}
|
|
30056
|
+
var init_resolve4 = __esm({
|
|
30057
|
+
"packages/pipeline/src/vars/resolve.ts"() {
|
|
30058
|
+
"use strict";
|
|
30059
|
+
init_runner2();
|
|
30060
|
+
}
|
|
30061
|
+
});
|
|
30062
|
+
|
|
30063
|
+
// packages/pipeline/src/vars/validate.ts
|
|
30064
|
+
function validatePhasePrompt(phase, definition, vars) {
|
|
30065
|
+
if (!definition) {
|
|
30066
|
+
return;
|
|
30067
|
+
}
|
|
30068
|
+
interpolatePipelineVars(definition.prompt, vars, phase);
|
|
30069
|
+
}
|
|
30070
|
+
function validateResolvedPromptVars(input) {
|
|
30071
|
+
const vars = input.vars ?? {};
|
|
30072
|
+
validatePhasePrompt("setup", input.setup, vars);
|
|
30073
|
+
for (const task of input.plan.tasks) {
|
|
30074
|
+
if (typeof task.status === "string") {
|
|
30075
|
+
buildExecutionPrompt({
|
|
30076
|
+
selection: { kind: "run", task },
|
|
30077
|
+
steps: input.steps,
|
|
30078
|
+
planPath: input.planPath,
|
|
30079
|
+
vars
|
|
30080
|
+
});
|
|
30081
|
+
continue;
|
|
30082
|
+
}
|
|
30083
|
+
for (const stepName of Object.keys(task.status)) {
|
|
30084
|
+
buildExecutionPrompt({
|
|
30085
|
+
selection: { kind: "run", task, stepName },
|
|
30086
|
+
steps: input.steps,
|
|
30087
|
+
planPath: input.planPath,
|
|
30088
|
+
vars
|
|
30089
|
+
});
|
|
30090
|
+
}
|
|
30091
|
+
}
|
|
30092
|
+
validatePhasePrompt("teardown", input.teardown, vars);
|
|
30093
|
+
}
|
|
30094
|
+
var init_validate = __esm({
|
|
30095
|
+
"packages/pipeline/src/vars/validate.ts"() {
|
|
30096
|
+
"use strict";
|
|
30097
|
+
init_runner2();
|
|
30098
|
+
init_interpolate();
|
|
30099
|
+
}
|
|
30100
|
+
});
|
|
30101
|
+
|
|
30102
|
+
// packages/pipeline/src/run/pipeline.ts
|
|
30103
|
+
import path38 from "node:path";
|
|
29946
30104
|
import * as fsPromises8 from "node:fs/promises";
|
|
29947
30105
|
function createDefaultFs5() {
|
|
29948
30106
|
return {
|
|
@@ -29950,11 +30108,11 @@ function createDefaultFs5() {
|
|
|
29950
30108
|
writeFile: fsPromises8.writeFile,
|
|
29951
30109
|
readdir: fsPromises8.readdir,
|
|
29952
30110
|
stat: async (filePath) => {
|
|
29953
|
-
const
|
|
30111
|
+
const stat24 = await fsPromises8.stat(filePath);
|
|
29954
30112
|
return {
|
|
29955
|
-
isFile: () =>
|
|
29956
|
-
isDirectory: () =>
|
|
29957
|
-
mtimeMs:
|
|
30113
|
+
isFile: () => stat24.isFile(),
|
|
30114
|
+
isDirectory: () => stat24.isDirectory(),
|
|
30115
|
+
mtimeMs: stat24.mtimeMs
|
|
29958
30116
|
};
|
|
29959
30117
|
},
|
|
29960
30118
|
mkdir: async (filePath, options) => {
|
|
@@ -29964,15 +30122,54 @@ function createDefaultFs5() {
|
|
|
29964
30122
|
rename: fsPromises8.rename
|
|
29965
30123
|
};
|
|
29966
30124
|
}
|
|
30125
|
+
function isTaskDone(status) {
|
|
30126
|
+
if (typeof status === "string") {
|
|
30127
|
+
return status === "done";
|
|
30128
|
+
}
|
|
30129
|
+
return Object.values(status).every((stepStatus) => stepStatus === "done");
|
|
30130
|
+
}
|
|
30131
|
+
function completesTaskOnSuccess(task, stepName) {
|
|
30132
|
+
if (!stepName || typeof task.status === "string") {
|
|
30133
|
+
return true;
|
|
30134
|
+
}
|
|
30135
|
+
return Object.entries(task.status).every(
|
|
30136
|
+
([currentStepName, currentStatus]) => currentStepName === stepName || currentStatus === "done"
|
|
30137
|
+
);
|
|
30138
|
+
}
|
|
29967
30139
|
function isAbortError(error2) {
|
|
29968
30140
|
return error2 instanceof Error && error2.name === "AbortError";
|
|
29969
30141
|
}
|
|
29970
|
-
|
|
29971
|
-
|
|
29972
|
-
|
|
29973
|
-
|
|
30142
|
+
function formatLockWaitMessage(planPath) {
|
|
30143
|
+
return `Another pipeline run is holding the lock for ${planPath}. Waiting...`;
|
|
30144
|
+
}
|
|
30145
|
+
function formatLockAcquiredMessage(planPath) {
|
|
30146
|
+
return `Lock acquired for ${planPath}. Continuing.`;
|
|
30147
|
+
}
|
|
30148
|
+
async function acquirePipelineLock(options) {
|
|
30149
|
+
let waitingReported = false;
|
|
30150
|
+
const timerId = global.setTimeout(() => {
|
|
30151
|
+
waitingReported = true;
|
|
30152
|
+
options.onLockStatusChange?.({
|
|
30153
|
+
state: "waiting",
|
|
30154
|
+
message: formatLockWaitMessage(options.planPath)
|
|
30155
|
+
});
|
|
30156
|
+
}, 2e3);
|
|
30157
|
+
try {
|
|
30158
|
+
const release = await lockWorkflow(options.absolutePlanPath, {
|
|
30159
|
+
fs: options.fs,
|
|
30160
|
+
retries: Number.POSITIVE_INFINITY,
|
|
30161
|
+
...options.signal ? { signal: options.signal } : {}
|
|
30162
|
+
});
|
|
30163
|
+
if (waitingReported) {
|
|
30164
|
+
options.onLockStatusChange?.({
|
|
30165
|
+
state: "acquired",
|
|
30166
|
+
message: formatLockAcquiredMessage(options.planPath)
|
|
30167
|
+
});
|
|
30168
|
+
}
|
|
30169
|
+
return release;
|
|
30170
|
+
} finally {
|
|
30171
|
+
global.clearTimeout(timerId);
|
|
29974
30172
|
}
|
|
29975
|
-
return resolved;
|
|
29976
30173
|
}
|
|
29977
30174
|
function resolveMode2(stepName, steps) {
|
|
29978
30175
|
if (!stepName) {
|
|
@@ -29985,9 +30182,9 @@ function resolveMode2(stepName, steps) {
|
|
|
29985
30182
|
return step.mode;
|
|
29986
30183
|
}
|
|
29987
30184
|
async function archivePlan(fs17, absolutePlanPath) {
|
|
29988
|
-
const dir =
|
|
29989
|
-
const archiveDir =
|
|
29990
|
-
const archivePath =
|
|
30185
|
+
const dir = path38.dirname(absolutePlanPath);
|
|
30186
|
+
const archiveDir = path38.join(dir, "archive");
|
|
30187
|
+
const archivePath = path38.join(archiveDir, path38.basename(absolutePlanPath));
|
|
29991
30188
|
await fs17.mkdir(archiveDir, { recursive: true });
|
|
29992
30189
|
await fs17.rename(absolutePlanPath, archivePath);
|
|
29993
30190
|
}
|
|
@@ -30024,11 +30221,7 @@ async function runPipeline(options) {
|
|
|
30024
30221
|
metrics
|
|
30025
30222
|
};
|
|
30026
30223
|
}
|
|
30027
|
-
const absolutePlanPath = resolveAbsolutePlanPath(
|
|
30028
|
-
planPath,
|
|
30029
|
-
options.cwd,
|
|
30030
|
-
options.homeDir
|
|
30031
|
-
);
|
|
30224
|
+
const absolutePlanPath = resolveAbsolutePlanPath(planPath, options.cwd, options.homeDir);
|
|
30032
30225
|
const runLogDir = options.logDir ?? resolveRunLogDir({
|
|
30033
30226
|
planPath: absolutePlanPath,
|
|
30034
30227
|
runner: "pipeline",
|
|
@@ -30038,10 +30231,7 @@ async function runPipeline(options) {
|
|
|
30038
30231
|
const content = await fs17.readFile(absolutePlanPath, "utf8");
|
|
30039
30232
|
const plan = parsePlan(content);
|
|
30040
30233
|
const total = plan.tasks.length;
|
|
30041
|
-
const done = plan.tasks.filter((t) =>
|
|
30042
|
-
if (typeof t.status === "string") return t.status === "done";
|
|
30043
|
-
return Object.values(t.status).every((s) => s === "done");
|
|
30044
|
-
}).length;
|
|
30234
|
+
const done = plan.tasks.filter((t) => isTaskDone(t.status)).length;
|
|
30045
30235
|
const failed = plan.tasks.filter((t) => {
|
|
30046
30236
|
if (typeof t.status === "string") return t.status === "failed";
|
|
30047
30237
|
return Object.values(t.status).some((s) => s === "failed");
|
|
@@ -30061,6 +30251,20 @@ async function runPipeline(options) {
|
|
|
30061
30251
|
let lastGoodPlan;
|
|
30062
30252
|
let lastGoodStepsConfig;
|
|
30063
30253
|
const pipelineStartTime = Date.now();
|
|
30254
|
+
async function readResolvedPlanFromContent(content) {
|
|
30255
|
+
const draftPlan = parsePlan(content);
|
|
30256
|
+
const stepsConfig = await loadResolvedSteps({
|
|
30257
|
+
cwd: options.cwd,
|
|
30258
|
+
homeDir: options.homeDir,
|
|
30259
|
+
fs: fs17,
|
|
30260
|
+
name: draftPlan.extends,
|
|
30261
|
+
stepOverrides: draftPlan.stepOverrides
|
|
30262
|
+
});
|
|
30263
|
+
return {
|
|
30264
|
+
plan: parsePlan(content, { availableSteps: stepsConfig.steps }),
|
|
30265
|
+
stepsConfig
|
|
30266
|
+
};
|
|
30267
|
+
}
|
|
30064
30268
|
async function runPhase(phaseDef, phase, totalTasks, vars, mcp) {
|
|
30065
30269
|
const phaseProgress = {
|
|
30066
30270
|
taskId: phase,
|
|
@@ -30073,7 +30277,7 @@ async function runPipeline(options) {
|
|
|
30073
30277
|
const startTime = Date.now();
|
|
30074
30278
|
let result;
|
|
30075
30279
|
try {
|
|
30076
|
-
const rawPrompt =
|
|
30280
|
+
const rawPrompt = interpolatePipelineVars(phaseDef.prompt, vars, phase);
|
|
30077
30281
|
const phasePrompt = await resolveFileIncludes(rawPrompt, options.cwd, fs17.readFile.bind(fs17));
|
|
30078
30282
|
result = await runAgent({
|
|
30079
30283
|
agent: phaseDef.agent ?? options.agent,
|
|
@@ -30108,19 +30312,35 @@ async function runPipeline(options) {
|
|
|
30108
30312
|
});
|
|
30109
30313
|
return { success: success2, cancelled: false };
|
|
30110
30314
|
}
|
|
30111
|
-
const initialStepsConfig = await loadResolvedSteps({
|
|
30112
|
-
cwd: options.cwd,
|
|
30113
|
-
homeDir: options.homeDir,
|
|
30114
|
-
fs: fs17
|
|
30115
|
-
});
|
|
30116
30315
|
const initialContent = await fs17.readFile(absolutePlanPath, "utf8");
|
|
30117
|
-
const
|
|
30316
|
+
const {
|
|
30317
|
+
plan: initialPlan,
|
|
30318
|
+
stepsConfig: initialStepsConfig
|
|
30319
|
+
} = await readResolvedPlanFromContent(initialContent);
|
|
30118
30320
|
const resolvedSetup = initialPlan.setup === null ? void 0 : initialPlan.setup ?? initialStepsConfig.setup;
|
|
30119
|
-
const
|
|
30321
|
+
const initialResolvedTeardown = initialPlan.teardown === null ? void 0 : initialPlan.teardown ?? initialStepsConfig.teardown;
|
|
30120
30322
|
const initialTotalTasks = initialPlan.tasks.length;
|
|
30121
|
-
const initialVars = await
|
|
30323
|
+
const initialVars = await resolvePipelineVars(
|
|
30324
|
+
initialPlan.vars ?? {},
|
|
30325
|
+
options.cwd,
|
|
30326
|
+
fs17.readFile.bind(fs17)
|
|
30327
|
+
);
|
|
30328
|
+
validateResolvedPromptVars({
|
|
30329
|
+
plan: initialPlan,
|
|
30330
|
+
steps: initialStepsConfig.steps,
|
|
30331
|
+
planPath,
|
|
30332
|
+
vars: initialVars,
|
|
30333
|
+
...resolvedSetup ? { setup: resolvedSetup } : {},
|
|
30334
|
+
...initialResolvedTeardown ? { teardown: initialResolvedTeardown } : {}
|
|
30335
|
+
});
|
|
30122
30336
|
if (resolvedSetup) {
|
|
30123
|
-
const { success: success2, cancelled } = await runPhase(
|
|
30337
|
+
const { success: success2, cancelled } = await runPhase(
|
|
30338
|
+
resolvedSetup,
|
|
30339
|
+
"setup",
|
|
30340
|
+
initialTotalTasks,
|
|
30341
|
+
initialVars,
|
|
30342
|
+
initialPlan.mcp
|
|
30343
|
+
);
|
|
30124
30344
|
if (cancelled || !success2) {
|
|
30125
30345
|
return {
|
|
30126
30346
|
stopReason: cancelled ? "cancelled" : "failed",
|
|
@@ -30133,18 +30353,19 @@ async function runPipeline(options) {
|
|
|
30133
30353
|
}
|
|
30134
30354
|
while (runsCompleted < maxRuns) {
|
|
30135
30355
|
assertNotAborted4(options.signal);
|
|
30136
|
-
const release = await
|
|
30356
|
+
const release = await acquirePipelineLock({
|
|
30357
|
+
absolutePlanPath,
|
|
30358
|
+
planPath,
|
|
30359
|
+
fs: fs17,
|
|
30360
|
+
...options.signal ? { signal: options.signal } : {},
|
|
30361
|
+
onLockStatusChange: options.onLockStatusChange
|
|
30362
|
+
});
|
|
30137
30363
|
try {
|
|
30138
30364
|
let stepsConfig;
|
|
30139
30365
|
let plan;
|
|
30140
30366
|
try {
|
|
30141
|
-
stepsConfig = await loadResolvedSteps({
|
|
30142
|
-
cwd: options.cwd,
|
|
30143
|
-
homeDir: options.homeDir,
|
|
30144
|
-
fs: fs17
|
|
30145
|
-
});
|
|
30146
30367
|
const content = await fs17.readFile(absolutePlanPath, "utf8");
|
|
30147
|
-
|
|
30368
|
+
({ plan, stepsConfig } = await readResolvedPlanFromContent(content));
|
|
30148
30369
|
lastGoodPlan = plan;
|
|
30149
30370
|
lastGoodStepsConfig = stepsConfig;
|
|
30150
30371
|
} catch (reloadError) {
|
|
@@ -30158,13 +30379,31 @@ async function runPipeline(options) {
|
|
|
30158
30379
|
stepsConfig = lastGoodStepsConfig;
|
|
30159
30380
|
}
|
|
30160
30381
|
const totalTasks = plan.tasks.length;
|
|
30161
|
-
const planVars = await
|
|
30382
|
+
const planVars = await resolvePipelineVars(
|
|
30383
|
+
plan.vars ?? {},
|
|
30384
|
+
options.cwd,
|
|
30385
|
+
fs17.readFile.bind(fs17)
|
|
30386
|
+
);
|
|
30387
|
+
const resolvedTeardown = plan.teardown === null ? void 0 : plan.teardown ?? stepsConfig.teardown;
|
|
30388
|
+
validateResolvedPromptVars({
|
|
30389
|
+
plan,
|
|
30390
|
+
steps: stepsConfig.steps,
|
|
30391
|
+
planPath,
|
|
30392
|
+
vars: planVars,
|
|
30393
|
+
...resolvedTeardown ? { teardown: resolvedTeardown } : {}
|
|
30394
|
+
});
|
|
30162
30395
|
const selection = selectNextExecution(plan, options.task);
|
|
30163
30396
|
if (selection.kind === "completed") {
|
|
30164
30397
|
if (runsCompleted > 0) {
|
|
30165
30398
|
await archivePlan(fs17, absolutePlanPath);
|
|
30166
30399
|
if (resolvedTeardown) {
|
|
30167
|
-
const { success: success3, cancelled } = await runPhase(
|
|
30400
|
+
const { success: success3, cancelled } = await runPhase(
|
|
30401
|
+
resolvedTeardown,
|
|
30402
|
+
"teardown",
|
|
30403
|
+
initialTotalTasks,
|
|
30404
|
+
planVars,
|
|
30405
|
+
plan.mcp
|
|
30406
|
+
);
|
|
30168
30407
|
if (cancelled || !success3) {
|
|
30169
30408
|
return {
|
|
30170
30409
|
stopReason: cancelled ? "cancelled" : "failed",
|
|
@@ -30250,8 +30489,11 @@ async function runPipeline(options) {
|
|
|
30250
30489
|
metrics.totalCachedTokens += result.usage.cachedTokens ?? 0;
|
|
30251
30490
|
}
|
|
30252
30491
|
metrics.stepsCompleted += 1;
|
|
30492
|
+
const taskCompleted = success2 && completesTaskOnSuccess(selection.task, selection.stepName);
|
|
30253
30493
|
if (success2) {
|
|
30254
|
-
|
|
30494
|
+
if (taskCompleted) {
|
|
30495
|
+
metrics.tasksCompleted += 1;
|
|
30496
|
+
}
|
|
30255
30497
|
} else {
|
|
30256
30498
|
metrics.tasksFailed += 1;
|
|
30257
30499
|
}
|
|
@@ -30278,6 +30520,7 @@ async function runPipeline(options) {
|
|
|
30278
30520
|
...taskProgress,
|
|
30279
30521
|
durationMs: taskDurationMs,
|
|
30280
30522
|
success: success2,
|
|
30523
|
+
taskCompleted,
|
|
30281
30524
|
...result.usage ? { usage: result.usage } : {}
|
|
30282
30525
|
});
|
|
30283
30526
|
if (!success2) {
|
|
@@ -30312,6 +30555,9 @@ var init_pipeline = __esm({
|
|
|
30312
30555
|
init_parser2();
|
|
30313
30556
|
init_writer2();
|
|
30314
30557
|
init_runner2();
|
|
30558
|
+
init_interpolate();
|
|
30559
|
+
init_resolve4();
|
|
30560
|
+
init_validate();
|
|
30315
30561
|
init_utils2();
|
|
30316
30562
|
}
|
|
30317
30563
|
});
|
|
@@ -30326,6 +30572,9 @@ var init_src18 = __esm({
|
|
|
30326
30572
|
init_writer2();
|
|
30327
30573
|
init_runner2();
|
|
30328
30574
|
init_pipeline();
|
|
30575
|
+
init_interpolate();
|
|
30576
|
+
init_resolve4();
|
|
30577
|
+
init_validate();
|
|
30329
30578
|
}
|
|
30330
30579
|
});
|
|
30331
30580
|
|
|
@@ -30339,7 +30588,7 @@ var init_types4 = __esm({
|
|
|
30339
30588
|
// packages/experiment-loop/src/frontmatter/frontmatter.ts
|
|
30340
30589
|
import matter2 from "gray-matter";
|
|
30341
30590
|
import { dirname } from "node:path";
|
|
30342
|
-
import { stringify
|
|
30591
|
+
import { stringify } from "yaml";
|
|
30343
30592
|
function parseExperimentFrontmatter(content) {
|
|
30344
30593
|
const parsed = matter2(content);
|
|
30345
30594
|
return {
|
|
@@ -30638,7 +30887,7 @@ var init_git = __esm({
|
|
|
30638
30887
|
});
|
|
30639
30888
|
|
|
30640
30889
|
// packages/experiment-loop/src/config/loader.ts
|
|
30641
|
-
import
|
|
30890
|
+
import path39 from "node:path";
|
|
30642
30891
|
import { readFile as readFile9 } from "node:fs/promises";
|
|
30643
30892
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
30644
30893
|
import { parse as parse8 } from "yaml";
|
|
@@ -30709,7 +30958,7 @@ async function loadInstructions() {
|
|
|
30709
30958
|
return readBundledFile("default-instructions.md");
|
|
30710
30959
|
}
|
|
30711
30960
|
async function loadRunConfig(options) {
|
|
30712
|
-
const projectPath =
|
|
30961
|
+
const projectPath = path39.join(options.cwd, ".poe-code", "experiments", "run.yaml");
|
|
30713
30962
|
const projectContent = await readOptionalFile3(options.fs, projectPath);
|
|
30714
30963
|
if (projectContent == null) {
|
|
30715
30964
|
return readDefaultRunConfig();
|
|
@@ -30718,8 +30967,8 @@ async function loadRunConfig(options) {
|
|
|
30718
30967
|
if (projectDocument === null || projectDocument === void 0) {
|
|
30719
30968
|
return readDefaultRunConfig();
|
|
30720
30969
|
}
|
|
30721
|
-
const bundledConfigDir =
|
|
30722
|
-
const globalConfigDir =
|
|
30970
|
+
const bundledConfigDir = path39.resolve(fileURLToPath6(new URL(".", import.meta.url)));
|
|
30971
|
+
const globalConfigDir = path39.resolve(path39.join(options.homeDir, ".poe-code", "experiments"));
|
|
30723
30972
|
const resolved = await resolve(
|
|
30724
30973
|
[
|
|
30725
30974
|
{ source: "document", filePath: projectPath, content: projectContent },
|
|
@@ -30742,15 +30991,15 @@ var init_loader2 = __esm({
|
|
|
30742
30991
|
});
|
|
30743
30992
|
|
|
30744
30993
|
// packages/experiment-loop/src/discovery/discovery.ts
|
|
30745
|
-
import
|
|
30994
|
+
import path40 from "node:path";
|
|
30746
30995
|
import * as fsPromises9 from "node:fs/promises";
|
|
30747
30996
|
function createDefaultFs6() {
|
|
30748
30997
|
return {
|
|
30749
30998
|
readdir: fsPromises9.readdir,
|
|
30750
30999
|
stat: async (filePath) => {
|
|
30751
|
-
const
|
|
31000
|
+
const stat24 = await fsPromises9.stat(filePath);
|
|
30752
31001
|
return {
|
|
30753
|
-
isFile: () =>
|
|
31002
|
+
isFile: () => stat24.isFile()
|
|
30754
31003
|
};
|
|
30755
31004
|
}
|
|
30756
31005
|
};
|
|
@@ -30776,12 +31025,12 @@ async function scanDir(fs17, absoluteDir, displayDir) {
|
|
|
30776
31025
|
if (!isMarkdownFile(entry)) {
|
|
30777
31026
|
continue;
|
|
30778
31027
|
}
|
|
30779
|
-
const absolutePath =
|
|
30780
|
-
const
|
|
30781
|
-
if (!
|
|
31028
|
+
const absolutePath = path40.join(absoluteDir, entry);
|
|
31029
|
+
const stat24 = await fs17.stat(absolutePath);
|
|
31030
|
+
if (!stat24.isFile()) {
|
|
30782
31031
|
continue;
|
|
30783
31032
|
}
|
|
30784
|
-
const displayPath2 =
|
|
31033
|
+
const displayPath2 = path40.join(displayDir, entry);
|
|
30785
31034
|
docs.push({
|
|
30786
31035
|
path: displayPath2,
|
|
30787
31036
|
displayPath: displayPath2
|
|
@@ -30790,18 +31039,18 @@ async function scanDir(fs17, absoluteDir, displayDir) {
|
|
|
30790
31039
|
return docs;
|
|
30791
31040
|
}
|
|
30792
31041
|
function toDisplayPath(options) {
|
|
30793
|
-
const localDir =
|
|
30794
|
-
const globalDir =
|
|
30795
|
-
if (options.absolutePath.startsWith(`${localDir}${
|
|
30796
|
-
return
|
|
31042
|
+
const localDir = path40.join(options.cwd, ".poe-code", "experiments");
|
|
31043
|
+
const globalDir = path40.join(options.homeDir, ".poe-code", "experiments");
|
|
31044
|
+
if (options.absolutePath.startsWith(`${localDir}${path40.sep}`)) {
|
|
31045
|
+
return path40.join(
|
|
30797
31046
|
".poe-code/experiments",
|
|
30798
|
-
|
|
31047
|
+
path40.relative(localDir, options.absolutePath)
|
|
30799
31048
|
);
|
|
30800
31049
|
}
|
|
30801
|
-
if (options.absolutePath.startsWith(`${globalDir}${
|
|
30802
|
-
return
|
|
31050
|
+
if (options.absolutePath.startsWith(`${globalDir}${path40.sep}`)) {
|
|
31051
|
+
return path40.join(
|
|
30803
31052
|
"~/.poe-code/experiments",
|
|
30804
|
-
|
|
31053
|
+
path40.relative(globalDir, options.absolutePath)
|
|
30805
31054
|
);
|
|
30806
31055
|
}
|
|
30807
31056
|
return options.absolutePath;
|
|
@@ -30834,8 +31083,8 @@ async function discoverExperimentDocs(options) {
|
|
|
30834
31083
|
const customDir = options.planDirectory?.trim();
|
|
30835
31084
|
const docs = customDir ? await scanCustomDir(fs17, customDir, options.cwd, options.homeDir) : await scanDefaultDirs(fs17, options.cwd, options.homeDir);
|
|
30836
31085
|
return docs.sort((left, right) => {
|
|
30837
|
-
const leftName =
|
|
30838
|
-
const rightName =
|
|
31086
|
+
const leftName = path40.basename(left.displayPath).toLowerCase();
|
|
31087
|
+
const rightName = path40.basename(right.displayPath).toLowerCase();
|
|
30839
31088
|
return leftName === rightName ? left.displayPath.localeCompare(right.displayPath) : leftName.localeCompare(rightName);
|
|
30840
31089
|
});
|
|
30841
31090
|
}
|
|
@@ -30849,18 +31098,18 @@ var init_discovery2 = __esm({
|
|
|
30849
31098
|
// packages/experiment-loop/src/run/loop.ts
|
|
30850
31099
|
import { exec as execCallback } from "node:child_process";
|
|
30851
31100
|
import * as fsPromises10 from "node:fs/promises";
|
|
30852
|
-
import
|
|
31101
|
+
import path41 from "node:path";
|
|
30853
31102
|
function createDefaultFs7() {
|
|
30854
31103
|
return {
|
|
30855
31104
|
readFile: fsPromises10.readFile,
|
|
30856
31105
|
writeFile: (filePath, content) => fsPromises10.writeFile(filePath, content, "utf8"),
|
|
30857
31106
|
readdir: fsPromises10.readdir,
|
|
30858
31107
|
stat: async (filePath) => {
|
|
30859
|
-
const
|
|
31108
|
+
const stat24 = await fsPromises10.stat(filePath);
|
|
30860
31109
|
return {
|
|
30861
|
-
isFile: () =>
|
|
30862
|
-
isDirectory: () =>
|
|
30863
|
-
mtimeMs:
|
|
31110
|
+
isFile: () => stat24.isFile(),
|
|
31111
|
+
isDirectory: () => stat24.isDirectory(),
|
|
31112
|
+
mtimeMs: stat24.mtimeMs
|
|
30864
31113
|
};
|
|
30865
31114
|
},
|
|
30866
31115
|
mkdir: async (filePath, options) => {
|
|
@@ -30896,9 +31145,9 @@ function createDefaultExec() {
|
|
|
30896
31145
|
});
|
|
30897
31146
|
}
|
|
30898
31147
|
function resolveJournalPath(docPath) {
|
|
30899
|
-
return
|
|
30900
|
-
|
|
30901
|
-
`${
|
|
31148
|
+
return path41.join(
|
|
31149
|
+
path41.dirname(docPath),
|
|
31150
|
+
`${path41.basename(docPath, path41.extname(docPath))}.journal.jsonl`
|
|
30902
31151
|
);
|
|
30903
31152
|
}
|
|
30904
31153
|
function normalizeMetrics(metric) {
|
|
@@ -30939,9 +31188,9 @@ function assertNotAborted5(signal) {
|
|
|
30939
31188
|
if (!signal?.aborted) {
|
|
30940
31189
|
return;
|
|
30941
31190
|
}
|
|
30942
|
-
throw
|
|
31191
|
+
throw createAbortError6();
|
|
30943
31192
|
}
|
|
30944
|
-
function
|
|
31193
|
+
function createAbortError6() {
|
|
30945
31194
|
const error2 = new Error("Experiment loop cancelled");
|
|
30946
31195
|
error2.name = "AbortError";
|
|
30947
31196
|
return error2;
|
|
@@ -30949,7 +31198,7 @@ function createAbortError5() {
|
|
|
30949
31198
|
function isAbortError2(error2) {
|
|
30950
31199
|
return error2 instanceof Error && error2.name === "AbortError";
|
|
30951
31200
|
}
|
|
30952
|
-
function
|
|
31201
|
+
function interpolate(template, values) {
|
|
30953
31202
|
let output = template;
|
|
30954
31203
|
for (const [key, value] of Object.entries(values)) {
|
|
30955
31204
|
output = output.split(`{{${key}}}`).join(value);
|
|
@@ -30980,8 +31229,8 @@ function buildPrompt(options) {
|
|
|
30980
31229
|
doc_path: options.docPath,
|
|
30981
31230
|
doc_name: options.docName
|
|
30982
31231
|
};
|
|
30983
|
-
const context =
|
|
30984
|
-
const instructions =
|
|
31232
|
+
const context = interpolate(options.runConfig.prompt, vars).trim();
|
|
31233
|
+
const instructions = interpolate(options.instructions, vars).trim();
|
|
30985
31234
|
return `${context}
|
|
30986
31235
|
|
|
30987
31236
|
${instructions}`;
|
|
@@ -31032,8 +31281,8 @@ async function runExperimentLoop(options) {
|
|
|
31032
31281
|
[
|
|
31033
31282
|
{ source: "cli", data: { agent: options.agent } },
|
|
31034
31283
|
{ source: "document", filePath: absoluteDocPath, content: rawContent },
|
|
31035
|
-
{ source: "base", path:
|
|
31036
|
-
{ source: "base", path:
|
|
31284
|
+
{ source: "base", path: path41.join(options.cwd, ".poe-code/experiments/bases") },
|
|
31285
|
+
{ source: "base", path: path41.join(options.homeDir, ".poe-code/experiments/bases") },
|
|
31037
31286
|
{ source: "defaults", data: { agent: "claude-code" } }
|
|
31038
31287
|
],
|
|
31039
31288
|
{ fs: fs17 }
|
|
@@ -31113,7 +31362,7 @@ async function runExperimentLoop(options) {
|
|
|
31113
31362
|
experimentIndex,
|
|
31114
31363
|
baseline,
|
|
31115
31364
|
docPath: options.docPath,
|
|
31116
|
-
docName:
|
|
31365
|
+
docName: path41.basename(absoluteDocPath, path41.extname(absoluteDocPath))
|
|
31117
31366
|
});
|
|
31118
31367
|
const currentSpecifier = agents[(experimentIndex - 1) % agents.length];
|
|
31119
31368
|
const model = currentSpecifier.model;
|
|
@@ -31209,7 +31458,7 @@ var init_src19 = __esm({
|
|
|
31209
31458
|
});
|
|
31210
31459
|
|
|
31211
31460
|
// packages/ralph/src/frontmatter/frontmatter.ts
|
|
31212
|
-
import { parse as parse9, stringify as
|
|
31461
|
+
import { parse as parse9, stringify as stringify2 } from "yaml";
|
|
31213
31462
|
function parseFrontmatter2(content) {
|
|
31214
31463
|
if (!content.startsWith(`${FENCE}
|
|
31215
31464
|
`)) {
|
|
@@ -31248,7 +31497,7 @@ function writeFrontmatter(data, body) {
|
|
|
31248
31497
|
iteration: data.status.iteration
|
|
31249
31498
|
}
|
|
31250
31499
|
};
|
|
31251
|
-
const yaml =
|
|
31500
|
+
const yaml = stringify2(serialized).trimEnd();
|
|
31252
31501
|
return `${FENCE}
|
|
31253
31502
|
${yaml}
|
|
31254
31503
|
${FENCE}
|
|
@@ -31346,17 +31595,17 @@ var init_frontmatter3 = __esm({
|
|
|
31346
31595
|
});
|
|
31347
31596
|
|
|
31348
31597
|
// packages/ralph/src/discovery/discovery.ts
|
|
31349
|
-
import
|
|
31598
|
+
import path42 from "node:path";
|
|
31350
31599
|
import * as fsPromises11 from "node:fs/promises";
|
|
31351
31600
|
function createDefaultFs8() {
|
|
31352
31601
|
return {
|
|
31353
31602
|
readdir: fsPromises11.readdir,
|
|
31354
31603
|
stat: async (filePath) => {
|
|
31355
|
-
const
|
|
31604
|
+
const stat24 = await fsPromises11.stat(filePath);
|
|
31356
31605
|
return {
|
|
31357
|
-
isFile: () =>
|
|
31358
|
-
isDirectory: () =>
|
|
31359
|
-
mtimeMs:
|
|
31606
|
+
isFile: () => stat24.isFile(),
|
|
31607
|
+
isDirectory: () => stat24.isDirectory(),
|
|
31608
|
+
mtimeMs: stat24.mtimeMs
|
|
31360
31609
|
};
|
|
31361
31610
|
}
|
|
31362
31611
|
};
|
|
@@ -31382,12 +31631,12 @@ async function scanDir2(fs17, absoluteDir, displayDir) {
|
|
|
31382
31631
|
if (!isMarkdownFile2(entry)) {
|
|
31383
31632
|
continue;
|
|
31384
31633
|
}
|
|
31385
|
-
const absolutePath =
|
|
31386
|
-
const
|
|
31387
|
-
if (!
|
|
31634
|
+
const absolutePath = path42.join(absoluteDir, entry);
|
|
31635
|
+
const stat24 = await fs17.stat(absolutePath);
|
|
31636
|
+
if (!stat24.isFile()) {
|
|
31388
31637
|
continue;
|
|
31389
31638
|
}
|
|
31390
|
-
const displayPath2 =
|
|
31639
|
+
const displayPath2 = path42.join(displayDir, entry);
|
|
31391
31640
|
docs.push({
|
|
31392
31641
|
path: displayPath2,
|
|
31393
31642
|
displayPath: displayPath2
|
|
@@ -31396,18 +31645,18 @@ async function scanDir2(fs17, absoluteDir, displayDir) {
|
|
|
31396
31645
|
return docs;
|
|
31397
31646
|
}
|
|
31398
31647
|
function toDisplayPath2(options) {
|
|
31399
|
-
const localDir =
|
|
31400
|
-
const globalDir =
|
|
31401
|
-
if (options.absolutePath.startsWith(`${localDir}${
|
|
31402
|
-
return
|
|
31648
|
+
const localDir = path42.join(options.cwd, ".poe-code", "ralph", "plans");
|
|
31649
|
+
const globalDir = path42.join(options.homeDir, ".poe-code", "ralph", "plans");
|
|
31650
|
+
if (options.absolutePath.startsWith(`${localDir}${path42.sep}`)) {
|
|
31651
|
+
return path42.join(
|
|
31403
31652
|
".poe-code/ralph/plans",
|
|
31404
|
-
|
|
31653
|
+
path42.relative(localDir, options.absolutePath)
|
|
31405
31654
|
);
|
|
31406
31655
|
}
|
|
31407
|
-
if (options.absolutePath.startsWith(`${globalDir}${
|
|
31408
|
-
return
|
|
31656
|
+
if (options.absolutePath.startsWith(`${globalDir}${path42.sep}`)) {
|
|
31657
|
+
return path42.join(
|
|
31409
31658
|
"~/.poe-code/ralph/plans",
|
|
31410
|
-
|
|
31659
|
+
path42.relative(globalDir, options.absolutePath)
|
|
31411
31660
|
);
|
|
31412
31661
|
}
|
|
31413
31662
|
return options.absolutePath;
|
|
@@ -31440,8 +31689,8 @@ async function discoverDocs(options) {
|
|
|
31440
31689
|
const customDir = options.planDirectory?.trim();
|
|
31441
31690
|
const docs = customDir ? await scanCustomDir2(fs17, customDir, options.cwd, options.homeDir) : await scanDefaultDirs2(fs17, options.cwd, options.homeDir);
|
|
31442
31691
|
return docs.sort((left, right) => {
|
|
31443
|
-
const leftName =
|
|
31444
|
-
const rightName =
|
|
31692
|
+
const leftName = path42.basename(left.displayPath).toLowerCase();
|
|
31693
|
+
const rightName = path42.basename(right.displayPath).toLowerCase();
|
|
31445
31694
|
return leftName === rightName ? left.displayPath.localeCompare(right.displayPath) : leftName.localeCompare(rightName);
|
|
31446
31695
|
});
|
|
31447
31696
|
}
|
|
@@ -31465,7 +31714,7 @@ var init_variables = __esm({
|
|
|
31465
31714
|
});
|
|
31466
31715
|
|
|
31467
31716
|
// packages/ralph/src/run/ralph.ts
|
|
31468
|
-
import
|
|
31717
|
+
import path43 from "node:path";
|
|
31469
31718
|
import * as fsPromises12 from "node:fs/promises";
|
|
31470
31719
|
async function runRalph(options) {
|
|
31471
31720
|
const fs17 = options.fs ?? createDefaultFs9();
|
|
@@ -31669,11 +31918,11 @@ async function resolveDocumentConfigFromContent(options, fs17, absoluteDocPath,
|
|
|
31669
31918
|
},
|
|
31670
31919
|
{
|
|
31671
31920
|
source: "base",
|
|
31672
|
-
path:
|
|
31921
|
+
path: path43.join(options.cwd, ".poe-code/ralph/bases")
|
|
31673
31922
|
},
|
|
31674
31923
|
{
|
|
31675
31924
|
source: "base",
|
|
31676
|
-
path:
|
|
31925
|
+
path: path43.join(options.homeDir, ".poe-code/ralph/bases")
|
|
31677
31926
|
},
|
|
31678
31927
|
{
|
|
31679
31928
|
source: "defaults",
|
|
@@ -31724,11 +31973,11 @@ function createDefaultFs9() {
|
|
|
31724
31973
|
writeFile: (filePath, content) => fsPromises12.writeFile(filePath, content, "utf8"),
|
|
31725
31974
|
readdir: fsPromises12.readdir,
|
|
31726
31975
|
stat: async (filePath) => {
|
|
31727
|
-
const
|
|
31976
|
+
const stat24 = await fsPromises12.stat(filePath);
|
|
31728
31977
|
return {
|
|
31729
|
-
isFile: () =>
|
|
31730
|
-
isDirectory: () =>
|
|
31731
|
-
mtimeMs:
|
|
31978
|
+
isFile: () => stat24.isFile(),
|
|
31979
|
+
isDirectory: () => stat24.isDirectory(),
|
|
31980
|
+
mtimeMs: stat24.mtimeMs
|
|
31732
31981
|
};
|
|
31733
31982
|
},
|
|
31734
31983
|
mkdir: async (filePath, options) => {
|
|
@@ -31806,9 +32055,9 @@ async function updateFrontmatter2(fs17, absoluteDocPath, state, iteration) {
|
|
|
31806
32055
|
await fs17.writeFile(absoluteDocPath, content);
|
|
31807
32056
|
}
|
|
31808
32057
|
async function archivePlan2(fs17, absoluteDocPath) {
|
|
31809
|
-
const dir =
|
|
31810
|
-
const archiveDir =
|
|
31811
|
-
const archivePath =
|
|
32058
|
+
const dir = path43.dirname(absoluteDocPath);
|
|
32059
|
+
const archiveDir = path43.join(dir, "archive");
|
|
32060
|
+
const archivePath = path43.join(archiveDir, path43.basename(absoluteDocPath));
|
|
31812
32061
|
await fs17.mkdir(archiveDir, { recursive: true });
|
|
31813
32062
|
await fs17.rename(absoluteDocPath, archivePath);
|
|
31814
32063
|
}
|
|
@@ -31843,7 +32092,7 @@ var init_src20 = __esm({
|
|
|
31843
32092
|
});
|
|
31844
32093
|
|
|
31845
32094
|
// packages/plan-browser/src/format.ts
|
|
31846
|
-
import
|
|
32095
|
+
import path44 from "node:path";
|
|
31847
32096
|
import { parseDocument as parseDocument5 } from "yaml";
|
|
31848
32097
|
function isPipelineTaskDone(task) {
|
|
31849
32098
|
if (typeof task.status === "string") {
|
|
@@ -32014,9 +32263,9 @@ function formatPipelinePlanMarkdown(options) {
|
|
|
32014
32263
|
return lines.join("\n").trimEnd();
|
|
32015
32264
|
}
|
|
32016
32265
|
function resolveExperimentJournalPath(absolutePath) {
|
|
32017
|
-
return
|
|
32018
|
-
|
|
32019
|
-
`${
|
|
32266
|
+
return path44.join(
|
|
32267
|
+
path44.dirname(absolutePath),
|
|
32268
|
+
`${path44.basename(absolutePath, path44.extname(absolutePath))}.journal.jsonl`
|
|
32020
32269
|
);
|
|
32021
32270
|
}
|
|
32022
32271
|
async function readExperimentState(fs17, absolutePath) {
|
|
@@ -32046,7 +32295,7 @@ function resolveFormatFromPath(filePath) {
|
|
|
32046
32295
|
}
|
|
32047
32296
|
async function readPlanMetadata(options) {
|
|
32048
32297
|
const content = await options.fs.readFile(options.absolutePath, "utf8");
|
|
32049
|
-
const fallbackName =
|
|
32298
|
+
const fallbackName = path44.basename(options.path);
|
|
32050
32299
|
if (options.kind === "pipeline") {
|
|
32051
32300
|
return {
|
|
32052
32301
|
title: fallbackName,
|
|
@@ -32107,7 +32356,7 @@ var init_format = __esm({
|
|
|
32107
32356
|
});
|
|
32108
32357
|
|
|
32109
32358
|
// packages/plan-browser/src/discovery.ts
|
|
32110
|
-
import
|
|
32359
|
+
import path45 from "node:path";
|
|
32111
32360
|
import * as fsPromises13 from "node:fs/promises";
|
|
32112
32361
|
function createDefaultFs10() {
|
|
32113
32362
|
return {
|
|
@@ -32115,11 +32364,11 @@ function createDefaultFs10() {
|
|
|
32115
32364
|
writeFile: fsPromises13.writeFile,
|
|
32116
32365
|
readdir: fsPromises13.readdir,
|
|
32117
32366
|
stat: async (filePath) => {
|
|
32118
|
-
const
|
|
32367
|
+
const stat24 = await fsPromises13.stat(filePath);
|
|
32119
32368
|
return {
|
|
32120
|
-
isFile: () =>
|
|
32121
|
-
isDirectory: () =>
|
|
32122
|
-
mtimeMs:
|
|
32369
|
+
isFile: () => stat24.isFile(),
|
|
32370
|
+
isDirectory: () => stat24.isDirectory(),
|
|
32371
|
+
mtimeMs: stat24.mtimeMs
|
|
32123
32372
|
};
|
|
32124
32373
|
},
|
|
32125
32374
|
mkdir: async (directoryPath, mkdirOptions) => {
|
|
@@ -32134,9 +32383,9 @@ function isNotFound5(error2) {
|
|
|
32134
32383
|
}
|
|
32135
32384
|
function resolveAbsoluteDirectory3(dir, cwd, homeDir) {
|
|
32136
32385
|
if (dir.startsWith("~/")) {
|
|
32137
|
-
return
|
|
32386
|
+
return path45.join(homeDir, dir.slice(2));
|
|
32138
32387
|
}
|
|
32139
|
-
return
|
|
32388
|
+
return path45.isAbsolute(dir) ? dir : path45.resolve(cwd, dir);
|
|
32140
32389
|
}
|
|
32141
32390
|
function isMarkdownFile3(name) {
|
|
32142
32391
|
return name.toLowerCase().endsWith(".md");
|
|
@@ -32213,12 +32462,12 @@ async function discoverSharedPlans(options) {
|
|
|
32213
32462
|
if (!isMarkdownFile3(name)) {
|
|
32214
32463
|
continue;
|
|
32215
32464
|
}
|
|
32216
|
-
const absolutePath =
|
|
32217
|
-
const
|
|
32218
|
-
if (!
|
|
32465
|
+
const absolutePath = path45.join(absoluteDir, name);
|
|
32466
|
+
const stat24 = await options.fs.stat(absolutePath);
|
|
32467
|
+
if (!stat24.isFile()) {
|
|
32219
32468
|
continue;
|
|
32220
32469
|
}
|
|
32221
|
-
const displayPath2 =
|
|
32470
|
+
const displayPath2 = path45.join(displayDir, name);
|
|
32222
32471
|
const content = await options.fs.readFile(absolutePath, "utf8");
|
|
32223
32472
|
const kind = classifyPlanKind(content, displayPath2);
|
|
32224
32473
|
if (options.kind && kind !== options.kind) {
|
|
@@ -32239,7 +32488,7 @@ async function discoverSharedPlans(options) {
|
|
|
32239
32488
|
format: metadata.format,
|
|
32240
32489
|
title: metadata.title,
|
|
32241
32490
|
detail: metadata.detail,
|
|
32242
|
-
updatedAt:
|
|
32491
|
+
updatedAt: stat24.mtimeMs
|
|
32243
32492
|
});
|
|
32244
32493
|
}
|
|
32245
32494
|
return plans;
|
|
@@ -32263,7 +32512,7 @@ var init_discovery4 = __esm({
|
|
|
32263
32512
|
});
|
|
32264
32513
|
|
|
32265
32514
|
// packages/plan-browser/src/actions.ts
|
|
32266
|
-
import
|
|
32515
|
+
import path46 from "node:path";
|
|
32267
32516
|
import { spawnSync as nodeSpawnSync2 } from "node:child_process";
|
|
32268
32517
|
function resolveEditor2(env = process.env) {
|
|
32269
32518
|
const editor = env.EDITOR?.trim() || env.VISUAL?.trim() || "vi";
|
|
@@ -32275,8 +32524,8 @@ function editPlan2(absolutePath, options = {}) {
|
|
|
32275
32524
|
spawnSync3(editor, [absolutePath], { stdio: "inherit" });
|
|
32276
32525
|
}
|
|
32277
32526
|
async function archivePlan3(entry, fs17) {
|
|
32278
|
-
const archiveDir =
|
|
32279
|
-
const archivedPath =
|
|
32527
|
+
const archiveDir = path46.join(path46.dirname(entry.absolutePath), "archive");
|
|
32528
|
+
const archivedPath = path46.join(archiveDir, path46.basename(entry.absolutePath));
|
|
32280
32529
|
await fs17.mkdir(archiveDir, { recursive: true });
|
|
32281
32530
|
await fs17.rename(entry.absolutePath, archivedPath);
|
|
32282
32531
|
return archivedPath;
|
|
@@ -32291,7 +32540,7 @@ var init_actions = __esm({
|
|
|
32291
32540
|
});
|
|
32292
32541
|
|
|
32293
32542
|
// packages/plan-browser/src/browser.ts
|
|
32294
|
-
import
|
|
32543
|
+
import path47 from "node:path";
|
|
32295
32544
|
async function runPlanBrowser(options) {
|
|
32296
32545
|
const renderPlanPreview = async (entry) => {
|
|
32297
32546
|
const markdown = await loadPlanPreviewMarkdown(entry, options.fs);
|
|
@@ -32320,7 +32569,7 @@ async function runPlanBrowser(options) {
|
|
|
32320
32569
|
const selectedPath = await select2({
|
|
32321
32570
|
message: "Select a plan",
|
|
32322
32571
|
options: plans.map((plan) => ({
|
|
32323
|
-
label: text.selectLabel(
|
|
32572
|
+
label: text.selectLabel(path47.basename(plan.path), plan.detail),
|
|
32324
32573
|
hint: plan.typeLabel,
|
|
32325
32574
|
value: plan.absolutePath
|
|
32326
32575
|
}))
|
|
@@ -32356,7 +32605,7 @@ async function runPlanBrowser(options) {
|
|
|
32356
32605
|
if (action === "archive") {
|
|
32357
32606
|
try {
|
|
32358
32607
|
const confirmed = options.assumeYes || await confirmOrCancel({
|
|
32359
|
-
message: `Archive ${
|
|
32608
|
+
message: `Archive ${path47.basename(selectedPlan.path)}?`,
|
|
32360
32609
|
initialValue: true
|
|
32361
32610
|
});
|
|
32362
32611
|
if (confirmed) {
|
|
@@ -32371,7 +32620,7 @@ async function runPlanBrowser(options) {
|
|
|
32371
32620
|
}
|
|
32372
32621
|
try {
|
|
32373
32622
|
const confirmed = options.assumeYes || await confirmOrCancel({
|
|
32374
|
-
message: `Permanently delete ${
|
|
32623
|
+
message: `Permanently delete ${path47.basename(selectedPlan.path)}?`,
|
|
32375
32624
|
initialValue: true
|
|
32376
32625
|
});
|
|
32377
32626
|
if (confirmed) {
|
|
@@ -32516,7 +32765,7 @@ var init_scan = __esm({
|
|
|
32516
32765
|
|
|
32517
32766
|
// packages/markdown-reader/src/core/document.ts
|
|
32518
32767
|
import nodeFs2 from "node:fs/promises";
|
|
32519
|
-
import
|
|
32768
|
+
import path48 from "node:path";
|
|
32520
32769
|
import { parseDocument as parseDocument6 } from "yaml";
|
|
32521
32770
|
async function loadMarkdownDocument(file, dependencies = {}) {
|
|
32522
32771
|
const resolvedFile = resolveMarkdownPath(file, dependencies.cwd);
|
|
@@ -32531,7 +32780,7 @@ async function loadMarkdownDocument(file, dependencies = {}) {
|
|
|
32531
32780
|
};
|
|
32532
32781
|
}
|
|
32533
32782
|
function resolveMarkdownPath(file, cwd = process.cwd()) {
|
|
32534
|
-
return
|
|
32783
|
+
return path48.isAbsolute(file) ? file : path48.resolve(cwd, file);
|
|
32535
32784
|
}
|
|
32536
32785
|
function sliceMarkdownBytes(source, start, end) {
|
|
32537
32786
|
return Buffer.from(source, "utf8").subarray(start, end).toString("utf8");
|
|
@@ -32678,7 +32927,7 @@ function resolveSection(sections, id) {
|
|
|
32678
32927
|
`no section matching "${id}" (try 'read-markdown' to see the table of contents)`
|
|
32679
32928
|
);
|
|
32680
32929
|
}
|
|
32681
|
-
var
|
|
32930
|
+
var init_resolve5 = __esm({
|
|
32682
32931
|
"packages/markdown-reader/src/core/resolve.ts"() {
|
|
32683
32932
|
"use strict";
|
|
32684
32933
|
init_src13();
|
|
@@ -32707,7 +32956,7 @@ var init_read_section = __esm({
|
|
|
32707
32956
|
"packages/markdown-reader/src/core/read-section.ts"() {
|
|
32708
32957
|
"use strict";
|
|
32709
32958
|
init_document();
|
|
32710
|
-
|
|
32959
|
+
init_resolve5();
|
|
32711
32960
|
readSection = createReadSection();
|
|
32712
32961
|
}
|
|
32713
32962
|
});
|
|
@@ -33624,13 +33873,13 @@ function isPlainObject3(value) {
|
|
|
33624
33873
|
}
|
|
33625
33874
|
function createFs() {
|
|
33626
33875
|
return {
|
|
33627
|
-
readFile: async (
|
|
33628
|
-
writeFile: async (
|
|
33629
|
-
await writeFile9(
|
|
33876
|
+
readFile: async (path84, encoding = "utf8") => readFile13(path84, { encoding }),
|
|
33877
|
+
writeFile: async (path84, contents) => {
|
|
33878
|
+
await writeFile9(path84, contents);
|
|
33630
33879
|
},
|
|
33631
|
-
exists: async (
|
|
33880
|
+
exists: async (path84) => {
|
|
33632
33881
|
try {
|
|
33633
|
-
await access(
|
|
33882
|
+
await access(path84);
|
|
33634
33883
|
return true;
|
|
33635
33884
|
} catch {
|
|
33636
33885
|
return false;
|
|
@@ -33675,11 +33924,11 @@ function applySchemaCasing(schema, casing) {
|
|
|
33675
33924
|
...required === void 0 ? {} : { required }
|
|
33676
33925
|
};
|
|
33677
33926
|
}
|
|
33678
|
-
function collectParamSummaries(schema, casing,
|
|
33927
|
+
function collectParamSummaries(schema, casing, path84 = [], inheritedOptional = false) {
|
|
33679
33928
|
const summaries = [];
|
|
33680
33929
|
for (const [key, rawChildSchema] of Object.entries(schema.shape)) {
|
|
33681
33930
|
const childSchema = unwrapOptional2(rawChildSchema);
|
|
33682
|
-
const nextPath = [...
|
|
33931
|
+
const nextPath = [...path84, formatSegment(key, casing)];
|
|
33683
33932
|
const optional = inheritedOptional || isOptional(rawChildSchema);
|
|
33684
33933
|
if (childSchema.kind === "object") {
|
|
33685
33934
|
summaries.push(...collectParamSummaries(childSchema, casing, nextPath, optional));
|
|
@@ -33708,17 +33957,17 @@ function matchesAllowlist(toolName, allowlist) {
|
|
|
33708
33957
|
const candidates = segments.map((_segment, index) => segments.slice(0, index + 1).join("__"));
|
|
33709
33958
|
return candidates.some((candidate) => allowlist.includes(candidate));
|
|
33710
33959
|
}
|
|
33711
|
-
function formatToolName(
|
|
33712
|
-
return
|
|
33960
|
+
function formatToolName(path84) {
|
|
33961
|
+
return path84.map((segment) => formatSegment(segment, "snake")).join("__");
|
|
33713
33962
|
}
|
|
33714
33963
|
function enumerateTools(root, casing, allowlist) {
|
|
33715
33964
|
const tools = [];
|
|
33716
|
-
function visit(node,
|
|
33965
|
+
function visit(node, path84) {
|
|
33717
33966
|
if (node.kind === "command") {
|
|
33718
33967
|
if (!node.scope.includes("mcp")) {
|
|
33719
33968
|
return;
|
|
33720
33969
|
}
|
|
33721
|
-
const name = formatToolName([...
|
|
33970
|
+
const name = formatToolName([...path84, node.name]);
|
|
33722
33971
|
const params = filterSchemaForScope(node.params, "mcp");
|
|
33723
33972
|
if (!matchesAllowlist(name, allowlist)) {
|
|
33724
33973
|
return;
|
|
@@ -33734,7 +33983,7 @@ function enumerateTools(root, casing, allowlist) {
|
|
|
33734
33983
|
});
|
|
33735
33984
|
return;
|
|
33736
33985
|
}
|
|
33737
|
-
const nextPath = [...
|
|
33986
|
+
const nextPath = [...path84, node.name];
|
|
33738
33987
|
for (const child of node.children) {
|
|
33739
33988
|
visit(child, nextPath);
|
|
33740
33989
|
}
|
|
@@ -33993,7 +34242,7 @@ var init_SKILL_plan = __esm({
|
|
|
33993
34242
|
});
|
|
33994
34243
|
|
|
33995
34244
|
// src/cli/commands/plan.ts
|
|
33996
|
-
import
|
|
34245
|
+
import path49 from "node:path";
|
|
33997
34246
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
33998
34247
|
function buildPlanPrompt(options) {
|
|
33999
34248
|
const trimmedQuestion = options.question.trim();
|
|
@@ -34145,7 +34394,7 @@ async function discoverPlans(container, kind) {
|
|
|
34145
34394
|
async function resolveSelectedPlan(options) {
|
|
34146
34395
|
const providedPath = options.providedPath?.trim();
|
|
34147
34396
|
if (providedPath) {
|
|
34148
|
-
const resolvedAbsolute = providedPath.startsWith("~/") ?
|
|
34397
|
+
const resolvedAbsolute = providedPath.startsWith("~/") ? path49.join(options.container.env.homeDir, providedPath.slice(2)) : path49.isAbsolute(providedPath) ? providedPath : path49.resolve(options.container.env.cwd, providedPath);
|
|
34149
34398
|
const matched2 = options.plans.find(
|
|
34150
34399
|
(plan) => plan.path === providedPath || plan.absolutePath === providedPath || plan.absolutePath === resolvedAbsolute
|
|
34151
34400
|
);
|
|
@@ -34163,7 +34412,7 @@ async function resolveSelectedPlan(options) {
|
|
|
34163
34412
|
const selected = await select2({
|
|
34164
34413
|
message: options.promptMessage,
|
|
34165
34414
|
options: options.plans.map((plan) => ({
|
|
34166
|
-
label: text.selectLabel(
|
|
34415
|
+
label: text.selectLabel(path49.basename(plan.path), plan.detail),
|
|
34167
34416
|
hint: plan.typeLabel,
|
|
34168
34417
|
value: plan.absolutePath
|
|
34169
34418
|
}))
|
|
@@ -34201,7 +34450,7 @@ async function renderPlanList(container, options) {
|
|
|
34201
34450
|
kind: plan.kind,
|
|
34202
34451
|
type: plan.typeLabel,
|
|
34203
34452
|
runner: plan.runner,
|
|
34204
|
-
name:
|
|
34453
|
+
name: path49.basename(plan.path),
|
|
34205
34454
|
path: plan.path,
|
|
34206
34455
|
detail: plan.detail,
|
|
34207
34456
|
updated: formatDate(plan.updatedAt)
|
|
@@ -34226,7 +34475,7 @@ async function renderPlanList(container, options) {
|
|
|
34226
34475
|
rows: plans.map((plan) => ({
|
|
34227
34476
|
kind: plan.kind,
|
|
34228
34477
|
type: plan.typeLabel,
|
|
34229
|
-
name:
|
|
34478
|
+
name: path49.basename(plan.path),
|
|
34230
34479
|
detail: plan.detail,
|
|
34231
34480
|
updated: formatDate(plan.updatedAt)
|
|
34232
34481
|
}))
|
|
@@ -34260,7 +34509,7 @@ async function executePlanAction(options) {
|
|
|
34260
34509
|
}
|
|
34261
34510
|
if (!flags.assumeYes) {
|
|
34262
34511
|
const confirmed = await confirmOrCancel({
|
|
34263
|
-
message: options.action === "archive" ? `Archive ${
|
|
34512
|
+
message: options.action === "archive" ? `Archive ${path49.basename(plan.path)}?` : `Permanently delete ${path49.basename(plan.path)}?`,
|
|
34264
34513
|
initialValue: true
|
|
34265
34514
|
});
|
|
34266
34515
|
if (!confirmed) {
|
|
@@ -34610,7 +34859,7 @@ var init_plan = __esm({
|
|
|
34610
34859
|
});
|
|
34611
34860
|
|
|
34612
34861
|
// src/cli/commands/pipeline-init.ts
|
|
34613
|
-
import
|
|
34862
|
+
import path50 from "node:path";
|
|
34614
34863
|
function buildPipelineInitPrompt(options) {
|
|
34615
34864
|
const trimmedQuestion = options.question?.trim() ?? "";
|
|
34616
34865
|
const sourceTitle = extractTitle2(options.sourceDocPath, options.sourceDocContent);
|
|
@@ -34623,7 +34872,9 @@ function buildPipelineInitPrompt(options) {
|
|
|
34623
34872
|
"",
|
|
34624
34873
|
"---",
|
|
34625
34874
|
"",
|
|
34626
|
-
|
|
34875
|
+
"Edit the source document in place by prepending valid YAML frontmatter.",
|
|
34876
|
+
"Do not create a new file.",
|
|
34877
|
+
`The final result must remain at: ${options.sourceDocPath}`,
|
|
34627
34878
|
"",
|
|
34628
34879
|
"User request:",
|
|
34629
34880
|
userRequest,
|
|
@@ -34650,7 +34901,7 @@ async function discoverPipelineInitSources(options) {
|
|
|
34650
34901
|
const sourceFiles = await discoverMarkdownFiles(options.container.fs, sourceAbsoluteDirectory);
|
|
34651
34902
|
const sources = [];
|
|
34652
34903
|
for (const file of sourceFiles) {
|
|
34653
|
-
const sourceName =
|
|
34904
|
+
const sourceName = path50.basename(file.relativePath, path50.extname(file.relativePath));
|
|
34654
34905
|
if (existingPlanNames.has(`plan-${sourceName}`)) {
|
|
34655
34906
|
continue;
|
|
34656
34907
|
}
|
|
@@ -34700,12 +34951,12 @@ async function discoverExistingPipelinePlanNames(fs17, absoluteDirectory) {
|
|
|
34700
34951
|
if (!lower.endsWith(".md") && !lower.endsWith(".yaml")) {
|
|
34701
34952
|
continue;
|
|
34702
34953
|
}
|
|
34703
|
-
const absolutePath =
|
|
34704
|
-
const
|
|
34705
|
-
if (!
|
|
34954
|
+
const absolutePath = path50.join(absoluteDirectory, entry);
|
|
34955
|
+
const stat24 = await fs17.stat(absolutePath);
|
|
34956
|
+
if (!stat24.isFile()) {
|
|
34706
34957
|
continue;
|
|
34707
34958
|
}
|
|
34708
|
-
planNames.add(
|
|
34959
|
+
planNames.add(path50.basename(entry, path50.extname(entry)));
|
|
34709
34960
|
}
|
|
34710
34961
|
return planNames;
|
|
34711
34962
|
}
|
|
@@ -34721,17 +34972,17 @@ async function discoverMarkdownFiles(fs17, absoluteDirectory, parentRelativePath
|
|
|
34721
34972
|
}
|
|
34722
34973
|
const markdownFiles = [];
|
|
34723
34974
|
for (const entry of [...entries].sort((left, right) => left.localeCompare(right))) {
|
|
34724
|
-
const absolutePath =
|
|
34725
|
-
const relativePath = parentRelativePath.length > 0 ?
|
|
34726
|
-
const
|
|
34727
|
-
if (
|
|
34975
|
+
const absolutePath = path50.join(absoluteDirectory, entry);
|
|
34976
|
+
const relativePath = parentRelativePath.length > 0 ? path50.join(parentRelativePath, entry) : entry;
|
|
34977
|
+
const stat24 = await fs17.stat(absolutePath);
|
|
34978
|
+
if (stat24.isDirectory()) {
|
|
34728
34979
|
if (entry === "archive") {
|
|
34729
34980
|
continue;
|
|
34730
34981
|
}
|
|
34731
34982
|
markdownFiles.push(...await discoverMarkdownFiles(fs17, absolutePath, relativePath));
|
|
34732
34983
|
continue;
|
|
34733
34984
|
}
|
|
34734
|
-
if (!
|
|
34985
|
+
if (!stat24.isFile() || !entry.toLowerCase().endsWith(".md")) {
|
|
34735
34986
|
continue;
|
|
34736
34987
|
}
|
|
34737
34988
|
markdownFiles.push({
|
|
@@ -34752,7 +35003,7 @@ function extractTitle2(filePath, content) {
|
|
|
34752
35003
|
return title;
|
|
34753
35004
|
}
|
|
34754
35005
|
}
|
|
34755
|
-
return
|
|
35006
|
+
return path50.basename(filePath, path50.extname(filePath));
|
|
34756
35007
|
}
|
|
34757
35008
|
function createMarkdownFence(content) {
|
|
34758
35009
|
return "`".repeat(Math.max(3, longestBacktickRun(content) + 1));
|
|
@@ -34794,33 +35045,150 @@ var init_pipeline_init = __esm({
|
|
|
34794
35045
|
var SKILL_plan_default2;
|
|
34795
35046
|
var init_SKILL_plan2 = __esm({
|
|
34796
35047
|
"src/templates/pipeline/SKILL_plan.md"() {
|
|
34797
|
-
SKILL_plan_default2 = '---\nname: poe-code-pipeline-plan\ndescription: \'Generate a Pipeline plan markdown file with YAML frontmatter from a user request. Triggers on: create a pipeline plan, write plan for, plan this feature, pipeline plan.\'\n---\n\n## If The Request Is Empty\n\nAsk the user for a one-sentence description of what they want to build.\n\n## Goal\n\nWrite a markdown pipeline plan with YAML frontmatter. Before writing, determine where to place it:\n\n1. Write the plan to `docs/plans/plan-<name>.md` by default.\n2. Find
|
|
35048
|
+
SKILL_plan_default2 = '---\nname: poe-code-pipeline-plan\ndescription: \'Generate a Pipeline plan markdown file with YAML frontmatter from a user request. Triggers on: create a pipeline plan, write plan for, plan this feature, pipeline plan.\'\n---\n\n## If The Request Is Empty\n\nAsk the user for a one-sentence description of what they want to build.\n\n## Goal\n\nWrite a markdown pipeline plan with YAML frontmatter. Before writing, determine where to place it:\n\n1. Write the plan to `docs/plans/plan-<name>.md` by default.\n2. Find named step configs in `.poe-code/pipeline/steps/`.\n a. Check `<project-root>/.poe-code/pipeline/steps/` first.\n b. If that directory does not exist, check `~/.poe-code/pipeline/steps/`.\n c. Read the available `*.yaml` files there (for example `default.yaml`, `fast.yaml`). Use `default` when the user does not ask for a different config. If no directory exists, use stepless tasks.\n3. Decide what belongs in the markdown body. If the user already has a Markdown design/context doc (for example in `docs/plans/`), use that content as the plan body when it makes sense. If they want to keep the source doc separate, link it via `vars` so it is available in every prompt without repeating the path.\n\n## Rules\n\n- Each task must be self-contained. Put all context needed to execute the task inside that task\'s `prompt`.\n- Do not create tasks that depend on hidden state from previous tasks.\n- Use short kebab-case ids.\n- Keep titles concise and descriptive.\n- The available steps come from the named step config you found in `.poe-code/pipeline/steps/`. Use the current step names instead of inventing hardcoded ones.\n- Always write `extends: <name>` in the frontmatter. Use `default` unless you discovered or intentionally chose another named config.\n- If no step configuration directory is present, use stepless tasks with scalar `status: open`.\n- If step configuration is present, start every configured step status at `open`.\n- `setup` and `teardown` from the extended step config are inherited automatically.\n- To disable an inherited hook for a specific plan, set `setup: false` or `teardown: false`.\n- To override an inherited hook, define the full block with a `prompt` field.\n- Use the plan-level `steps:` block only for per-plan step overrides. Override only the fields you need; unset fields inherit from the extended config.\n- If the user keeps an existing Markdown plan document as a separate file, add a `vars` block with a `plan_doc` key pointing to the file path. The pipeline runtime reads the file and makes its contents available as a named placeholder in every prompt.\n- `vars` values are plain strings. Use the `file` include syntax inside a value to load a file at runtime (path relative to project root): write `var_name: "` followed by the file include tag and a closing `"`.\n- Each var name becomes a double-curly-brace placeholder usable in any task, step, setup, or teardown prompt.\n- The markdown body is for context, notes, acceptance criteria, or the design doc. Keep executable pipeline config in the YAML frontmatter.\n- Do not rely on the body alone for runtime context. Each task prompt must still include everything it needs directly or via `vars` placeholders.\n- Start the frontmatter with canonical metadata: `$schema: https://poe-platform.github.io/poe-code/schemas/plans/pipeline.schema.json`, `kind: pipeline`, and `version: 1`.\n\n## Output Format\n\n```markdown\n---\n$schema: https://poe-platform.github.io/poe-code/schemas/plans/pipeline.schema.json\nkind: pipeline\nversion: 1\nextends: default\n\n# vars: optional. Define named values available as double-curly-brace placeholders in every prompt.\n# Each value is a plain string. To load a file at runtime, write the value using the\n# file include syntax: double-curly-brace file followed by a quoted path.\n# Omit this block if there are no shared values to inject.\n#\n# vars:\n# plan_doc: "(file include for docs/plans/my-feature.md)" # loaded at runtime\n# env: production # literal string\n\n# Optional per-plan step overrides. Unset fields inherit from the extended config.\n# Omit this block when the base config already fits.\n#\n# steps:\n# implement:\n# prompt: |\n# Focus on the risky auth paths first.\n# test:\n# mode: read\n\n# setup/teardown are inherited from the extended step config automatically.\n# Include them only to disable or override:\n#\n# setup: false # disable the inherited setup hook\n# teardown: false # disable the inherited teardown hook\n# setup: # override with a different prompt\n# prompt: Custom setup\n# mode: yolo\n\ntasks:\n - id: auth-hardening\n title: Harden auth flow\n prompt: |\n Improve auth validation and session handling.\n # If vars defines plan_doc, reference it here using the double-curly-brace placeholder syntax.\n # scalar when no step config is available:\n status: open\n # stepped when the extended config defines steps:\n # status:\n # implement: open\n # test: open\n # commit: open\n---\n\n# Context\n\nPaste the design doc, notes, acceptance criteria, or implementation details here.\nThis body is for human-readable context and future tooling.\nAny context needed at runtime must still appear in each task prompt or via vars placeholders.\n```\n\n## After Writing\n\nRun `poe-code pipeline validate <path>` to check the plan is valid before running it.\n\n## Notes\n\n- Match the uncommented step names and order from the named step config you choose.\n- If `poe-code` is not available as a global command, use `npx poe-code` instead.\n';
|
|
34798
35049
|
}
|
|
34799
35050
|
});
|
|
34800
35051
|
|
|
34801
35052
|
// src/sdk/pipeline.ts
|
|
34802
35053
|
import * as fsPromises14 from "node:fs/promises";
|
|
35054
|
+
import path51 from "node:path";
|
|
34803
35055
|
function isAbortError4(error2) {
|
|
34804
35056
|
return error2 instanceof Error && error2.name === "AbortError";
|
|
34805
35057
|
}
|
|
35058
|
+
function createDefaultFs11() {
|
|
35059
|
+
return {
|
|
35060
|
+
readFile: fsPromises14.readFile,
|
|
35061
|
+
writeFile: fsPromises14.writeFile,
|
|
35062
|
+
readdir: fsPromises14.readdir,
|
|
35063
|
+
stat: async (filePath) => {
|
|
35064
|
+
const stat24 = await fsPromises14.stat(filePath);
|
|
35065
|
+
return {
|
|
35066
|
+
isFile: () => stat24.isFile(),
|
|
35067
|
+
isDirectory: () => stat24.isDirectory(),
|
|
35068
|
+
mtimeMs: stat24.mtimeMs
|
|
35069
|
+
};
|
|
35070
|
+
},
|
|
35071
|
+
mkdir: async (filePath, options) => {
|
|
35072
|
+
await fsPromises14.mkdir(filePath, options);
|
|
35073
|
+
},
|
|
35074
|
+
rmdir: fsPromises14.rmdir,
|
|
35075
|
+
rename: fsPromises14.rename
|
|
35076
|
+
};
|
|
35077
|
+
}
|
|
35078
|
+
function createEmptyMetrics() {
|
|
35079
|
+
return {
|
|
35080
|
+
totalInputTokens: 0,
|
|
35081
|
+
totalOutputTokens: 0,
|
|
35082
|
+
totalCachedTokens: 0,
|
|
35083
|
+
tasksCompleted: 0,
|
|
35084
|
+
tasksFailed: 0,
|
|
35085
|
+
stepsCompleted: 0
|
|
35086
|
+
};
|
|
35087
|
+
}
|
|
35088
|
+
function needsPipelineInit(planContent) {
|
|
35089
|
+
try {
|
|
35090
|
+
return parsePlan(planContent).tasks.length === 0;
|
|
35091
|
+
} catch (error2) {
|
|
35092
|
+
const message2 = error2 instanceof Error ? error2.message : String(error2);
|
|
35093
|
+
if (message2 === "Invalid plan YAML: expected a top-level object." || message2 === 'Invalid plan YAML: expected "tasks" to be an array.') {
|
|
35094
|
+
return true;
|
|
35095
|
+
}
|
|
35096
|
+
throw error2;
|
|
35097
|
+
}
|
|
35098
|
+
}
|
|
35099
|
+
function withPipelineTimeoutRetries(runAgent) {
|
|
35100
|
+
return async (input) => {
|
|
35101
|
+
for (let attempt = 1; attempt <= PIPELINE_ACTIVITY_TIMEOUT_RETRY_COUNT; attempt += 1) {
|
|
35102
|
+
try {
|
|
35103
|
+
return await runAgent(input);
|
|
35104
|
+
} catch (error2) {
|
|
35105
|
+
if (!isActivityTimeoutError(error2) || attempt === PIPELINE_ACTIVITY_TIMEOUT_RETRY_COUNT) {
|
|
35106
|
+
throw error2;
|
|
35107
|
+
}
|
|
35108
|
+
}
|
|
35109
|
+
}
|
|
35110
|
+
throw new Error("Unreachable");
|
|
35111
|
+
};
|
|
35112
|
+
}
|
|
34806
35113
|
async function runPipeline2(options) {
|
|
34807
|
-
const
|
|
35114
|
+
const fs17 = options.fs ?? createDefaultFs11();
|
|
35115
|
+
const runAgent = withPipelineTimeoutRetries(options.runAgent ?? (async (input) => {
|
|
34808
35116
|
return await spawn7.autonomous(input.agent, {
|
|
34809
35117
|
prompt: input.prompt,
|
|
34810
35118
|
cwd: input.cwd,
|
|
34811
35119
|
logDir: input.logDir,
|
|
34812
35120
|
model: input.model,
|
|
34813
35121
|
mode: input.mode,
|
|
35122
|
+
maxTimeoutRetries: 1,
|
|
34814
35123
|
...input.mcpServers ? { mcpServers: input.mcpServers } : {},
|
|
34815
35124
|
...input.signal ? { signal: input.signal } : {}
|
|
34816
35125
|
});
|
|
35126
|
+
}));
|
|
35127
|
+
const planPath = await resolvePlanPath({
|
|
35128
|
+
cwd: options.cwd,
|
|
35129
|
+
homeDir: options.homeDir,
|
|
35130
|
+
plan: options.plan,
|
|
35131
|
+
planDirectory: options.planDirectory,
|
|
35132
|
+
assumeYes: options.assumeYes,
|
|
35133
|
+
fs: fs17,
|
|
35134
|
+
selectPlan: options.selectPlan,
|
|
35135
|
+
promptForPath: options.promptForPath
|
|
34817
35136
|
});
|
|
35137
|
+
if (!planPath) {
|
|
35138
|
+
return {
|
|
35139
|
+
stopReason: "cancelled",
|
|
35140
|
+
planPath: "",
|
|
35141
|
+
runsCompleted: 0,
|
|
35142
|
+
totalDurationMs: 0,
|
|
35143
|
+
metrics: createEmptyMetrics()
|
|
35144
|
+
};
|
|
35145
|
+
}
|
|
35146
|
+
const absolutePlanPath = resolveAbsolutePlanPath(planPath, options.cwd, options.homeDir);
|
|
35147
|
+
const planContent = await fs17.readFile(absolutePlanPath, "utf8");
|
|
35148
|
+
if (needsPipelineInit(planContent)) {
|
|
35149
|
+
const initResult = await runPipelineInit({
|
|
35150
|
+
agent: options.agent,
|
|
35151
|
+
...options.model ? { model: options.model } : {},
|
|
35152
|
+
cwd: options.cwd,
|
|
35153
|
+
homeDir: options.homeDir,
|
|
35154
|
+
fs: fs17,
|
|
35155
|
+
sources: [
|
|
35156
|
+
{
|
|
35157
|
+
absolutePath: absolutePlanPath,
|
|
35158
|
+
relativePath: planPath,
|
|
35159
|
+
title: path51.basename(planPath, path51.extname(planPath))
|
|
35160
|
+
}
|
|
35161
|
+
],
|
|
35162
|
+
assumeYes: options.assumeYes ?? false,
|
|
35163
|
+
runAgent,
|
|
35164
|
+
...options.signal ? { signal: options.signal } : {}
|
|
35165
|
+
});
|
|
35166
|
+
if (initResult.stopReason === "cancelled") {
|
|
35167
|
+
return {
|
|
35168
|
+
stopReason: "cancelled",
|
|
35169
|
+
planPath,
|
|
35170
|
+
runsCompleted: 0,
|
|
35171
|
+
totalDurationMs: 0,
|
|
35172
|
+
metrics: createEmptyMetrics()
|
|
35173
|
+
};
|
|
35174
|
+
}
|
|
35175
|
+
if (initResult.stopReason === "failed") {
|
|
35176
|
+
throw new Error(`Pipeline init failed for "${planPath}".`);
|
|
35177
|
+
}
|
|
35178
|
+
const initializedPlanContent = await fs17.readFile(absolutePlanPath, "utf8");
|
|
35179
|
+
if (needsPipelineInit(initializedPlanContent)) {
|
|
35180
|
+
throw new Error(`Pipeline init did not produce runnable tasks for "${planPath}".`);
|
|
35181
|
+
}
|
|
35182
|
+
}
|
|
34818
35183
|
return runPipeline({
|
|
34819
35184
|
...options,
|
|
35185
|
+
fs: fs17,
|
|
35186
|
+
plan: planPath,
|
|
34820
35187
|
runAgent
|
|
34821
35188
|
});
|
|
34822
35189
|
}
|
|
34823
35190
|
async function runPipelineInit(options) {
|
|
35191
|
+
const fs17 = options.fs ?? createDefaultFs11();
|
|
34824
35192
|
const runAgent = options.runAgent ?? (async (input) => {
|
|
34825
35193
|
return await spawn7.autonomous(input.agent, {
|
|
34826
35194
|
prompt: input.prompt,
|
|
@@ -34836,11 +35204,6 @@ async function runPipelineInit(options) {
|
|
|
34836
35204
|
sourcesProcessed: 0
|
|
34837
35205
|
};
|
|
34838
35206
|
}
|
|
34839
|
-
const planDirectory = resolvePlanDirectory2({
|
|
34840
|
-
cwd: options.cwd,
|
|
34841
|
-
homeDir: options.homeDir,
|
|
34842
|
-
planDirectory: options.planDirectory ?? ".poe-code/pipeline/plans"
|
|
34843
|
-
});
|
|
34844
35207
|
let sourcesProcessed = 0;
|
|
34845
35208
|
const totalSources = options.sources.length;
|
|
34846
35209
|
for (const [sourceIndex, source] of options.sources.entries()) {
|
|
@@ -34853,7 +35216,7 @@ async function runPipelineInit(options) {
|
|
|
34853
35216
|
const displayIndex = sourceIndex + 1;
|
|
34854
35217
|
try {
|
|
34855
35218
|
options.onSourceStart?.(source, displayIndex, totalSources);
|
|
34856
|
-
const sourceDocContent = await
|
|
35219
|
+
const sourceDocContent = await fs17.readFile(source.absolutePath, "utf8");
|
|
34857
35220
|
if (options.signal?.aborted) {
|
|
34858
35221
|
return {
|
|
34859
35222
|
stopReason: "cancelled",
|
|
@@ -34862,7 +35225,6 @@ async function runPipelineInit(options) {
|
|
|
34862
35225
|
}
|
|
34863
35226
|
const prompt = buildPipelineInitPrompt({
|
|
34864
35227
|
question: options.question,
|
|
34865
|
-
planDirectory,
|
|
34866
35228
|
sourceDocPath: source.relativePath,
|
|
34867
35229
|
sourceDocContent,
|
|
34868
35230
|
skillContent: SKILL_plan_default2
|
|
@@ -34903,19 +35265,22 @@ async function runPipelineInit(options) {
|
|
|
34903
35265
|
sourcesProcessed
|
|
34904
35266
|
};
|
|
34905
35267
|
}
|
|
35268
|
+
var PIPELINE_ACTIVITY_TIMEOUT_RETRY_COUNT;
|
|
34906
35269
|
var init_pipeline2 = __esm({
|
|
34907
35270
|
async "src/sdk/pipeline.ts"() {
|
|
34908
35271
|
"use strict";
|
|
35272
|
+
init_src8();
|
|
34909
35273
|
init_src18();
|
|
34910
35274
|
await init_pipeline_init();
|
|
34911
35275
|
init_SKILL_plan2();
|
|
34912
35276
|
await init_spawn3();
|
|
34913
35277
|
init_src18();
|
|
35278
|
+
PIPELINE_ACTIVITY_TIMEOUT_RETRY_COUNT = 3;
|
|
34914
35279
|
}
|
|
34915
35280
|
});
|
|
34916
35281
|
|
|
34917
35282
|
// packages/process-launcher/src/state/state-store.ts
|
|
34918
|
-
import
|
|
35283
|
+
import path52 from "node:path";
|
|
34919
35284
|
import * as nodeFs3 from "node:fs/promises";
|
|
34920
35285
|
function isNotFoundError2(error2) {
|
|
34921
35286
|
return error2 instanceof Error && "code" in error2 && error2.code === "ENOENT";
|
|
@@ -34931,9 +35296,9 @@ async function removeDirectory2(fs17, directoryPath) {
|
|
|
34931
35296
|
throw error2;
|
|
34932
35297
|
}
|
|
34933
35298
|
for (const entry of entries) {
|
|
34934
|
-
const entryPath =
|
|
34935
|
-
const
|
|
34936
|
-
if (
|
|
35299
|
+
const entryPath = path52.join(directoryPath, entry);
|
|
35300
|
+
const stat24 = await fs17.stat(entryPath);
|
|
35301
|
+
if (stat24.isFile()) {
|
|
34937
35302
|
await fs17.rm(entryPath, { force: true });
|
|
34938
35303
|
continue;
|
|
34939
35304
|
}
|
|
@@ -34948,7 +35313,7 @@ async function removeDirectory2(fs17, directoryPath) {
|
|
|
34948
35313
|
}
|
|
34949
35314
|
function createStateStore(stateDir, fs17 = nodeFs3) {
|
|
34950
35315
|
async function read(id) {
|
|
34951
|
-
const statePath =
|
|
35316
|
+
const statePath = path52.join(stateDir, id, "state.json");
|
|
34952
35317
|
try {
|
|
34953
35318
|
const content = await fs17.readFile(statePath, "utf8");
|
|
34954
35319
|
return JSON.parse(content);
|
|
@@ -34960,9 +35325,9 @@ function createStateStore(stateDir, fs17 = nodeFs3) {
|
|
|
34960
35325
|
}
|
|
34961
35326
|
}
|
|
34962
35327
|
async function write2(id, state) {
|
|
34963
|
-
const processDir =
|
|
35328
|
+
const processDir = path52.join(stateDir, id);
|
|
34964
35329
|
await fs17.mkdir(processDir, { recursive: true });
|
|
34965
|
-
await fs17.writeFile(
|
|
35330
|
+
await fs17.writeFile(path52.join(processDir, "state.json"), `${JSON.stringify(state, null, 2)}
|
|
34966
35331
|
`);
|
|
34967
35332
|
}
|
|
34968
35333
|
async function list() {
|
|
@@ -34977,10 +35342,10 @@ function createStateStore(stateDir, fs17 = nodeFs3) {
|
|
|
34977
35342
|
}
|
|
34978
35343
|
const states = [];
|
|
34979
35344
|
for (const entry of [...entries].sort()) {
|
|
34980
|
-
const entryPath =
|
|
35345
|
+
const entryPath = path52.join(stateDir, entry);
|
|
34981
35346
|
try {
|
|
34982
|
-
const
|
|
34983
|
-
if (
|
|
35347
|
+
const stat24 = await fs17.stat(entryPath);
|
|
35348
|
+
if (stat24.isFile()) {
|
|
34984
35349
|
continue;
|
|
34985
35350
|
}
|
|
34986
35351
|
} catch (error2) {
|
|
@@ -34997,7 +35362,7 @@ function createStateStore(stateDir, fs17 = nodeFs3) {
|
|
|
34997
35362
|
return states;
|
|
34998
35363
|
}
|
|
34999
35364
|
async function remove2(id) {
|
|
35000
|
-
await removeDirectory2(fs17,
|
|
35365
|
+
await removeDirectory2(fs17, path52.join(stateDir, id));
|
|
35001
35366
|
}
|
|
35002
35367
|
return { read, write: write2, list, remove: remove2 };
|
|
35003
35368
|
}
|
|
@@ -35008,16 +35373,16 @@ var init_state_store = __esm({
|
|
|
35008
35373
|
});
|
|
35009
35374
|
|
|
35010
35375
|
// packages/process-launcher/src/logs/log-writer.ts
|
|
35011
|
-
import
|
|
35376
|
+
import path53 from "node:path";
|
|
35012
35377
|
import * as nodeFs4 from "node:fs/promises";
|
|
35013
35378
|
function isNotFoundError3(error2) {
|
|
35014
35379
|
return error2 instanceof Error && "code" in error2 && error2.code === "ENOENT";
|
|
35015
35380
|
}
|
|
35016
35381
|
function getCurrentLogPath(logDir, stream) {
|
|
35017
|
-
return
|
|
35382
|
+
return path53.join(logDir, `${stream}.log`);
|
|
35018
35383
|
}
|
|
35019
35384
|
function getRotatedLogPath(logDir, stream, index) {
|
|
35020
|
-
return
|
|
35385
|
+
return path53.join(logDir, `${stream}.${index}.log`);
|
|
35021
35386
|
}
|
|
35022
35387
|
async function isFile(fs17, filePath) {
|
|
35023
35388
|
try {
|
|
@@ -35064,7 +35429,7 @@ async function removeAllStreamLogs(fs17, logDir, stream) {
|
|
|
35064
35429
|
if (getRotatedLogIndex(fileName, stream) === null) {
|
|
35065
35430
|
continue;
|
|
35066
35431
|
}
|
|
35067
|
-
await fs17.rm(
|
|
35432
|
+
await fs17.rm(path53.join(logDir, fileName), { force: true });
|
|
35068
35433
|
}
|
|
35069
35434
|
} catch (error2) {
|
|
35070
35435
|
if (isNotFoundError3(error2)) {
|
|
@@ -35324,7 +35689,7 @@ var init_engine = __esm({
|
|
|
35324
35689
|
});
|
|
35325
35690
|
|
|
35326
35691
|
// packages/process-runner/src/docker/args.ts
|
|
35327
|
-
import
|
|
35692
|
+
import path54 from "node:path";
|
|
35328
35693
|
function buildDockerRunArgs(input) {
|
|
35329
35694
|
const args = [input.engine];
|
|
35330
35695
|
if (input.engine === "docker" && input.context) {
|
|
@@ -35351,7 +35716,7 @@ function buildDockerRunArgs(input) {
|
|
|
35351
35716
|
args.push("-e", `${key}=${value}`);
|
|
35352
35717
|
}
|
|
35353
35718
|
for (const mount of input.mounts) {
|
|
35354
|
-
const volume = `${
|
|
35719
|
+
const volume = `${path54.resolve(mount.source)}:${mount.target}${mount.readonly ? ":ro" : ""}`;
|
|
35355
35720
|
args.push("-v", volume);
|
|
35356
35721
|
}
|
|
35357
35722
|
for (const port of input.ports) {
|
|
@@ -35608,13 +35973,13 @@ var init_src24 = __esm({
|
|
|
35608
35973
|
import { spawnSync } from "node:child_process";
|
|
35609
35974
|
import * as nodeFs5 from "node:fs/promises";
|
|
35610
35975
|
import os5 from "node:os";
|
|
35611
|
-
import
|
|
35976
|
+
import path55 from "node:path";
|
|
35612
35977
|
function createSupervisor(options) {
|
|
35613
35978
|
const { spec: spec10 } = options;
|
|
35614
35979
|
const runner = resolveRunner(options);
|
|
35615
35980
|
const stateStore = createStateStore(options.stateDir, options.fs);
|
|
35616
35981
|
const logWriter = createLogWriter(
|
|
35617
|
-
|
|
35982
|
+
path55.join(options.stateDir, spec10.id, "logs"),
|
|
35618
35983
|
spec10.logRetainCount ?? 5,
|
|
35619
35984
|
options.fs
|
|
35620
35985
|
);
|
|
@@ -35982,8 +36347,8 @@ async function resolveProcessWorkspace(cwd, stateDir) {
|
|
|
35982
36347
|
};
|
|
35983
36348
|
}
|
|
35984
36349
|
function resolveWorkspaceHomeDir(stateDir) {
|
|
35985
|
-
if (
|
|
35986
|
-
return
|
|
36350
|
+
if (path55.basename(stateDir) === "launch" && path55.basename(path55.dirname(stateDir)) === ".poe-code") {
|
|
36351
|
+
return path55.dirname(path55.dirname(stateDir));
|
|
35987
36352
|
}
|
|
35988
36353
|
return os5.homedir();
|
|
35989
36354
|
}
|
|
@@ -36035,7 +36400,7 @@ var init_supervisor = __esm({
|
|
|
36035
36400
|
});
|
|
36036
36401
|
|
|
36037
36402
|
// packages/process-launcher/src/launcher.ts
|
|
36038
|
-
import
|
|
36403
|
+
import path56 from "node:path";
|
|
36039
36404
|
import * as nodeFs6 from "node:fs/promises";
|
|
36040
36405
|
async function startManagedProcess(options) {
|
|
36041
36406
|
const fs17 = options.fs ?? defaultFs2();
|
|
@@ -36384,10 +36749,10 @@ async function listIds(fs17, baseDir) {
|
|
|
36384
36749
|
const entries = await fs17.readdir(baseDir);
|
|
36385
36750
|
const ids = [];
|
|
36386
36751
|
for (const entry of entries) {
|
|
36387
|
-
const entryPath =
|
|
36752
|
+
const entryPath = path56.join(baseDir, entry);
|
|
36388
36753
|
try {
|
|
36389
|
-
const
|
|
36390
|
-
if (!
|
|
36754
|
+
const stat24 = await fs17.stat(entryPath);
|
|
36755
|
+
if (!stat24.isFile()) {
|
|
36391
36756
|
ids.push(entry);
|
|
36392
36757
|
}
|
|
36393
36758
|
} catch (error2) {
|
|
@@ -36434,24 +36799,24 @@ async function readJsonFile(fs17, filePath) {
|
|
|
36434
36799
|
}
|
|
36435
36800
|
}
|
|
36436
36801
|
async function writeJsonFile(fs17, filePath, value) {
|
|
36437
|
-
await fs17.mkdir(
|
|
36802
|
+
await fs17.mkdir(path56.dirname(filePath), { recursive: true });
|
|
36438
36803
|
await fs17.writeFile(filePath, `${JSON.stringify(value, null, 2)}
|
|
36439
36804
|
`);
|
|
36440
36805
|
}
|
|
36441
36806
|
function resolveProcessDir(baseDir, id) {
|
|
36442
|
-
return
|
|
36807
|
+
return path56.join(baseDir, id);
|
|
36443
36808
|
}
|
|
36444
36809
|
function resolveSpecPath(baseDir, id) {
|
|
36445
|
-
return
|
|
36810
|
+
return path56.join(resolveProcessDir(baseDir, id), "spec.json");
|
|
36446
36811
|
}
|
|
36447
36812
|
function resolveStatePath(baseDir, id) {
|
|
36448
|
-
return
|
|
36813
|
+
return path56.join(resolveProcessDir(baseDir, id), "state.json");
|
|
36449
36814
|
}
|
|
36450
36815
|
function resolveMetaPath(baseDir, id) {
|
|
36451
|
-
return
|
|
36816
|
+
return path56.join(resolveProcessDir(baseDir, id), "meta.json");
|
|
36452
36817
|
}
|
|
36453
36818
|
function resolveLogDir2(baseDir, id) {
|
|
36454
|
-
return
|
|
36819
|
+
return path56.join(resolveProcessDir(baseDir, id), "logs");
|
|
36455
36820
|
}
|
|
36456
36821
|
function isNotFoundError4(error2) {
|
|
36457
36822
|
return error2 instanceof Error && "code" in error2 && error2.code === "ENOENT";
|
|
@@ -36532,8 +36897,8 @@ var init_ralph2 = __esm({
|
|
|
36532
36897
|
|
|
36533
36898
|
// src/sdk/experiment.ts
|
|
36534
36899
|
import * as fsPromises15 from "node:fs/promises";
|
|
36535
|
-
import
|
|
36536
|
-
function
|
|
36900
|
+
import path57 from "node:path";
|
|
36901
|
+
function createDefaultFs12() {
|
|
36537
36902
|
return {
|
|
36538
36903
|
readFile: fsPromises15.readFile,
|
|
36539
36904
|
writeFile: async (filePath, content) => {
|
|
@@ -36541,11 +36906,11 @@ function createDefaultFs11() {
|
|
|
36541
36906
|
},
|
|
36542
36907
|
readdir: fsPromises15.readdir,
|
|
36543
36908
|
stat: async (filePath) => {
|
|
36544
|
-
const
|
|
36909
|
+
const stat24 = await fsPromises15.stat(filePath);
|
|
36545
36910
|
return {
|
|
36546
|
-
isFile: () =>
|
|
36547
|
-
isDirectory: () =>
|
|
36548
|
-
mtimeMs:
|
|
36911
|
+
isFile: () => stat24.isFile(),
|
|
36912
|
+
isDirectory: () => stat24.isDirectory(),
|
|
36913
|
+
mtimeMs: stat24.mtimeMs
|
|
36549
36914
|
};
|
|
36550
36915
|
},
|
|
36551
36916
|
mkdir: async (filePath, options) => {
|
|
@@ -36560,9 +36925,9 @@ function createDefaultFs11() {
|
|
|
36560
36925
|
};
|
|
36561
36926
|
}
|
|
36562
36927
|
function resolveJournalPath2(docPath) {
|
|
36563
|
-
return
|
|
36564
|
-
|
|
36565
|
-
`${
|
|
36928
|
+
return path57.join(
|
|
36929
|
+
path57.dirname(docPath),
|
|
36930
|
+
`${path57.basename(docPath, path57.extname(docPath))}.journal.jsonl`
|
|
36566
36931
|
);
|
|
36567
36932
|
}
|
|
36568
36933
|
async function runExperiment(options) {
|
|
@@ -36580,13 +36945,13 @@ async function runExperiment(options) {
|
|
|
36580
36945
|
});
|
|
36581
36946
|
}
|
|
36582
36947
|
async function readExperimentJournal(options) {
|
|
36583
|
-
const fs17 = options.fs ??
|
|
36948
|
+
const fs17 = options.fs ?? createDefaultFs12();
|
|
36584
36949
|
const absoluteDocPath = resolveWorkflowPath(options.docPath, options.cwd, options.homeDir);
|
|
36585
36950
|
const journal = new ExperimentJournal(resolveJournalPath2(absoluteDocPath), fs17);
|
|
36586
36951
|
return await journal.readAll();
|
|
36587
36952
|
}
|
|
36588
36953
|
async function appendExperimentJournalEntry(options) {
|
|
36589
|
-
const fs17 = options.fs ??
|
|
36954
|
+
const fs17 = options.fs ?? createDefaultFs12();
|
|
36590
36955
|
const absoluteDocPath = resolveWorkflowPath(options.docPath, options.cwd, options.homeDir);
|
|
36591
36956
|
const journal = new ExperimentJournal(resolveJournalPath2(absoluteDocPath), fs17);
|
|
36592
36957
|
await journal.init();
|
|
@@ -36769,7 +37134,7 @@ var init_frontmatter4 = __esm({
|
|
|
36769
37134
|
});
|
|
36770
37135
|
|
|
36771
37136
|
// packages/github-workflows/src/discover.ts
|
|
36772
|
-
import { readdir as
|
|
37137
|
+
import { readdir as readdir16, readFile as readFile16 } from "node:fs/promises";
|
|
36773
37138
|
import { join as join2 } from "node:path";
|
|
36774
37139
|
async function discoverAutomations(builtInDir, ...projectDirs) {
|
|
36775
37140
|
const directories = [builtInDir, ...projectDirs];
|
|
@@ -36802,7 +37167,7 @@ async function loadAutomation(name, dirs) {
|
|
|
36802
37167
|
}
|
|
36803
37168
|
async function listMarkdownFiles(dir) {
|
|
36804
37169
|
try {
|
|
36805
|
-
const entries = await
|
|
37170
|
+
const entries = await readdir16(dir);
|
|
36806
37171
|
return entries.filter((entry) => entry.endsWith(".md")).sort((left, right) => left.localeCompare(right));
|
|
36807
37172
|
} catch (error2) {
|
|
36808
37173
|
if (isMissingPathError(error2)) {
|
|
@@ -37122,9 +37487,9 @@ var init_setup_agent = __esm({
|
|
|
37122
37487
|
});
|
|
37123
37488
|
|
|
37124
37489
|
// packages/github-workflows/src/variables.ts
|
|
37125
|
-
import
|
|
37490
|
+
import path58 from "node:path";
|
|
37126
37491
|
import { readFile as readFile17 } from "node:fs/promises";
|
|
37127
|
-
import { isMap as isMap3, parseDocument as parseDocument7, stringify as
|
|
37492
|
+
import { isMap as isMap3, parseDocument as parseDocument7, stringify as stringify3 } from "yaml";
|
|
37128
37493
|
function isRecord18(value) {
|
|
37129
37494
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
37130
37495
|
}
|
|
@@ -37236,15 +37601,15 @@ function formatVariableBlock(name, value) {
|
|
|
37236
37601
|
return formatYamlBlock(name, value);
|
|
37237
37602
|
}
|
|
37238
37603
|
function formatYamlBlock(name, value) {
|
|
37239
|
-
return
|
|
37604
|
+
return stringify3({ [name]: value }).trimEnd();
|
|
37240
37605
|
}
|
|
37241
37606
|
function formatCommentedBlock(name, value) {
|
|
37242
37607
|
return formatVariableBlock(name, value).split("\n").map((line) => `# ${line}`).join("\n");
|
|
37243
37608
|
}
|
|
37244
37609
|
async function loadVariableSources(builtInDir, projectDir) {
|
|
37245
|
-
const builtInPath =
|
|
37610
|
+
const builtInPath = path58.join(builtInDir, VARIABLES_FILE_NAME);
|
|
37246
37611
|
const builtInVariables = parseVariables(builtInPath, await readFile17(builtInPath, "utf8"));
|
|
37247
|
-
const projectVariablesPath = projectDir === void 0 ? void 0 :
|
|
37612
|
+
const projectVariablesPath = projectDir === void 0 ? void 0 : path58.join(projectDir, VARIABLES_FILE_NAME);
|
|
37248
37613
|
const projectVariablesContent = projectVariablesPath === void 0 ? void 0 : await readOptionalVariablesContent(projectVariablesPath);
|
|
37249
37614
|
if (projectVariablesPath === void 0 || projectVariablesContent === void 0) {
|
|
37250
37615
|
return { builtInVariables, extendsBuiltIns: true, projectVariables: {} };
|
|
@@ -37256,13 +37621,13 @@ async function loadVariableSources(builtInDir, projectDir) {
|
|
|
37256
37621
|
return { builtInVariables, extendsBuiltIns, projectVariables };
|
|
37257
37622
|
}
|
|
37258
37623
|
async function loadVariables(builtInDir, projectDir) {
|
|
37259
|
-
const builtInPath =
|
|
37624
|
+
const builtInPath = path58.join(builtInDir, VARIABLES_FILE_NAME);
|
|
37260
37625
|
const builtInContent = await readFile17(builtInPath, "utf8");
|
|
37261
37626
|
const builtInVariables = parseVariables(builtInPath, builtInContent);
|
|
37262
37627
|
if (projectDir === void 0) {
|
|
37263
37628
|
return filterDisabledVariables(builtInVariables);
|
|
37264
37629
|
}
|
|
37265
|
-
const projectVariablesPath =
|
|
37630
|
+
const projectVariablesPath = path58.join(projectDir, VARIABLES_FILE_NAME);
|
|
37266
37631
|
const projectVariablesContent = await readOptionalVariablesContent(projectVariablesPath);
|
|
37267
37632
|
if (projectVariablesContent === void 0) {
|
|
37268
37633
|
return filterDisabledVariables(builtInVariables);
|
|
@@ -37295,7 +37660,7 @@ async function loadVariableStatuses(builtInDir, projectDir) {
|
|
|
37295
37660
|
(key) => !extendsBuiltIns || !Object.prototype.hasOwnProperty.call(builtInVariables, key)
|
|
37296
37661
|
)
|
|
37297
37662
|
];
|
|
37298
|
-
const projectVariablesPath = projectDir === void 0 ? void 0 :
|
|
37663
|
+
const projectVariablesPath = projectDir === void 0 ? void 0 : path58.join(projectDir, VARIABLES_FILE_NAME);
|
|
37299
37664
|
return orderedNames.map((name) => {
|
|
37300
37665
|
if (!Object.prototype.hasOwnProperty.call(projectVariables, name)) {
|
|
37301
37666
|
return {
|
|
@@ -37356,8 +37721,8 @@ var init_variables2 = __esm({
|
|
|
37356
37721
|
});
|
|
37357
37722
|
|
|
37358
37723
|
// packages/github-workflows/src/commands.ts
|
|
37359
|
-
import { access as access2, mkdir as
|
|
37360
|
-
import
|
|
37724
|
+
import { access as access2, mkdir as mkdir16, readFile as readFile18, unlink as unlink5, writeFile as writeFile12 } from "node:fs/promises";
|
|
37725
|
+
import path59 from "node:path";
|
|
37361
37726
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
37362
37727
|
import Mustache3 from "mustache";
|
|
37363
37728
|
function formatLabel(name) {
|
|
@@ -37380,7 +37745,7 @@ async function loadNamedAutomation(name, cwd) {
|
|
|
37380
37745
|
}
|
|
37381
37746
|
async function readBuiltInPromptFile(name) {
|
|
37382
37747
|
try {
|
|
37383
|
-
return await readFile18(
|
|
37748
|
+
return await readFile18(path59.join(await resolveBuiltInPromptsDir(), `${name}.md`), "utf8");
|
|
37384
37749
|
} catch (error2) {
|
|
37385
37750
|
if (isMissingPathError2(error2)) {
|
|
37386
37751
|
throw new UserError(`Automation "${name}" was not found.`);
|
|
@@ -37389,11 +37754,11 @@ async function readBuiltInPromptFile(name) {
|
|
|
37389
37754
|
}
|
|
37390
37755
|
}
|
|
37391
37756
|
async function readBuiltInWorkflowTemplate(name, variant, automationName = name, promptPath) {
|
|
37392
|
-
const templatePath =
|
|
37757
|
+
const templatePath = path59.join(await resolveBuiltInWorkflowTemplatesDir(), `${name}.${variant}.yml`);
|
|
37393
37758
|
try {
|
|
37394
37759
|
const content = await readFile18(templatePath, "utf8");
|
|
37395
37760
|
const header = promptPath !== void 0 ? `# Auto-generated by: poe-code github-workflows install ${name}
|
|
37396
|
-
# Edit ${
|
|
37761
|
+
# Edit ${path59.relative(process.cwd(), promptPath)} to customize the prompt.
|
|
37397
37762
|
` : `# Auto-generated by: poe-code github-workflows install ${name}
|
|
37398
37763
|
`;
|
|
37399
37764
|
const processedContent = content.replaceAll(` ${name}`, ` ${automationName}`).replaceAll("__UPSTREAM_REPO__", UPSTREAM_REPO);
|
|
@@ -37422,7 +37787,7 @@ function projectPromptDirs(cwd) {
|
|
|
37422
37787
|
return [projectWorkflowDir(cwd)];
|
|
37423
37788
|
}
|
|
37424
37789
|
function projectWorkflowDir(cwd) {
|
|
37425
|
-
return
|
|
37790
|
+
return path59.join(cwd, ".github", "workflows");
|
|
37426
37791
|
}
|
|
37427
37792
|
function projectGitHubWorkflowsDir(cwd) {
|
|
37428
37793
|
return projectWorkflowDir(cwd);
|
|
@@ -37441,7 +37806,7 @@ async function resolveBuiltInPromptsDir() {
|
|
|
37441
37806
|
return builtInPromptsDirCandidates[0];
|
|
37442
37807
|
}
|
|
37443
37808
|
async function resolveBuiltInAssetsDir() {
|
|
37444
|
-
return
|
|
37809
|
+
return path59.dirname(await resolveBuiltInPromptsDir());
|
|
37445
37810
|
}
|
|
37446
37811
|
function resolveCwd(cwd) {
|
|
37447
37812
|
return cwd ?? process.cwd();
|
|
@@ -37595,17 +37960,17 @@ function addPromptHeader(content, name) {
|
|
|
37595
37960
|
async function installAutomation(name, cwd, isEject) {
|
|
37596
37961
|
const variant = isEject ? "ejected" : "caller";
|
|
37597
37962
|
const localAutomationName = isEject ? `poe-code-${name}` : name;
|
|
37598
|
-
const promptPath = isEject ?
|
|
37963
|
+
const promptPath = isEject ? path59.join(projectWorkflowDir(cwd), `${localAutomationName}.md`) : void 0;
|
|
37599
37964
|
const [workflowTemplate, rawPrompt] = await Promise.all([
|
|
37600
37965
|
readBuiltInWorkflowTemplate(name, variant, localAutomationName, promptPath),
|
|
37601
37966
|
readBuiltInPromptFile(name)
|
|
37602
37967
|
]);
|
|
37603
|
-
const workflowPath =
|
|
37604
|
-
await
|
|
37605
|
-
await
|
|
37968
|
+
const workflowPath = path59.join(cwd, ".github", "workflows", `poe-code-${name}.yml`);
|
|
37969
|
+
await mkdir16(path59.dirname(workflowPath), { recursive: true });
|
|
37970
|
+
await writeFile12(workflowPath, workflowTemplate, "utf8");
|
|
37606
37971
|
if (promptPath !== void 0) {
|
|
37607
|
-
await
|
|
37608
|
-
await
|
|
37972
|
+
await mkdir16(path59.dirname(promptPath), { recursive: true });
|
|
37973
|
+
await writeFile12(promptPath, addPromptHeader(rawPrompt, name), "utf8");
|
|
37609
37974
|
}
|
|
37610
37975
|
return {
|
|
37611
37976
|
name,
|
|
@@ -37617,15 +37982,15 @@ async function installAutomation(name, cwd, isEject) {
|
|
|
37617
37982
|
}
|
|
37618
37983
|
async function ensureProjectSupportFiles(cwd, builtInVariables) {
|
|
37619
37984
|
const projectDir = projectGitHubWorkflowsDir(cwd);
|
|
37620
|
-
const variablesPath =
|
|
37621
|
-
const readmePath =
|
|
37622
|
-
await
|
|
37623
|
-
await
|
|
37985
|
+
const variablesPath = path59.join(projectDir, "variables.yaml");
|
|
37986
|
+
const readmePath = path59.join(projectDir, "README.md");
|
|
37987
|
+
await mkdir16(projectDir, { recursive: true });
|
|
37988
|
+
await writeFile12(
|
|
37624
37989
|
variablesPath,
|
|
37625
37990
|
generateProjectVariablesFile(builtInVariables, await readOptionalFile4(variablesPath)),
|
|
37626
37991
|
"utf8"
|
|
37627
37992
|
);
|
|
37628
|
-
await
|
|
37993
|
+
await writeFile12(readmePath, renderProjectReadme(), "utf8");
|
|
37629
37994
|
return { readmePath, variablesPath };
|
|
37630
37995
|
}
|
|
37631
37996
|
async function readOptionalFile4(filePath) {
|
|
@@ -37900,7 +38265,7 @@ var init_commands2 = __esm({
|
|
|
37900
38265
|
scope: ["cli"],
|
|
37901
38266
|
handler: async ({ params }) => {
|
|
37902
38267
|
const name = params.name;
|
|
37903
|
-
const workflowPath =
|
|
38268
|
+
const workflowPath = path59.join(resolveCwd(), ".github", "workflows", `poe-code-${name}.yml`);
|
|
37904
38269
|
try {
|
|
37905
38270
|
await unlink5(workflowPath);
|
|
37906
38271
|
} catch (error2) {
|
|
@@ -38003,7 +38368,7 @@ var init_commands2 = __esm({
|
|
|
38003
38368
|
return (await loadVariableStatuses(await resolveBuiltInAssetsDir(), projectGitHubWorkflowsDir(cwd))).map(
|
|
38004
38369
|
(status) => ({
|
|
38005
38370
|
...status,
|
|
38006
|
-
source: status.source === "built-in" ? status.source :
|
|
38371
|
+
source: status.source === "built-in" ? status.source : path59.relative(cwd, status.source)
|
|
38007
38372
|
})
|
|
38008
38373
|
);
|
|
38009
38374
|
},
|
|
@@ -38181,7 +38546,7 @@ var init_execution_context = __esm({
|
|
|
38181
38546
|
});
|
|
38182
38547
|
|
|
38183
38548
|
// src/sdk/launch.ts
|
|
38184
|
-
import
|
|
38549
|
+
import path60 from "node:path";
|
|
38185
38550
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
38186
38551
|
async function startLaunch(options) {
|
|
38187
38552
|
const homeDir = resolveHomeDir(options.homeDir);
|
|
@@ -38287,7 +38652,7 @@ async function runLaunchDaemon(options) {
|
|
|
38287
38652
|
});
|
|
38288
38653
|
}
|
|
38289
38654
|
function resolveLaunchBaseDir(homeDir) {
|
|
38290
|
-
return
|
|
38655
|
+
return path60.join(homeDir, ".poe-code", "launch");
|
|
38291
38656
|
}
|
|
38292
38657
|
function resolveHomeDir(homeDir) {
|
|
38293
38658
|
if (homeDir) {
|
|
@@ -38303,7 +38668,7 @@ function normalizeLaunchSpec(spec10, baseDir) {
|
|
|
38303
38668
|
if (locator.scheme !== "local") {
|
|
38304
38669
|
return spec10;
|
|
38305
38670
|
}
|
|
38306
|
-
const cwd =
|
|
38671
|
+
const cwd = path60.isAbsolute(locator.path) ? locator.path : path60.resolve(baseDir, locator.path);
|
|
38307
38672
|
return {
|
|
38308
38673
|
...spec10,
|
|
38309
38674
|
cwd
|
|
@@ -39280,15 +39645,15 @@ var init_renderer3 = __esm({
|
|
|
39280
39645
|
});
|
|
39281
39646
|
|
|
39282
39647
|
// packages/cmdkit/src/cli.ts
|
|
39283
|
-
import { access as access3, readFile as readFile19, writeFile as
|
|
39284
|
-
import
|
|
39648
|
+
import { access as access3, readFile as readFile19, writeFile as writeFile13 } from "node:fs/promises";
|
|
39649
|
+
import path62 from "node:path";
|
|
39285
39650
|
import { Command as CommanderCommand, CommanderError, InvalidArgumentError, Option } from "commander";
|
|
39286
39651
|
function inferProgramName(argv) {
|
|
39287
39652
|
const entrypoint = argv[1];
|
|
39288
39653
|
if (typeof entrypoint !== "string" || entrypoint.length === 0) {
|
|
39289
39654
|
return "cmdkit";
|
|
39290
39655
|
}
|
|
39291
|
-
const parsed =
|
|
39656
|
+
const parsed = path62.parse(entrypoint);
|
|
39292
39657
|
return parsed.name.length > 0 ? parsed.name : "cmdkit";
|
|
39293
39658
|
}
|
|
39294
39659
|
function normalizeRoots2(roots, argv) {
|
|
@@ -39345,11 +39710,11 @@ function formatSegment2(segment, casing) {
|
|
|
39345
39710
|
const separator = casing === "snake" ? "_" : "-";
|
|
39346
39711
|
return splitWords2(segment).join(separator);
|
|
39347
39712
|
}
|
|
39348
|
-
function toOptionFlag(
|
|
39349
|
-
return `--${
|
|
39713
|
+
function toOptionFlag(path84, casing) {
|
|
39714
|
+
return `--${path84.map((segment) => formatSegment2(segment, casing)).join(".")}`;
|
|
39350
39715
|
}
|
|
39351
|
-
function toOptionAttribute(
|
|
39352
|
-
return
|
|
39716
|
+
function toOptionAttribute(path84, casing) {
|
|
39717
|
+
return path84.map((segment) => {
|
|
39353
39718
|
const formatted = formatSegment2(segment, casing);
|
|
39354
39719
|
if (casing === "snake") {
|
|
39355
39720
|
return formatted;
|
|
@@ -39360,13 +39725,13 @@ function toOptionAttribute(path82, casing) {
|
|
|
39360
39725
|
).join("");
|
|
39361
39726
|
}).join(".");
|
|
39362
39727
|
}
|
|
39363
|
-
function toDisplayPath3(
|
|
39364
|
-
return
|
|
39728
|
+
function toDisplayPath3(path84) {
|
|
39729
|
+
return path84.join(".");
|
|
39365
39730
|
}
|
|
39366
|
-
function collectFields(schema, casing,
|
|
39731
|
+
function collectFields(schema, casing, path84 = [], inheritedOptional = false) {
|
|
39367
39732
|
const fields = [];
|
|
39368
39733
|
for (const [key, rawChildSchema] of Object.entries(schema.shape)) {
|
|
39369
|
-
const nextPath = [...
|
|
39734
|
+
const nextPath = [...path84, key];
|
|
39370
39735
|
const optional = inheritedOptional || rawChildSchema.kind === "optional";
|
|
39371
39736
|
const childSchema = unwrapOptional3(rawChildSchema);
|
|
39372
39737
|
if (childSchema.kind === "object") {
|
|
@@ -39389,9 +39754,9 @@ function collectFields(schema, casing, path82 = [], inheritedOptional = false) {
|
|
|
39389
39754
|
}
|
|
39390
39755
|
return fields;
|
|
39391
39756
|
}
|
|
39392
|
-
function toCommanderOptionAttribute(
|
|
39393
|
-
const optionAttribute = toOptionAttribute(
|
|
39394
|
-
const optionFlag = toOptionFlag(
|
|
39757
|
+
function toCommanderOptionAttribute(path84, casing) {
|
|
39758
|
+
const optionAttribute = toOptionAttribute(path84, casing);
|
|
39759
|
+
const optionFlag = toOptionFlag(path84, casing);
|
|
39395
39760
|
if (!GLOBAL_LONG_OPTION_FLAGS.has(optionFlag)) {
|
|
39396
39761
|
return optionAttribute;
|
|
39397
39762
|
}
|
|
@@ -39850,10 +40215,10 @@ function addGlobalOptions(command) {
|
|
|
39850
40215
|
throw new InvalidArgumentError('Invalid value for "--output". Expected one of: rich, md, markdown, json.');
|
|
39851
40216
|
}).option("--verbose", "Print stack traces for unexpected errors.");
|
|
39852
40217
|
}
|
|
39853
|
-
function setNestedValue(target,
|
|
40218
|
+
function setNestedValue(target, path84, value) {
|
|
39854
40219
|
let cursor = target;
|
|
39855
|
-
for (let index = 0; index <
|
|
39856
|
-
const segment =
|
|
40220
|
+
for (let index = 0; index < path84.length - 1; index += 1) {
|
|
40221
|
+
const segment = path84[index] ?? "";
|
|
39857
40222
|
const existing = cursor[segment];
|
|
39858
40223
|
if (typeof existing === "object" && existing !== null) {
|
|
39859
40224
|
cursor = existing;
|
|
@@ -39863,7 +40228,7 @@ function setNestedValue(target, path82, value) {
|
|
|
39863
40228
|
cursor[segment] = next;
|
|
39864
40229
|
cursor = next;
|
|
39865
40230
|
}
|
|
39866
|
-
const leaf =
|
|
40231
|
+
const leaf = path84[path84.length - 1];
|
|
39867
40232
|
if (leaf !== void 0) {
|
|
39868
40233
|
cursor[leaf] = value;
|
|
39869
40234
|
}
|
|
@@ -39954,13 +40319,13 @@ async function withOutputFormat2(output, fn) {
|
|
|
39954
40319
|
}
|
|
39955
40320
|
function createFs2() {
|
|
39956
40321
|
return {
|
|
39957
|
-
readFile: async (
|
|
39958
|
-
writeFile: async (
|
|
39959
|
-
await
|
|
40322
|
+
readFile: async (path84, encoding = "utf8") => readFile19(path84, { encoding }),
|
|
40323
|
+
writeFile: async (path84, contents) => {
|
|
40324
|
+
await writeFile13(path84, contents);
|
|
39960
40325
|
},
|
|
39961
|
-
exists: async (
|
|
40326
|
+
exists: async (path84) => {
|
|
39962
40327
|
try {
|
|
39963
|
-
await access3(
|
|
40328
|
+
await access3(path84);
|
|
39964
40329
|
return true;
|
|
39965
40330
|
} catch {
|
|
39966
40331
|
return false;
|
|
@@ -39981,9 +40346,9 @@ function isPlainObject4(value) {
|
|
|
39981
40346
|
function hasFieldValue(value) {
|
|
39982
40347
|
return value !== void 0;
|
|
39983
40348
|
}
|
|
39984
|
-
function hasNestedField(fields,
|
|
40349
|
+
function hasNestedField(fields, path84) {
|
|
39985
40350
|
return fields.some(
|
|
39986
|
-
(field) =>
|
|
40351
|
+
(field) => path84.length < field.path.length && path84.every((segment, index) => field.path[index] === segment)
|
|
39987
40352
|
);
|
|
39988
40353
|
}
|
|
39989
40354
|
function describeExpectedPresetValue(schema) {
|
|
@@ -40070,9 +40435,9 @@ async function loadPresetValues(fields, presetPath) {
|
|
|
40070
40435
|
}
|
|
40071
40436
|
const fieldByPath = new Map(fields.map((field) => [field.displayPath, field]));
|
|
40072
40437
|
const presetValues = {};
|
|
40073
|
-
function visitObject(current,
|
|
40438
|
+
function visitObject(current, path84) {
|
|
40074
40439
|
for (const [key, value] of Object.entries(current)) {
|
|
40075
|
-
const nextPath = [...
|
|
40440
|
+
const nextPath = [...path84, key];
|
|
40076
40441
|
const displayPath2 = toDisplayPath3(nextPath);
|
|
40077
40442
|
const field = fieldByPath.get(displayPath2);
|
|
40078
40443
|
if (field !== void 0) {
|
|
@@ -40270,8 +40635,8 @@ function createFixtureService(definition) {
|
|
|
40270
40635
|
);
|
|
40271
40636
|
}
|
|
40272
40637
|
function resolveFixturePath(commandPath) {
|
|
40273
|
-
const parsed =
|
|
40274
|
-
return
|
|
40638
|
+
const parsed = path62.parse(commandPath);
|
|
40639
|
+
return path62.join(parsed.dir, `${parsed.name}.fixture.json`);
|
|
40275
40640
|
}
|
|
40276
40641
|
function selectFixtureScenario(scenarios, selector) {
|
|
40277
40642
|
if (isNumericFixtureSelector(selector)) {
|
|
@@ -40990,7 +41355,7 @@ var init_agent2 = __esm({
|
|
|
40990
41355
|
});
|
|
40991
41356
|
|
|
40992
41357
|
// src/cli/commands/spawn.ts
|
|
40993
|
-
import
|
|
41358
|
+
import path63 from "node:path";
|
|
40994
41359
|
import { Option as Option2 } from "commander";
|
|
40995
41360
|
function registerSpawnCommand(program, container, options = {}) {
|
|
40996
41361
|
const spawnServices = container.registry.list().filter((service) => typeof service.spawn === "function" || getSpawnConfig(service.name));
|
|
@@ -41271,7 +41636,7 @@ async function resolvePromptInput(input, fs17, baseDir) {
|
|
|
41271
41636
|
if (rawPath.length === 0) {
|
|
41272
41637
|
throw new ValidationError("prompt @<path> requires a file path after '@'");
|
|
41273
41638
|
}
|
|
41274
|
-
const filePath =
|
|
41639
|
+
const filePath = path63.isAbsolute(rawPath) ? rawPath : path63.join(baseDir, rawPath);
|
|
41275
41640
|
try {
|
|
41276
41641
|
const contents = await fs17.readFile(filePath, "utf8");
|
|
41277
41642
|
return contents.trim();
|
|
@@ -41292,7 +41657,7 @@ async function resolveMcpSpawnInput(input, fs17, baseDir) {
|
|
|
41292
41657
|
if (rawPath.length === 0) {
|
|
41293
41658
|
throw new ValidationError("--mcp-servers @<path> requires a file path after '@'");
|
|
41294
41659
|
}
|
|
41295
|
-
const filePath =
|
|
41660
|
+
const filePath = path63.isAbsolute(rawPath) ? rawPath : path63.join(baseDir, rawPath);
|
|
41296
41661
|
try {
|
|
41297
41662
|
return await fs17.readFile(filePath, "utf8");
|
|
41298
41663
|
} catch (error2) {
|
|
@@ -42132,9 +42497,9 @@ var init_command_not_found = __esm({
|
|
|
42132
42497
|
|
|
42133
42498
|
// src/cli/commands/utils-symlink-ops.ts
|
|
42134
42499
|
import { dirname as dirname4 } from "node:path";
|
|
42135
|
-
async function tryLstat(fs17,
|
|
42500
|
+
async function tryLstat(fs17, path84) {
|
|
42136
42501
|
try {
|
|
42137
|
-
return await fs17.lstat(
|
|
42502
|
+
return await fs17.lstat(path84);
|
|
42138
42503
|
} catch (error2) {
|
|
42139
42504
|
if (isNotFound(error2)) {
|
|
42140
42505
|
return null;
|
|
@@ -42185,13 +42550,13 @@ async function applySymlinkOps(fs17, ops, opts) {
|
|
|
42185
42550
|
}
|
|
42186
42551
|
return { conflicts };
|
|
42187
42552
|
}
|
|
42188
|
-
async function isSymlinkPointingTo(fs17,
|
|
42553
|
+
async function isSymlinkPointingTo(fs17, path84, expectedTarget) {
|
|
42189
42554
|
try {
|
|
42190
|
-
const stats = await fs17.lstat(
|
|
42555
|
+
const stats = await fs17.lstat(path84);
|
|
42191
42556
|
if (!stats.isSymbolicLink()) {
|
|
42192
42557
|
return false;
|
|
42193
42558
|
}
|
|
42194
|
-
return await fs17.readlink(
|
|
42559
|
+
return await fs17.readlink(path84) === expectedTarget;
|
|
42195
42560
|
} catch (error2) {
|
|
42196
42561
|
if (isNotFound(error2)) {
|
|
42197
42562
|
return false;
|
|
@@ -42668,7 +43033,7 @@ var init_media_download = __esm({
|
|
|
42668
43033
|
});
|
|
42669
43034
|
|
|
42670
43035
|
// src/cli/commands/generate.ts
|
|
42671
|
-
import
|
|
43036
|
+
import path64 from "node:path";
|
|
42672
43037
|
function registerGenerateCommand(program, container) {
|
|
42673
43038
|
const generate2 = program.command("generate").alias("g").description("Generate content via Poe API.").option("--model <model>", `Model identifier (default: ${DEFAULT_TEXT_MODEL})`).option(
|
|
42674
43039
|
"--param <key=value>",
|
|
@@ -42941,11 +43306,11 @@ function getDefaultMimeType(type) {
|
|
|
42941
43306
|
return defaults[type];
|
|
42942
43307
|
}
|
|
42943
43308
|
function resolveOutputPath(filename, cwd) {
|
|
42944
|
-
if (
|
|
43309
|
+
if (path64.isAbsolute(filename)) {
|
|
42945
43310
|
return { path: filename, label: filename };
|
|
42946
43311
|
}
|
|
42947
43312
|
return {
|
|
42948
|
-
path:
|
|
43313
|
+
path: path64.join(cwd, filename),
|
|
42949
43314
|
label: `./${filename}`
|
|
42950
43315
|
};
|
|
42951
43316
|
}
|
|
@@ -43546,10 +43911,10 @@ var init_shapes = __esm({
|
|
|
43546
43911
|
});
|
|
43547
43912
|
|
|
43548
43913
|
// packages/agent-mcp-config/src/apply.ts
|
|
43549
|
-
import
|
|
43914
|
+
import path65 from "node:path";
|
|
43550
43915
|
import { parse as parseYaml3, stringify as stringifyYaml3 } from "yaml";
|
|
43551
43916
|
function getConfigDirectory(configPath) {
|
|
43552
|
-
return
|
|
43917
|
+
return path65.dirname(configPath);
|
|
43553
43918
|
}
|
|
43554
43919
|
function isConfigObject6(value) {
|
|
43555
43920
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
@@ -43569,9 +43934,9 @@ function expandHomePath(configPath, homeDir) {
|
|
|
43569
43934
|
return homeDir;
|
|
43570
43935
|
}
|
|
43571
43936
|
if (configPath.startsWith("~/")) {
|
|
43572
|
-
return
|
|
43937
|
+
return path65.join(homeDir, configPath.slice(2));
|
|
43573
43938
|
}
|
|
43574
|
-
return
|
|
43939
|
+
return path65.join(homeDir, configPath.slice(1));
|
|
43575
43940
|
}
|
|
43576
43941
|
function parseYamlDocument2(content) {
|
|
43577
43942
|
if (content.trim() === "") {
|
|
@@ -43604,7 +43969,7 @@ async function writeYamlConfig(configPath, document, options) {
|
|
|
43604
43969
|
return;
|
|
43605
43970
|
}
|
|
43606
43971
|
const absolutePath = expandHomePath(configPath, options.homeDir);
|
|
43607
|
-
const configDir =
|
|
43972
|
+
const configDir = path65.dirname(absolutePath);
|
|
43608
43973
|
await options.fs.mkdir(configDir, { recursive: true });
|
|
43609
43974
|
await options.fs.writeFile(absolutePath, serializeYamlDocument(document), {
|
|
43610
43975
|
encoding: "utf8"
|
|
@@ -44875,8 +45240,8 @@ var init_dashboard_loop_shared = __esm({
|
|
|
44875
45240
|
});
|
|
44876
45241
|
|
|
44877
45242
|
// src/cli/commands/pipeline.ts
|
|
44878
|
-
import
|
|
44879
|
-
import { readFile as readFile20, stat as
|
|
45243
|
+
import path66 from "node:path";
|
|
45244
|
+
import { readFile as readFile20, stat as stat18 } from "node:fs/promises";
|
|
44880
45245
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
44881
45246
|
async function resolvePipelineCommandConfig(container) {
|
|
44882
45247
|
const configDoc = await readMergedDocument(
|
|
@@ -44924,18 +45289,19 @@ function resolveMaxRuns(value) {
|
|
|
44924
45289
|
return parsed;
|
|
44925
45290
|
}
|
|
44926
45291
|
function resolvePipelineInitSourcePath(container, sourcePath) {
|
|
44927
|
-
const absolutePath = sourcePath.startsWith("~/") ?
|
|
45292
|
+
const absolutePath = sourcePath.startsWith("~/") ? path66.join(container.env.homeDir, sourcePath.slice(2)) : path66.isAbsolute(sourcePath) ? sourcePath : path66.resolve(container.env.cwd, sourcePath);
|
|
44928
45293
|
return {
|
|
44929
45294
|
absolutePath,
|
|
44930
45295
|
relativePath: sourcePath,
|
|
44931
|
-
title:
|
|
45296
|
+
title: path66.basename(sourcePath, path66.extname(sourcePath))
|
|
44932
45297
|
};
|
|
44933
45298
|
}
|
|
44934
45299
|
function formatRunSummary(result) {
|
|
44935
45300
|
const metrics = result.metrics;
|
|
44936
45301
|
return [
|
|
44937
45302
|
`Runs: ${result.runsCompleted}`,
|
|
44938
|
-
`
|
|
45303
|
+
`Tasks: ${metrics.tasksCompleted} completed, ${metrics.tasksFailed} failed`,
|
|
45304
|
+
`Steps: ${metrics.stepsCompleted} completed`,
|
|
44939
45305
|
`Total tokens: ${metrics.totalInputTokens} input, ${metrics.totalOutputTokens} output, ${metrics.totalCachedTokens} cached`,
|
|
44940
45306
|
`Duration: ${formatDashboardDuration(result.totalDurationMs)}`
|
|
44941
45307
|
].join("\n ");
|
|
@@ -44976,6 +45342,14 @@ function formatTaskCompleteMessage(progress) {
|
|
|
44976
45342
|
if (progress.phase) {
|
|
44977
45343
|
return `${progress.taskTitle} ${status} in ${duration}${usage}`;
|
|
44978
45344
|
}
|
|
45345
|
+
if (progress.stepName) {
|
|
45346
|
+
if (progress.success && !progress.taskCompleted) {
|
|
45347
|
+
return `Task ${progress.taskId} (${progress.stepName}) step done in ${duration}${usage}`;
|
|
45348
|
+
}
|
|
45349
|
+
if (!progress.success) {
|
|
45350
|
+
return `Task ${progress.taskId} (${progress.stepName}) failed in ${duration}${usage}`;
|
|
45351
|
+
}
|
|
45352
|
+
}
|
|
44979
45353
|
return `Task ${progress.taskId} ${status} in ${duration}${usage}`;
|
|
44980
45354
|
}
|
|
44981
45355
|
function formatDashboardCurrentAction(progress) {
|
|
@@ -45059,68 +45433,63 @@ async function streamAcpEventsToDashboard(options) {
|
|
|
45059
45433
|
}
|
|
45060
45434
|
function createPipelineDashboardRunAgent(options) {
|
|
45061
45435
|
return async (input) => {
|
|
45062
|
-
|
|
45063
|
-
|
|
45064
|
-
|
|
45065
|
-
|
|
45066
|
-
|
|
45067
|
-
|
|
45068
|
-
|
|
45069
|
-
|
|
45070
|
-
|
|
45071
|
-
|
|
45072
|
-
|
|
45073
|
-
|
|
45074
|
-
|
|
45075
|
-
|
|
45076
|
-
|
|
45077
|
-
|
|
45078
|
-
|
|
45079
|
-
|
|
45080
|
-
|
|
45081
|
-
|
|
45082
|
-
|
|
45083
|
-
|
|
45084
|
-
toolBuffer.push(chunk);
|
|
45085
|
-
}
|
|
45086
|
-
},
|
|
45087
|
-
stderr: {
|
|
45088
|
-
write(chunk) {
|
|
45089
|
-
sawStderr = true;
|
|
45090
|
-
errorBuffer.push(chunk);
|
|
45091
|
-
}
|
|
45436
|
+
const toolBuffer = createDashboardLineBuffer((line) => {
|
|
45437
|
+
options.appendOutput("tool", `[${options.activeStage()}] ${line}`);
|
|
45438
|
+
});
|
|
45439
|
+
const errorBuffer = createDashboardLineBuffer((line) => {
|
|
45440
|
+
options.appendOutput("error", `[${options.activeStage()}] ${line}`);
|
|
45441
|
+
});
|
|
45442
|
+
let sawStdout = false;
|
|
45443
|
+
let sawStderr = false;
|
|
45444
|
+
try {
|
|
45445
|
+
const { events, result } = spawn7(input.agent, {
|
|
45446
|
+
prompt: input.prompt,
|
|
45447
|
+
cwd: input.cwd,
|
|
45448
|
+
logDir: input.logDir,
|
|
45449
|
+
model: input.model,
|
|
45450
|
+
mode: input.mode,
|
|
45451
|
+
...input.mcpServers ? { mcpServers: input.mcpServers } : {},
|
|
45452
|
+
...input.signal ? { signal: input.signal } : {},
|
|
45453
|
+
tee: {
|
|
45454
|
+
stdout: {
|
|
45455
|
+
write(chunk) {
|
|
45456
|
+
sawStdout = true;
|
|
45457
|
+
toolBuffer.push(chunk);
|
|
45092
45458
|
}
|
|
45093
45459
|
},
|
|
45094
|
-
|
|
45095
|
-
|
|
45096
|
-
|
|
45097
|
-
|
|
45098
|
-
|
|
45099
|
-
toolBuffer.push(chunk);
|
|
45100
|
-
},
|
|
45101
|
-
onErrorOutput(chunk) {
|
|
45102
|
-
errorBuffer.push(chunk);
|
|
45460
|
+
stderr: {
|
|
45461
|
+
write(chunk) {
|
|
45462
|
+
sawStderr = true;
|
|
45463
|
+
errorBuffer.push(chunk);
|
|
45464
|
+
}
|
|
45103
45465
|
}
|
|
45104
|
-
}
|
|
45105
|
-
|
|
45106
|
-
|
|
45107
|
-
|
|
45108
|
-
|
|
45109
|
-
|
|
45110
|
-
|
|
45111
|
-
}
|
|
45112
|
-
|
|
45113
|
-
|
|
45114
|
-
return spawnResult;
|
|
45115
|
-
} catch (error2) {
|
|
45116
|
-
toolBuffer.flush();
|
|
45117
|
-
errorBuffer.flush();
|
|
45118
|
-
if (!isActivityTimeoutError(error2) || attempt === 3) {
|
|
45119
|
-
throw error2;
|
|
45466
|
+
},
|
|
45467
|
+
activityTimeoutMs: 10 * 60 * 1e3
|
|
45468
|
+
});
|
|
45469
|
+
const eventStream = streamAcpEventsToDashboard({
|
|
45470
|
+
events,
|
|
45471
|
+
onToolOutput(chunk) {
|
|
45472
|
+
toolBuffer.push(chunk);
|
|
45473
|
+
},
|
|
45474
|
+
onErrorOutput(chunk) {
|
|
45475
|
+
errorBuffer.push(chunk);
|
|
45120
45476
|
}
|
|
45477
|
+
});
|
|
45478
|
+
const [spawnResult, sawEvents] = await Promise.all([result, eventStream]);
|
|
45479
|
+
if (!sawEvents && !sawStdout && spawnResult.stdout.length > 0) {
|
|
45480
|
+
toolBuffer.push(spawnResult.stdout);
|
|
45481
|
+
}
|
|
45482
|
+
if (!sawStderr && spawnResult.stderr.length > 0) {
|
|
45483
|
+
errorBuffer.push(spawnResult.stderr);
|
|
45121
45484
|
}
|
|
45485
|
+
toolBuffer.flush();
|
|
45486
|
+
errorBuffer.flush();
|
|
45487
|
+
return spawnResult;
|
|
45488
|
+
} catch (error2) {
|
|
45489
|
+
toolBuffer.flush();
|
|
45490
|
+
errorBuffer.flush();
|
|
45491
|
+
throw error2;
|
|
45122
45492
|
}
|
|
45123
|
-
throw new Error("Unreachable");
|
|
45124
45493
|
};
|
|
45125
45494
|
}
|
|
45126
45495
|
function dashboardStatusForResult(result) {
|
|
@@ -45145,15 +45514,18 @@ async function runPipelineWithDashboard(options) {
|
|
|
45145
45514
|
let currentAction;
|
|
45146
45515
|
let currentStage = "pipeline";
|
|
45147
45516
|
let status = "running";
|
|
45517
|
+
let waitingForLock = false;
|
|
45148
45518
|
const syncStats = () => {
|
|
45149
|
-
|
|
45519
|
+
const stats = {
|
|
45150
45520
|
status,
|
|
45151
45521
|
iterations,
|
|
45522
|
+
iterationsLabel: "Tasks",
|
|
45152
45523
|
tokensIn,
|
|
45153
45524
|
tokensOut,
|
|
45154
45525
|
elapsedMs: Math.max(0, Date.now() - startedAt),
|
|
45155
45526
|
...currentAction ? { currentAction } : {}
|
|
45156
|
-
}
|
|
45527
|
+
};
|
|
45528
|
+
dashboard.updateStats(stats);
|
|
45157
45529
|
};
|
|
45158
45530
|
const appendOutput = (kind, message2) => {
|
|
45159
45531
|
dashboard.appendOutput({
|
|
@@ -45196,6 +45568,17 @@ async function runPipelineWithDashboard(options) {
|
|
|
45196
45568
|
onPlanReloadError(error2) {
|
|
45197
45569
|
appendOutput("error", `Plan reload failed, using last good state: ${error2.message}`);
|
|
45198
45570
|
},
|
|
45571
|
+
onLockStatusChange(lockStatus) {
|
|
45572
|
+
appendOutput("status", lockStatus.message);
|
|
45573
|
+
if (lockStatus.state === "waiting") {
|
|
45574
|
+
waitingForLock = true;
|
|
45575
|
+
currentAction = lockStatus.message;
|
|
45576
|
+
} else if (waitingForLock) {
|
|
45577
|
+
waitingForLock = false;
|
|
45578
|
+
currentAction = void 0;
|
|
45579
|
+
}
|
|
45580
|
+
syncStats();
|
|
45581
|
+
},
|
|
45199
45582
|
onPlanResolved(summary) {
|
|
45200
45583
|
appendOutput(
|
|
45201
45584
|
"info",
|
|
@@ -45217,7 +45600,9 @@ async function runPipelineWithDashboard(options) {
|
|
|
45217
45600
|
syncStats();
|
|
45218
45601
|
},
|
|
45219
45602
|
onTaskComplete(progress) {
|
|
45220
|
-
|
|
45603
|
+
if (progress.taskCompleted) {
|
|
45604
|
+
iterations += 1;
|
|
45605
|
+
}
|
|
45221
45606
|
if (progress.usage) {
|
|
45222
45607
|
tokensIn += progress.usage.inputTokens;
|
|
45223
45608
|
tokensOut += progress.usage.outputTokens;
|
|
@@ -45243,13 +45628,18 @@ async function runPipelineWithDashboard(options) {
|
|
|
45243
45628
|
}
|
|
45244
45629
|
}
|
|
45245
45630
|
function resolvePipelinePaths(scope, cwd, homeDir) {
|
|
45246
|
-
const rootPath = scope === "global" ?
|
|
45631
|
+
const rootPath = scope === "global" ? path66.join(homeDir, ".poe-code", "pipeline") : path66.join(cwd, ".poe-code", "pipeline");
|
|
45247
45632
|
const displayRoot = scope === "global" ? "~/.poe-code/pipeline" : ".poe-code/pipeline";
|
|
45633
|
+
const stepsDirectoryPath = path66.join(rootPath, "steps");
|
|
45248
45634
|
return {
|
|
45249
|
-
plansPath:
|
|
45250
|
-
|
|
45635
|
+
plansPath: path66.join(rootPath, "plans"),
|
|
45636
|
+
stepsDirectoryPath,
|
|
45637
|
+
defaultStepsPath: path66.join(stepsDirectoryPath, "default.yaml"),
|
|
45638
|
+
legacyStepsPath: path66.join(rootPath, "steps.yaml"),
|
|
45251
45639
|
displayPlansPath: `${displayRoot}/plans`,
|
|
45252
|
-
|
|
45640
|
+
displayStepsDirectoryPath: `${displayRoot}/steps`,
|
|
45641
|
+
displayDefaultStepsPath: `${displayRoot}/steps/default.yaml`,
|
|
45642
|
+
displayLegacyStepsPath: `${displayRoot}/steps.yaml`
|
|
45253
45643
|
};
|
|
45254
45644
|
}
|
|
45255
45645
|
async function loadPipelineTemplates() {
|
|
@@ -45258,16 +45648,16 @@ async function loadPipelineTemplates() {
|
|
|
45258
45648
|
}
|
|
45259
45649
|
const packageRoot = await findPackageRoot3(fileURLToPath9(import.meta.url));
|
|
45260
45650
|
const templateRoots = [
|
|
45261
|
-
|
|
45262
|
-
|
|
45651
|
+
path66.join(packageRoot, "src", "templates", "pipeline"),
|
|
45652
|
+
path66.join(packageRoot, "dist", "templates", "pipeline")
|
|
45263
45653
|
];
|
|
45264
45654
|
for (const templateRoot of templateRoots) {
|
|
45265
45655
|
if (!await pathExistsOnDisk(templateRoot)) {
|
|
45266
45656
|
continue;
|
|
45267
45657
|
}
|
|
45268
45658
|
const [skillPlan, steps] = await Promise.all([
|
|
45269
|
-
readFile20(
|
|
45270
|
-
readFile20(
|
|
45659
|
+
readFile20(path66.join(templateRoot, "SKILL_plan.md"), "utf8"),
|
|
45660
|
+
readFile20(path66.join(templateRoot, "steps.yaml.mustache"), "utf8")
|
|
45271
45661
|
]);
|
|
45272
45662
|
pipelineTemplatesCache = { skillPlan, steps };
|
|
45273
45663
|
return pipelineTemplatesCache;
|
|
@@ -45276,7 +45666,7 @@ async function loadPipelineTemplates() {
|
|
|
45276
45666
|
}
|
|
45277
45667
|
async function pathExistsOnDisk(targetPath) {
|
|
45278
45668
|
try {
|
|
45279
|
-
await
|
|
45669
|
+
await stat18(targetPath);
|
|
45280
45670
|
return true;
|
|
45281
45671
|
} catch (error2) {
|
|
45282
45672
|
if (error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT") {
|
|
@@ -45286,12 +45676,12 @@ async function pathExistsOnDisk(targetPath) {
|
|
|
45286
45676
|
}
|
|
45287
45677
|
}
|
|
45288
45678
|
async function findPackageRoot3(entryFilePath) {
|
|
45289
|
-
let currentPath =
|
|
45679
|
+
let currentPath = path66.dirname(entryFilePath);
|
|
45290
45680
|
while (true) {
|
|
45291
|
-
if (await pathExistsOnDisk(
|
|
45681
|
+
if (await pathExistsOnDisk(path66.join(currentPath, "package.json"))) {
|
|
45292
45682
|
return currentPath;
|
|
45293
45683
|
}
|
|
45294
|
-
const parentPath =
|
|
45684
|
+
const parentPath = path66.dirname(currentPath);
|
|
45295
45685
|
if (parentPath === currentPath) {
|
|
45296
45686
|
throw new Error("Unable to locate package root for Pipeline templates.");
|
|
45297
45687
|
}
|
|
@@ -45407,6 +45797,9 @@ function registerPipelineCommand(program, container) {
|
|
|
45407
45797
|
`Plan reload failed, using last good state: ${error2.message}`
|
|
45408
45798
|
);
|
|
45409
45799
|
},
|
|
45800
|
+
onLockStatusChange(lockStatus) {
|
|
45801
|
+
resources.logger.info(lockStatus.message);
|
|
45802
|
+
},
|
|
45410
45803
|
onPlanResolved(summary2) {
|
|
45411
45804
|
resources.logger.resolved(
|
|
45412
45805
|
"Config",
|
|
@@ -45463,11 +45856,7 @@ function registerPipelineCommand(program, container) {
|
|
|
45463
45856
|
});
|
|
45464
45857
|
pipeline.command("init").description("Initialize pipeline plans from source Markdown docs.").argument("[question]", "Optional user question to forward to the plan generator").option("--agent <name>", "Agent to generate the plan with").option("--model <model>", "Model override passed to the agent").option("--source <path>", "Single source Markdown doc to convert").option("--sources <paths...>", "Multiple source Markdown docs to convert").action(async function(question) {
|
|
45465
45858
|
const flags = resolveCommandFlags(program);
|
|
45466
|
-
const resources = createExecutionResources(
|
|
45467
|
-
container,
|
|
45468
|
-
flags,
|
|
45469
|
-
"pipeline:init"
|
|
45470
|
-
);
|
|
45859
|
+
const resources = createExecutionResources(container, flags, "pipeline:init");
|
|
45471
45860
|
const options = this.opts();
|
|
45472
45861
|
resources.logger.intro("pipeline init");
|
|
45473
45862
|
try {
|
|
@@ -45499,7 +45888,6 @@ function registerPipelineCommand(program, container) {
|
|
|
45499
45888
|
}
|
|
45500
45889
|
agent2 = resolvePipelineAgent(selected);
|
|
45501
45890
|
}
|
|
45502
|
-
const commandConfig = await resolvePipelineCommandConfig(container);
|
|
45503
45891
|
if (options.source && sourcePaths && sourcePaths.length > 0) {
|
|
45504
45892
|
throw new ValidationError("Use either --source or --sources, not both.");
|
|
45505
45893
|
}
|
|
@@ -45532,7 +45920,9 @@ function registerPipelineCommand(program, container) {
|
|
|
45532
45920
|
return;
|
|
45533
45921
|
}
|
|
45534
45922
|
const selectedSourcePaths = Array.isArray(selected) ? new Set(selected) : /* @__PURE__ */ new Set();
|
|
45535
|
-
sources = discoveredSources.filter(
|
|
45923
|
+
sources = discoveredSources.filter(
|
|
45924
|
+
(source) => selectedSourcePaths.has(source.relativePath)
|
|
45925
|
+
);
|
|
45536
45926
|
if (sources.length === 0) {
|
|
45537
45927
|
return;
|
|
45538
45928
|
}
|
|
@@ -45541,7 +45931,6 @@ function registerPipelineCommand(program, container) {
|
|
|
45541
45931
|
agent: agent2,
|
|
45542
45932
|
cwd: container.env.cwd,
|
|
45543
45933
|
homeDir: container.env.homeDir,
|
|
45544
|
-
...commandConfig.planDirectory ? { planDirectory: commandConfig.planDirectory } : {},
|
|
45545
45934
|
...options.model ? { model: options.model } : {},
|
|
45546
45935
|
...resolvedQuestion ? { question: resolvedQuestion } : {},
|
|
45547
45936
|
sources,
|
|
@@ -45581,35 +45970,46 @@ function registerPipelineCommand(program, container) {
|
|
|
45581
45970
|
container.env.homeDir
|
|
45582
45971
|
);
|
|
45583
45972
|
const content = await container.fs.readFile(absolutePath, "utf8");
|
|
45973
|
+
const draftPlan = parsePlan(content);
|
|
45584
45974
|
const steps = await loadResolvedSteps({
|
|
45585
45975
|
cwd: container.env.cwd,
|
|
45586
45976
|
homeDir: container.env.homeDir,
|
|
45587
|
-
fs: container.fs
|
|
45977
|
+
fs: container.fs,
|
|
45978
|
+
name: draftPlan.extends,
|
|
45979
|
+
stepOverrides: draftPlan.stepOverrides
|
|
45588
45980
|
});
|
|
45589
|
-
const
|
|
45590
|
-
const plan = parsePlan(content, hasSteps ? { availableSteps: steps.steps } : {});
|
|
45981
|
+
const plan = parsePlan(content, { availableSteps: steps.steps });
|
|
45591
45982
|
const total = plan.tasks.length;
|
|
45592
45983
|
const done = plan.tasks.filter((t) => {
|
|
45593
45984
|
if (typeof t.status === "string") return t.status === "done";
|
|
45594
45985
|
return Object.values(t.status).every((s) => s === "done");
|
|
45595
45986
|
}).length;
|
|
45987
|
+
const readFile34 = container.fs.readFile.bind(container.fs);
|
|
45988
|
+
const resolvedVars = await resolvePipelineVars(
|
|
45989
|
+
plan.vars ?? {},
|
|
45990
|
+
container.env.cwd,
|
|
45991
|
+
readFile34
|
|
45992
|
+
);
|
|
45993
|
+
const resolvedSetup = plan.setup === null ? void 0 : plan.setup ?? steps.setup;
|
|
45994
|
+
const resolvedTeardown = plan.teardown === null ? void 0 : plan.teardown ?? steps.teardown;
|
|
45995
|
+
validateResolvedPromptVars({
|
|
45996
|
+
plan,
|
|
45997
|
+
steps: steps.steps,
|
|
45998
|
+
planPath: file,
|
|
45999
|
+
vars: resolvedVars,
|
|
46000
|
+
setup: resolvedSetup,
|
|
46001
|
+
teardown: resolvedTeardown
|
|
46002
|
+
});
|
|
45596
46003
|
resources.logger.resolved("Plan", file);
|
|
45597
46004
|
resources.logger.resolved("Tasks", `${total} tasks (${done} done)`);
|
|
45598
|
-
if (
|
|
46005
|
+
if (Object.keys(steps.steps).length > 0) {
|
|
45599
46006
|
resources.logger.resolved("Steps", Object.keys(steps.steps).join(", "));
|
|
45600
46007
|
}
|
|
45601
46008
|
resources.logger.success("Plan is valid.");
|
|
45602
46009
|
const opts = this.opts();
|
|
45603
46010
|
if (opts.preview) {
|
|
45604
|
-
const readFile34 = container.fs.readFile.bind(container.fs);
|
|
45605
|
-
const resolvedVars = {};
|
|
45606
|
-
for (const [key, value] of Object.entries(plan.vars ?? {})) {
|
|
45607
|
-
resolvedVars[key] = await resolveFileIncludes(value, container.env.cwd, readFile34);
|
|
45608
|
-
}
|
|
45609
|
-
const resolvedSetup = plan.setup === null ? void 0 : plan.setup ?? steps.setup;
|
|
45610
|
-
const resolvedTeardown = plan.teardown === null ? void 0 : plan.teardown ?? steps.teardown;
|
|
45611
46011
|
if (resolvedSetup) {
|
|
45612
|
-
const raw =
|
|
46012
|
+
const raw = interpolatePipelineVars(resolvedSetup.prompt, resolvedVars, "setup");
|
|
45613
46013
|
const expanded = await resolveFileIncludes(raw, container.env.cwd, readFile34);
|
|
45614
46014
|
resources.logger.resolved("setup", expanded);
|
|
45615
46015
|
}
|
|
@@ -45643,7 +46043,7 @@ function registerPipelineCommand(program, container) {
|
|
|
45643
46043
|
}
|
|
45644
46044
|
}
|
|
45645
46045
|
if (resolvedTeardown) {
|
|
45646
|
-
const raw =
|
|
46046
|
+
const raw = interpolatePipelineVars(resolvedTeardown.prompt, resolvedVars, "teardown");
|
|
45647
46047
|
const expanded = await resolveFileIncludes(raw, container.env.cwd, readFile34);
|
|
45648
46048
|
resources.logger.resolved("teardown", expanded);
|
|
45649
46049
|
}
|
|
@@ -45662,7 +46062,7 @@ function registerPipelineCommand(program, container) {
|
|
|
45662
46062
|
process.stdout.write(`${resolvedPath}
|
|
45663
46063
|
`);
|
|
45664
46064
|
});
|
|
45665
|
-
pipeline.command("install").description("Install the Pipeline /plan skill and scaffold pipeline files.").option("--agent <name>", "Agent to install the Pipeline skill for").option("--local", "Install project-local skill and pipeline files").option("--global", "Install user-global skill and pipeline files").option("--force", "Overwrite an existing
|
|
46065
|
+
pipeline.command("install").description("Install the Pipeline /plan skill and scaffold pipeline files.").option("--agent <name>", "Agent to install the Pipeline skill for").option("--local", "Install project-local skill and pipeline files").option("--global", "Install user-global skill and pipeline files").option("--force", "Overwrite an existing default step config scaffold").action(async function() {
|
|
45666
46066
|
const flags = resolveCommandFlags(program);
|
|
45667
46067
|
const resources = createExecutionResources(container, flags, "pipeline:install");
|
|
45668
46068
|
const options = this.opts();
|
|
@@ -45747,22 +46147,39 @@ function registerPipelineCommand(program, container) {
|
|
|
45747
46147
|
resources.logger.info(`Create: ${pipelinePaths.displayPlansPath}`);
|
|
45748
46148
|
}
|
|
45749
46149
|
}
|
|
45750
|
-
const
|
|
46150
|
+
const legacyStepsExists = await pathExists5(container.fs, pipelinePaths.legacyStepsPath);
|
|
46151
|
+
let stepsExists = await pathExists5(container.fs, pipelinePaths.defaultStepsPath);
|
|
46152
|
+
if (legacyStepsExists && !stepsExists) {
|
|
46153
|
+
if (flags.dryRun) {
|
|
46154
|
+
resources.logger.dryRun(
|
|
46155
|
+
`Would rename: ${pipelinePaths.displayLegacyStepsPath} -> ${pipelinePaths.displayDefaultStepsPath}`
|
|
46156
|
+
);
|
|
46157
|
+
} else {
|
|
46158
|
+
await container.fs.mkdir(pipelinePaths.stepsDirectoryPath, {
|
|
46159
|
+
recursive: true
|
|
46160
|
+
});
|
|
46161
|
+
await container.fs.rename(pipelinePaths.legacyStepsPath, pipelinePaths.defaultStepsPath);
|
|
46162
|
+
resources.logger.info(
|
|
46163
|
+
`Rename: ${pipelinePaths.displayLegacyStepsPath} -> ${pipelinePaths.displayDefaultStepsPath}`
|
|
46164
|
+
);
|
|
46165
|
+
}
|
|
46166
|
+
stepsExists = true;
|
|
46167
|
+
}
|
|
45751
46168
|
if (stepsExists && !options.force) {
|
|
45752
|
-
resources.logger.info(`Skip: ${pipelinePaths.
|
|
46169
|
+
resources.logger.info(`Skip: ${pipelinePaths.displayDefaultStepsPath} (already exists)`);
|
|
45753
46170
|
} else if (flags.dryRun) {
|
|
45754
46171
|
resources.logger.dryRun(
|
|
45755
|
-
`Would ${stepsExists ? "overwrite" : "create"}: ${pipelinePaths.
|
|
46172
|
+
`Would ${stepsExists ? "overwrite" : "create"}: ${pipelinePaths.displayDefaultStepsPath}`
|
|
45756
46173
|
);
|
|
45757
46174
|
} else {
|
|
45758
|
-
await container.fs.mkdir(
|
|
46175
|
+
await container.fs.mkdir(path66.dirname(pipelinePaths.defaultStepsPath), {
|
|
45759
46176
|
recursive: true
|
|
45760
46177
|
});
|
|
45761
|
-
await container.fs.writeFile(pipelinePaths.
|
|
46178
|
+
await container.fs.writeFile(pipelinePaths.defaultStepsPath, templates.steps, {
|
|
45762
46179
|
encoding: "utf8"
|
|
45763
46180
|
});
|
|
45764
46181
|
resources.logger.info(
|
|
45765
|
-
`${stepsExists ? "Overwrite" : "Create"}: ${pipelinePaths.
|
|
46182
|
+
`${stepsExists ? "Overwrite" : "Create"}: ${pipelinePaths.displayDefaultStepsPath}`
|
|
45766
46183
|
);
|
|
45767
46184
|
}
|
|
45768
46185
|
resources.context.complete({
|
|
@@ -45798,7 +46215,7 @@ var init_pipeline3 = __esm({
|
|
|
45798
46215
|
});
|
|
45799
46216
|
|
|
45800
46217
|
// src/cli/commands/ralph.ts
|
|
45801
|
-
import
|
|
46218
|
+
import path67 from "node:path";
|
|
45802
46219
|
function formatRalphAgentSummary(agent2) {
|
|
45803
46220
|
return Array.isArray(agent2) ? agent2.join(", ") : agent2;
|
|
45804
46221
|
}
|
|
@@ -45979,9 +46396,9 @@ function normalizeConfiguredIterations(value) {
|
|
|
45979
46396
|
}
|
|
45980
46397
|
function resolveAbsoluteDocPath(container, docPath) {
|
|
45981
46398
|
if (docPath.startsWith("~/")) {
|
|
45982
|
-
return
|
|
46399
|
+
return path67.join(container.env.homeDir, docPath.slice(2));
|
|
45983
46400
|
}
|
|
45984
|
-
return
|
|
46401
|
+
return path67.isAbsolute(docPath) ? docPath : path67.resolve(container.env.cwd, docPath);
|
|
45985
46402
|
}
|
|
45986
46403
|
async function resolveRalphCommandConfig(container) {
|
|
45987
46404
|
const configDoc = await readMergedDocument(
|
|
@@ -46360,11 +46777,11 @@ var init_ralph3 = __esm({
|
|
|
46360
46777
|
});
|
|
46361
46778
|
|
|
46362
46779
|
// src/cli/commands/experiment.ts
|
|
46363
|
-
import
|
|
46364
|
-
import { readFile as readFile21, stat as
|
|
46780
|
+
import path68 from "node:path";
|
|
46781
|
+
import { readFile as readFile21, stat as stat19 } from "node:fs/promises";
|
|
46365
46782
|
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
46366
46783
|
function resolveExperimentPaths(scope, cwd, homeDir) {
|
|
46367
|
-
const rootPath = scope === "global" ?
|
|
46784
|
+
const rootPath = scope === "global" ? path68.join(homeDir, ".poe-code", "experiments") : path68.join(cwd, ".poe-code", "experiments");
|
|
46368
46785
|
const displayRoot = scope === "global" ? "~/.poe-code/experiments" : ".poe-code/experiments";
|
|
46369
46786
|
return {
|
|
46370
46787
|
experimentsPath: rootPath,
|
|
@@ -46373,7 +46790,7 @@ function resolveExperimentPaths(scope, cwd, homeDir) {
|
|
|
46373
46790
|
}
|
|
46374
46791
|
async function pathExistsOnDisk2(targetPath) {
|
|
46375
46792
|
try {
|
|
46376
|
-
await
|
|
46793
|
+
await stat19(targetPath);
|
|
46377
46794
|
return true;
|
|
46378
46795
|
} catch (error2) {
|
|
46379
46796
|
if (error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT") {
|
|
@@ -46383,12 +46800,12 @@ async function pathExistsOnDisk2(targetPath) {
|
|
|
46383
46800
|
}
|
|
46384
46801
|
}
|
|
46385
46802
|
async function findPackageRoot4(entryFilePath) {
|
|
46386
|
-
let currentPath =
|
|
46803
|
+
let currentPath = path68.dirname(entryFilePath);
|
|
46387
46804
|
while (true) {
|
|
46388
|
-
if (await pathExistsOnDisk2(
|
|
46805
|
+
if (await pathExistsOnDisk2(path68.join(currentPath, "package.json"))) {
|
|
46389
46806
|
return currentPath;
|
|
46390
46807
|
}
|
|
46391
|
-
const parentPath =
|
|
46808
|
+
const parentPath = path68.dirname(currentPath);
|
|
46392
46809
|
if (parentPath === currentPath) {
|
|
46393
46810
|
throw new Error("Unable to locate package root for Experiment templates.");
|
|
46394
46811
|
}
|
|
@@ -46401,16 +46818,16 @@ async function loadExperimentTemplates() {
|
|
|
46401
46818
|
}
|
|
46402
46819
|
const packageRoot = await findPackageRoot4(fileURLToPath10(import.meta.url));
|
|
46403
46820
|
const templateRoots = [
|
|
46404
|
-
|
|
46405
|
-
|
|
46821
|
+
path68.join(packageRoot, "src", "templates", "experiment"),
|
|
46822
|
+
path68.join(packageRoot, "dist", "templates", "experiment")
|
|
46406
46823
|
];
|
|
46407
46824
|
for (const templateRoot of templateRoots) {
|
|
46408
46825
|
if (!await pathExistsOnDisk2(templateRoot)) {
|
|
46409
46826
|
continue;
|
|
46410
46827
|
}
|
|
46411
46828
|
const [skillPlan, runYaml] = await Promise.all([
|
|
46412
|
-
readFile21(
|
|
46413
|
-
readFile21(
|
|
46829
|
+
readFile21(path68.join(templateRoot, "SKILL_experiment.md"), "utf8"),
|
|
46830
|
+
readFile21(path68.join(templateRoot, "run.yaml.mustache"), "utf8")
|
|
46414
46831
|
]);
|
|
46415
46832
|
experimentTemplatesCache = { skillPlan, runYaml };
|
|
46416
46833
|
return experimentTemplatesCache;
|
|
@@ -47095,8 +47512,8 @@ function registerExperimentCommand(program, container) {
|
|
|
47095
47512
|
resources.logger.info(`Create: ${experimentPaths.displayExperimentsPath}`);
|
|
47096
47513
|
}
|
|
47097
47514
|
}
|
|
47098
|
-
const runYamlPath =
|
|
47099
|
-
const runYamlDisplayPath =
|
|
47515
|
+
const runYamlPath = path68.join(experimentPaths.experimentsPath, "run.yaml");
|
|
47516
|
+
const runYamlDisplayPath = path68.join(experimentPaths.displayExperimentsPath, "run.yaml");
|
|
47100
47517
|
if (!await pathExists6(container.fs, runYamlPath)) {
|
|
47101
47518
|
if (flags.dryRun) {
|
|
47102
47519
|
resources.logger.dryRun(`Would create: ${runYamlDisplayPath}`);
|
|
@@ -47559,9 +47976,9 @@ var init_launch2 = __esm({
|
|
|
47559
47976
|
});
|
|
47560
47977
|
|
|
47561
47978
|
// packages/memory/src/paths.ts
|
|
47562
|
-
import
|
|
47979
|
+
import path69 from "node:path";
|
|
47563
47980
|
function resolveMemoryRoot(cwd) {
|
|
47564
|
-
return
|
|
47981
|
+
return path69.resolve(cwd, ".poe-code", "memory");
|
|
47565
47982
|
}
|
|
47566
47983
|
function assertSafeRelPath(input) {
|
|
47567
47984
|
const trimmed = input.trim();
|
|
@@ -47569,10 +47986,10 @@ function assertSafeRelPath(input) {
|
|
|
47569
47986
|
throw new MemoryPathError("Expected a non-empty relative path.");
|
|
47570
47987
|
}
|
|
47571
47988
|
const slashNormalized = trimmed.replaceAll("\\", "/");
|
|
47572
|
-
if (
|
|
47989
|
+
if (path69.posix.isAbsolute(slashNormalized) || path69.win32.isAbsolute(slashNormalized)) {
|
|
47573
47990
|
throw new MemoryPathError(`Expected a relative path, received absolute path "${input}".`);
|
|
47574
47991
|
}
|
|
47575
|
-
const normalized =
|
|
47992
|
+
const normalized = path69.posix.normalize(slashNormalized);
|
|
47576
47993
|
if (normalized === "." || normalized.length === 0) {
|
|
47577
47994
|
throw new MemoryPathError("Expected a relative path to a file or directory.");
|
|
47578
47995
|
}
|
|
@@ -47602,11 +48019,11 @@ var init_paths2 = __esm({
|
|
|
47602
48019
|
|
|
47603
48020
|
// packages/memory/src/init.ts
|
|
47604
48021
|
import * as fs4 from "node:fs/promises";
|
|
47605
|
-
import
|
|
48022
|
+
import path70 from "node:path";
|
|
47606
48023
|
async function initMemory(root) {
|
|
47607
|
-
await fs4.mkdir(
|
|
47608
|
-
await writeFileIfMissing(
|
|
47609
|
-
await writeFileIfMissing(
|
|
48024
|
+
await fs4.mkdir(path70.join(root, MEMORY_PAGES_DIR_RELPATH), { recursive: true });
|
|
48025
|
+
await writeFileIfMissing(path70.join(root, MEMORY_INDEX_RELPATH), "# Memory index\n");
|
|
48026
|
+
await writeFileIfMissing(path70.join(root, MEMORY_LOG_RELPATH), "");
|
|
47610
48027
|
}
|
|
47611
48028
|
async function writeFileIfMissing(filePath, content) {
|
|
47612
48029
|
try {
|
|
@@ -47628,7 +48045,7 @@ var init_init = __esm({
|
|
|
47628
48045
|
});
|
|
47629
48046
|
|
|
47630
48047
|
// packages/memory/src/frontmatter.ts
|
|
47631
|
-
import { parse as parse11, stringify as
|
|
48048
|
+
import { parse as parse11, stringify as stringify4 } from "yaml";
|
|
47632
48049
|
function parseFrontmatter4(markdown) {
|
|
47633
48050
|
const content = markdown.startsWith("\uFEFF") ? markdown.slice(1) : markdown;
|
|
47634
48051
|
const openingLineBreak = readOpeningLineBreak5(content);
|
|
@@ -47790,10 +48207,10 @@ function parseSources(value) {
|
|
|
47790
48207
|
if (!isRecord20(item)) {
|
|
47791
48208
|
throw new Error('Invalid "sources" frontmatter. Expected each source to be a string or object.');
|
|
47792
48209
|
}
|
|
47793
|
-
const
|
|
48210
|
+
const path84 = readRequiredString(item.path, "sources[].path");
|
|
47794
48211
|
const startLine = readOptionalPositiveInteger(item.startLine, "sources[].startLine");
|
|
47795
48212
|
const endLine = readOptionalPositiveInteger(item.endLine, "sources[].endLine");
|
|
47796
|
-
return parseSourceRef(serializeSourceRef({ path:
|
|
48213
|
+
return parseSourceRef(serializeSourceRef({ path: path84, ...startLine === void 0 ? {} : { startLine }, ...endLine === void 0 ? {} : { endLine } }));
|
|
47797
48214
|
});
|
|
47798
48215
|
}
|
|
47799
48216
|
function readOptionalString3(value, field) {
|
|
@@ -47837,7 +48254,7 @@ var init_frontmatter5 = __esm({
|
|
|
47837
48254
|
|
|
47838
48255
|
// packages/memory/src/pages.ts
|
|
47839
48256
|
import * as fs5 from "node:fs/promises";
|
|
47840
|
-
import
|
|
48257
|
+
import path71 from "node:path";
|
|
47841
48258
|
async function listPages(root) {
|
|
47842
48259
|
const relPaths = await collectMarkdownRelPaths(root, MEMORY_PAGES_DIR_RELPATH);
|
|
47843
48260
|
const pages = await Promise.all(relPaths.map(async (relPath) => readPage(root, relPath)));
|
|
@@ -47845,8 +48262,8 @@ async function listPages(root) {
|
|
|
47845
48262
|
}
|
|
47846
48263
|
async function readPage(root, relPath) {
|
|
47847
48264
|
const normalizedRelPath = assertMarkdownRelPath(relPath);
|
|
47848
|
-
const absPath =
|
|
47849
|
-
const [content,
|
|
48265
|
+
const absPath = path71.join(root, normalizedRelPath);
|
|
48266
|
+
const [content, stat24] = await Promise.all([fs5.readFile(absPath, "utf8"), fs5.stat(absPath)]);
|
|
47850
48267
|
try {
|
|
47851
48268
|
const parsed = parseFrontmatter4(content);
|
|
47852
48269
|
return {
|
|
@@ -47854,7 +48271,7 @@ async function readPage(root, relPath) {
|
|
|
47854
48271
|
frontmatter: parsed.frontmatter,
|
|
47855
48272
|
body: parsed.body,
|
|
47856
48273
|
bytes: Buffer.byteLength(content),
|
|
47857
|
-
mtimeMs:
|
|
48274
|
+
mtimeMs: stat24.mtimeMs
|
|
47858
48275
|
};
|
|
47859
48276
|
} catch (error2) {
|
|
47860
48277
|
const message2 = error2 instanceof Error ? error2.message : String(error2);
|
|
@@ -47864,7 +48281,7 @@ async function readPage(root, relPath) {
|
|
|
47864
48281
|
frontmatter: {},
|
|
47865
48282
|
body: content,
|
|
47866
48283
|
bytes: Buffer.byteLength(content),
|
|
47867
|
-
mtimeMs:
|
|
48284
|
+
mtimeMs: stat24.mtimeMs
|
|
47868
48285
|
};
|
|
47869
48286
|
}
|
|
47870
48287
|
}
|
|
@@ -47874,7 +48291,7 @@ async function collectMarkdownRelPaths(root, startRelPath = "") {
|
|
|
47874
48291
|
return relPaths.sort((left, right) => left.localeCompare(right));
|
|
47875
48292
|
}
|
|
47876
48293
|
async function collectMarkdownRelPathsInto(root, currentRelPath, relPaths) {
|
|
47877
|
-
const absPath =
|
|
48294
|
+
const absPath = path71.join(root, currentRelPath);
|
|
47878
48295
|
let entryNames;
|
|
47879
48296
|
try {
|
|
47880
48297
|
entryNames = await fs5.readdir(absPath);
|
|
@@ -47885,8 +48302,8 @@ async function collectMarkdownRelPathsInto(root, currentRelPath, relPaths) {
|
|
|
47885
48302
|
throw error2;
|
|
47886
48303
|
}
|
|
47887
48304
|
for (const entryName of entryNames.sort((left, right) => left.localeCompare(right))) {
|
|
47888
|
-
const entryRelPath = currentRelPath.length === 0 ? entryName :
|
|
47889
|
-
const entryAbsPath =
|
|
48305
|
+
const entryRelPath = currentRelPath.length === 0 ? entryName : path71.posix.join(currentRelPath, entryName);
|
|
48306
|
+
const entryAbsPath = path71.join(root, entryRelPath);
|
|
47890
48307
|
const entryStat = await fs5.stat(entryAbsPath);
|
|
47891
48308
|
if (entryStat.isDirectory()) {
|
|
47892
48309
|
if (entryName === MEMORY_CACHE_DIR_RELPATH) {
|
|
@@ -47916,7 +48333,7 @@ function assertMarkdownRelPath(relPath) {
|
|
|
47916
48333
|
return normalizedRelPath;
|
|
47917
48334
|
}
|
|
47918
48335
|
function isMarkdownPath(relPath) {
|
|
47919
|
-
return
|
|
48336
|
+
return path71.posix.extname(relPath).toLowerCase() === ".md";
|
|
47920
48337
|
}
|
|
47921
48338
|
function isMissing(error2) {
|
|
47922
48339
|
return typeof error2 === "object" && error2 !== null && "code" in error2 && error2.code === "ENOENT";
|
|
@@ -47931,7 +48348,7 @@ var init_pages = __esm({
|
|
|
47931
48348
|
|
|
47932
48349
|
// packages/memory/src/search.ts
|
|
47933
48350
|
import * as fs6 from "node:fs/promises";
|
|
47934
|
-
import
|
|
48351
|
+
import path72 from "node:path";
|
|
47935
48352
|
async function searchMemory(root, query) {
|
|
47936
48353
|
const normalizedQuery = query.trim();
|
|
47937
48354
|
if (normalizedQuery.length === 0) {
|
|
@@ -47940,7 +48357,7 @@ async function searchMemory(root, query) {
|
|
|
47940
48357
|
const relPaths = await collectMarkdownRelPaths(root);
|
|
47941
48358
|
const hits = [];
|
|
47942
48359
|
for (const relPath of relPaths) {
|
|
47943
|
-
const content = await fs6.readFile(
|
|
48360
|
+
const content = await fs6.readFile(path72.join(root, relPath), "utf8");
|
|
47944
48361
|
if (content.length === 0) {
|
|
47945
48362
|
continue;
|
|
47946
48363
|
}
|
|
@@ -47967,7 +48384,7 @@ var init_search = __esm({
|
|
|
47967
48384
|
|
|
47968
48385
|
// packages/memory/src/status.ts
|
|
47969
48386
|
import * as fs7 from "node:fs/promises";
|
|
47970
|
-
import
|
|
48387
|
+
import path73 from "node:path";
|
|
47971
48388
|
async function statusOf(root) {
|
|
47972
48389
|
if (!await pathExists7(root)) {
|
|
47973
48390
|
return {
|
|
@@ -47984,9 +48401,9 @@ async function statusOf(root) {
|
|
|
47984
48401
|
let totalBytes = 0;
|
|
47985
48402
|
let lastWriteAtMs = Number.NEGATIVE_INFINITY;
|
|
47986
48403
|
for (const relPath of markdownRelPaths) {
|
|
47987
|
-
const
|
|
47988
|
-
totalBytes +=
|
|
47989
|
-
lastWriteAtMs = Math.max(lastWriteAtMs,
|
|
48404
|
+
const stat24 = await fs7.stat(path73.join(root, relPath));
|
|
48405
|
+
totalBytes += stat24.size;
|
|
48406
|
+
lastWriteAtMs = Math.max(lastWriteAtMs, stat24.mtimeMs);
|
|
47990
48407
|
}
|
|
47991
48408
|
return {
|
|
47992
48409
|
pageCount: pageRelPaths.length,
|
|
@@ -48016,8 +48433,8 @@ var init_status = __esm({
|
|
|
48016
48433
|
|
|
48017
48434
|
// packages/memory/src/lock.ts
|
|
48018
48435
|
import * as fsPromises18 from "node:fs/promises";
|
|
48019
|
-
import
|
|
48020
|
-
function
|
|
48436
|
+
import path74 from "node:path";
|
|
48437
|
+
function createDefaultFs13() {
|
|
48021
48438
|
return {
|
|
48022
48439
|
readFile: (filePath, encoding) => fsPromises18.readFile(filePath, encoding),
|
|
48023
48440
|
unlink: fsPromises18.unlink,
|
|
@@ -48074,8 +48491,8 @@ async function readLockPid(fs17, lockPath) {
|
|
|
48074
48491
|
}
|
|
48075
48492
|
}
|
|
48076
48493
|
async function withLock(root, run, options = {}) {
|
|
48077
|
-
const fs17 = options.fs ??
|
|
48078
|
-
const lockPath =
|
|
48494
|
+
const fs17 = options.fs ?? createDefaultFs13();
|
|
48495
|
+
const lockPath = path74.join(root, MEMORY_LOCK_RELPATH);
|
|
48079
48496
|
const pid = options.pid ?? process.pid;
|
|
48080
48497
|
const retries = options.retries ?? 20;
|
|
48081
48498
|
const minTimeoutMs = options.minTimeoutMs ?? 25;
|
|
@@ -48127,7 +48544,7 @@ var init_confidence = __esm({
|
|
|
48127
48544
|
// packages/memory/src/reconcile.ts
|
|
48128
48545
|
import { createHash } from "node:crypto";
|
|
48129
48546
|
import * as fs8 from "node:fs/promises";
|
|
48130
|
-
import
|
|
48547
|
+
import path75 from "node:path";
|
|
48131
48548
|
var init_reconcile = __esm({
|
|
48132
48549
|
"packages/memory/src/reconcile.ts"() {
|
|
48133
48550
|
"use strict";
|
|
@@ -48141,7 +48558,7 @@ var init_reconcile = __esm({
|
|
|
48141
48558
|
|
|
48142
48559
|
// packages/memory/src/write.ts
|
|
48143
48560
|
import * as fs9 from "node:fs/promises";
|
|
48144
|
-
import
|
|
48561
|
+
import path76 from "node:path";
|
|
48145
48562
|
async function clearMemory(root) {
|
|
48146
48563
|
await withLock(root, async () => {
|
|
48147
48564
|
await removeChildren(root);
|
|
@@ -48153,13 +48570,13 @@ async function removeChildren(directoryPath) {
|
|
|
48153
48570
|
if (entryName === MEMORY_LOCK_RELPATH) {
|
|
48154
48571
|
continue;
|
|
48155
48572
|
}
|
|
48156
|
-
const entryPath =
|
|
48157
|
-
const
|
|
48158
|
-
if (
|
|
48573
|
+
const entryPath = path76.join(directoryPath, entryName);
|
|
48574
|
+
const stat24 = await fs9.stat(entryPath);
|
|
48575
|
+
if (stat24.isDirectory()) {
|
|
48159
48576
|
await removeDirectory3(entryPath);
|
|
48160
48577
|
continue;
|
|
48161
48578
|
}
|
|
48162
|
-
if (
|
|
48579
|
+
if (stat24.isFile()) {
|
|
48163
48580
|
await fs9.unlink(entryPath);
|
|
48164
48581
|
}
|
|
48165
48582
|
}
|
|
@@ -48181,7 +48598,7 @@ var init_write2 = __esm({
|
|
|
48181
48598
|
|
|
48182
48599
|
// packages/memory/src/edit.ts
|
|
48183
48600
|
import * as fs10 from "node:fs/promises";
|
|
48184
|
-
import
|
|
48601
|
+
import path77 from "node:path";
|
|
48185
48602
|
var init_edit = __esm({
|
|
48186
48603
|
"packages/memory/src/edit.ts"() {
|
|
48187
48604
|
"use strict";
|
|
@@ -48192,7 +48609,7 @@ var init_edit = __esm({
|
|
|
48192
48609
|
|
|
48193
48610
|
// packages/memory/src/audit.ts
|
|
48194
48611
|
import * as fs11 from "node:fs/promises";
|
|
48195
|
-
import
|
|
48612
|
+
import path78 from "node:path";
|
|
48196
48613
|
var init_audit = __esm({
|
|
48197
48614
|
"packages/memory/src/audit.ts"() {
|
|
48198
48615
|
"use strict";
|
|
@@ -48205,7 +48622,7 @@ var init_audit = __esm({
|
|
|
48205
48622
|
// packages/memory/src/cache.ts
|
|
48206
48623
|
import { createHash as createHash2 } from "node:crypto";
|
|
48207
48624
|
import * as fs12 from "node:fs/promises";
|
|
48208
|
-
import
|
|
48625
|
+
import path79 from "node:path";
|
|
48209
48626
|
var init_cache = __esm({
|
|
48210
48627
|
"packages/memory/src/cache.ts"() {
|
|
48211
48628
|
"use strict";
|
|
@@ -48312,7 +48729,7 @@ var init_src28 = __esm({
|
|
|
48312
48729
|
|
|
48313
48730
|
// packages/memory/src/tokens.ts
|
|
48314
48731
|
import * as fs13 from "node:fs/promises";
|
|
48315
|
-
import
|
|
48732
|
+
import path80 from "node:path";
|
|
48316
48733
|
async function computeTokenStats(root) {
|
|
48317
48734
|
if (!await pathExists8(root)) {
|
|
48318
48735
|
return {
|
|
@@ -48334,11 +48751,11 @@ async function computeTokenStats(root) {
|
|
|
48334
48751
|
}
|
|
48335
48752
|
}
|
|
48336
48753
|
}
|
|
48337
|
-
const repoRoot =
|
|
48754
|
+
const repoRoot = path80.resolve(root, "..", "..");
|
|
48338
48755
|
let sourceTokens = 0;
|
|
48339
48756
|
const missingSources = [];
|
|
48340
48757
|
for (const sourcePath of sourcePaths) {
|
|
48341
|
-
const absPath =
|
|
48758
|
+
const absPath = path80.isAbsolute(sourcePath) ? sourcePath : path80.resolve(repoRoot, sourcePath);
|
|
48342
48759
|
try {
|
|
48343
48760
|
const content = await fs13.readFile(absPath, "utf8");
|
|
48344
48761
|
sourceTokens += countTokens(content);
|
|
@@ -48383,7 +48800,7 @@ var init_tokens2 = __esm({
|
|
|
48383
48800
|
|
|
48384
48801
|
// packages/memory/src/ingest.ts
|
|
48385
48802
|
import * as fs14 from "node:fs/promises";
|
|
48386
|
-
import
|
|
48803
|
+
import path81 from "node:path";
|
|
48387
48804
|
var init_ingest = __esm({
|
|
48388
48805
|
"packages/memory/src/ingest.ts"() {
|
|
48389
48806
|
"use strict";
|
|
@@ -48418,7 +48835,7 @@ var init_install3 = __esm({
|
|
|
48418
48835
|
|
|
48419
48836
|
// packages/memory/src/query.ts
|
|
48420
48837
|
import * as fs15 from "node:fs/promises";
|
|
48421
|
-
import
|
|
48838
|
+
import path82 from "node:path";
|
|
48422
48839
|
var init_query = __esm({
|
|
48423
48840
|
"packages/memory/src/query.ts"() {
|
|
48424
48841
|
"use strict";
|
|
@@ -48474,7 +48891,7 @@ var init_src29 = __esm({
|
|
|
48474
48891
|
});
|
|
48475
48892
|
|
|
48476
48893
|
// src/cli/commands/memory.ts
|
|
48477
|
-
import
|
|
48894
|
+
import path83 from "node:path";
|
|
48478
48895
|
import * as fs16 from "node:fs/promises";
|
|
48479
48896
|
function resolvePageRelPath(input) {
|
|
48480
48897
|
const trimmed = input.trim();
|
|
@@ -48482,7 +48899,7 @@ function resolvePageRelPath(input) {
|
|
|
48482
48899
|
throw new ValidationError("Missing page path.");
|
|
48483
48900
|
}
|
|
48484
48901
|
const normalized = trimmed.replaceAll("\\", "/");
|
|
48485
|
-
const withExt =
|
|
48902
|
+
const withExt = path83.posix.extname(normalized).length === 0 ? `${normalized}.md` : normalized;
|
|
48486
48903
|
return withExt.startsWith("pages/") ? withExt : `pages/${withExt}`;
|
|
48487
48904
|
}
|
|
48488
48905
|
function displayPageRelPath(relPath) {
|
|
@@ -48520,8 +48937,8 @@ function registerMemoryCommand(program, container) {
|
|
|
48520
48937
|
}
|
|
48521
48938
|
await initMemory(root);
|
|
48522
48939
|
resources.context.complete({
|
|
48523
|
-
success: `Initialized memory at ${
|
|
48524
|
-
dry: `Would initialize memory at ${
|
|
48940
|
+
success: `Initialized memory at ${path83.relative(container.env.cwd, root)}`,
|
|
48941
|
+
dry: `Would initialize memory at ${path83.relative(container.env.cwd, root)}`
|
|
48525
48942
|
});
|
|
48526
48943
|
resources.context.finalize();
|
|
48527
48944
|
});
|
|
@@ -48551,7 +48968,7 @@ function registerMemoryCommand(program, container) {
|
|
|
48551
48968
|
resources.logger.intro("memory show");
|
|
48552
48969
|
await assertInitialized(root);
|
|
48553
48970
|
const relPath = resolvePageRelPath(pagePath);
|
|
48554
|
-
const absPath =
|
|
48971
|
+
const absPath = path83.join(root, relPath);
|
|
48555
48972
|
try {
|
|
48556
48973
|
const content = await fs16.readFile(absPath, "utf8");
|
|
48557
48974
|
process.stdout.write(content.endsWith("\n") ? content : `${content}
|
|
@@ -48649,7 +49066,7 @@ var init_package2 = __esm({
|
|
|
48649
49066
|
"package.json"() {
|
|
48650
49067
|
package_default2 = {
|
|
48651
49068
|
name: "poe-code",
|
|
48652
|
-
version: "3.0.
|
|
49069
|
+
version: "3.0.184",
|
|
48653
49070
|
description: "CLI tool to configure Poe API for developer workflows.",
|
|
48654
49071
|
type: "module",
|
|
48655
49072
|
main: "./dist/index.js",
|
|
@@ -48864,22 +49281,22 @@ function formatCommandHeader(cmd) {
|
|
|
48864
49281
|
}
|
|
48865
49282
|
return `Poe - ${parts.reverse().join(" ")}`;
|
|
48866
49283
|
}
|
|
48867
|
-
function findCommandByPath(root,
|
|
49284
|
+
function findCommandByPath(root, path84) {
|
|
48868
49285
|
let current = root;
|
|
48869
|
-
for (const segment of
|
|
49286
|
+
for (const segment of path84) {
|
|
48870
49287
|
const next = current.commands.find(
|
|
48871
49288
|
(command) => Reflect.get(command, "_hidden") !== true && command.name() === segment
|
|
48872
49289
|
);
|
|
48873
49290
|
if (!next) {
|
|
48874
|
-
throw new Error(`Root help command is missing: ${
|
|
49291
|
+
throw new Error(`Root help command is missing: ${path84.join(" ")}`);
|
|
48875
49292
|
}
|
|
48876
49293
|
current = next;
|
|
48877
49294
|
}
|
|
48878
49295
|
return current;
|
|
48879
49296
|
}
|
|
48880
|
-
function formatRootHelpCommandName(
|
|
49297
|
+
function formatRootHelpCommandName(path84, command) {
|
|
48881
49298
|
const leaf = [command.name(), ...command.aliases()].join(", ");
|
|
48882
|
-
return
|
|
49299
|
+
return path84.length > 1 ? [...path84.slice(0, -1), leaf].join(" ") : leaf;
|
|
48883
49300
|
}
|
|
48884
49301
|
function splitUsageParts(usage) {
|
|
48885
49302
|
return usage.split(" ").map((part) => part.trim()).filter((part) => part.length > 0);
|
|
@@ -49546,7 +49963,7 @@ init_config3();
|
|
|
49546
49963
|
init_constants();
|
|
49547
49964
|
init_errors2();
|
|
49548
49965
|
import os7 from "node:os";
|
|
49549
|
-
import
|
|
49966
|
+
import path61 from "node:path";
|
|
49550
49967
|
import fsPromises17 from "node:fs/promises";
|
|
49551
49968
|
import { Command } from "commander";
|
|
49552
49969
|
function parseMcpSpawnConfig(input) {
|
|
@@ -49618,10 +50035,10 @@ function resolveWorkingDirectory(baseDir, candidate) {
|
|
|
49618
50035
|
if (!candidate || candidate.trim().length === 0) {
|
|
49619
50036
|
return void 0;
|
|
49620
50037
|
}
|
|
49621
|
-
if (
|
|
50038
|
+
if (path61.isAbsolute(candidate)) {
|
|
49622
50039
|
return candidate;
|
|
49623
50040
|
}
|
|
49624
|
-
return
|
|
50041
|
+
return path61.resolve(baseDir, candidate);
|
|
49625
50042
|
}
|
|
49626
50043
|
function configurePoeAgentRunOptions(command) {
|
|
49627
50044
|
return command.option("-y, --yes", "Accept configured defaults without prompting").option("--model <model>", "Model identifier override").option("--prompt <text>", "Prompt text to send").option("-C, --cwd <path>", "Working directory for the agent").option("--stdin", "Read the prompt from stdin").option(
|