poe-code 3.0.121 → 3.0.123
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/auth.js +1 -1
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/install.js +1 -1
- package/dist/cli/commands/install.js.map +1 -1
- package/dist/cli/commands/launch.d.ts +3 -0
- package/dist/cli/commands/launch.js +456 -0
- package/dist/cli/commands/launch.js.map +1 -0
- package/dist/cli/program.js +13 -23
- package/dist/cli/program.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2538 -434
- package/dist/index.js.map +4 -4
- package/dist/sdk/launch.d.ts +45 -0
- package/dist/sdk/launch.js +165 -0
- package/dist/sdk/launch.js.map +1 -0
- package/dist/sdk/process-launcher.d.ts +2 -0
- package/dist/sdk/process-launcher.js +2 -0
- package/dist/sdk/process-launcher.js.map +1 -0
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -925,16 +925,16 @@ function getConfigFormat(pathOrFormat) {
|
|
|
925
925
|
}
|
|
926
926
|
return formatRegistry[formatName];
|
|
927
927
|
}
|
|
928
|
-
function detectFormat(
|
|
929
|
-
const ext = getExtension(
|
|
928
|
+
function detectFormat(path39) {
|
|
929
|
+
const ext = getExtension(path39);
|
|
930
930
|
return extensionMap[ext];
|
|
931
931
|
}
|
|
932
|
-
function getExtension(
|
|
933
|
-
const lastDot =
|
|
932
|
+
function getExtension(path39) {
|
|
933
|
+
const lastDot = path39.lastIndexOf(".");
|
|
934
934
|
if (lastDot === -1) {
|
|
935
935
|
return "";
|
|
936
936
|
}
|
|
937
|
-
return
|
|
937
|
+
return path39.slice(lastDot).toLowerCase();
|
|
938
938
|
}
|
|
939
939
|
var formatRegistry, extensionMap;
|
|
940
940
|
var init_formats = __esm({
|
|
@@ -1989,38 +1989,38 @@ import { createTwoFilesPatch } from "diff";
|
|
|
1989
1989
|
import chalk from "chalk";
|
|
1990
1990
|
function createDryRunFileSystem(base, recorder) {
|
|
1991
1991
|
const proxy = {
|
|
1992
|
-
async readFile(
|
|
1992
|
+
async readFile(path39, encoding) {
|
|
1993
1993
|
if (encoding) {
|
|
1994
|
-
return base.readFile(
|
|
1994
|
+
return base.readFile(path39, encoding);
|
|
1995
1995
|
}
|
|
1996
|
-
return base.readFile(
|
|
1996
|
+
return base.readFile(path39);
|
|
1997
1997
|
},
|
|
1998
|
-
async writeFile(
|
|
1999
|
-
const previousContent = await tryReadText(base,
|
|
1998
|
+
async writeFile(path39, data, options) {
|
|
1999
|
+
const previousContent = await tryReadText(base, path39);
|
|
2000
2000
|
const nextContent = formatData(data, options?.encoding);
|
|
2001
2001
|
recorder.record({
|
|
2002
2002
|
type: "writeFile",
|
|
2003
|
-
path:
|
|
2003
|
+
path: path39,
|
|
2004
2004
|
nextContent,
|
|
2005
2005
|
previousContent
|
|
2006
2006
|
});
|
|
2007
2007
|
},
|
|
2008
|
-
async mkdir(
|
|
2009
|
-
recorder.record({ type: "mkdir", path:
|
|
2008
|
+
async mkdir(path39, options) {
|
|
2009
|
+
recorder.record({ type: "mkdir", path: path39, options });
|
|
2010
2010
|
},
|
|
2011
|
-
async stat(
|
|
2012
|
-
return base.stat(
|
|
2011
|
+
async stat(path39) {
|
|
2012
|
+
return base.stat(path39);
|
|
2013
2013
|
},
|
|
2014
|
-
async unlink(
|
|
2015
|
-
recorder.record({ type: "unlink", path:
|
|
2014
|
+
async unlink(path39) {
|
|
2015
|
+
recorder.record({ type: "unlink", path: path39 });
|
|
2016
2016
|
},
|
|
2017
|
-
async readdir(
|
|
2018
|
-
return base.readdir(
|
|
2017
|
+
async readdir(path39) {
|
|
2018
|
+
return base.readdir(path39);
|
|
2019
2019
|
}
|
|
2020
2020
|
};
|
|
2021
2021
|
if (typeof base.rm === "function") {
|
|
2022
|
-
proxy.rm = async (
|
|
2023
|
-
recorder.record({ type: "rm", path:
|
|
2022
|
+
proxy.rm = async (path39, options) => {
|
|
2023
|
+
recorder.record({ type: "rm", path: path39, options });
|
|
2024
2024
|
};
|
|
2025
2025
|
}
|
|
2026
2026
|
if (typeof base.copyFile === "function") {
|
|
@@ -2110,8 +2110,8 @@ function describeWriteChange(previous, next) {
|
|
|
2110
2110
|
}
|
|
2111
2111
|
return "update";
|
|
2112
2112
|
}
|
|
2113
|
-
function renderWriteCommand(
|
|
2114
|
-
const command = `cat > ${
|
|
2113
|
+
function renderWriteCommand(path39, change) {
|
|
2114
|
+
const command = `cat > ${path39}`;
|
|
2115
2115
|
if (change === "create") {
|
|
2116
2116
|
return renderOperationCommand(command, chalk.green, "# create");
|
|
2117
2117
|
}
|
|
@@ -2273,9 +2273,9 @@ function redactTomlLine(line) {
|
|
|
2273
2273
|
}
|
|
2274
2274
|
return line;
|
|
2275
2275
|
}
|
|
2276
|
-
async function tryReadText(base,
|
|
2276
|
+
async function tryReadText(base, path39) {
|
|
2277
2277
|
try {
|
|
2278
|
-
return await base.readFile(
|
|
2278
|
+
return await base.readFile(path39, "utf8");
|
|
2279
2279
|
} catch (error) {
|
|
2280
2280
|
if (isNotFound(error)) {
|
|
2281
2281
|
return null;
|
|
@@ -4123,21 +4123,21 @@ async function* adaptClaude(lines) {
|
|
|
4123
4123
|
if (blockType !== "tool_result") continue;
|
|
4124
4124
|
const kind = toolKindsById.get(item.tool_use_id);
|
|
4125
4125
|
toolKindsById.delete(item.tool_use_id);
|
|
4126
|
-
let
|
|
4126
|
+
let path39;
|
|
4127
4127
|
if (typeof item.content === "string") {
|
|
4128
|
-
|
|
4128
|
+
path39 = item.content;
|
|
4129
4129
|
} else {
|
|
4130
4130
|
try {
|
|
4131
|
-
|
|
4131
|
+
path39 = JSON.stringify(item.content);
|
|
4132
4132
|
} catch {
|
|
4133
|
-
|
|
4133
|
+
path39 = String(item.content);
|
|
4134
4134
|
}
|
|
4135
4135
|
}
|
|
4136
4136
|
yield {
|
|
4137
4137
|
event: "tool_complete",
|
|
4138
4138
|
id: item.tool_use_id,
|
|
4139
4139
|
kind,
|
|
4140
|
-
path:
|
|
4140
|
+
path: path39
|
|
4141
4141
|
};
|
|
4142
4142
|
}
|
|
4143
4143
|
}
|
|
@@ -4259,10 +4259,10 @@ async function* adaptCodex(lines) {
|
|
|
4259
4259
|
const kindFromStart = toolKindById.get(item.id);
|
|
4260
4260
|
const kind = kindFromStart ?? (itemType === "command_execution" ? "exec" : itemType === "file_edit" ? "edit" : "other");
|
|
4261
4261
|
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;
|
|
4262
|
-
const
|
|
4262
|
+
const path39 = titleFromEvent ?? toolTitleById.get(item.id) ?? "";
|
|
4263
4263
|
toolTitleById.delete(item.id);
|
|
4264
4264
|
toolKindById.delete(item.id);
|
|
4265
|
-
yield { event: "tool_complete", id: item.id, kind, path:
|
|
4265
|
+
yield { event: "tool_complete", id: item.id, kind, path: path39 };
|
|
4266
4266
|
}
|
|
4267
4267
|
}
|
|
4268
4268
|
}
|
|
@@ -4711,7 +4711,7 @@ function updateSessionFromEvent(ctx, event, toolCallsById) {
|
|
|
4711
4711
|
}
|
|
4712
4712
|
const id = readString(event.id);
|
|
4713
4713
|
const kind = readString(event.kind);
|
|
4714
|
-
const
|
|
4714
|
+
const path39 = readString(event.path);
|
|
4715
4715
|
let toolCall = id ? toolCallsById.get(id) : void 0;
|
|
4716
4716
|
if (!toolCall) {
|
|
4717
4717
|
toolCall = {};
|
|
@@ -4726,8 +4726,8 @@ function updateSessionFromEvent(ctx, event, toolCallsById) {
|
|
|
4726
4726
|
if (kind) {
|
|
4727
4727
|
toolCall.kind = kind;
|
|
4728
4728
|
}
|
|
4729
|
-
if (
|
|
4730
|
-
toolCall.path =
|
|
4729
|
+
if (path39) {
|
|
4730
|
+
toolCall.path = path39;
|
|
4731
4731
|
}
|
|
4732
4732
|
}
|
|
4733
4733
|
var sessionCapture;
|
|
@@ -6729,21 +6729,21 @@ function createSdkContainer(options) {
|
|
|
6729
6729
|
});
|
|
6730
6730
|
loggerFactory.setErrorLogger(errorLogger);
|
|
6731
6731
|
const asyncFs = {
|
|
6732
|
-
readFile: ((
|
|
6732
|
+
readFile: ((path39, encoding) => {
|
|
6733
6733
|
if (encoding) {
|
|
6734
|
-
return fs2.readFile(
|
|
6734
|
+
return fs2.readFile(path39, encoding);
|
|
6735
6735
|
}
|
|
6736
|
-
return fs2.readFile(
|
|
6736
|
+
return fs2.readFile(path39);
|
|
6737
6737
|
}),
|
|
6738
|
-
writeFile: (
|
|
6739
|
-
mkdir: (
|
|
6738
|
+
writeFile: (path39, data, opts) => fs2.writeFile(path39, data, opts),
|
|
6739
|
+
mkdir: (path39, opts) => fs2.mkdir(path39, opts).then(() => {
|
|
6740
6740
|
}),
|
|
6741
|
-
stat: (
|
|
6742
|
-
rm: (
|
|
6743
|
-
unlink: (
|
|
6744
|
-
readdir: (
|
|
6741
|
+
stat: (path39) => fs2.stat(path39),
|
|
6742
|
+
rm: (path39, opts) => fs2.rm(path39, opts),
|
|
6743
|
+
unlink: (path39) => fs2.unlink(path39),
|
|
6744
|
+
readdir: (path39) => fs2.readdir(path39),
|
|
6745
6745
|
copyFile: (src, dest) => fs2.copyFile(src, dest),
|
|
6746
|
-
chmod: (
|
|
6746
|
+
chmod: (path39, mode) => fs2.chmod(path39, mode)
|
|
6747
6747
|
};
|
|
6748
6748
|
const contextFactory = createCommandContextFactory({ fs: asyncFs });
|
|
6749
6749
|
const authFs = {
|
|
@@ -7510,8 +7510,8 @@ function sleep(ms) {
|
|
|
7510
7510
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
7511
7511
|
}
|
|
7512
7512
|
function backoff(attempt, min, max) {
|
|
7513
|
-
const
|
|
7514
|
-
return
|
|
7513
|
+
const delay2 = Math.min(max, min * Math.pow(2, attempt));
|
|
7514
|
+
return delay2 + Math.random() * delay2 * 0.1;
|
|
7515
7515
|
}
|
|
7516
7516
|
function createDefaultFs2() {
|
|
7517
7517
|
return {
|
|
@@ -7889,6 +7889,1503 @@ var init_pipeline2 = __esm({
|
|
|
7889
7889
|
}
|
|
7890
7890
|
});
|
|
7891
7891
|
|
|
7892
|
+
// packages/process-launcher/src/state/state-store.ts
|
|
7893
|
+
import path15 from "node:path";
|
|
7894
|
+
import * as nodeFs from "node:fs/promises";
|
|
7895
|
+
function isNotFoundError2(error) {
|
|
7896
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
7897
|
+
}
|
|
7898
|
+
async function removeDirectory2(fs3, directoryPath) {
|
|
7899
|
+
let entries;
|
|
7900
|
+
try {
|
|
7901
|
+
entries = await fs3.readdir(directoryPath);
|
|
7902
|
+
} catch (error) {
|
|
7903
|
+
if (isNotFoundError2(error)) {
|
|
7904
|
+
return;
|
|
7905
|
+
}
|
|
7906
|
+
throw error;
|
|
7907
|
+
}
|
|
7908
|
+
for (const entry of entries) {
|
|
7909
|
+
const entryPath = path15.join(directoryPath, entry);
|
|
7910
|
+
const stat11 = await fs3.stat(entryPath);
|
|
7911
|
+
if (stat11.isFile()) {
|
|
7912
|
+
await fs3.rm(entryPath, { force: true });
|
|
7913
|
+
continue;
|
|
7914
|
+
}
|
|
7915
|
+
await removeDirectory2(fs3, entryPath);
|
|
7916
|
+
}
|
|
7917
|
+
const fsWithDirectoryRemoval = fs3;
|
|
7918
|
+
if (typeof fsWithDirectoryRemoval.rmdir === "function") {
|
|
7919
|
+
await fsWithDirectoryRemoval.rmdir(directoryPath);
|
|
7920
|
+
return;
|
|
7921
|
+
}
|
|
7922
|
+
await fs3.rm(directoryPath, { force: true });
|
|
7923
|
+
}
|
|
7924
|
+
function createStateStore(stateDir, fs3 = nodeFs) {
|
|
7925
|
+
async function read(id) {
|
|
7926
|
+
const statePath = path15.join(stateDir, id, "state.json");
|
|
7927
|
+
try {
|
|
7928
|
+
const content = await fs3.readFile(statePath, "utf8");
|
|
7929
|
+
return JSON.parse(content);
|
|
7930
|
+
} catch (error) {
|
|
7931
|
+
if (isNotFoundError2(error)) {
|
|
7932
|
+
return null;
|
|
7933
|
+
}
|
|
7934
|
+
throw error;
|
|
7935
|
+
}
|
|
7936
|
+
}
|
|
7937
|
+
async function write2(id, state) {
|
|
7938
|
+
const processDir = path15.join(stateDir, id);
|
|
7939
|
+
await fs3.mkdir(processDir, { recursive: true });
|
|
7940
|
+
await fs3.writeFile(path15.join(processDir, "state.json"), `${JSON.stringify(state, null, 2)}
|
|
7941
|
+
`);
|
|
7942
|
+
}
|
|
7943
|
+
async function list() {
|
|
7944
|
+
let entries;
|
|
7945
|
+
try {
|
|
7946
|
+
entries = await fs3.readdir(stateDir);
|
|
7947
|
+
} catch (error) {
|
|
7948
|
+
if (isNotFoundError2(error)) {
|
|
7949
|
+
return [];
|
|
7950
|
+
}
|
|
7951
|
+
throw error;
|
|
7952
|
+
}
|
|
7953
|
+
const states = [];
|
|
7954
|
+
for (const entry of [...entries].sort()) {
|
|
7955
|
+
const entryPath = path15.join(stateDir, entry);
|
|
7956
|
+
try {
|
|
7957
|
+
const stat11 = await fs3.stat(entryPath);
|
|
7958
|
+
if (stat11.isFile()) {
|
|
7959
|
+
continue;
|
|
7960
|
+
}
|
|
7961
|
+
} catch (error) {
|
|
7962
|
+
if (isNotFoundError2(error)) {
|
|
7963
|
+
continue;
|
|
7964
|
+
}
|
|
7965
|
+
throw error;
|
|
7966
|
+
}
|
|
7967
|
+
const state = await read(entry);
|
|
7968
|
+
if (state !== null) {
|
|
7969
|
+
states.push(state);
|
|
7970
|
+
}
|
|
7971
|
+
}
|
|
7972
|
+
return states;
|
|
7973
|
+
}
|
|
7974
|
+
async function remove2(id) {
|
|
7975
|
+
await removeDirectory2(fs3, path15.join(stateDir, id));
|
|
7976
|
+
}
|
|
7977
|
+
return { read, write: write2, list, remove: remove2 };
|
|
7978
|
+
}
|
|
7979
|
+
var init_state_store = __esm({
|
|
7980
|
+
"packages/process-launcher/src/state/state-store.ts"() {
|
|
7981
|
+
"use strict";
|
|
7982
|
+
}
|
|
7983
|
+
});
|
|
7984
|
+
|
|
7985
|
+
// packages/process-launcher/src/logs/log-writer.ts
|
|
7986
|
+
import path16 from "node:path";
|
|
7987
|
+
import * as nodeFs2 from "node:fs/promises";
|
|
7988
|
+
function isNotFoundError3(error) {
|
|
7989
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
7990
|
+
}
|
|
7991
|
+
function getCurrentLogPath(logDir, stream) {
|
|
7992
|
+
return path16.join(logDir, `${stream}.log`);
|
|
7993
|
+
}
|
|
7994
|
+
function getRotatedLogPath(logDir, stream, index) {
|
|
7995
|
+
return path16.join(logDir, `${stream}.${index}.log`);
|
|
7996
|
+
}
|
|
7997
|
+
async function isFile(fs3, filePath) {
|
|
7998
|
+
try {
|
|
7999
|
+
return (await fs3.stat(filePath)).isFile();
|
|
8000
|
+
} catch (error) {
|
|
8001
|
+
if (isNotFoundError3(error)) {
|
|
8002
|
+
return false;
|
|
8003
|
+
}
|
|
8004
|
+
throw error;
|
|
8005
|
+
}
|
|
8006
|
+
}
|
|
8007
|
+
async function removeIfExists(fs3, filePath) {
|
|
8008
|
+
if (!await isFile(fs3, filePath)) {
|
|
8009
|
+
return;
|
|
8010
|
+
}
|
|
8011
|
+
await fs3.rm(filePath, { force: true });
|
|
8012
|
+
}
|
|
8013
|
+
async function moveIfExists(fs3, sourcePath, destinationPath) {
|
|
8014
|
+
if (!await isFile(fs3, sourcePath)) {
|
|
8015
|
+
return;
|
|
8016
|
+
}
|
|
8017
|
+
const content = await fs3.readFile(sourcePath, "utf8");
|
|
8018
|
+
await fs3.writeFile(destinationPath, content);
|
|
8019
|
+
await fs3.rm(sourcePath, { force: true });
|
|
8020
|
+
}
|
|
8021
|
+
function getRotatedLogIndex(fileName, stream) {
|
|
8022
|
+
const prefix = `${stream}.`;
|
|
8023
|
+
const suffix = ".log";
|
|
8024
|
+
if (!fileName.startsWith(prefix) || !fileName.endsWith(suffix)) {
|
|
8025
|
+
return null;
|
|
8026
|
+
}
|
|
8027
|
+
const rawIndex = fileName.slice(prefix.length, -suffix.length);
|
|
8028
|
+
const index = Number.parseInt(rawIndex, 10);
|
|
8029
|
+
if (!Number.isInteger(index) || index < 1 || `${index}` !== rawIndex) {
|
|
8030
|
+
return null;
|
|
8031
|
+
}
|
|
8032
|
+
return index;
|
|
8033
|
+
}
|
|
8034
|
+
async function removeAllStreamLogs(fs3, logDir, stream) {
|
|
8035
|
+
await removeIfExists(fs3, getCurrentLogPath(logDir, stream));
|
|
8036
|
+
try {
|
|
8037
|
+
const fileNames = await fs3.readdir(logDir);
|
|
8038
|
+
for (const fileName of fileNames) {
|
|
8039
|
+
if (getRotatedLogIndex(fileName, stream) === null) {
|
|
8040
|
+
continue;
|
|
8041
|
+
}
|
|
8042
|
+
await fs3.rm(path16.join(logDir, fileName), { force: true });
|
|
8043
|
+
}
|
|
8044
|
+
} catch (error) {
|
|
8045
|
+
if (isNotFoundError3(error)) {
|
|
8046
|
+
return;
|
|
8047
|
+
}
|
|
8048
|
+
throw error;
|
|
8049
|
+
}
|
|
8050
|
+
}
|
|
8051
|
+
function getLines(content) {
|
|
8052
|
+
if (content.length === 0) {
|
|
8053
|
+
return [];
|
|
8054
|
+
}
|
|
8055
|
+
const lines = content.split("\n");
|
|
8056
|
+
if (content.endsWith("\n")) {
|
|
8057
|
+
lines.pop();
|
|
8058
|
+
}
|
|
8059
|
+
return lines;
|
|
8060
|
+
}
|
|
8061
|
+
function createLogWriter(logDir, retainCount, fs3 = nodeFs2) {
|
|
8062
|
+
const maxRetainedRuns = Math.max(0, Math.trunc(retainCount));
|
|
8063
|
+
async function write2(line, stream) {
|
|
8064
|
+
await fs3.mkdir(logDir, { recursive: true });
|
|
8065
|
+
await fs3.appendFile(getCurrentLogPath(logDir, stream), `${line}
|
|
8066
|
+
`);
|
|
8067
|
+
}
|
|
8068
|
+
async function rotateStream(stream) {
|
|
8069
|
+
const currentPath = getCurrentLogPath(logDir, stream);
|
|
8070
|
+
if (maxRetainedRuns === 0) {
|
|
8071
|
+
await removeAllStreamLogs(fs3, logDir, stream);
|
|
8072
|
+
return;
|
|
8073
|
+
}
|
|
8074
|
+
await removeIfExists(fs3, getRotatedLogPath(logDir, stream, maxRetainedRuns));
|
|
8075
|
+
for (let index = maxRetainedRuns - 1; index >= 1; index -= 1) {
|
|
8076
|
+
await moveIfExists(
|
|
8077
|
+
fs3,
|
|
8078
|
+
getRotatedLogPath(logDir, stream, index),
|
|
8079
|
+
getRotatedLogPath(logDir, stream, index + 1)
|
|
8080
|
+
);
|
|
8081
|
+
}
|
|
8082
|
+
await moveIfExists(fs3, currentPath, getRotatedLogPath(logDir, stream, 1));
|
|
8083
|
+
}
|
|
8084
|
+
async function rotate() {
|
|
8085
|
+
await rotateStream("stdout");
|
|
8086
|
+
await rotateStream("stderr");
|
|
8087
|
+
}
|
|
8088
|
+
async function tail(stream, lines = 50) {
|
|
8089
|
+
try {
|
|
8090
|
+
const content = await fs3.readFile(getCurrentLogPath(logDir, stream), "utf8");
|
|
8091
|
+
const allLines = getLines(content);
|
|
8092
|
+
const lineCount = Math.max(0, Math.trunc(lines));
|
|
8093
|
+
if (lineCount === 0) {
|
|
8094
|
+
return [];
|
|
8095
|
+
}
|
|
8096
|
+
return allLines.slice(-lineCount);
|
|
8097
|
+
} catch (error) {
|
|
8098
|
+
if (isNotFoundError3(error)) {
|
|
8099
|
+
return [];
|
|
8100
|
+
}
|
|
8101
|
+
throw error;
|
|
8102
|
+
}
|
|
8103
|
+
}
|
|
8104
|
+
function close() {
|
|
8105
|
+
}
|
|
8106
|
+
return { write: write2, rotate, tail, close };
|
|
8107
|
+
}
|
|
8108
|
+
var init_log_writer = __esm({
|
|
8109
|
+
"packages/process-launcher/src/logs/log-writer.ts"() {
|
|
8110
|
+
"use strict";
|
|
8111
|
+
}
|
|
8112
|
+
});
|
|
8113
|
+
|
|
8114
|
+
// packages/process-launcher/src/health/health-check.ts
|
|
8115
|
+
import net from "node:net";
|
|
8116
|
+
async function waitForReady(check, options) {
|
|
8117
|
+
if (check.kind === "log-pattern") {
|
|
8118
|
+
return waitForLogPattern(check.pattern, options);
|
|
8119
|
+
}
|
|
8120
|
+
return waitForTcp(check, options.signal);
|
|
8121
|
+
}
|
|
8122
|
+
function waitForLogPattern(pattern, options) {
|
|
8123
|
+
if (options.signal?.aborted) {
|
|
8124
|
+
return Promise.resolve(false);
|
|
8125
|
+
}
|
|
8126
|
+
return new Promise((resolve) => {
|
|
8127
|
+
let finished = false;
|
|
8128
|
+
const timeout = setTimeout(() => {
|
|
8129
|
+
finish(false);
|
|
8130
|
+
}, options.timeoutMs ?? 3e4);
|
|
8131
|
+
const logSource = options.onLog;
|
|
8132
|
+
const unsubscribe = logSource?.subscribe?.((line) => {
|
|
8133
|
+
if (line.includes(pattern)) {
|
|
8134
|
+
finish(true);
|
|
8135
|
+
}
|
|
8136
|
+
}) ?? (() => {
|
|
8137
|
+
});
|
|
8138
|
+
const onAbort = () => {
|
|
8139
|
+
finish(false);
|
|
8140
|
+
};
|
|
8141
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
8142
|
+
function finish(result) {
|
|
8143
|
+
if (finished) {
|
|
8144
|
+
return;
|
|
8145
|
+
}
|
|
8146
|
+
finished = true;
|
|
8147
|
+
clearTimeout(timeout);
|
|
8148
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
8149
|
+
unsubscribe();
|
|
8150
|
+
resolve(result);
|
|
8151
|
+
}
|
|
8152
|
+
});
|
|
8153
|
+
}
|
|
8154
|
+
function waitForTcp(check, signal) {
|
|
8155
|
+
if (signal?.aborted) {
|
|
8156
|
+
return Promise.resolve(false);
|
|
8157
|
+
}
|
|
8158
|
+
const timeoutMs = check.timeoutMs ?? 3e4;
|
|
8159
|
+
const deadline = Date.now() + timeoutMs;
|
|
8160
|
+
return new Promise((resolve) => {
|
|
8161
|
+
let finished = false;
|
|
8162
|
+
let activeSocket;
|
|
8163
|
+
let retryTimer;
|
|
8164
|
+
const onAbort = () => {
|
|
8165
|
+
finish(false);
|
|
8166
|
+
};
|
|
8167
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
8168
|
+
attemptConnection();
|
|
8169
|
+
function attemptConnection() {
|
|
8170
|
+
if (finished) {
|
|
8171
|
+
return;
|
|
8172
|
+
}
|
|
8173
|
+
if (signal?.aborted || Date.now() >= deadline) {
|
|
8174
|
+
finish(false);
|
|
8175
|
+
return;
|
|
8176
|
+
}
|
|
8177
|
+
const socket = net.connect({
|
|
8178
|
+
host: check.host ?? "127.0.0.1",
|
|
8179
|
+
port: check.port
|
|
8180
|
+
});
|
|
8181
|
+
activeSocket = socket;
|
|
8182
|
+
const socketTimeoutMs = Math.max(1, Math.min(500, deadline - Date.now()));
|
|
8183
|
+
socket.setTimeout(socketTimeoutMs);
|
|
8184
|
+
socket.once("connect", () => {
|
|
8185
|
+
clearActiveSocket(socket);
|
|
8186
|
+
socket.end();
|
|
8187
|
+
socket.destroy();
|
|
8188
|
+
finish(true);
|
|
8189
|
+
});
|
|
8190
|
+
socket.once("error", () => {
|
|
8191
|
+
failAttempt(socket);
|
|
8192
|
+
});
|
|
8193
|
+
socket.once("timeout", () => {
|
|
8194
|
+
failAttempt(socket);
|
|
8195
|
+
});
|
|
8196
|
+
}
|
|
8197
|
+
function failAttempt(socket) {
|
|
8198
|
+
clearActiveSocket(socket);
|
|
8199
|
+
socket.destroy();
|
|
8200
|
+
if (finished) {
|
|
8201
|
+
return;
|
|
8202
|
+
}
|
|
8203
|
+
const remainingMs = deadline - Date.now();
|
|
8204
|
+
if (remainingMs <= 0) {
|
|
8205
|
+
finish(false);
|
|
8206
|
+
return;
|
|
8207
|
+
}
|
|
8208
|
+
retryTimer = setTimeout(attemptConnection, Math.min(500, remainingMs));
|
|
8209
|
+
}
|
|
8210
|
+
function clearActiveSocket(socket) {
|
|
8211
|
+
if (activeSocket === socket) {
|
|
8212
|
+
activeSocket = void 0;
|
|
8213
|
+
}
|
|
8214
|
+
}
|
|
8215
|
+
function finish(result) {
|
|
8216
|
+
if (finished) {
|
|
8217
|
+
return;
|
|
8218
|
+
}
|
|
8219
|
+
finished = true;
|
|
8220
|
+
if (retryTimer) {
|
|
8221
|
+
clearTimeout(retryTimer);
|
|
8222
|
+
}
|
|
8223
|
+
activeSocket?.destroy();
|
|
8224
|
+
activeSocket = void 0;
|
|
8225
|
+
signal?.removeEventListener("abort", onAbort);
|
|
8226
|
+
resolve(result);
|
|
8227
|
+
}
|
|
8228
|
+
});
|
|
8229
|
+
}
|
|
8230
|
+
var init_health_check = __esm({
|
|
8231
|
+
"packages/process-launcher/src/health/health-check.ts"() {
|
|
8232
|
+
"use strict";
|
|
8233
|
+
}
|
|
8234
|
+
});
|
|
8235
|
+
|
|
8236
|
+
// packages/process-runner/src/docker/context.ts
|
|
8237
|
+
import { execSync } from "node:child_process";
|
|
8238
|
+
function detectContext() {
|
|
8239
|
+
try {
|
|
8240
|
+
const output = execSync("colima list --json", {
|
|
8241
|
+
encoding: "utf-8",
|
|
8242
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
8243
|
+
});
|
|
8244
|
+
const lines = output.trim().split("\n").filter(Boolean);
|
|
8245
|
+
for (const line of lines) {
|
|
8246
|
+
const profile = JSON.parse(line);
|
|
8247
|
+
if (profile.status === "Running" && profile.runtime === "docker") {
|
|
8248
|
+
const name = profile.name ?? profile.profile;
|
|
8249
|
+
if (!name) {
|
|
8250
|
+
continue;
|
|
8251
|
+
}
|
|
8252
|
+
return name === "default" ? "colima" : `colima-${name}`;
|
|
8253
|
+
}
|
|
8254
|
+
}
|
|
8255
|
+
} catch {
|
|
8256
|
+
return null;
|
|
8257
|
+
}
|
|
8258
|
+
return null;
|
|
8259
|
+
}
|
|
8260
|
+
function buildContextArgs(engine, context) {
|
|
8261
|
+
if (engine === "docker" && context) {
|
|
8262
|
+
return ["--context", context];
|
|
8263
|
+
}
|
|
8264
|
+
return [];
|
|
8265
|
+
}
|
|
8266
|
+
var init_context2 = __esm({
|
|
8267
|
+
"packages/process-runner/src/docker/context.ts"() {
|
|
8268
|
+
"use strict";
|
|
8269
|
+
}
|
|
8270
|
+
});
|
|
8271
|
+
|
|
8272
|
+
// packages/process-runner/src/docker/engine.ts
|
|
8273
|
+
import { execSync as execSync2 } from "node:child_process";
|
|
8274
|
+
function detectEngine() {
|
|
8275
|
+
if (isEngineAvailable("docker")) {
|
|
8276
|
+
return "docker";
|
|
8277
|
+
}
|
|
8278
|
+
if (isEngineAvailable("podman")) {
|
|
8279
|
+
return "podman";
|
|
8280
|
+
}
|
|
8281
|
+
throw new Error(
|
|
8282
|
+
"No container engine found. Please install Docker or Podman:\n - Docker Desktop: https://www.docker.com/products/docker-desktop\n - Colima (macOS): brew install colima && colima start\n - Podman: https://podman.io/docs/installation"
|
|
8283
|
+
);
|
|
8284
|
+
}
|
|
8285
|
+
function isEngineAvailable(engine) {
|
|
8286
|
+
try {
|
|
8287
|
+
execSync2(`${engine} --version`, {
|
|
8288
|
+
stdio: "ignore"
|
|
8289
|
+
});
|
|
8290
|
+
return true;
|
|
8291
|
+
} catch {
|
|
8292
|
+
return false;
|
|
8293
|
+
}
|
|
8294
|
+
}
|
|
8295
|
+
var init_engine = __esm({
|
|
8296
|
+
"packages/process-runner/src/docker/engine.ts"() {
|
|
8297
|
+
"use strict";
|
|
8298
|
+
}
|
|
8299
|
+
});
|
|
8300
|
+
|
|
8301
|
+
// packages/process-runner/src/docker/args.ts
|
|
8302
|
+
import path17 from "node:path";
|
|
8303
|
+
function buildDockerRunArgs(input) {
|
|
8304
|
+
const args = [input.engine];
|
|
8305
|
+
if (input.engine === "docker" && input.context) {
|
|
8306
|
+
args.push("--context", input.context);
|
|
8307
|
+
}
|
|
8308
|
+
args.push("run");
|
|
8309
|
+
if (input.rm) {
|
|
8310
|
+
args.push("--rm");
|
|
8311
|
+
}
|
|
8312
|
+
if (input.detached) {
|
|
8313
|
+
args.push("-d");
|
|
8314
|
+
}
|
|
8315
|
+
if (input.interactive) {
|
|
8316
|
+
args.push("-i");
|
|
8317
|
+
}
|
|
8318
|
+
if (input.tty) {
|
|
8319
|
+
args.push("-t");
|
|
8320
|
+
}
|
|
8321
|
+
args.push("--name", input.containerName);
|
|
8322
|
+
if (input.cwd !== void 0) {
|
|
8323
|
+
args.push("-w", input.cwd);
|
|
8324
|
+
}
|
|
8325
|
+
for (const [key, value] of Object.entries(input.env ?? {})) {
|
|
8326
|
+
args.push("-e", `${key}=${value}`);
|
|
8327
|
+
}
|
|
8328
|
+
for (const mount of input.mounts) {
|
|
8329
|
+
const volume = `${path17.resolve(mount.source)}:${mount.target}${mount.readonly ? ":ro" : ""}`;
|
|
8330
|
+
args.push("-v", volume);
|
|
8331
|
+
}
|
|
8332
|
+
for (const port of input.ports) {
|
|
8333
|
+
const mapping = `${port.host}:${port.container}${port.protocol === void 0 || port.protocol === "tcp" ? "" : `/${port.protocol}`}`;
|
|
8334
|
+
args.push("-p", mapping);
|
|
8335
|
+
}
|
|
8336
|
+
if (input.network !== void 0) {
|
|
8337
|
+
args.push("--network", input.network);
|
|
8338
|
+
}
|
|
8339
|
+
args.push(...input.extraArgs, input.image, input.command, ...input.args);
|
|
8340
|
+
return args;
|
|
8341
|
+
}
|
|
8342
|
+
var init_args = __esm({
|
|
8343
|
+
"packages/process-runner/src/docker/args.ts"() {
|
|
8344
|
+
"use strict";
|
|
8345
|
+
}
|
|
8346
|
+
});
|
|
8347
|
+
|
|
8348
|
+
// packages/process-runner/src/docker/docker-runner.ts
|
|
8349
|
+
import * as childProcess from "node:child_process";
|
|
8350
|
+
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
8351
|
+
function createDockerRunner(options) {
|
|
8352
|
+
const engine = options.engine ?? detectEngine();
|
|
8353
|
+
const context = options.context ?? detectContext();
|
|
8354
|
+
return {
|
|
8355
|
+
name: "docker",
|
|
8356
|
+
exec(spec) {
|
|
8357
|
+
const stdinMode = spec.stdin ?? "ignore";
|
|
8358
|
+
const stdoutMode = spec.stdout ?? "pipe";
|
|
8359
|
+
const stderrMode = spec.stderr ?? "pipe";
|
|
8360
|
+
const interactiveMode = stdinMode === "inherit" && stdoutMode === "inherit" && stderrMode === "inherit" && spec.tty === true;
|
|
8361
|
+
const containerName = buildContainerName(options.containerName ?? spec.command);
|
|
8362
|
+
const runArgs = buildDockerRunArgs({
|
|
8363
|
+
engine,
|
|
8364
|
+
context,
|
|
8365
|
+
image: options.image,
|
|
8366
|
+
command: spec.command,
|
|
8367
|
+
args: spec.args ?? [],
|
|
8368
|
+
cwd: spec.cwd,
|
|
8369
|
+
env: spec.env,
|
|
8370
|
+
mounts: options.mounts ?? [],
|
|
8371
|
+
ports: options.ports ?? [],
|
|
8372
|
+
network: options.network,
|
|
8373
|
+
containerName,
|
|
8374
|
+
detached: false,
|
|
8375
|
+
interactive: stdinMode === "pipe" || stdinMode === "inherit",
|
|
8376
|
+
tty: spec.tty ?? false,
|
|
8377
|
+
rm: true,
|
|
8378
|
+
extraArgs: options.extraArgs ?? []
|
|
8379
|
+
});
|
|
8380
|
+
const [command, ...args] = runArgs;
|
|
8381
|
+
const child = childProcess.spawn(command, args, {
|
|
8382
|
+
stdio: interactiveMode ? "inherit" : [stdinMode, stdoutMode, stderrMode]
|
|
8383
|
+
});
|
|
8384
|
+
let isResultSettled = false;
|
|
8385
|
+
let resolveResult = null;
|
|
8386
|
+
const result = new Promise((resolve) => {
|
|
8387
|
+
resolveResult = resolve;
|
|
8388
|
+
});
|
|
8389
|
+
const cleanupAbort = bindAbortSignal(spec.signal, () => {
|
|
8390
|
+
spawnControlCommand(engine, context, ["stop", containerName]);
|
|
8391
|
+
});
|
|
8392
|
+
const settleResult = (exitCode) => {
|
|
8393
|
+
if (isResultSettled) {
|
|
8394
|
+
return;
|
|
8395
|
+
}
|
|
8396
|
+
isResultSettled = true;
|
|
8397
|
+
cleanupAbort();
|
|
8398
|
+
resolveResult?.({ exitCode });
|
|
8399
|
+
};
|
|
8400
|
+
child.once("error", () => {
|
|
8401
|
+
settleResult(1);
|
|
8402
|
+
});
|
|
8403
|
+
child.once("close", (code) => {
|
|
8404
|
+
settleResult(code ?? 1);
|
|
8405
|
+
});
|
|
8406
|
+
return {
|
|
8407
|
+
pid: null,
|
|
8408
|
+
stdin: interactiveMode ? null : child.stdin,
|
|
8409
|
+
stdout: interactiveMode ? null : child.stdout,
|
|
8410
|
+
stderr: interactiveMode ? null : child.stderr,
|
|
8411
|
+
result,
|
|
8412
|
+
kill(signal) {
|
|
8413
|
+
if (signal === "SIGKILL") {
|
|
8414
|
+
spawnControlCommand(engine, context, ["kill", containerName]);
|
|
8415
|
+
return;
|
|
8416
|
+
}
|
|
8417
|
+
if (signal === void 0 || signal === "SIGTERM") {
|
|
8418
|
+
spawnControlCommand(engine, context, ["stop", containerName]);
|
|
8419
|
+
return;
|
|
8420
|
+
}
|
|
8421
|
+
spawnControlCommand(engine, context, ["kill", `--signal=${signal}`, containerName]);
|
|
8422
|
+
}
|
|
8423
|
+
};
|
|
8424
|
+
}
|
|
8425
|
+
};
|
|
8426
|
+
}
|
|
8427
|
+
function buildContainerName(name) {
|
|
8428
|
+
const suffix = randomBytes2(3).toString("hex").slice(0, 6);
|
|
8429
|
+
const sanitizedName = sanitizeContainerName(name);
|
|
8430
|
+
return `poe-run-${sanitizedName}-${suffix}`;
|
|
8431
|
+
}
|
|
8432
|
+
function sanitizeContainerName(name) {
|
|
8433
|
+
let sanitized = "";
|
|
8434
|
+
for (const char of name) {
|
|
8435
|
+
if (isContainerNameCharacter(char)) {
|
|
8436
|
+
sanitized += char;
|
|
8437
|
+
continue;
|
|
8438
|
+
}
|
|
8439
|
+
sanitized += "-";
|
|
8440
|
+
}
|
|
8441
|
+
return sanitized.length > 0 ? sanitized : "command";
|
|
8442
|
+
}
|
|
8443
|
+
function isContainerNameCharacter(char) {
|
|
8444
|
+
const code = char.charCodeAt(0);
|
|
8445
|
+
if (code >= 48 && code <= 57) {
|
|
8446
|
+
return true;
|
|
8447
|
+
}
|
|
8448
|
+
if (code >= 65 && code <= 90) {
|
|
8449
|
+
return true;
|
|
8450
|
+
}
|
|
8451
|
+
if (code >= 97 && code <= 122) {
|
|
8452
|
+
return true;
|
|
8453
|
+
}
|
|
8454
|
+
return char === "." || char === "_" || char === "-";
|
|
8455
|
+
}
|
|
8456
|
+
function spawnControlCommand(engine, context, args) {
|
|
8457
|
+
childProcess.spawn(engine, [...buildContextArgs(engine, context), ...args], {
|
|
8458
|
+
stdio: "ignore"
|
|
8459
|
+
});
|
|
8460
|
+
}
|
|
8461
|
+
function bindAbortSignal(signal, onAbort) {
|
|
8462
|
+
if (signal === void 0) {
|
|
8463
|
+
return () => {
|
|
8464
|
+
};
|
|
8465
|
+
}
|
|
8466
|
+
if (signal.aborted) {
|
|
8467
|
+
onAbort();
|
|
8468
|
+
return () => {
|
|
8469
|
+
};
|
|
8470
|
+
}
|
|
8471
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
8472
|
+
return () => {
|
|
8473
|
+
signal.removeEventListener("abort", onAbort);
|
|
8474
|
+
};
|
|
8475
|
+
}
|
|
8476
|
+
var init_docker_runner = __esm({
|
|
8477
|
+
"packages/process-runner/src/docker/docker-runner.ts"() {
|
|
8478
|
+
"use strict";
|
|
8479
|
+
init_args();
|
|
8480
|
+
init_context2();
|
|
8481
|
+
init_engine();
|
|
8482
|
+
}
|
|
8483
|
+
});
|
|
8484
|
+
|
|
8485
|
+
// packages/process-runner/src/host/host-runner.ts
|
|
8486
|
+
import * as childProcess2 from "node:child_process";
|
|
8487
|
+
function createHostRunner(options = {}) {
|
|
8488
|
+
const detached = options.detached === true;
|
|
8489
|
+
return {
|
|
8490
|
+
name: "host",
|
|
8491
|
+
exec(spec) {
|
|
8492
|
+
const stdinMode = spec.stdin ?? "ignore";
|
|
8493
|
+
const stdoutMode = spec.stdout ?? "pipe";
|
|
8494
|
+
const stderrMode = spec.stderr ?? "pipe";
|
|
8495
|
+
const child = childProcess2.spawn(spec.command, spec.args ?? [], {
|
|
8496
|
+
cwd: spec.cwd,
|
|
8497
|
+
env: spec.env,
|
|
8498
|
+
stdio: [stdinMode, stdoutMode, stderrMode],
|
|
8499
|
+
...detached ? { detached: true } : {}
|
|
8500
|
+
});
|
|
8501
|
+
if (detached) {
|
|
8502
|
+
child.unref();
|
|
8503
|
+
}
|
|
8504
|
+
const kill = (signal) => {
|
|
8505
|
+
if (detached && process.platform !== "win32" && child.pid !== void 0) {
|
|
8506
|
+
process.kill(-child.pid, signal);
|
|
8507
|
+
return;
|
|
8508
|
+
}
|
|
8509
|
+
child.kill(signal);
|
|
8510
|
+
};
|
|
8511
|
+
let resolveResult = null;
|
|
8512
|
+
const result = new Promise((resolve) => {
|
|
8513
|
+
resolveResult = resolve;
|
|
8514
|
+
});
|
|
8515
|
+
const cleanupAbort = bindAbortSignal2(spec.signal, () => {
|
|
8516
|
+
kill("SIGTERM");
|
|
8517
|
+
});
|
|
8518
|
+
child.once("close", (code) => {
|
|
8519
|
+
cleanupAbort();
|
|
8520
|
+
resolveResult?.({ exitCode: code ?? 1 });
|
|
8521
|
+
});
|
|
8522
|
+
return {
|
|
8523
|
+
pid: child.pid ?? null,
|
|
8524
|
+
stdin: child.stdin,
|
|
8525
|
+
stdout: child.stdout,
|
|
8526
|
+
stderr: child.stderr,
|
|
8527
|
+
result,
|
|
8528
|
+
kill
|
|
8529
|
+
};
|
|
8530
|
+
}
|
|
8531
|
+
};
|
|
8532
|
+
}
|
|
8533
|
+
function bindAbortSignal2(signal, onAbort) {
|
|
8534
|
+
if (signal === void 0) {
|
|
8535
|
+
return () => {
|
|
8536
|
+
};
|
|
8537
|
+
}
|
|
8538
|
+
if (signal.aborted) {
|
|
8539
|
+
onAbort();
|
|
8540
|
+
return () => {
|
|
8541
|
+
};
|
|
8542
|
+
}
|
|
8543
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
8544
|
+
return () => {
|
|
8545
|
+
signal.removeEventListener("abort", onAbort);
|
|
8546
|
+
};
|
|
8547
|
+
}
|
|
8548
|
+
var init_host_runner = __esm({
|
|
8549
|
+
"packages/process-runner/src/host/host-runner.ts"() {
|
|
8550
|
+
"use strict";
|
|
8551
|
+
}
|
|
8552
|
+
});
|
|
8553
|
+
|
|
8554
|
+
// packages/process-runner/src/testing/mock-runner.ts
|
|
8555
|
+
import { Readable, Writable } from "node:stream";
|
|
8556
|
+
var init_mock_runner = __esm({
|
|
8557
|
+
"packages/process-runner/src/testing/mock-runner.ts"() {
|
|
8558
|
+
"use strict";
|
|
8559
|
+
}
|
|
8560
|
+
});
|
|
8561
|
+
|
|
8562
|
+
// packages/process-runner/src/testing/index.ts
|
|
8563
|
+
var init_testing = __esm({
|
|
8564
|
+
"packages/process-runner/src/testing/index.ts"() {
|
|
8565
|
+
"use strict";
|
|
8566
|
+
init_mock_runner();
|
|
8567
|
+
}
|
|
8568
|
+
});
|
|
8569
|
+
|
|
8570
|
+
// packages/process-runner/src/index.ts
|
|
8571
|
+
var init_src9 = __esm({
|
|
8572
|
+
"packages/process-runner/src/index.ts"() {
|
|
8573
|
+
"use strict";
|
|
8574
|
+
init_context2();
|
|
8575
|
+
init_engine();
|
|
8576
|
+
init_docker_runner();
|
|
8577
|
+
init_host_runner();
|
|
8578
|
+
init_testing();
|
|
8579
|
+
}
|
|
8580
|
+
});
|
|
8581
|
+
|
|
8582
|
+
// packages/process-launcher/src/supervisor/supervisor.ts
|
|
8583
|
+
import path18 from "node:path";
|
|
8584
|
+
function createSupervisor(options) {
|
|
8585
|
+
const { spec } = options;
|
|
8586
|
+
const runner = resolveRunner(options);
|
|
8587
|
+
const stateStore = createStateStore(options.stateDir, options.fs);
|
|
8588
|
+
const logWriter = createLogWriter(
|
|
8589
|
+
path18.join(options.stateDir, spec.id, "logs"),
|
|
8590
|
+
spec.logRetainCount ?? 5,
|
|
8591
|
+
options.fs
|
|
8592
|
+
);
|
|
8593
|
+
const logSource = createLogSource(options.onLog);
|
|
8594
|
+
let state = createInitialState(spec, runner);
|
|
8595
|
+
let handle = null;
|
|
8596
|
+
let runId = 0;
|
|
8597
|
+
let startPromise = null;
|
|
8598
|
+
let pendingRestart = null;
|
|
8599
|
+
let activeReadyController = null;
|
|
8600
|
+
let stableTimer = null;
|
|
8601
|
+
let stopRequested = false;
|
|
8602
|
+
const onAbort = () => {
|
|
8603
|
+
void stop();
|
|
8604
|
+
};
|
|
8605
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
8606
|
+
async function start() {
|
|
8607
|
+
if (handle !== null || pendingRestart !== null) {
|
|
8608
|
+
return;
|
|
8609
|
+
}
|
|
8610
|
+
if (startPromise !== null) {
|
|
8611
|
+
await startPromise;
|
|
8612
|
+
return;
|
|
8613
|
+
}
|
|
8614
|
+
stopRequested = false;
|
|
8615
|
+
startPromise = launch(false);
|
|
8616
|
+
try {
|
|
8617
|
+
await startPromise;
|
|
8618
|
+
} finally {
|
|
8619
|
+
startPromise = null;
|
|
8620
|
+
}
|
|
8621
|
+
}
|
|
8622
|
+
async function stop() {
|
|
8623
|
+
stopRequested = true;
|
|
8624
|
+
pendingRestart = null;
|
|
8625
|
+
activeReadyController?.abort();
|
|
8626
|
+
activeReadyController = null;
|
|
8627
|
+
const activeHandle = handle;
|
|
8628
|
+
if (activeHandle !== null) {
|
|
8629
|
+
activeHandle.kill("SIGTERM");
|
|
8630
|
+
const exited = await waitForExit(activeHandle, 5e3);
|
|
8631
|
+
if (!exited) {
|
|
8632
|
+
activeHandle.kill("SIGKILL");
|
|
8633
|
+
await activeHandle.result;
|
|
8634
|
+
}
|
|
8635
|
+
}
|
|
8636
|
+
clearStableTimer();
|
|
8637
|
+
handle = null;
|
|
8638
|
+
state.pid = null;
|
|
8639
|
+
state.lastStoppedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
8640
|
+
await transitionTo("stopped");
|
|
8641
|
+
}
|
|
8642
|
+
async function restart() {
|
|
8643
|
+
await stop();
|
|
8644
|
+
await start();
|
|
8645
|
+
}
|
|
8646
|
+
function getState() {
|
|
8647
|
+
return {
|
|
8648
|
+
...state,
|
|
8649
|
+
args: [...state.args]
|
|
8650
|
+
};
|
|
8651
|
+
}
|
|
8652
|
+
async function launch(isRestart) {
|
|
8653
|
+
const nextRunId = runId + 1;
|
|
8654
|
+
runId = nextRunId;
|
|
8655
|
+
const nextHandle = runner.exec(createRunSpec(spec));
|
|
8656
|
+
handle = nextHandle;
|
|
8657
|
+
state.pid = nextHandle.pid;
|
|
8658
|
+
state.lastExitCode = null;
|
|
8659
|
+
state.lastStartedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
8660
|
+
const stdoutPump = pipeOutput(nextHandle.stdout, "stdout", logWriter.write, logSource);
|
|
8661
|
+
const stderrPump = pipeOutput(nextHandle.stderr, "stderr", logWriter.write, logSource);
|
|
8662
|
+
const outputSettled = Promise.all([stdoutPump, stderrPump]).then(() => void 0);
|
|
8663
|
+
scheduleStableReset(nextRunId, nextHandle);
|
|
8664
|
+
void monitorExit(nextHandle, nextRunId, outputSettled);
|
|
8665
|
+
if (spec.readyCheck !== void 0) {
|
|
8666
|
+
await transitionTo("restarting");
|
|
8667
|
+
activeReadyController = new AbortController();
|
|
8668
|
+
const ready = await waitForReady(resolveReadyCheck(spec.readyCheck, spec), {
|
|
8669
|
+
onLog: logSource,
|
|
8670
|
+
signal: activeReadyController.signal
|
|
8671
|
+
});
|
|
8672
|
+
activeReadyController = null;
|
|
8673
|
+
if (runId !== nextRunId || handle !== nextHandle) {
|
|
8674
|
+
return;
|
|
8675
|
+
}
|
|
8676
|
+
if (!ready) {
|
|
8677
|
+
nextHandle.kill("SIGTERM");
|
|
8678
|
+
return;
|
|
8679
|
+
}
|
|
8680
|
+
}
|
|
8681
|
+
if (isRestart || spec.readyCheck !== void 0) {
|
|
8682
|
+
await transitionTo("running");
|
|
8683
|
+
return;
|
|
8684
|
+
}
|
|
8685
|
+
await transitionTo("running");
|
|
8686
|
+
}
|
|
8687
|
+
async function monitorExit(finishedHandle, finishedRunId, outputSettled) {
|
|
8688
|
+
const result = await finishedHandle.result;
|
|
8689
|
+
await outputSettled;
|
|
8690
|
+
if (runId !== finishedRunId) {
|
|
8691
|
+
return;
|
|
8692
|
+
}
|
|
8693
|
+
clearStableTimer();
|
|
8694
|
+
activeReadyController?.abort();
|
|
8695
|
+
activeReadyController = null;
|
|
8696
|
+
handle = null;
|
|
8697
|
+
state.pid = null;
|
|
8698
|
+
state.lastExitCode = result.exitCode;
|
|
8699
|
+
state.lastStoppedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
8700
|
+
if (stopRequested || options.signal?.aborted) {
|
|
8701
|
+
await transitionTo("stopped");
|
|
8702
|
+
return;
|
|
8703
|
+
}
|
|
8704
|
+
if (!shouldRestart(result.exitCode, spec.restart)) {
|
|
8705
|
+
await transitionTo("stopped");
|
|
8706
|
+
return;
|
|
8707
|
+
}
|
|
8708
|
+
const maxRestarts = spec.maxRestarts ?? 5;
|
|
8709
|
+
if (maxRestarts > 0 && state.restartCount >= maxRestarts) {
|
|
8710
|
+
await transitionTo("crashed");
|
|
8711
|
+
return;
|
|
8712
|
+
}
|
|
8713
|
+
const backoffMs = getBackoffDelay(
|
|
8714
|
+
state.restartCount,
|
|
8715
|
+
spec.backoffMs ?? 1e3,
|
|
8716
|
+
spec.maxBackoffMs ?? 3e4
|
|
8717
|
+
);
|
|
8718
|
+
state.restartCount += 1;
|
|
8719
|
+
await logWriter.rotate();
|
|
8720
|
+
await transitionTo("restarting");
|
|
8721
|
+
const restartToken = /* @__PURE__ */ Symbol("restart");
|
|
8722
|
+
pendingRestart = restartToken;
|
|
8723
|
+
await delay(backoffMs);
|
|
8724
|
+
if (pendingRestart !== restartToken || stopRequested || options.signal?.aborted) {
|
|
8725
|
+
return;
|
|
8726
|
+
}
|
|
8727
|
+
pendingRestart = null;
|
|
8728
|
+
await launch(true);
|
|
8729
|
+
}
|
|
8730
|
+
async function transitionTo(status) {
|
|
8731
|
+
if (state.status === status) {
|
|
8732
|
+
return;
|
|
8733
|
+
}
|
|
8734
|
+
state = {
|
|
8735
|
+
...state,
|
|
8736
|
+
args: [...state.args],
|
|
8737
|
+
status
|
|
8738
|
+
};
|
|
8739
|
+
await stateStore.write(spec.id, state);
|
|
8740
|
+
options.onStatusChange?.(getState());
|
|
8741
|
+
}
|
|
8742
|
+
function scheduleStableReset(activeRunId, activeHandle) {
|
|
8743
|
+
clearStableTimer();
|
|
8744
|
+
stableTimer = setTimeout(() => {
|
|
8745
|
+
if (runId !== activeRunId || handle !== activeHandle || state.restartCount === 0) {
|
|
8746
|
+
return;
|
|
8747
|
+
}
|
|
8748
|
+
state.restartCount = 0;
|
|
8749
|
+
void stateStore.write(spec.id, getState());
|
|
8750
|
+
}, 6e4);
|
|
8751
|
+
}
|
|
8752
|
+
function clearStableTimer() {
|
|
8753
|
+
if (stableTimer !== null) {
|
|
8754
|
+
clearTimeout(stableTimer);
|
|
8755
|
+
stableTimer = null;
|
|
8756
|
+
}
|
|
8757
|
+
}
|
|
8758
|
+
return {
|
|
8759
|
+
start,
|
|
8760
|
+
stop,
|
|
8761
|
+
restart,
|
|
8762
|
+
getState
|
|
8763
|
+
};
|
|
8764
|
+
}
|
|
8765
|
+
function resolveRunner(options) {
|
|
8766
|
+
if (options.runner !== void 0) {
|
|
8767
|
+
return options.runner;
|
|
8768
|
+
}
|
|
8769
|
+
if (options.spec.docker !== void 0) {
|
|
8770
|
+
return createDockerRunner(options.spec.docker);
|
|
8771
|
+
}
|
|
8772
|
+
return createHostRunner();
|
|
8773
|
+
}
|
|
8774
|
+
function createInitialState(spec, runner) {
|
|
8775
|
+
return {
|
|
8776
|
+
id: spec.id,
|
|
8777
|
+
pid: null,
|
|
8778
|
+
status: "stopped",
|
|
8779
|
+
runtime: spec.docker !== void 0 || runner.name === "docker" ? "docker" : "host",
|
|
8780
|
+
restartCount: 0,
|
|
8781
|
+
lastExitCode: null,
|
|
8782
|
+
lastStartedAt: null,
|
|
8783
|
+
lastStoppedAt: null,
|
|
8784
|
+
command: spec.command,
|
|
8785
|
+
args: [...spec.args ?? []]
|
|
8786
|
+
};
|
|
8787
|
+
}
|
|
8788
|
+
function createRunSpec(spec) {
|
|
8789
|
+
return {
|
|
8790
|
+
command: spec.command,
|
|
8791
|
+
args: spec.args,
|
|
8792
|
+
cwd: spec.cwd,
|
|
8793
|
+
env: spec.env,
|
|
8794
|
+
stderr: "pipe",
|
|
8795
|
+
stdout: "pipe"
|
|
8796
|
+
};
|
|
8797
|
+
}
|
|
8798
|
+
function shouldRestart(exitCode, policy) {
|
|
8799
|
+
if (policy === "always") {
|
|
8800
|
+
return true;
|
|
8801
|
+
}
|
|
8802
|
+
if (policy === "on-failure") {
|
|
8803
|
+
return exitCode !== 0;
|
|
8804
|
+
}
|
|
8805
|
+
return false;
|
|
8806
|
+
}
|
|
8807
|
+
function getBackoffDelay(restartCount, backoffMs, maxBackoffMs) {
|
|
8808
|
+
return Math.min(backoffMs * 2 ** restartCount, maxBackoffMs);
|
|
8809
|
+
}
|
|
8810
|
+
function delay(durationMs) {
|
|
8811
|
+
return new Promise((resolve) => {
|
|
8812
|
+
setTimeout(resolve, durationMs);
|
|
8813
|
+
});
|
|
8814
|
+
}
|
|
8815
|
+
function waitForExit(activeHandle, timeoutMs) {
|
|
8816
|
+
return new Promise((resolve) => {
|
|
8817
|
+
let finished = false;
|
|
8818
|
+
const timeout = setTimeout(() => {
|
|
8819
|
+
finish(false);
|
|
8820
|
+
}, timeoutMs);
|
|
8821
|
+
void activeHandle.result.then(() => {
|
|
8822
|
+
finish(true);
|
|
8823
|
+
});
|
|
8824
|
+
function finish(result) {
|
|
8825
|
+
if (finished) {
|
|
8826
|
+
return;
|
|
8827
|
+
}
|
|
8828
|
+
finished = true;
|
|
8829
|
+
clearTimeout(timeout);
|
|
8830
|
+
resolve(result);
|
|
8831
|
+
}
|
|
8832
|
+
});
|
|
8833
|
+
}
|
|
8834
|
+
function createLogSource(onLog) {
|
|
8835
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
8836
|
+
const log3 = ((line, stream) => {
|
|
8837
|
+
onLog?.(line, stream);
|
|
8838
|
+
for (const listener of listeners) {
|
|
8839
|
+
listener(line, stream);
|
|
8840
|
+
}
|
|
8841
|
+
});
|
|
8842
|
+
log3.subscribe = (listener) => {
|
|
8843
|
+
listeners.add(listener);
|
|
8844
|
+
return () => {
|
|
8845
|
+
listeners.delete(listener);
|
|
8846
|
+
};
|
|
8847
|
+
};
|
|
8848
|
+
return log3;
|
|
8849
|
+
}
|
|
8850
|
+
function pipeOutput(stream, output, write2, onLog) {
|
|
8851
|
+
if (stream === null) {
|
|
8852
|
+
return Promise.resolve();
|
|
8853
|
+
}
|
|
8854
|
+
return new Promise((resolve, reject) => {
|
|
8855
|
+
let remainder = "";
|
|
8856
|
+
let writes = Promise.resolve();
|
|
8857
|
+
stream.setEncoding("utf8");
|
|
8858
|
+
stream.on("data", (chunk) => {
|
|
8859
|
+
remainder += chunk;
|
|
8860
|
+
while (true) {
|
|
8861
|
+
const lineBreak = remainder.indexOf("\n");
|
|
8862
|
+
if (lineBreak === -1) {
|
|
8863
|
+
break;
|
|
8864
|
+
}
|
|
8865
|
+
const rawLine = remainder.slice(0, lineBreak);
|
|
8866
|
+
remainder = remainder.slice(lineBreak + 1);
|
|
8867
|
+
writes = writes.then(async () => {
|
|
8868
|
+
const line = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
|
|
8869
|
+
onLog(line, output);
|
|
8870
|
+
await write2(line, output);
|
|
8871
|
+
});
|
|
8872
|
+
}
|
|
8873
|
+
});
|
|
8874
|
+
stream.once("end", () => {
|
|
8875
|
+
if (remainder.length > 0) {
|
|
8876
|
+
const finalLine = remainder.endsWith("\r") ? remainder.slice(0, -1) : remainder;
|
|
8877
|
+
writes = writes.then(async () => {
|
|
8878
|
+
onLog(finalLine, output);
|
|
8879
|
+
await write2(finalLine, output);
|
|
8880
|
+
});
|
|
8881
|
+
}
|
|
8882
|
+
void writes.then(() => {
|
|
8883
|
+
resolve();
|
|
8884
|
+
}, reject);
|
|
8885
|
+
});
|
|
8886
|
+
stream.once("error", reject);
|
|
8887
|
+
});
|
|
8888
|
+
}
|
|
8889
|
+
function resolveReadyCheck(check, spec) {
|
|
8890
|
+
if (check.kind !== "tcp" || spec.docker === void 0) {
|
|
8891
|
+
return check;
|
|
8892
|
+
}
|
|
8893
|
+
const portMapping = spec.docker.ports?.find((mapping) => {
|
|
8894
|
+
if (mapping.container !== check.port) {
|
|
8895
|
+
return false;
|
|
8896
|
+
}
|
|
8897
|
+
return mapping.protocol === void 0 || mapping.protocol === "tcp";
|
|
8898
|
+
});
|
|
8899
|
+
if (portMapping === void 0) {
|
|
8900
|
+
return check;
|
|
8901
|
+
}
|
|
8902
|
+
return {
|
|
8903
|
+
...check,
|
|
8904
|
+
port: portMapping.host
|
|
8905
|
+
};
|
|
8906
|
+
}
|
|
8907
|
+
var init_supervisor = __esm({
|
|
8908
|
+
"packages/process-launcher/src/supervisor/supervisor.ts"() {
|
|
8909
|
+
"use strict";
|
|
8910
|
+
init_src9();
|
|
8911
|
+
init_health_check();
|
|
8912
|
+
init_log_writer();
|
|
8913
|
+
init_state_store();
|
|
8914
|
+
}
|
|
8915
|
+
});
|
|
8916
|
+
|
|
8917
|
+
// packages/process-launcher/src/launcher.ts
|
|
8918
|
+
import path19 from "node:path";
|
|
8919
|
+
import * as nodeFs3 from "node:fs/promises";
|
|
8920
|
+
async function startManagedProcess(options) {
|
|
8921
|
+
const fs3 = options.fs ?? defaultFs();
|
|
8922
|
+
const spec = normalizeSpec(options.spec);
|
|
8923
|
+
const existing = await readManagedProcess({
|
|
8924
|
+
baseDir: options.baseDir,
|
|
8925
|
+
fs: fs3,
|
|
8926
|
+
id: spec.id,
|
|
8927
|
+
isPidRunning: options.isPidRunning
|
|
8928
|
+
});
|
|
8929
|
+
if (isActiveRecord(existing)) {
|
|
8930
|
+
throw new Error(`Managed process "${spec.id}" is already running.`);
|
|
8931
|
+
}
|
|
8932
|
+
await fs3.mkdir(resolveProcessDir(options.baseDir, spec.id), { recursive: true });
|
|
8933
|
+
await writeSpec(fs3, options.baseDir, spec);
|
|
8934
|
+
await writeState(fs3, options.baseDir, createBootstrapState(spec));
|
|
8935
|
+
await writeMeta(fs3, options.baseDir, spec.id, { daemonPid: null });
|
|
8936
|
+
const daemonPid = await options.spawnDaemon(spec.id);
|
|
8937
|
+
await writeMeta(fs3, options.baseDir, spec.id, { daemonPid });
|
|
8938
|
+
const started = await waitForRecord({
|
|
8939
|
+
baseDir: options.baseDir,
|
|
8940
|
+
fs: fs3,
|
|
8941
|
+
id: spec.id,
|
|
8942
|
+
isPidRunning: options.isPidRunning,
|
|
8943
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
8944
|
+
timeoutMs: options.startupTimeoutMs,
|
|
8945
|
+
ready: (record) => record.state !== null && record.state.status !== "restarting"
|
|
8946
|
+
});
|
|
8947
|
+
return started;
|
|
8948
|
+
}
|
|
8949
|
+
async function stopManagedProcess(options) {
|
|
8950
|
+
const fs3 = options.fs ?? defaultFs();
|
|
8951
|
+
const record = await readManagedProcess({
|
|
8952
|
+
baseDir: options.baseDir,
|
|
8953
|
+
fs: fs3,
|
|
8954
|
+
id: options.id,
|
|
8955
|
+
isPidRunning: options.isPidRunning
|
|
8956
|
+
});
|
|
8957
|
+
if (record.spec === null && record.state === null && record.daemonPid === null) {
|
|
8958
|
+
return null;
|
|
8959
|
+
}
|
|
8960
|
+
const signal = options.force ? "SIGKILL" : "SIGTERM";
|
|
8961
|
+
const signalProcess = options.signalProcess ?? defaultSignalProcess;
|
|
8962
|
+
const daemonPid = record.daemonPid;
|
|
8963
|
+
if (daemonPid !== null && isProcessRunning(daemonPid, options.isPidRunning)) {
|
|
8964
|
+
signalProcess(daemonPid, signal);
|
|
8965
|
+
} else if (record.state?.runtime === "host" && record.state.pid !== null) {
|
|
8966
|
+
if (isProcessRunning(record.state.pid, options.isPidRunning)) {
|
|
8967
|
+
signalProcess(record.state.pid, signal);
|
|
8968
|
+
}
|
|
8969
|
+
}
|
|
8970
|
+
if (record.spec?.docker && options.stopRuntimeArtifacts) {
|
|
8971
|
+
await options.stopRuntimeArtifacts({ record, force: Boolean(options.force) });
|
|
8972
|
+
}
|
|
8973
|
+
const stopped = await waitForStop({
|
|
8974
|
+
baseDir: options.baseDir,
|
|
8975
|
+
fs: fs3,
|
|
8976
|
+
id: options.id,
|
|
8977
|
+
isPidRunning: options.isPidRunning,
|
|
8978
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
8979
|
+
timeoutMs: options.stopTimeoutMs
|
|
8980
|
+
});
|
|
8981
|
+
if (isActiveRecord(stopped)) {
|
|
8982
|
+
const persisted = createStoppedState(stopped);
|
|
8983
|
+
await writeState(fs3, options.baseDir, persisted);
|
|
8984
|
+
await writeMeta(fs3, options.baseDir, options.id, { daemonPid: null });
|
|
8985
|
+
return {
|
|
8986
|
+
...stopped,
|
|
8987
|
+
daemonPid: null,
|
|
8988
|
+
state: persisted
|
|
8989
|
+
};
|
|
8990
|
+
}
|
|
8991
|
+
if (record.state !== null && isActiveStatus(record.state.status) && stopped.state !== null && !isActiveStatus(stopped.state.status)) {
|
|
8992
|
+
await writeState(fs3, options.baseDir, stopped.state);
|
|
8993
|
+
await writeMeta(fs3, options.baseDir, options.id, { daemonPid: null });
|
|
8994
|
+
}
|
|
8995
|
+
return stopped;
|
|
8996
|
+
}
|
|
8997
|
+
async function restartManagedProcess(options) {
|
|
8998
|
+
const fs3 = options.fs ?? defaultFs();
|
|
8999
|
+
const record = await readManagedProcess({
|
|
9000
|
+
baseDir: options.baseDir,
|
|
9001
|
+
fs: fs3,
|
|
9002
|
+
id: options.id,
|
|
9003
|
+
isPidRunning: options.isPidRunning
|
|
9004
|
+
});
|
|
9005
|
+
if (record.spec === null) {
|
|
9006
|
+
throw new Error(`Managed process "${options.id}" was not found.`);
|
|
9007
|
+
}
|
|
9008
|
+
await stopManagedProcess({
|
|
9009
|
+
baseDir: options.baseDir,
|
|
9010
|
+
force: false,
|
|
9011
|
+
fs: fs3,
|
|
9012
|
+
id: options.id,
|
|
9013
|
+
isPidRunning: options.isPidRunning,
|
|
9014
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
9015
|
+
signalProcess: options.signalProcess,
|
|
9016
|
+
stopRuntimeArtifacts: options.stopRuntimeArtifacts,
|
|
9017
|
+
stopTimeoutMs: options.stopTimeoutMs
|
|
9018
|
+
});
|
|
9019
|
+
return await startManagedProcess({
|
|
9020
|
+
baseDir: options.baseDir,
|
|
9021
|
+
fs: fs3,
|
|
9022
|
+
isPidRunning: options.isPidRunning,
|
|
9023
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
9024
|
+
spawnDaemon: options.spawnDaemon,
|
|
9025
|
+
spec: record.spec,
|
|
9026
|
+
startupTimeoutMs: options.startupTimeoutMs
|
|
9027
|
+
});
|
|
9028
|
+
}
|
|
9029
|
+
async function listManagedProcesses(options) {
|
|
9030
|
+
const fs3 = options.fs ?? defaultFs();
|
|
9031
|
+
const ids = await listIds(fs3, options.baseDir);
|
|
9032
|
+
const records = [];
|
|
9033
|
+
for (const id of ids) {
|
|
9034
|
+
records.push(
|
|
9035
|
+
await readManagedProcess({
|
|
9036
|
+
baseDir: options.baseDir,
|
|
9037
|
+
fs: fs3,
|
|
9038
|
+
id,
|
|
9039
|
+
isPidRunning: options.isPidRunning
|
|
9040
|
+
})
|
|
9041
|
+
);
|
|
9042
|
+
}
|
|
9043
|
+
return records.sort((left, right) => {
|
|
9044
|
+
const leftId = left.spec?.id ?? left.state?.id ?? "";
|
|
9045
|
+
const rightId = right.spec?.id ?? right.state?.id ?? "";
|
|
9046
|
+
return leftId.localeCompare(rightId);
|
|
9047
|
+
});
|
|
9048
|
+
}
|
|
9049
|
+
async function readManagedLogs(options) {
|
|
9050
|
+
const fs3 = options.fs ?? defaultFs();
|
|
9051
|
+
const logWriter = createLogWriter(
|
|
9052
|
+
resolveLogDir2(options.baseDir, options.id),
|
|
9053
|
+
5,
|
|
9054
|
+
fs3
|
|
9055
|
+
);
|
|
9056
|
+
return await logWriter.tail(options.stream ?? "stdout", options.lines ?? 50);
|
|
9057
|
+
}
|
|
9058
|
+
async function* followManagedLogs(options) {
|
|
9059
|
+
const stream = options.stream ?? "stdout";
|
|
9060
|
+
let previous = await readManagedLogs(options);
|
|
9061
|
+
const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
9062
|
+
while (!options.signal?.aborted) {
|
|
9063
|
+
await sleep2(pollIntervalMs);
|
|
9064
|
+
if (options.signal?.aborted) {
|
|
9065
|
+
return;
|
|
9066
|
+
}
|
|
9067
|
+
const next = await readManagedLogs({
|
|
9068
|
+
baseDir: options.baseDir,
|
|
9069
|
+
fs: options.fs,
|
|
9070
|
+
id: options.id,
|
|
9071
|
+
lines: options.lines,
|
|
9072
|
+
stream
|
|
9073
|
+
});
|
|
9074
|
+
const delta = next.slice(previous.length);
|
|
9075
|
+
previous = next;
|
|
9076
|
+
for (const line of delta) {
|
|
9077
|
+
yield line;
|
|
9078
|
+
}
|
|
9079
|
+
}
|
|
9080
|
+
}
|
|
9081
|
+
async function removeManagedProcess(options) {
|
|
9082
|
+
const fs3 = options.fs ?? defaultFs();
|
|
9083
|
+
const record = await readManagedProcess({
|
|
9084
|
+
baseDir: options.baseDir,
|
|
9085
|
+
fs: fs3,
|
|
9086
|
+
id: options.id,
|
|
9087
|
+
isPidRunning: options.isPidRunning
|
|
9088
|
+
});
|
|
9089
|
+
if (isActiveRecord(record)) {
|
|
9090
|
+
throw new Error(`Managed process "${options.id}" must be stopped before removal.`);
|
|
9091
|
+
}
|
|
9092
|
+
if (record.spec !== null && options.removeRuntimeArtifacts) {
|
|
9093
|
+
await options.removeRuntimeArtifacts({ record });
|
|
9094
|
+
}
|
|
9095
|
+
const stateStore = createStateStore(options.baseDir, fs3);
|
|
9096
|
+
await stateStore.remove(options.id);
|
|
9097
|
+
}
|
|
9098
|
+
async function runManagedProcess(options) {
|
|
9099
|
+
const fs3 = options.fs ?? defaultFs();
|
|
9100
|
+
const spec = await readSpec(fs3, options.baseDir, options.id);
|
|
9101
|
+
if (spec === null) {
|
|
9102
|
+
throw new Error(`Managed process "${options.id}" was not found.`);
|
|
9103
|
+
}
|
|
9104
|
+
const controller = new AbortController();
|
|
9105
|
+
const onExternalAbort = () => {
|
|
9106
|
+
controller.abort();
|
|
9107
|
+
};
|
|
9108
|
+
options.signal?.addEventListener("abort", onExternalAbort, { once: true });
|
|
9109
|
+
const onSignal = () => {
|
|
9110
|
+
controller.abort();
|
|
9111
|
+
};
|
|
9112
|
+
process.once("SIGINT", onSignal);
|
|
9113
|
+
process.once("SIGTERM", onSignal);
|
|
9114
|
+
try {
|
|
9115
|
+
await writeMeta(fs3, options.baseDir, options.id, { daemonPid: process.pid });
|
|
9116
|
+
const supervisor = createSupervisor({
|
|
9117
|
+
fs: fs3,
|
|
9118
|
+
signal: controller.signal,
|
|
9119
|
+
spec,
|
|
9120
|
+
stateDir: options.baseDir
|
|
9121
|
+
});
|
|
9122
|
+
await supervisor.start();
|
|
9123
|
+
const pollIntervalMs = options.pollIntervalMs ?? 250;
|
|
9124
|
+
while (!controller.signal.aborted) {
|
|
9125
|
+
const state = supervisor.getState();
|
|
9126
|
+
if (!isActiveStatus(state.status) && state.pid === null) {
|
|
9127
|
+
return;
|
|
9128
|
+
}
|
|
9129
|
+
await sleep2(pollIntervalMs);
|
|
9130
|
+
}
|
|
9131
|
+
await supervisor.stop();
|
|
9132
|
+
} finally {
|
|
9133
|
+
process.removeListener("SIGINT", onSignal);
|
|
9134
|
+
process.removeListener("SIGTERM", onSignal);
|
|
9135
|
+
options.signal?.removeEventListener("abort", onExternalAbort);
|
|
9136
|
+
await writeMeta(fs3, options.baseDir, options.id, { daemonPid: null });
|
|
9137
|
+
}
|
|
9138
|
+
}
|
|
9139
|
+
async function waitForRecord(options) {
|
|
9140
|
+
const deadline = Date.now() + (options.timeoutMs ?? DEFAULT_STARTUP_TIMEOUT_MS);
|
|
9141
|
+
while (Date.now() <= deadline) {
|
|
9142
|
+
const record = await readManagedProcess(options);
|
|
9143
|
+
if (options.ready(record)) {
|
|
9144
|
+
return record;
|
|
9145
|
+
}
|
|
9146
|
+
await sleep2(options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);
|
|
9147
|
+
}
|
|
9148
|
+
throw new Error(`Timed out waiting for managed process "${options.id}".`);
|
|
9149
|
+
}
|
|
9150
|
+
async function waitForStop(options) {
|
|
9151
|
+
const deadline = Date.now() + (options.timeoutMs ?? DEFAULT_STOP_TIMEOUT_MS);
|
|
9152
|
+
while (Date.now() <= deadline) {
|
|
9153
|
+
const record = await readManagedProcess(options);
|
|
9154
|
+
if (!isActiveRecord(record)) {
|
|
9155
|
+
return record;
|
|
9156
|
+
}
|
|
9157
|
+
await sleep2(options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);
|
|
9158
|
+
}
|
|
9159
|
+
return await readManagedProcess(options);
|
|
9160
|
+
}
|
|
9161
|
+
async function readManagedProcess(options) {
|
|
9162
|
+
const spec = await readSpec(options.fs, options.baseDir, options.id);
|
|
9163
|
+
const state = await readState(options.fs, options.baseDir, options.id);
|
|
9164
|
+
const meta = await readMeta(options.fs, options.baseDir, options.id);
|
|
9165
|
+
return normalizeRecord(
|
|
9166
|
+
{ daemonPid: meta?.daemonPid ?? null, spec, state },
|
|
9167
|
+
options.isPidRunning
|
|
9168
|
+
);
|
|
9169
|
+
}
|
|
9170
|
+
function normalizeRecord(record, isPidRunningOverride) {
|
|
9171
|
+
if (record.state === null || !isActiveStatus(record.state.status)) {
|
|
9172
|
+
return {
|
|
9173
|
+
...record,
|
|
9174
|
+
daemonPid: isProcessRunning(record.daemonPid, isPidRunningOverride) ? record.daemonPid : null
|
|
9175
|
+
};
|
|
9176
|
+
}
|
|
9177
|
+
if (isProcessRunning(record.daemonPid, isPidRunningOverride)) {
|
|
9178
|
+
return record;
|
|
9179
|
+
}
|
|
9180
|
+
return {
|
|
9181
|
+
...record,
|
|
9182
|
+
daemonPid: null,
|
|
9183
|
+
state: createStoppedState(record)
|
|
9184
|
+
};
|
|
9185
|
+
}
|
|
9186
|
+
function createStoppedState(record) {
|
|
9187
|
+
const spec = record.spec;
|
|
9188
|
+
const state = record.state;
|
|
9189
|
+
if (state !== null) {
|
|
9190
|
+
return {
|
|
9191
|
+
...state,
|
|
9192
|
+
pid: null,
|
|
9193
|
+
status: state.lastExitCode != null && state.lastExitCode !== 0 ? "crashed" : "stopped",
|
|
9194
|
+
lastStoppedAt: state.lastStoppedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
9195
|
+
};
|
|
9196
|
+
}
|
|
9197
|
+
if (spec === null) {
|
|
9198
|
+
throw new Error("Cannot create a stopped state without spec or state.");
|
|
9199
|
+
}
|
|
9200
|
+
return {
|
|
9201
|
+
args: [...spec.args ?? []],
|
|
9202
|
+
command: spec.command,
|
|
9203
|
+
id: spec.id,
|
|
9204
|
+
lastExitCode: null,
|
|
9205
|
+
lastStartedAt: null,
|
|
9206
|
+
lastStoppedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9207
|
+
pid: null,
|
|
9208
|
+
restartCount: 0,
|
|
9209
|
+
runtime: spec.docker ? "docker" : "host",
|
|
9210
|
+
status: "stopped"
|
|
9211
|
+
};
|
|
9212
|
+
}
|
|
9213
|
+
function createBootstrapState(spec) {
|
|
9214
|
+
return {
|
|
9215
|
+
args: [...spec.args ?? []],
|
|
9216
|
+
command: spec.command,
|
|
9217
|
+
id: spec.id,
|
|
9218
|
+
lastExitCode: null,
|
|
9219
|
+
lastStartedAt: null,
|
|
9220
|
+
lastStoppedAt: null,
|
|
9221
|
+
pid: null,
|
|
9222
|
+
restartCount: 0,
|
|
9223
|
+
runtime: spec.docker ? "docker" : "host",
|
|
9224
|
+
status: "restarting"
|
|
9225
|
+
};
|
|
9226
|
+
}
|
|
9227
|
+
function normalizeSpec(spec) {
|
|
9228
|
+
if (!spec.docker) {
|
|
9229
|
+
return {
|
|
9230
|
+
...spec,
|
|
9231
|
+
args: [...spec.args ?? []],
|
|
9232
|
+
env: spec.env ? { ...spec.env } : void 0
|
|
9233
|
+
};
|
|
9234
|
+
}
|
|
9235
|
+
return {
|
|
9236
|
+
...spec,
|
|
9237
|
+
args: [...spec.args ?? []],
|
|
9238
|
+
docker: {
|
|
9239
|
+
...spec.docker,
|
|
9240
|
+
containerName: spec.docker.containerName ?? buildContainerName2(spec.id),
|
|
9241
|
+
mounts: spec.docker.mounts ? [...spec.docker.mounts] : void 0,
|
|
9242
|
+
ports: spec.docker.ports ? [...spec.docker.ports] : void 0
|
|
9243
|
+
},
|
|
9244
|
+
env: spec.env ? { ...spec.env } : void 0
|
|
9245
|
+
};
|
|
9246
|
+
}
|
|
9247
|
+
function buildContainerName2(id) {
|
|
9248
|
+
let output = "poe-launch-";
|
|
9249
|
+
for (const char of id) {
|
|
9250
|
+
const code = char.charCodeAt(0);
|
|
9251
|
+
const isAlphaNumeric = code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122;
|
|
9252
|
+
output += isAlphaNumeric || char === "." || char === "_" || char === "-" ? char : "-";
|
|
9253
|
+
}
|
|
9254
|
+
return output;
|
|
9255
|
+
}
|
|
9256
|
+
function isActiveRecord(record) {
|
|
9257
|
+
return record.state !== null && isActiveStatus(record.state.status);
|
|
9258
|
+
}
|
|
9259
|
+
function isActiveStatus(status) {
|
|
9260
|
+
return status === "running" || status === "restarting";
|
|
9261
|
+
}
|
|
9262
|
+
async function listIds(fs3, baseDir) {
|
|
9263
|
+
try {
|
|
9264
|
+
const entries = await fs3.readdir(baseDir);
|
|
9265
|
+
const ids = [];
|
|
9266
|
+
for (const entry of entries) {
|
|
9267
|
+
const entryPath = path19.join(baseDir, entry);
|
|
9268
|
+
try {
|
|
9269
|
+
const stat11 = await fs3.stat(entryPath);
|
|
9270
|
+
if (!stat11.isFile()) {
|
|
9271
|
+
ids.push(entry);
|
|
9272
|
+
}
|
|
9273
|
+
} catch (error) {
|
|
9274
|
+
if (!isNotFoundError4(error)) {
|
|
9275
|
+
throw error;
|
|
9276
|
+
}
|
|
9277
|
+
}
|
|
9278
|
+
}
|
|
9279
|
+
return ids.sort();
|
|
9280
|
+
} catch (error) {
|
|
9281
|
+
if (isNotFoundError4(error)) {
|
|
9282
|
+
return [];
|
|
9283
|
+
}
|
|
9284
|
+
throw error;
|
|
9285
|
+
}
|
|
9286
|
+
}
|
|
9287
|
+
async function readSpec(fs3, baseDir, id) {
|
|
9288
|
+
return await readJsonFile(fs3, resolveSpecPath(baseDir, id));
|
|
9289
|
+
}
|
|
9290
|
+
async function writeSpec(fs3, baseDir, spec) {
|
|
9291
|
+
await writeJsonFile(fs3, resolveSpecPath(baseDir, spec.id), spec);
|
|
9292
|
+
}
|
|
9293
|
+
async function readState(fs3, baseDir, id) {
|
|
9294
|
+
return await readJsonFile(fs3, resolveStatePath(baseDir, id));
|
|
9295
|
+
}
|
|
9296
|
+
async function writeState(fs3, baseDir, state) {
|
|
9297
|
+
await writeJsonFile(fs3, resolveStatePath(baseDir, state.id), state);
|
|
9298
|
+
}
|
|
9299
|
+
async function readMeta(fs3, baseDir, id) {
|
|
9300
|
+
return await readJsonFile(fs3, resolveMetaPath(baseDir, id));
|
|
9301
|
+
}
|
|
9302
|
+
async function writeMeta(fs3, baseDir, id, meta) {
|
|
9303
|
+
await writeJsonFile(fs3, resolveMetaPath(baseDir, id), meta);
|
|
9304
|
+
}
|
|
9305
|
+
async function readJsonFile(fs3, filePath) {
|
|
9306
|
+
try {
|
|
9307
|
+
const content = await fs3.readFile(filePath, "utf8");
|
|
9308
|
+
return JSON.parse(content);
|
|
9309
|
+
} catch (error) {
|
|
9310
|
+
if (isNotFoundError4(error)) {
|
|
9311
|
+
return null;
|
|
9312
|
+
}
|
|
9313
|
+
throw error;
|
|
9314
|
+
}
|
|
9315
|
+
}
|
|
9316
|
+
async function writeJsonFile(fs3, filePath, value) {
|
|
9317
|
+
await fs3.mkdir(path19.dirname(filePath), { recursive: true });
|
|
9318
|
+
await fs3.writeFile(filePath, `${JSON.stringify(value, null, 2)}
|
|
9319
|
+
`);
|
|
9320
|
+
}
|
|
9321
|
+
function resolveProcessDir(baseDir, id) {
|
|
9322
|
+
return path19.join(baseDir, id);
|
|
9323
|
+
}
|
|
9324
|
+
function resolveSpecPath(baseDir, id) {
|
|
9325
|
+
return path19.join(resolveProcessDir(baseDir, id), "spec.json");
|
|
9326
|
+
}
|
|
9327
|
+
function resolveStatePath(baseDir, id) {
|
|
9328
|
+
return path19.join(resolveProcessDir(baseDir, id), "state.json");
|
|
9329
|
+
}
|
|
9330
|
+
function resolveMetaPath(baseDir, id) {
|
|
9331
|
+
return path19.join(resolveProcessDir(baseDir, id), "meta.json");
|
|
9332
|
+
}
|
|
9333
|
+
function resolveLogDir2(baseDir, id) {
|
|
9334
|
+
return path19.join(resolveProcessDir(baseDir, id), "logs");
|
|
9335
|
+
}
|
|
9336
|
+
function isNotFoundError4(error) {
|
|
9337
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
9338
|
+
}
|
|
9339
|
+
function defaultFs() {
|
|
9340
|
+
return nodeFs3;
|
|
9341
|
+
}
|
|
9342
|
+
function defaultSignalProcess(pid, signal) {
|
|
9343
|
+
process.kill(pid, signal);
|
|
9344
|
+
}
|
|
9345
|
+
function isProcessRunning(pid, isPidRunningOverride) {
|
|
9346
|
+
if (pid === null) {
|
|
9347
|
+
return false;
|
|
9348
|
+
}
|
|
9349
|
+
if (isPidRunningOverride) {
|
|
9350
|
+
return isPidRunningOverride(pid);
|
|
9351
|
+
}
|
|
9352
|
+
try {
|
|
9353
|
+
process.kill(pid, 0);
|
|
9354
|
+
return true;
|
|
9355
|
+
} catch {
|
|
9356
|
+
return false;
|
|
9357
|
+
}
|
|
9358
|
+
}
|
|
9359
|
+
function sleep2(durationMs) {
|
|
9360
|
+
return new Promise((resolve) => {
|
|
9361
|
+
setTimeout(resolve, durationMs);
|
|
9362
|
+
});
|
|
9363
|
+
}
|
|
9364
|
+
var DEFAULT_POLL_INTERVAL_MS, DEFAULT_STARTUP_TIMEOUT_MS, DEFAULT_STOP_TIMEOUT_MS;
|
|
9365
|
+
var init_launcher = __esm({
|
|
9366
|
+
"packages/process-launcher/src/launcher.ts"() {
|
|
9367
|
+
"use strict";
|
|
9368
|
+
init_log_writer();
|
|
9369
|
+
init_state_store();
|
|
9370
|
+
init_supervisor();
|
|
9371
|
+
DEFAULT_POLL_INTERVAL_MS = 100;
|
|
9372
|
+
DEFAULT_STARTUP_TIMEOUT_MS = 3e4;
|
|
9373
|
+
DEFAULT_STOP_TIMEOUT_MS = 5e3;
|
|
9374
|
+
}
|
|
9375
|
+
});
|
|
9376
|
+
|
|
9377
|
+
// packages/process-launcher/src/index.ts
|
|
9378
|
+
var init_src10 = __esm({
|
|
9379
|
+
"packages/process-launcher/src/index.ts"() {
|
|
9380
|
+
"use strict";
|
|
9381
|
+
init_state_store();
|
|
9382
|
+
init_log_writer();
|
|
9383
|
+
init_health_check();
|
|
9384
|
+
init_supervisor();
|
|
9385
|
+
init_launcher();
|
|
9386
|
+
}
|
|
9387
|
+
});
|
|
9388
|
+
|
|
7892
9389
|
// packages/ralph/src/frontmatter/frontmatter.ts
|
|
7893
9390
|
import { parse as parse6, stringify } from "yaml";
|
|
7894
9391
|
function parseFrontmatter(content) {
|
|
@@ -8017,7 +9514,7 @@ var init_frontmatter = __esm({
|
|
|
8017
9514
|
});
|
|
8018
9515
|
|
|
8019
9516
|
// packages/ralph/src/discovery/discovery.ts
|
|
8020
|
-
import
|
|
9517
|
+
import path20 from "node:path";
|
|
8021
9518
|
import * as fsPromises4 from "node:fs/promises";
|
|
8022
9519
|
function createDefaultFs4() {
|
|
8023
9520
|
return {
|
|
@@ -8052,12 +9549,12 @@ async function scanDir(fs3, absoluteDir, displayDir) {
|
|
|
8052
9549
|
if (!isMarkdownFile(entry)) {
|
|
8053
9550
|
continue;
|
|
8054
9551
|
}
|
|
8055
|
-
const absolutePath =
|
|
9552
|
+
const absolutePath = path20.join(absoluteDir, entry);
|
|
8056
9553
|
const stat11 = await fs3.stat(absolutePath);
|
|
8057
9554
|
if (!stat11.isFile()) {
|
|
8058
9555
|
continue;
|
|
8059
9556
|
}
|
|
8060
|
-
const displayPath =
|
|
9557
|
+
const displayPath = path20.join(displayDir, entry);
|
|
8061
9558
|
docs.push({
|
|
8062
9559
|
path: displayPath,
|
|
8063
9560
|
displayPath
|
|
@@ -8070,8 +9567,8 @@ async function discoverDocs(options) {
|
|
|
8070
9567
|
const customDir = options.planDirectory?.trim();
|
|
8071
9568
|
const docs = customDir ? await scanCustomDir(fs3, customDir, options.cwd, options.homeDir) : await scanDefaultDirs(fs3, options.cwd, options.homeDir);
|
|
8072
9569
|
return docs.sort((left, right) => {
|
|
8073
|
-
const leftName =
|
|
8074
|
-
const rightName =
|
|
9570
|
+
const leftName = path20.basename(left.displayPath).toLowerCase();
|
|
9571
|
+
const rightName = path20.basename(right.displayPath).toLowerCase();
|
|
8075
9572
|
return leftName === rightName ? left.displayPath.localeCompare(right.displayPath) : leftName.localeCompare(rightName);
|
|
8076
9573
|
});
|
|
8077
9574
|
}
|
|
@@ -8084,12 +9581,12 @@ async function scanDefaultDirs(fs3, cwd, homeDir) {
|
|
|
8084
9581
|
const [localDocs, globalDocs] = await Promise.all([
|
|
8085
9582
|
scanDir(
|
|
8086
9583
|
fs3,
|
|
8087
|
-
|
|
9584
|
+
path20.join(cwd, ".poe-code", "ralph", "plans"),
|
|
8088
9585
|
".poe-code/ralph/plans"
|
|
8089
9586
|
),
|
|
8090
9587
|
scanDir(
|
|
8091
9588
|
fs3,
|
|
8092
|
-
|
|
9589
|
+
path20.join(homeDir, ".poe-code", "ralph", "plans"),
|
|
8093
9590
|
"~/.poe-code/ralph/plans"
|
|
8094
9591
|
)
|
|
8095
9592
|
]);
|
|
@@ -8097,9 +9594,9 @@ async function scanDefaultDirs(fs3, cwd, homeDir) {
|
|
|
8097
9594
|
}
|
|
8098
9595
|
function resolveAbsoluteDirectory2(dir, cwd, homeDir) {
|
|
8099
9596
|
if (dir.startsWith("~/")) {
|
|
8100
|
-
return
|
|
9597
|
+
return path20.join(homeDir, dir.slice(2));
|
|
8101
9598
|
}
|
|
8102
|
-
return
|
|
9599
|
+
return path20.isAbsolute(dir) ? dir : path20.resolve(cwd, dir);
|
|
8103
9600
|
}
|
|
8104
9601
|
var init_discovery2 = __esm({
|
|
8105
9602
|
"packages/ralph/src/discovery/discovery.ts"() {
|
|
@@ -8108,7 +9605,7 @@ var init_discovery2 = __esm({
|
|
|
8108
9605
|
});
|
|
8109
9606
|
|
|
8110
9607
|
// packages/ralph/src/run/ralph.ts
|
|
8111
|
-
import
|
|
9608
|
+
import path21 from "node:path";
|
|
8112
9609
|
import * as fsPromises5 from "node:fs/promises";
|
|
8113
9610
|
async function runRalph(options) {
|
|
8114
9611
|
const fs3 = options.fs ?? createDefaultFs5();
|
|
@@ -8240,9 +9737,9 @@ function normalizeAgents(agent2) {
|
|
|
8240
9737
|
}
|
|
8241
9738
|
function resolveAbsoluteDocPath(docPath, cwd, homeDir) {
|
|
8242
9739
|
if (docPath.startsWith("~/")) {
|
|
8243
|
-
return
|
|
9740
|
+
return path21.join(homeDir, docPath.slice(2));
|
|
8244
9741
|
}
|
|
8245
|
-
return
|
|
9742
|
+
return path21.isAbsolute(docPath) ? docPath : path21.resolve(cwd, docPath);
|
|
8246
9743
|
}
|
|
8247
9744
|
function assertNotAborted2(signal) {
|
|
8248
9745
|
if (!signal?.aborted) {
|
|
@@ -8273,9 +9770,9 @@ async function updateFrontmatter(fs3, absoluteDocPath, body, frontmatter, state,
|
|
|
8273
9770
|
await fs3.writeFile(absoluteDocPath, content);
|
|
8274
9771
|
}
|
|
8275
9772
|
async function archivePlan2(fs3, absoluteDocPath) {
|
|
8276
|
-
const dir =
|
|
8277
|
-
const archiveDir =
|
|
8278
|
-
const archivePath =
|
|
9773
|
+
const dir = path21.dirname(absoluteDocPath);
|
|
9774
|
+
const archiveDir = path21.join(dir, "archive");
|
|
9775
|
+
const archivePath = path21.join(archiveDir, path21.basename(absoluteDocPath));
|
|
8279
9776
|
await fs3.mkdir(archiveDir, { recursive: true });
|
|
8280
9777
|
await fs3.rename(absoluteDocPath, archivePath);
|
|
8281
9778
|
}
|
|
@@ -8299,7 +9796,7 @@ var init_ralph = __esm({
|
|
|
8299
9796
|
});
|
|
8300
9797
|
|
|
8301
9798
|
// packages/ralph/src/index.ts
|
|
8302
|
-
var
|
|
9799
|
+
var init_src11 = __esm({
|
|
8303
9800
|
"packages/ralph/src/index.ts"() {
|
|
8304
9801
|
"use strict";
|
|
8305
9802
|
init_frontmatter();
|
|
@@ -8328,7 +9825,7 @@ async function runRalph2(options) {
|
|
|
8328
9825
|
var init_ralph2 = __esm({
|
|
8329
9826
|
async "src/sdk/ralph.ts"() {
|
|
8330
9827
|
"use strict";
|
|
8331
|
-
|
|
9828
|
+
init_src11();
|
|
8332
9829
|
init_src6();
|
|
8333
9830
|
await init_spawn3();
|
|
8334
9831
|
}
|
|
@@ -8510,7 +10007,7 @@ var TSV_HEADER, ExperimentJournal;
|
|
|
8510
10007
|
var init_journal = __esm({
|
|
8511
10008
|
"packages/experiment-loop/src/journal/journal.ts"() {
|
|
8512
10009
|
"use strict";
|
|
8513
|
-
TSV_HEADER = ["commit", "status", "score", "durationMs", "timestamp", "output"].join(" ");
|
|
10010
|
+
TSV_HEADER = ["commit", "status", "score", "durationMs", "timestamp", "output", "agentOutput"].join(" ");
|
|
8514
10011
|
ExperimentJournal = class {
|
|
8515
10012
|
constructor(journalPath, fs3) {
|
|
8516
10013
|
this.journalPath = journalPath;
|
|
@@ -8555,7 +10052,8 @@ var init_journal = __esm({
|
|
|
8555
10052
|
entry.score === null ? "null" : String(entry.score),
|
|
8556
10053
|
String(entry.durationMs),
|
|
8557
10054
|
entry.timestamp,
|
|
8558
|
-
formatOutput(entry.output)
|
|
10055
|
+
formatOutput(entry.output),
|
|
10056
|
+
formatOutput(entry.agentOutput ?? "")
|
|
8559
10057
|
].join(" ")
|
|
8560
10058
|
)
|
|
8561
10059
|
].join("\n");
|
|
@@ -8668,7 +10166,7 @@ var init_git = __esm({
|
|
|
8668
10166
|
});
|
|
8669
10167
|
|
|
8670
10168
|
// packages/experiment-loop/src/config/loader.ts
|
|
8671
|
-
import
|
|
10169
|
+
import path22 from "node:path";
|
|
8672
10170
|
import { parse as parse7 } from "yaml";
|
|
8673
10171
|
function isRecord6(value) {
|
|
8674
10172
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -8710,8 +10208,8 @@ function defaultRunConfig() {
|
|
|
8710
10208
|
return { prompt: DEFAULT_PROMPT };
|
|
8711
10209
|
}
|
|
8712
10210
|
async function loadRunConfig(options) {
|
|
8713
|
-
const projectPath =
|
|
8714
|
-
const globalPath =
|
|
10211
|
+
const projectPath = path22.join(options.cwd, ".poe-code", "experiments", "run.yaml");
|
|
10212
|
+
const globalPath = path22.join(options.homeDir, ".poe-code", "experiments", "run.yaml");
|
|
8715
10213
|
const projectContent = await readOptionalFile2(options.fs, projectPath);
|
|
8716
10214
|
if (projectContent != null) {
|
|
8717
10215
|
const config = parseRunConfigDocument(projectPath, projectContent);
|
|
@@ -8752,7 +10250,7 @@ Do not write to the journal file or commit changes. Both are managed automatical
|
|
|
8752
10250
|
// packages/experiment-loop/src/run/loop.ts
|
|
8753
10251
|
import { exec as execCallback } from "node:child_process";
|
|
8754
10252
|
import * as fsPromises6 from "node:fs/promises";
|
|
8755
|
-
import
|
|
10253
|
+
import path23 from "node:path";
|
|
8756
10254
|
function createDefaultFs6() {
|
|
8757
10255
|
return {
|
|
8758
10256
|
readFile: fsPromises6.readFile,
|
|
@@ -8796,14 +10294,14 @@ function createDefaultExec() {
|
|
|
8796
10294
|
}
|
|
8797
10295
|
function resolveAbsoluteDocPath2(docPath, cwd, homeDir) {
|
|
8798
10296
|
if (docPath.startsWith("~/")) {
|
|
8799
|
-
return
|
|
10297
|
+
return path23.join(homeDir, docPath.slice(2));
|
|
8800
10298
|
}
|
|
8801
|
-
return
|
|
10299
|
+
return path23.isAbsolute(docPath) ? docPath : path23.resolve(cwd, docPath);
|
|
8802
10300
|
}
|
|
8803
10301
|
function resolveJournalPath(docPath) {
|
|
8804
|
-
return
|
|
8805
|
-
|
|
8806
|
-
`${
|
|
10302
|
+
return path23.join(
|
|
10303
|
+
path23.dirname(docPath),
|
|
10304
|
+
`${path23.basename(docPath, path23.extname(docPath))}.journal.jsonl`
|
|
8807
10305
|
);
|
|
8808
10306
|
}
|
|
8809
10307
|
function normalizeMetrics(metric) {
|
|
@@ -8939,6 +10437,7 @@ function createEntry(options) {
|
|
|
8939
10437
|
status: options.status,
|
|
8940
10438
|
score: options.score,
|
|
8941
10439
|
output: options.output,
|
|
10440
|
+
agentOutput: options.agentOutput,
|
|
8942
10441
|
durationMs: options.durationMs,
|
|
8943
10442
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
8944
10443
|
};
|
|
@@ -9058,12 +10557,14 @@ async function runExperimentLoop(options) {
|
|
|
9058
10557
|
}
|
|
9059
10558
|
throw error;
|
|
9060
10559
|
}
|
|
10560
|
+
const agentOutput = combineOutput(agentResult.stdout, agentResult.stderr);
|
|
9061
10561
|
if (agentResult.exitCode !== 0) {
|
|
9062
10562
|
const entry2 = createEntry({
|
|
9063
10563
|
commit: preExperimentHash,
|
|
9064
10564
|
status: "crash",
|
|
9065
10565
|
score: null,
|
|
9066
|
-
output:
|
|
10566
|
+
output: agentOutput,
|
|
10567
|
+
agentOutput,
|
|
9067
10568
|
durationMs: Date.now() - experimentStart
|
|
9068
10569
|
});
|
|
9069
10570
|
experimentsCompleted += 1;
|
|
@@ -9081,7 +10582,7 @@ async function runExperimentLoop(options) {
|
|
|
9081
10582
|
});
|
|
9082
10583
|
continue;
|
|
9083
10584
|
}
|
|
9084
|
-
const commitMessage = `experiment-loop: ${
|
|
10585
|
+
const commitMessage = `experiment-loop: ${path23.basename(absoluteDocPath, path23.extname(absoluteDocPath))} #${experimentIndex}`;
|
|
9085
10586
|
let commitHash;
|
|
9086
10587
|
try {
|
|
9087
10588
|
commitHash = await git.commitAll(commitMessage, options.cwd);
|
|
@@ -9104,6 +10605,7 @@ ${errorMessage}`,
|
|
|
9104
10605
|
status: "crash",
|
|
9105
10606
|
score: null,
|
|
9106
10607
|
output: errorMessage,
|
|
10608
|
+
agentOutput,
|
|
9107
10609
|
durationMs: Date.now() - experimentStart
|
|
9108
10610
|
});
|
|
9109
10611
|
experimentsCompleted += 1;
|
|
@@ -9131,6 +10633,7 @@ ${errorMessage}`,
|
|
|
9131
10633
|
status: keep ? "keep" : "discard",
|
|
9132
10634
|
score: selectJournalScore(metrics, evaluationResults),
|
|
9133
10635
|
output: formatEvaluationOutput(metrics, evaluationResults),
|
|
10636
|
+
agentOutput,
|
|
9134
10637
|
durationMs: Date.now() - experimentStart
|
|
9135
10638
|
});
|
|
9136
10639
|
experimentsCompleted += 1;
|
|
@@ -9178,7 +10681,7 @@ var init_loop = __esm({
|
|
|
9178
10681
|
});
|
|
9179
10682
|
|
|
9180
10683
|
// packages/experiment-loop/src/index.ts
|
|
9181
|
-
var
|
|
10684
|
+
var init_src12 = __esm({
|
|
9182
10685
|
"packages/experiment-loop/src/index.ts"() {
|
|
9183
10686
|
"use strict";
|
|
9184
10687
|
init_types2();
|
|
@@ -9192,7 +10695,7 @@ var init_src10 = __esm({
|
|
|
9192
10695
|
});
|
|
9193
10696
|
|
|
9194
10697
|
// src/sdk/experiment.ts
|
|
9195
|
-
import
|
|
10698
|
+
import path24 from "node:path";
|
|
9196
10699
|
import * as fsPromises7 from "node:fs/promises";
|
|
9197
10700
|
function createDefaultFs7() {
|
|
9198
10701
|
return {
|
|
@@ -9218,14 +10721,14 @@ function createDefaultFs7() {
|
|
|
9218
10721
|
}
|
|
9219
10722
|
function resolveAbsoluteDocPath3(docPath, cwd, homeDir) {
|
|
9220
10723
|
if (docPath.startsWith("~/")) {
|
|
9221
|
-
return
|
|
10724
|
+
return path24.join(homeDir, docPath.slice(2));
|
|
9222
10725
|
}
|
|
9223
|
-
return
|
|
10726
|
+
return path24.isAbsolute(docPath) ? docPath : path24.resolve(cwd, docPath);
|
|
9224
10727
|
}
|
|
9225
10728
|
function resolveJournalPath2(docPath) {
|
|
9226
|
-
return
|
|
9227
|
-
|
|
9228
|
-
`${
|
|
10729
|
+
return path24.join(
|
|
10730
|
+
path24.dirname(docPath),
|
|
10731
|
+
`${path24.basename(docPath, path24.extname(docPath))}.journal.jsonl`
|
|
9229
10732
|
);
|
|
9230
10733
|
}
|
|
9231
10734
|
async function runExperiment(options) {
|
|
@@ -9253,7 +10756,7 @@ async function readExperimentJournal(options) {
|
|
|
9253
10756
|
var init_experiment = __esm({
|
|
9254
10757
|
async "src/sdk/experiment.ts"() {
|
|
9255
10758
|
"use strict";
|
|
9256
|
-
|
|
10759
|
+
init_src12();
|
|
9257
10760
|
init_src6();
|
|
9258
10761
|
await init_spawn3();
|
|
9259
10762
|
}
|
|
@@ -9322,99 +10825,393 @@ async function readErrorBody(response) {
|
|
|
9322
10825
|
return void 0;
|
|
9323
10826
|
}
|
|
9324
10827
|
}
|
|
9325
|
-
function extractTextContent(data) {
|
|
9326
|
-
if (!isRecord7(data)) return void 0;
|
|
9327
|
-
const choices = data.choices;
|
|
9328
|
-
if (!Array.isArray(choices) || choices.length === 0) return void 0;
|
|
9329
|
-
const first = choices[0];
|
|
9330
|
-
if (!isRecord7(first)) return void 0;
|
|
9331
|
-
const message = first.message;
|
|
9332
|
-
if (!isRecord7(message)) return void 0;
|
|
9333
|
-
return typeof message.content === "string" ? message.content : void 0;
|
|
10828
|
+
function extractTextContent(data) {
|
|
10829
|
+
if (!isRecord7(data)) return void 0;
|
|
10830
|
+
const choices = data.choices;
|
|
10831
|
+
if (!Array.isArray(choices) || choices.length === 0) return void 0;
|
|
10832
|
+
const first = choices[0];
|
|
10833
|
+
if (!isRecord7(first)) return void 0;
|
|
10834
|
+
const message = first.message;
|
|
10835
|
+
if (!isRecord7(message)) return void 0;
|
|
10836
|
+
return typeof message.content === "string" ? message.content : void 0;
|
|
10837
|
+
}
|
|
10838
|
+
function extractMediaFromCompletion(data) {
|
|
10839
|
+
const content = extractTextContent(data);
|
|
10840
|
+
if (!content) return {};
|
|
10841
|
+
try {
|
|
10842
|
+
const parsed = JSON.parse(content);
|
|
10843
|
+
if (isRecord7(parsed) && typeof parsed.url === "string") {
|
|
10844
|
+
return {
|
|
10845
|
+
url: parsed.url,
|
|
10846
|
+
mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0,
|
|
10847
|
+
data: typeof parsed.data === "string" ? parsed.data : void 0
|
|
10848
|
+
};
|
|
10849
|
+
}
|
|
10850
|
+
if (isRecord7(parsed) && typeof parsed.data === "string") {
|
|
10851
|
+
return {
|
|
10852
|
+
data: parsed.data,
|
|
10853
|
+
mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0
|
|
10854
|
+
};
|
|
10855
|
+
}
|
|
10856
|
+
} catch {
|
|
10857
|
+
}
|
|
10858
|
+
if (isValidUrl(content.trim())) {
|
|
10859
|
+
return { url: content.trim() };
|
|
10860
|
+
}
|
|
10861
|
+
const markdownUrl = extractMarkdownUrl(content);
|
|
10862
|
+
if (markdownUrl) {
|
|
10863
|
+
return { url: markdownUrl };
|
|
10864
|
+
}
|
|
10865
|
+
return { content };
|
|
10866
|
+
}
|
|
10867
|
+
function extractMarkdownUrl(content) {
|
|
10868
|
+
const start = content.indexOf("](");
|
|
10869
|
+
if (start === -1) return void 0;
|
|
10870
|
+
const urlStart = start + 2;
|
|
10871
|
+
const end = content.indexOf(")", urlStart);
|
|
10872
|
+
if (end === -1) return void 0;
|
|
10873
|
+
const url = content.slice(urlStart, end);
|
|
10874
|
+
return isValidUrl(url) ? url : void 0;
|
|
10875
|
+
}
|
|
10876
|
+
function isValidUrl(value) {
|
|
10877
|
+
try {
|
|
10878
|
+
new URL(value);
|
|
10879
|
+
return true;
|
|
10880
|
+
} catch {
|
|
10881
|
+
return false;
|
|
10882
|
+
}
|
|
10883
|
+
}
|
|
10884
|
+
function isRecord7(value) {
|
|
10885
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
10886
|
+
}
|
|
10887
|
+
var init_llm_client = __esm({
|
|
10888
|
+
"src/services/llm-client.ts"() {
|
|
10889
|
+
"use strict";
|
|
10890
|
+
init_errors();
|
|
10891
|
+
}
|
|
10892
|
+
});
|
|
10893
|
+
|
|
10894
|
+
// src/services/client-instance.ts
|
|
10895
|
+
function setGlobalClient(client) {
|
|
10896
|
+
globalClient = client;
|
|
10897
|
+
}
|
|
10898
|
+
function getGlobalClient() {
|
|
10899
|
+
if (!globalClient) {
|
|
10900
|
+
throw new Error("LLM client not initialized. Call setGlobalClient() first.");
|
|
10901
|
+
}
|
|
10902
|
+
return globalClient;
|
|
10903
|
+
}
|
|
10904
|
+
async function initializeClient(options) {
|
|
10905
|
+
if (globalClient !== null) {
|
|
10906
|
+
return;
|
|
10907
|
+
}
|
|
10908
|
+
const client = createPoeClient({
|
|
10909
|
+
apiKey: options.apiKey,
|
|
10910
|
+
baseUrl: options.baseUrl,
|
|
10911
|
+
httpClient: options.httpClient
|
|
10912
|
+
});
|
|
10913
|
+
setGlobalClient(client);
|
|
10914
|
+
}
|
|
10915
|
+
var globalClient;
|
|
10916
|
+
var init_client_instance = __esm({
|
|
10917
|
+
"src/services/client-instance.ts"() {
|
|
10918
|
+
"use strict";
|
|
10919
|
+
init_llm_client();
|
|
10920
|
+
globalClient = null;
|
|
10921
|
+
}
|
|
10922
|
+
});
|
|
10923
|
+
|
|
10924
|
+
// src/utils/execution-context.ts
|
|
10925
|
+
import { basename as basename2, dirname as dirname3 } from "node:path";
|
|
10926
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
10927
|
+
function detectExecutionContext(input) {
|
|
10928
|
+
const { argv, env, moduleUrl } = input;
|
|
10929
|
+
if (isDevelopmentMode(argv, env)) {
|
|
10930
|
+
return createDevelopmentContext(moduleUrl);
|
|
10931
|
+
}
|
|
10932
|
+
if (isNpxExecution(env)) {
|
|
10933
|
+
const version = detectNpxVersion(env);
|
|
10934
|
+
return createNpxContext(version);
|
|
10935
|
+
}
|
|
10936
|
+
const invoked = basename2(argv[1] ?? "");
|
|
10937
|
+
const isPoeShort = invoked === "poe" || invoked === "poe.cmd" || invoked === "poe.exe";
|
|
10938
|
+
return {
|
|
10939
|
+
mode: "global",
|
|
10940
|
+
command: {
|
|
10941
|
+
command: isPoeShort ? "poe" : "poe-code",
|
|
10942
|
+
args: []
|
|
10943
|
+
}
|
|
10944
|
+
};
|
|
10945
|
+
}
|
|
10946
|
+
function isDevelopmentMode(argv, env) {
|
|
10947
|
+
const scriptPath = argv[1] ?? "";
|
|
10948
|
+
if (scriptPath.endsWith(".ts") || scriptPath.includes("/src/")) {
|
|
10949
|
+
return true;
|
|
10950
|
+
}
|
|
10951
|
+
if (env.npm_lifecycle_event === "dev") {
|
|
10952
|
+
return true;
|
|
10953
|
+
}
|
|
10954
|
+
const nodeOptions = env.NODE_OPTIONS ?? "";
|
|
10955
|
+
if (nodeOptions.includes("tsx") || nodeOptions.includes("ts-node")) {
|
|
10956
|
+
return true;
|
|
10957
|
+
}
|
|
10958
|
+
return false;
|
|
10959
|
+
}
|
|
10960
|
+
function isNpxExecution(env) {
|
|
10961
|
+
const execPath = env.npm_execpath ?? "";
|
|
10962
|
+
if (execPath.includes("npx") || execPath.includes("npm")) {
|
|
10963
|
+
const packagePath = env.npm_package_json ?? "";
|
|
10964
|
+
if (packagePath.includes("_npx") || packagePath.includes(".npm/_cacache")) {
|
|
10965
|
+
return true;
|
|
10966
|
+
}
|
|
10967
|
+
}
|
|
10968
|
+
if (env.npm_command === "exec") {
|
|
10969
|
+
return true;
|
|
10970
|
+
}
|
|
10971
|
+
return false;
|
|
10972
|
+
}
|
|
10973
|
+
function detectNpxVersion(env) {
|
|
10974
|
+
const packageJson = env.npm_package_json ?? "";
|
|
10975
|
+
const packageVersion = env.npm_package_version ?? "";
|
|
10976
|
+
if (packageJson.includes("@beta") || packageVersion.includes("beta")) {
|
|
10977
|
+
return "beta";
|
|
10978
|
+
}
|
|
10979
|
+
if (packageJson.includes("@latest")) {
|
|
10980
|
+
return "latest";
|
|
10981
|
+
}
|
|
10982
|
+
return "default";
|
|
10983
|
+
}
|
|
10984
|
+
function createDevelopmentContext(moduleUrl) {
|
|
10985
|
+
const modulePath = fileURLToPath2(moduleUrl);
|
|
10986
|
+
const srcIndex = modulePath.lastIndexOf("/src/");
|
|
10987
|
+
const projectRoot = srcIndex !== -1 ? modulePath.substring(0, srcIndex) : dirname3(dirname3(modulePath));
|
|
10988
|
+
return {
|
|
10989
|
+
mode: "development",
|
|
10990
|
+
command: {
|
|
10991
|
+
command: "npm",
|
|
10992
|
+
args: ["--silent", "--prefix", projectRoot, "run", "dev", "--"]
|
|
10993
|
+
}
|
|
10994
|
+
};
|
|
10995
|
+
}
|
|
10996
|
+
function createNpxContext(version) {
|
|
10997
|
+
const packageSpec = version === "default" ? "poe-code" : `poe-code@${version}`;
|
|
10998
|
+
return {
|
|
10999
|
+
mode: version === "default" ? "npx" : `npx-${version}`,
|
|
11000
|
+
command: {
|
|
11001
|
+
command: "npx",
|
|
11002
|
+
args: ["--yes", packageSpec]
|
|
11003
|
+
}
|
|
11004
|
+
};
|
|
11005
|
+
}
|
|
11006
|
+
function toMcpServerCommand(execCommand, subcommand) {
|
|
11007
|
+
return {
|
|
11008
|
+
command: execCommand.command,
|
|
11009
|
+
args: [...execCommand.args, subcommand]
|
|
11010
|
+
};
|
|
11011
|
+
}
|
|
11012
|
+
function formatCliHelpCommand(context, args) {
|
|
11013
|
+
const base = formatCliUsageCommand(context);
|
|
11014
|
+
const trailing = args.join(" ");
|
|
11015
|
+
if (trailing.length === 0) {
|
|
11016
|
+
return base;
|
|
11017
|
+
}
|
|
11018
|
+
return `${base} ${trailing}`;
|
|
11019
|
+
}
|
|
11020
|
+
function formatCliUsageCommand(context) {
|
|
11021
|
+
switch (context.mode) {
|
|
11022
|
+
case "development":
|
|
11023
|
+
return "npm run dev --";
|
|
11024
|
+
case "npx":
|
|
11025
|
+
return "npx poe-code";
|
|
11026
|
+
case "npx-latest":
|
|
11027
|
+
return "npx poe-code@latest";
|
|
11028
|
+
case "npx-beta":
|
|
11029
|
+
return "npx poe-code@beta";
|
|
11030
|
+
case "global":
|
|
11031
|
+
default:
|
|
11032
|
+
return context.command.command;
|
|
11033
|
+
}
|
|
11034
|
+
}
|
|
11035
|
+
function getCurrentExecutionContext(moduleUrl) {
|
|
11036
|
+
return detectExecutionContext({
|
|
11037
|
+
argv: process.argv,
|
|
11038
|
+
env: process.env,
|
|
11039
|
+
moduleUrl
|
|
11040
|
+
});
|
|
11041
|
+
}
|
|
11042
|
+
var init_execution_context = __esm({
|
|
11043
|
+
"src/utils/execution-context.ts"() {
|
|
11044
|
+
"use strict";
|
|
11045
|
+
}
|
|
11046
|
+
});
|
|
11047
|
+
|
|
11048
|
+
// src/sdk/launch.ts
|
|
11049
|
+
import path25 from "node:path";
|
|
11050
|
+
import { spawnSync } from "node:child_process";
|
|
11051
|
+
async function startLaunch(options) {
|
|
11052
|
+
const homeDir = resolveHomeDir(options.homeDir);
|
|
11053
|
+
const cwd = options.cwd ?? process.cwd();
|
|
11054
|
+
const variables = options.variables ?? process.env;
|
|
11055
|
+
const executionContext = getCurrentExecutionContext(import.meta.url);
|
|
11056
|
+
const runner = createHostRunner({ detached: true });
|
|
11057
|
+
return await startManagedProcess({
|
|
11058
|
+
baseDir: resolveLaunchBaseDir(homeDir),
|
|
11059
|
+
spec: options.spec,
|
|
11060
|
+
spawnDaemon: async (id) => {
|
|
11061
|
+
const handle = runner.exec({
|
|
11062
|
+
args: [...executionContext.command.args, "launch", "__run", id],
|
|
11063
|
+
command: executionContext.command.command,
|
|
11064
|
+
cwd,
|
|
11065
|
+
env: objectToEnv(variables),
|
|
11066
|
+
stderr: "inherit",
|
|
11067
|
+
stdin: "ignore",
|
|
11068
|
+
stdout: "inherit"
|
|
11069
|
+
});
|
|
11070
|
+
return handle.pid;
|
|
11071
|
+
}
|
|
11072
|
+
});
|
|
11073
|
+
}
|
|
11074
|
+
async function stopLaunch(options) {
|
|
11075
|
+
const homeDir = resolveHomeDir(options.homeDir);
|
|
11076
|
+
return await stopManagedProcess({
|
|
11077
|
+
baseDir: resolveLaunchBaseDir(homeDir),
|
|
11078
|
+
force: options.force,
|
|
11079
|
+
id: options.id,
|
|
11080
|
+
signalProcess: sendSignalToManagedProcess,
|
|
11081
|
+
stopRuntimeArtifacts: async ({ record, force }) => {
|
|
11082
|
+
await stopDockerArtifacts(record, force);
|
|
11083
|
+
}
|
|
11084
|
+
});
|
|
9334
11085
|
}
|
|
9335
|
-
function
|
|
9336
|
-
const
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
|
|
9341
|
-
|
|
9342
|
-
|
|
9343
|
-
|
|
9344
|
-
|
|
9345
|
-
|
|
11086
|
+
async function restartLaunch(options) {
|
|
11087
|
+
const homeDir = resolveHomeDir(options.homeDir);
|
|
11088
|
+
const cwd = options.cwd ?? process.cwd();
|
|
11089
|
+
const variables = options.variables ?? process.env;
|
|
11090
|
+
const executionContext = getCurrentExecutionContext(import.meta.url);
|
|
11091
|
+
const runner = createHostRunner({ detached: true });
|
|
11092
|
+
return await restartManagedProcess({
|
|
11093
|
+
baseDir: resolveLaunchBaseDir(homeDir),
|
|
11094
|
+
id: options.id,
|
|
11095
|
+
signalProcess: sendSignalToManagedProcess,
|
|
11096
|
+
spawnDaemon: async (id) => {
|
|
11097
|
+
const handle = runner.exec({
|
|
11098
|
+
args: [...executionContext.command.args, "launch", "__run", id],
|
|
11099
|
+
command: executionContext.command.command,
|
|
11100
|
+
cwd,
|
|
11101
|
+
env: objectToEnv(variables),
|
|
11102
|
+
stderr: "inherit",
|
|
11103
|
+
stdin: "ignore",
|
|
11104
|
+
stdout: "inherit"
|
|
11105
|
+
});
|
|
11106
|
+
return handle.pid;
|
|
11107
|
+
},
|
|
11108
|
+
stopRuntimeArtifacts: async ({ record, force }) => {
|
|
11109
|
+
await stopDockerArtifacts(record, force);
|
|
9346
11110
|
}
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
11111
|
+
});
|
|
11112
|
+
}
|
|
11113
|
+
async function listLaunches(options = {}) {
|
|
11114
|
+
return await listManagedProcesses({
|
|
11115
|
+
baseDir: resolveLaunchBaseDir(resolveHomeDir(options.homeDir))
|
|
11116
|
+
});
|
|
11117
|
+
}
|
|
11118
|
+
async function readLaunchLogs(options) {
|
|
11119
|
+
return await readManagedLogs({
|
|
11120
|
+
baseDir: resolveLaunchBaseDir(resolveHomeDir(options.homeDir)),
|
|
11121
|
+
id: options.id,
|
|
11122
|
+
lines: options.lines,
|
|
11123
|
+
stream: options.stream
|
|
11124
|
+
});
|
|
11125
|
+
}
|
|
11126
|
+
function followLaunchLogs(options) {
|
|
11127
|
+
const forwarded = {
|
|
11128
|
+
baseDir: resolveLaunchBaseDir(resolveHomeDir(options.homeDir)),
|
|
11129
|
+
id: options.id,
|
|
11130
|
+
lines: options.lines,
|
|
11131
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
11132
|
+
signal: options.signal,
|
|
11133
|
+
stream: options.stream
|
|
11134
|
+
};
|
|
11135
|
+
return followManagedLogs(forwarded);
|
|
11136
|
+
}
|
|
11137
|
+
async function removeLaunch(options) {
|
|
11138
|
+
await removeManagedProcess({
|
|
11139
|
+
baseDir: resolveLaunchBaseDir(resolveHomeDir(options.homeDir)),
|
|
11140
|
+
id: options.id,
|
|
11141
|
+
removeRuntimeArtifacts: async ({ record }) => {
|
|
11142
|
+
await removeDockerArtifacts(record);
|
|
9352
11143
|
}
|
|
9353
|
-
}
|
|
9354
|
-
}
|
|
9355
|
-
if (isValidUrl(content.trim())) {
|
|
9356
|
-
return { url: content.trim() };
|
|
9357
|
-
}
|
|
9358
|
-
const markdownUrl = extractMarkdownUrl(content);
|
|
9359
|
-
if (markdownUrl) {
|
|
9360
|
-
return { url: markdownUrl };
|
|
9361
|
-
}
|
|
9362
|
-
return { content };
|
|
11144
|
+
});
|
|
9363
11145
|
}
|
|
9364
|
-
function
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
const url = content.slice(urlStart, end);
|
|
9371
|
-
return isValidUrl(url) ? url : void 0;
|
|
11146
|
+
async function runLaunchDaemon(options) {
|
|
11147
|
+
await runManagedProcess({
|
|
11148
|
+
baseDir: resolveLaunchBaseDir(resolveHomeDir(options.homeDir)),
|
|
11149
|
+
id: options.id,
|
|
11150
|
+
signal: options.signal
|
|
11151
|
+
});
|
|
9372
11152
|
}
|
|
9373
|
-
function
|
|
11153
|
+
function resolveLaunchBaseDir(homeDir) {
|
|
11154
|
+
return path25.join(homeDir, ".poe-code", "launch");
|
|
11155
|
+
}
|
|
11156
|
+
function resolveHomeDir(homeDir) {
|
|
11157
|
+
if (homeDir) {
|
|
11158
|
+
return homeDir;
|
|
11159
|
+
}
|
|
11160
|
+
return process.env.HOME ?? process.cwd();
|
|
11161
|
+
}
|
|
11162
|
+
function sendSignalToManagedProcess(pid, signal) {
|
|
11163
|
+
if (process.platform === "win32") {
|
|
11164
|
+
process.kill(pid, signal);
|
|
11165
|
+
return;
|
|
11166
|
+
}
|
|
9374
11167
|
try {
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
|
|
9378
|
-
|
|
11168
|
+
process.kill(-pid, signal);
|
|
11169
|
+
} catch (error) {
|
|
11170
|
+
if (!isMissingProcessGroupError(error)) {
|
|
11171
|
+
throw error;
|
|
11172
|
+
}
|
|
11173
|
+
process.kill(pid, signal);
|
|
9379
11174
|
}
|
|
9380
11175
|
}
|
|
9381
|
-
function
|
|
9382
|
-
return
|
|
11176
|
+
function isMissingProcessGroupError(error) {
|
|
11177
|
+
return error instanceof Error && "code" in error && error.code === "ESRCH";
|
|
9383
11178
|
}
|
|
9384
|
-
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
11179
|
+
function objectToEnv(variables) {
|
|
11180
|
+
const env = {};
|
|
11181
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
11182
|
+
if (value !== void 0) {
|
|
11183
|
+
env[key] = value;
|
|
11184
|
+
}
|
|
9388
11185
|
}
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
// src/services/client-instance.ts
|
|
9392
|
-
function setGlobalClient(client) {
|
|
9393
|
-
globalClient = client;
|
|
11186
|
+
return env;
|
|
9394
11187
|
}
|
|
9395
|
-
function
|
|
9396
|
-
if (!
|
|
9397
|
-
|
|
11188
|
+
async function stopDockerArtifacts(record, force) {
|
|
11189
|
+
if (!record.spec?.docker?.containerName) {
|
|
11190
|
+
return;
|
|
9398
11191
|
}
|
|
9399
|
-
|
|
11192
|
+
const engine = resolveEngine(record.spec.docker.engine);
|
|
11193
|
+
const command = force ? "kill" : "stop";
|
|
11194
|
+
spawnSync(engine, [command, record.spec.docker.containerName], { stdio: "ignore" });
|
|
9400
11195
|
}
|
|
9401
|
-
async function
|
|
9402
|
-
if (
|
|
11196
|
+
async function removeDockerArtifacts(record) {
|
|
11197
|
+
if (!record.spec?.docker?.containerName) {
|
|
9403
11198
|
return;
|
|
9404
11199
|
}
|
|
9405
|
-
const
|
|
9406
|
-
|
|
9407
|
-
baseUrl: options.baseUrl,
|
|
9408
|
-
httpClient: options.httpClient
|
|
9409
|
-
});
|
|
9410
|
-
setGlobalClient(client);
|
|
11200
|
+
const engine = resolveEngine(record.spec.docker.engine);
|
|
11201
|
+
spawnSync(engine, ["rm", "-f", record.spec.docker.containerName], { stdio: "ignore" });
|
|
9411
11202
|
}
|
|
9412
|
-
|
|
9413
|
-
|
|
9414
|
-
|
|
11203
|
+
function resolveEngine(engine) {
|
|
11204
|
+
if (engine) {
|
|
11205
|
+
return engine;
|
|
11206
|
+
}
|
|
11207
|
+
return detectEngine();
|
|
11208
|
+
}
|
|
11209
|
+
var init_launch = __esm({
|
|
11210
|
+
"src/sdk/launch.ts"() {
|
|
9415
11211
|
"use strict";
|
|
9416
|
-
|
|
9417
|
-
|
|
11212
|
+
init_src10();
|
|
11213
|
+
init_src9();
|
|
11214
|
+
init_execution_context();
|
|
9418
11215
|
}
|
|
9419
11216
|
});
|
|
9420
11217
|
|
|
@@ -9898,13 +11695,13 @@ var init_acp_transport = __esm({
|
|
|
9898
11695
|
env,
|
|
9899
11696
|
requestTimeoutMs,
|
|
9900
11697
|
firstRequestId,
|
|
9901
|
-
spawn:
|
|
11698
|
+
spawn: spawn9 = spawnChildProcess4
|
|
9902
11699
|
} = options;
|
|
9903
11700
|
this.command = command;
|
|
9904
11701
|
this.closed = new Promise((resolve) => {
|
|
9905
11702
|
this.resolveClosed = resolve;
|
|
9906
11703
|
});
|
|
9907
|
-
this.child =
|
|
11704
|
+
this.child = spawn9(command, [...args], {
|
|
9908
11705
|
cwd,
|
|
9909
11706
|
env,
|
|
9910
11707
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -10017,8 +11814,8 @@ function resourceNotFound(resource) {
|
|
|
10017
11814
|
`Resource not found: ${resource}`
|
|
10018
11815
|
);
|
|
10019
11816
|
}
|
|
10020
|
-
function assertAbsolutePath(
|
|
10021
|
-
if (!isAbsolute(
|
|
11817
|
+
function assertAbsolutePath(path39) {
|
|
11818
|
+
if (!isAbsolute(path39)) {
|
|
10022
11819
|
throw invalidParams('"path" must be an absolute path');
|
|
10023
11820
|
}
|
|
10024
11821
|
}
|
|
@@ -10752,7 +12549,7 @@ var init_run_report = __esm({
|
|
|
10752
12549
|
});
|
|
10753
12550
|
|
|
10754
12551
|
// packages/poe-acp-client/src/index.ts
|
|
10755
|
-
var
|
|
12552
|
+
var init_src13 = __esm({
|
|
10756
12553
|
"packages/poe-acp-client/src/index.ts"() {
|
|
10757
12554
|
"use strict";
|
|
10758
12555
|
init_acp_client();
|
|
@@ -11779,7 +13576,7 @@ var init_acp_core = __esm({
|
|
|
11779
13576
|
});
|
|
11780
13577
|
|
|
11781
13578
|
// packages/poe-agent/src/plugins/plugin-args.ts
|
|
11782
|
-
import
|
|
13579
|
+
import path26 from "node:path";
|
|
11783
13580
|
function isObjectRecord3(value) {
|
|
11784
13581
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11785
13582
|
}
|
|
@@ -11810,13 +13607,13 @@ function getOptionalString(args, key) {
|
|
|
11810
13607
|
return value;
|
|
11811
13608
|
}
|
|
11812
13609
|
function resolveAllowedPath(cwd, allowedPaths, inputPath) {
|
|
11813
|
-
const resolvedPath =
|
|
13610
|
+
const resolvedPath = path26.resolve(cwd, inputPath);
|
|
11814
13611
|
const isAllowed = allowedPaths.some((allowedPath) => {
|
|
11815
13612
|
if (allowedPath === resolvedPath) {
|
|
11816
13613
|
return true;
|
|
11817
13614
|
}
|
|
11818
|
-
const rel =
|
|
11819
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
13615
|
+
const rel = path26.relative(allowedPath, resolvedPath);
|
|
13616
|
+
return rel.length > 0 && !rel.startsWith("..") && !path26.isAbsolute(rel);
|
|
11820
13617
|
});
|
|
11821
13618
|
if (!isAllowed) {
|
|
11822
13619
|
throw new Error(`Path is outside allowed paths: ${inputPath}`);
|
|
@@ -11831,7 +13628,7 @@ var init_plugin_args = __esm({
|
|
|
11831
13628
|
|
|
11832
13629
|
// packages/poe-agent/src/plugins/poe-agent-plugin-files.ts
|
|
11833
13630
|
import fsPromises9 from "node:fs/promises";
|
|
11834
|
-
import
|
|
13631
|
+
import path27 from "node:path";
|
|
11835
13632
|
async function fileExists(fs3, filePath) {
|
|
11836
13633
|
try {
|
|
11837
13634
|
await fs3.readFile(filePath, "utf8");
|
|
@@ -11855,9 +13652,9 @@ var init_poe_agent_plugin_files = __esm({
|
|
|
11855
13652
|
"use strict";
|
|
11856
13653
|
init_plugin_args();
|
|
11857
13654
|
filesPlugin = (options = {}) => {
|
|
11858
|
-
const cwd =
|
|
13655
|
+
const cwd = path27.resolve(options.cwd ?? process.cwd());
|
|
11859
13656
|
const allowedPaths = (options.allowedPaths ?? [cwd]).map(
|
|
11860
|
-
(allowedPath) =>
|
|
13657
|
+
(allowedPath) => path27.resolve(cwd, allowedPath)
|
|
11861
13658
|
);
|
|
11862
13659
|
const fs3 = options.fs ?? fsPromises9;
|
|
11863
13660
|
const readFileTool = {
|
|
@@ -11911,7 +13708,7 @@ var init_poe_agent_plugin_files = __esm({
|
|
|
11911
13708
|
async call(args) {
|
|
11912
13709
|
const command = getRequiredString(args, "command");
|
|
11913
13710
|
const filePath = resolveAllowedPath(cwd, allowedPaths, getRequiredString(args, "path"));
|
|
11914
|
-
const displayedPath =
|
|
13711
|
+
const displayedPath = path27.relative(cwd, filePath) || path27.basename(filePath);
|
|
11915
13712
|
if (command === "str_replace") {
|
|
11916
13713
|
const oldStr = getRequiredString(args, "old_str", true);
|
|
11917
13714
|
const newStr = getRequiredString(args, "new_str", true);
|
|
@@ -11931,7 +13728,7 @@ var init_poe_agent_plugin_files = __esm({
|
|
|
11931
13728
|
if (await fileExists(fs3, filePath)) {
|
|
11932
13729
|
throw new Error("File already exists \u2014 use str_replace to edit");
|
|
11933
13730
|
}
|
|
11934
|
-
await fs3.mkdir(
|
|
13731
|
+
await fs3.mkdir(path27.dirname(filePath), { recursive: true });
|
|
11935
13732
|
await fs3.writeFile(filePath, fileText, "utf8");
|
|
11936
13733
|
return `Created file: ${displayedPath}`;
|
|
11937
13734
|
}
|
|
@@ -11972,7 +13769,7 @@ var init_poe_agent_plugin_files = __esm({
|
|
|
11972
13769
|
|
|
11973
13770
|
// packages/poe-agent/src/plugins/poe-agent-plugin-shell.ts
|
|
11974
13771
|
import { exec as execCallback2 } from "node:child_process";
|
|
11975
|
-
import
|
|
13772
|
+
import path28 from "node:path";
|
|
11976
13773
|
import { promisify } from "node:util";
|
|
11977
13774
|
async function defaultRunCommand(command, cwd) {
|
|
11978
13775
|
try {
|
|
@@ -12005,9 +13802,9 @@ var init_poe_agent_plugin_shell = __esm({
|
|
|
12005
13802
|
init_plugin_args();
|
|
12006
13803
|
exec = promisify(execCallback2);
|
|
12007
13804
|
shellPlugin = (options = {}) => {
|
|
12008
|
-
const cwd =
|
|
13805
|
+
const cwd = path28.resolve(options.cwd ?? process.cwd());
|
|
12009
13806
|
const allowedPaths = (options.allowedPaths ?? [cwd]).map(
|
|
12010
|
-
(allowedPath) =>
|
|
13807
|
+
(allowedPath) => path28.resolve(cwd, allowedPath)
|
|
12011
13808
|
);
|
|
12012
13809
|
const runCommand2 = options.runCommand ?? defaultRunCommand;
|
|
12013
13810
|
const runCommandTool = {
|
|
@@ -12046,7 +13843,7 @@ var init_poe_agent_plugin_shell = __esm({
|
|
|
12046
13843
|
// packages/poe-agent/src/system-prompt.ts
|
|
12047
13844
|
import { readFileSync } from "node:fs";
|
|
12048
13845
|
import { readFile as readFile7 } from "node:fs/promises";
|
|
12049
|
-
import { fileURLToPath as
|
|
13846
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
12050
13847
|
function loadSystemPromptSync() {
|
|
12051
13848
|
return readFileSync(SYSTEM_PROMPT_PATH, "utf8");
|
|
12052
13849
|
}
|
|
@@ -12054,7 +13851,7 @@ var SYSTEM_PROMPT_PATH;
|
|
|
12054
13851
|
var init_system_prompt = __esm({
|
|
12055
13852
|
"packages/poe-agent/src/system-prompt.ts"() {
|
|
12056
13853
|
"use strict";
|
|
12057
|
-
SYSTEM_PROMPT_PATH =
|
|
13854
|
+
SYSTEM_PROMPT_PATH = fileURLToPath3(new URL("./SYSTEM_PROMPT.md", import.meta.url));
|
|
12058
13855
|
}
|
|
12059
13856
|
});
|
|
12060
13857
|
|
|
@@ -12791,7 +14588,7 @@ var AgentHost;
|
|
|
12791
14588
|
var init_agent_host = __esm({
|
|
12792
14589
|
"packages/poe-agent/src/runtime/agent-host.ts"() {
|
|
12793
14590
|
"use strict";
|
|
12794
|
-
|
|
14591
|
+
init_src13();
|
|
12795
14592
|
init_agent_session();
|
|
12796
14593
|
init_acp_core();
|
|
12797
14594
|
init_run_context();
|
|
@@ -13158,10 +14955,10 @@ var init_config2 = __esm({
|
|
|
13158
14955
|
});
|
|
13159
14956
|
|
|
13160
14957
|
// packages/tiny-mcp-client/src/internal.ts
|
|
13161
|
-
import { spawn as
|
|
14958
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
13162
14959
|
import { PassThrough } from "node:stream";
|
|
13163
14960
|
function defaultStdioSpawn(command, args, options) {
|
|
13164
|
-
return
|
|
14961
|
+
return spawn7(command, args, options);
|
|
13165
14962
|
}
|
|
13166
14963
|
function serializeJsonRpcMessage2(message) {
|
|
13167
14964
|
return `${JSON.stringify(message)}
|
|
@@ -14078,7 +15875,7 @@ var init_internal = __esm({
|
|
|
14078
15875
|
});
|
|
14079
15876
|
|
|
14080
15877
|
// packages/tiny-mcp-client/src/index.ts
|
|
14081
|
-
var
|
|
15878
|
+
var init_src14 = __esm({
|
|
14082
15879
|
"packages/tiny-mcp-client/src/index.ts"() {
|
|
14083
15880
|
"use strict";
|
|
14084
15881
|
init_internal();
|
|
@@ -14127,7 +15924,7 @@ var DEFAULT_MCP_CLIENT_INFO, PluginApiImpl;
|
|
|
14127
15924
|
var init_plugin_api_impl = __esm({
|
|
14128
15925
|
"packages/poe-agent/src/runtime/plugin-api-impl.ts"() {
|
|
14129
15926
|
"use strict";
|
|
14130
|
-
|
|
15927
|
+
init_src14();
|
|
14131
15928
|
init_hooks();
|
|
14132
15929
|
DEFAULT_MCP_CLIENT_INFO = {
|
|
14133
15930
|
name: "poe-agent",
|
|
@@ -14694,7 +16491,7 @@ __export(src_exports, {
|
|
|
14694
16491
|
agent: () => agent,
|
|
14695
16492
|
createAgentSession: () => createAgentSession
|
|
14696
16493
|
});
|
|
14697
|
-
var
|
|
16494
|
+
var init_src15 = __esm({
|
|
14698
16495
|
"packages/poe-agent/src/index.ts"() {
|
|
14699
16496
|
"use strict";
|
|
14700
16497
|
init_agent();
|
|
@@ -15032,7 +16829,7 @@ function createInMemoryAcpTransport2(options) {
|
|
|
15032
16829
|
}
|
|
15033
16830
|
if (method === "session/new") {
|
|
15034
16831
|
const request = params;
|
|
15035
|
-
const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (
|
|
16832
|
+
const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (init_src15(), src_exports));
|
|
15036
16833
|
const session = await createAgentSession2({
|
|
15037
16834
|
model: options.model,
|
|
15038
16835
|
cwd: request.cwd || options.cwd,
|
|
@@ -15182,7 +16979,7 @@ var init_poe_agent = __esm({
|
|
|
15182
16979
|
"src/providers/poe-agent.ts"() {
|
|
15183
16980
|
"use strict";
|
|
15184
16981
|
init_constants();
|
|
15185
|
-
|
|
16982
|
+
init_src13();
|
|
15186
16983
|
init_create_provider();
|
|
15187
16984
|
poeAgentService = createProvider({
|
|
15188
16985
|
id: "poe-agent",
|
|
@@ -15376,7 +17173,7 @@ var init_container2 = __esm({
|
|
|
15376
17173
|
});
|
|
15377
17174
|
|
|
15378
17175
|
// src/services/config.ts
|
|
15379
|
-
import
|
|
17176
|
+
import path30 from "node:path";
|
|
15380
17177
|
async function deleteConfig(options) {
|
|
15381
17178
|
const { fs: fs3, filePath } = options;
|
|
15382
17179
|
try {
|
|
@@ -15457,7 +17254,7 @@ async function migrateLegacyCredentialsIfNeeded(fs3, filePath) {
|
|
|
15457
17254
|
await migrateLegacyCredentialsFile(fs3, filePath);
|
|
15458
17255
|
}
|
|
15459
17256
|
async function migrateLegacyCredentialsFile(fs3, configPath) {
|
|
15460
|
-
const legacyPath =
|
|
17257
|
+
const legacyPath = path30.join(path30.dirname(configPath), "credentials.json");
|
|
15461
17258
|
const raw = await readFileIfExists(fs3, legacyPath);
|
|
15462
17259
|
if (raw === null) {
|
|
15463
17260
|
return;
|
|
@@ -15525,9 +17322,9 @@ async function recoverInvalidConfig(fs3, filePath, content) {
|
|
|
15525
17322
|
await fs3.writeFile(filePath, EMPTY_DOCUMENT3, { encoding: "utf8" });
|
|
15526
17323
|
}
|
|
15527
17324
|
function createInvalidBackupPath2(filePath) {
|
|
15528
|
-
const directory =
|
|
15529
|
-
const baseName =
|
|
15530
|
-
return
|
|
17325
|
+
const directory = path30.dirname(filePath);
|
|
17326
|
+
const baseName = path30.basename(filePath);
|
|
17327
|
+
return path30.join(directory, `${baseName}.invalid-${createTimestamp()}.json`);
|
|
15531
17328
|
}
|
|
15532
17329
|
function isRecord8(value) {
|
|
15533
17330
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
@@ -15746,7 +17543,7 @@ function registerAgentCommand(program, container) {
|
|
|
15746
17543
|
}
|
|
15747
17544
|
let session;
|
|
15748
17545
|
try {
|
|
15749
|
-
const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (
|
|
17546
|
+
const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (init_src15(), src_exports));
|
|
15750
17547
|
session = await createAgentSession2({
|
|
15751
17548
|
model: options.model,
|
|
15752
17549
|
apiKey: options.apiKey,
|
|
@@ -15805,7 +17602,7 @@ var init_agent2 = __esm({
|
|
|
15805
17602
|
});
|
|
15806
17603
|
|
|
15807
17604
|
// src/cli/commands/spawn.ts
|
|
15808
|
-
import
|
|
17605
|
+
import path31 from "node:path";
|
|
15809
17606
|
function registerSpawnCommand(program, container, options = {}) {
|
|
15810
17607
|
const spawnServices = container.registry.list().filter((service) => typeof service.spawn === "function" || getSpawnConfig(service.name)).map((service) => service.name);
|
|
15811
17608
|
const extraServices = options.extraServices ?? [];
|
|
@@ -16007,10 +17804,10 @@ function resolveSpawnWorkingDirectory2(baseDir, candidate) {
|
|
|
16007
17804
|
if (!candidate || candidate.trim().length === 0) {
|
|
16008
17805
|
return void 0;
|
|
16009
17806
|
}
|
|
16010
|
-
if (
|
|
17807
|
+
if (path31.isAbsolute(candidate)) {
|
|
16011
17808
|
return candidate;
|
|
16012
17809
|
}
|
|
16013
|
-
return
|
|
17810
|
+
return path31.resolve(baseDir, candidate);
|
|
16014
17811
|
}
|
|
16015
17812
|
function parseMcpSpawnConfig2(input) {
|
|
16016
17813
|
if (!input) {
|
|
@@ -16128,7 +17925,7 @@ var init_spawn4 = __esm({
|
|
|
16128
17925
|
});
|
|
16129
17926
|
|
|
16130
17927
|
// src/sdk/research.ts
|
|
16131
|
-
import
|
|
17928
|
+
import path32 from "node:path";
|
|
16132
17929
|
async function research(container, options) {
|
|
16133
17930
|
const logger2 = options.logger;
|
|
16134
17931
|
const source = await resolveSource({
|
|
@@ -16163,7 +17960,7 @@ async function research(container, options) {
|
|
|
16163
17960
|
markdown: markdownOutput
|
|
16164
17961
|
});
|
|
16165
17962
|
outputPath = buildOutputPath(container.env.homeDir, options.prompt);
|
|
16166
|
-
await ensureDirectory2(container.fs,
|
|
17963
|
+
await ensureDirectory2(container.fs, path32.dirname(outputPath));
|
|
16167
17964
|
await container.fs.writeFile(outputPath, document, {
|
|
16168
17965
|
encoding: "utf8"
|
|
16169
17966
|
});
|
|
@@ -16238,7 +18035,7 @@ function buildResearchDocument(input) {
|
|
|
16238
18035
|
}
|
|
16239
18036
|
function buildClonePath(homeDir, github) {
|
|
16240
18037
|
const slug = extractRepoSlug(github);
|
|
16241
|
-
return
|
|
18038
|
+
return path32.join(homeDir, ".poe-code", "repos", slug);
|
|
16242
18039
|
}
|
|
16243
18040
|
function extractRepoSlug(value) {
|
|
16244
18041
|
const trimmed = value.trim();
|
|
@@ -16276,7 +18073,7 @@ function extractRepoSlug(value) {
|
|
|
16276
18073
|
function buildOutputPath(homeDir, prompt, now = /* @__PURE__ */ new Date()) {
|
|
16277
18074
|
const timestamp = formatTimestamp2(now);
|
|
16278
18075
|
const slug = buildSlug(prompt);
|
|
16279
|
-
return
|
|
18076
|
+
return path32.join(
|
|
16280
18077
|
homeDir,
|
|
16281
18078
|
".poe-code",
|
|
16282
18079
|
"research",
|
|
@@ -16297,7 +18094,7 @@ async function resolveSource(input) {
|
|
|
16297
18094
|
if (options.github) {
|
|
16298
18095
|
const cloneUrl = resolveGithubCloneUrl(options.github);
|
|
16299
18096
|
const clonePath = buildClonePath(container.env.homeDir, options.github);
|
|
16300
|
-
await ensureDirectory2(container.fs,
|
|
18097
|
+
await ensureDirectory2(container.fs, path32.dirname(clonePath));
|
|
16301
18098
|
const exists = await pathExists2(container.fs, clonePath);
|
|
16302
18099
|
if (!exists) {
|
|
16303
18100
|
const cloneResult = await container.commandRunner(
|
|
@@ -16395,10 +18192,10 @@ function formatYamlString(value) {
|
|
|
16395
18192
|
return JSON.stringify(value);
|
|
16396
18193
|
}
|
|
16397
18194
|
function resolvePath2(baseDir, candidate) {
|
|
16398
|
-
if (
|
|
18195
|
+
if (path32.isAbsolute(candidate)) {
|
|
16399
18196
|
return candidate;
|
|
16400
18197
|
}
|
|
16401
|
-
return
|
|
18198
|
+
return path32.resolve(baseDir, candidate);
|
|
16402
18199
|
}
|
|
16403
18200
|
function teeAcpStream(events) {
|
|
16404
18201
|
const chunks = [];
|
|
@@ -16458,7 +18255,7 @@ async function removePathFallback(fs3, target) {
|
|
|
16458
18255
|
if (stats && typeof stats.isDirectory === "function" && stats.isDirectory()) {
|
|
16459
18256
|
const entries = await fs3.readdir(target);
|
|
16460
18257
|
for (const entry of entries) {
|
|
16461
|
-
await removePathFallback(fs3,
|
|
18258
|
+
await removePathFallback(fs3, path32.join(target, entry));
|
|
16462
18259
|
}
|
|
16463
18260
|
}
|
|
16464
18261
|
try {
|
|
@@ -16624,7 +18421,7 @@ var init_research2 = __esm({
|
|
|
16624
18421
|
});
|
|
16625
18422
|
|
|
16626
18423
|
// src/cli/isolated-env-runner.ts
|
|
16627
|
-
import { spawn as
|
|
18424
|
+
import { spawn as spawn8 } from "node:child_process";
|
|
16628
18425
|
async function isolatedEnvRunner(input) {
|
|
16629
18426
|
const details = await resolveIsolatedEnvDetails(
|
|
16630
18427
|
input.env,
|
|
@@ -16649,7 +18446,7 @@ async function isolatedEnvRunner(input) {
|
|
|
16649
18446
|
);
|
|
16650
18447
|
args = buildArgsWithMergedSettings(args, resolvedSettings);
|
|
16651
18448
|
}
|
|
16652
|
-
const child =
|
|
18449
|
+
const child = spawn8(details.agentBinary, args, {
|
|
16653
18450
|
stdio: "inherit",
|
|
16654
18451
|
env: {
|
|
16655
18452
|
...process.env,
|
|
@@ -17020,7 +18817,7 @@ function registerAuthCommand(program, container) {
|
|
|
17020
18817
|
const auth = program.command("auth").description("Authentication and account commands.").action(async () => {
|
|
17021
18818
|
await executeStatus(program, container);
|
|
17022
18819
|
});
|
|
17023
|
-
auth.command("status").description("Show login
|
|
18820
|
+
auth.command("status").description("Show login status.").action(async () => {
|
|
17024
18821
|
await executeStatus(program, container);
|
|
17025
18822
|
});
|
|
17026
18823
|
auth.command("api_key").description("Display stored API key.").action(async () => {
|
|
@@ -17099,7 +18896,7 @@ var init_auth = __esm({
|
|
|
17099
18896
|
});
|
|
17100
18897
|
|
|
17101
18898
|
// src/cli/commands/config.ts
|
|
17102
|
-
import { execSync } from "node:child_process";
|
|
18899
|
+
import { execSync as execSync3 } from "node:child_process";
|
|
17103
18900
|
function registerConfigCommand(program, container) {
|
|
17104
18901
|
const config = program.command("config").description("Inspect and manage poe-code config files.").action(async () => {
|
|
17105
18902
|
await executeConfigInfo(program, container);
|
|
@@ -17188,7 +18985,7 @@ async function executeConfigEdit(program, container, options) {
|
|
|
17188
18985
|
if (!await pathExists(container.fs, targetPath)) {
|
|
17189
18986
|
await initProjectConfig(container.fs, targetPath);
|
|
17190
18987
|
}
|
|
17191
|
-
|
|
18988
|
+
execSync3(`${editor} ${shlexQuote(targetPath)}`, {
|
|
17192
18989
|
stdio: "inherit"
|
|
17193
18990
|
});
|
|
17194
18991
|
}
|
|
@@ -17238,7 +19035,7 @@ var init_utils3 = __esm({
|
|
|
17238
19035
|
function registerInstallCommand(program, container) {
|
|
17239
19036
|
const serviceNames = container.registry.list().filter((service) => typeof service.install === "function").map((service) => service.name);
|
|
17240
19037
|
const serviceDescription = `Agent to install${formatServiceList(serviceNames)}`;
|
|
17241
|
-
return program.command("install").alias("i").description("Install
|
|
19038
|
+
return program.command("install").alias("i").description("Install agent binary for a configured agent.").argument(
|
|
17242
19039
|
"[agent]",
|
|
17243
19040
|
serviceDescription
|
|
17244
19041
|
).action(async (service) => {
|
|
@@ -17430,7 +19227,7 @@ var init_media_download = __esm({
|
|
|
17430
19227
|
});
|
|
17431
19228
|
|
|
17432
19229
|
// src/cli/commands/generate.ts
|
|
17433
|
-
import
|
|
19230
|
+
import path33 from "node:path";
|
|
17434
19231
|
function registerGenerateCommand(program, container) {
|
|
17435
19232
|
const generate2 = program.command("generate").alias("g").description("Generate content via Poe API").option("--model <model>", `Model identifier (default: ${DEFAULT_TEXT_MODEL})`).option(
|
|
17436
19233
|
"--param <key=value>",
|
|
@@ -17703,11 +19500,11 @@ function getDefaultMimeType(type) {
|
|
|
17703
19500
|
return defaults[type];
|
|
17704
19501
|
}
|
|
17705
19502
|
function resolveOutputPath(filename, cwd) {
|
|
17706
|
-
if (
|
|
19503
|
+
if (path33.isAbsolute(filename)) {
|
|
17707
19504
|
return { path: filename, label: filename };
|
|
17708
19505
|
}
|
|
17709
19506
|
return {
|
|
17710
|
-
path:
|
|
19507
|
+
path: path33.join(cwd, filename),
|
|
17711
19508
|
label: `./${filename}`
|
|
17712
19509
|
};
|
|
17713
19510
|
}
|
|
@@ -18435,7 +20232,7 @@ var init_content = __esm({
|
|
|
18435
20232
|
});
|
|
18436
20233
|
|
|
18437
20234
|
// packages/tiny-stdio-mcp-server/src/index.ts
|
|
18438
|
-
var
|
|
20235
|
+
var init_src16 = __esm({
|
|
18439
20236
|
"packages/tiny-stdio-mcp-server/src/index.ts"() {
|
|
18440
20237
|
"use strict";
|
|
18441
20238
|
init_server();
|
|
@@ -18738,7 +20535,7 @@ var generateTextSchema, generateImageSchema, generateVideoSchema, generateAudioS
|
|
|
18738
20535
|
var init_mcp_server = __esm({
|
|
18739
20536
|
"src/cli/mcp-server.ts"() {
|
|
18740
20537
|
"use strict";
|
|
18741
|
-
|
|
20538
|
+
init_src16();
|
|
18742
20539
|
init_client_instance();
|
|
18743
20540
|
init_constants();
|
|
18744
20541
|
generateTextSchema = defineSchema({
|
|
@@ -18817,150 +20614,26 @@ function parseMcpOutputFormatPreferences(value) {
|
|
|
18817
20614
|
);
|
|
18818
20615
|
}
|
|
18819
20616
|
if (normalized !== "url" && normalized !== "base64" && normalized !== "markdown" && normalized !== "markdown_instructions") {
|
|
18820
|
-
throw new ValidationError(
|
|
18821
|
-
`Invalid --output-format entry "${raw.trim()}". Expected "url", "base64", "markdown", or "markdown_instructions".`
|
|
18822
|
-
);
|
|
18823
|
-
}
|
|
18824
|
-
preferences.push(normalized);
|
|
18825
|
-
}
|
|
18826
|
-
const standaloneFormats = ["markdown", "markdown_instructions"];
|
|
18827
|
-
for (const standalone of standaloneFormats) {
|
|
18828
|
-
if (preferences.includes(standalone) && preferences.length > 1) {
|
|
18829
|
-
throw new ValidationError(
|
|
18830
|
-
`${standalone} output format cannot be combined with other formats. Use ${standalone} alone or choose a different format combination.`
|
|
18831
|
-
);
|
|
18832
|
-
}
|
|
18833
|
-
}
|
|
18834
|
-
return preferences;
|
|
18835
|
-
}
|
|
18836
|
-
var init_mcp_output_format = __esm({
|
|
18837
|
-
"src/cli/mcp-output-format.ts"() {
|
|
18838
|
-
"use strict";
|
|
18839
|
-
init_errors();
|
|
18840
|
-
}
|
|
18841
|
-
});
|
|
18842
|
-
|
|
18843
|
-
// src/utils/execution-context.ts
|
|
18844
|
-
import { basename as basename2, dirname as dirname3 } from "node:path";
|
|
18845
|
-
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
18846
|
-
function detectExecutionContext(input) {
|
|
18847
|
-
const { argv, env, moduleUrl } = input;
|
|
18848
|
-
if (isDevelopmentMode(argv, env)) {
|
|
18849
|
-
return createDevelopmentContext(moduleUrl);
|
|
18850
|
-
}
|
|
18851
|
-
if (isNpxExecution(env)) {
|
|
18852
|
-
const version = detectNpxVersion(env);
|
|
18853
|
-
return createNpxContext(version);
|
|
18854
|
-
}
|
|
18855
|
-
const invoked = basename2(argv[1] ?? "");
|
|
18856
|
-
const isPoeShort = invoked === "poe" || invoked === "poe.cmd" || invoked === "poe.exe";
|
|
18857
|
-
return {
|
|
18858
|
-
mode: "global",
|
|
18859
|
-
command: {
|
|
18860
|
-
command: isPoeShort ? "poe" : "poe-code",
|
|
18861
|
-
args: []
|
|
18862
|
-
}
|
|
18863
|
-
};
|
|
18864
|
-
}
|
|
18865
|
-
function isDevelopmentMode(argv, env) {
|
|
18866
|
-
const scriptPath = argv[1] ?? "";
|
|
18867
|
-
if (scriptPath.endsWith(".ts") || scriptPath.includes("/src/")) {
|
|
18868
|
-
return true;
|
|
18869
|
-
}
|
|
18870
|
-
if (env.npm_lifecycle_event === "dev") {
|
|
18871
|
-
return true;
|
|
18872
|
-
}
|
|
18873
|
-
const nodeOptions = env.NODE_OPTIONS ?? "";
|
|
18874
|
-
if (nodeOptions.includes("tsx") || nodeOptions.includes("ts-node")) {
|
|
18875
|
-
return true;
|
|
18876
|
-
}
|
|
18877
|
-
return false;
|
|
18878
|
-
}
|
|
18879
|
-
function isNpxExecution(env) {
|
|
18880
|
-
const execPath = env.npm_execpath ?? "";
|
|
18881
|
-
if (execPath.includes("npx") || execPath.includes("npm")) {
|
|
18882
|
-
const packagePath = env.npm_package_json ?? "";
|
|
18883
|
-
if (packagePath.includes("_npx") || packagePath.includes(".npm/_cacache")) {
|
|
18884
|
-
return true;
|
|
18885
|
-
}
|
|
18886
|
-
}
|
|
18887
|
-
if (env.npm_command === "exec") {
|
|
18888
|
-
return true;
|
|
18889
|
-
}
|
|
18890
|
-
return false;
|
|
18891
|
-
}
|
|
18892
|
-
function detectNpxVersion(env) {
|
|
18893
|
-
const packageJson = env.npm_package_json ?? "";
|
|
18894
|
-
const packageVersion = env.npm_package_version ?? "";
|
|
18895
|
-
if (packageJson.includes("@beta") || packageVersion.includes("beta")) {
|
|
18896
|
-
return "beta";
|
|
18897
|
-
}
|
|
18898
|
-
if (packageJson.includes("@latest")) {
|
|
18899
|
-
return "latest";
|
|
18900
|
-
}
|
|
18901
|
-
return "default";
|
|
18902
|
-
}
|
|
18903
|
-
function createDevelopmentContext(moduleUrl) {
|
|
18904
|
-
const modulePath = fileURLToPath3(moduleUrl);
|
|
18905
|
-
const srcIndex = modulePath.lastIndexOf("/src/");
|
|
18906
|
-
const projectRoot = srcIndex !== -1 ? modulePath.substring(0, srcIndex) : dirname3(dirname3(modulePath));
|
|
18907
|
-
return {
|
|
18908
|
-
mode: "development",
|
|
18909
|
-
command: {
|
|
18910
|
-
command: "npm",
|
|
18911
|
-
args: ["--silent", "--prefix", projectRoot, "run", "dev", "--"]
|
|
18912
|
-
}
|
|
18913
|
-
};
|
|
18914
|
-
}
|
|
18915
|
-
function createNpxContext(version) {
|
|
18916
|
-
const packageSpec = version === "default" ? "poe-code" : `poe-code@${version}`;
|
|
18917
|
-
return {
|
|
18918
|
-
mode: version === "default" ? "npx" : `npx-${version}`,
|
|
18919
|
-
command: {
|
|
18920
|
-
command: "npx",
|
|
18921
|
-
args: ["--yes", packageSpec]
|
|
18922
|
-
}
|
|
18923
|
-
};
|
|
18924
|
-
}
|
|
18925
|
-
function toMcpServerCommand(execCommand, subcommand) {
|
|
18926
|
-
return {
|
|
18927
|
-
command: execCommand.command,
|
|
18928
|
-
args: [...execCommand.args, subcommand]
|
|
18929
|
-
};
|
|
18930
|
-
}
|
|
18931
|
-
function formatCliHelpCommand(context, args) {
|
|
18932
|
-
const base = formatCliUsageCommand(context);
|
|
18933
|
-
const trailing = args.join(" ");
|
|
18934
|
-
if (trailing.length === 0) {
|
|
18935
|
-
return base;
|
|
20617
|
+
throw new ValidationError(
|
|
20618
|
+
`Invalid --output-format entry "${raw.trim()}". Expected "url", "base64", "markdown", or "markdown_instructions".`
|
|
20619
|
+
);
|
|
20620
|
+
}
|
|
20621
|
+
preferences.push(normalized);
|
|
18936
20622
|
}
|
|
18937
|
-
|
|
18938
|
-
|
|
18939
|
-
|
|
18940
|
-
|
|
18941
|
-
|
|
18942
|
-
|
|
18943
|
-
|
|
18944
|
-
return "npx poe-code";
|
|
18945
|
-
case "npx-latest":
|
|
18946
|
-
return "npx poe-code@latest";
|
|
18947
|
-
case "npx-beta":
|
|
18948
|
-
return "npx poe-code@beta";
|
|
18949
|
-
case "global":
|
|
18950
|
-
default:
|
|
18951
|
-
return context.command.command;
|
|
20623
|
+
const standaloneFormats = ["markdown", "markdown_instructions"];
|
|
20624
|
+
for (const standalone of standaloneFormats) {
|
|
20625
|
+
if (preferences.includes(standalone) && preferences.length > 1) {
|
|
20626
|
+
throw new ValidationError(
|
|
20627
|
+
`${standalone} output format cannot be combined with other formats. Use ${standalone} alone or choose a different format combination.`
|
|
20628
|
+
);
|
|
20629
|
+
}
|
|
18952
20630
|
}
|
|
20631
|
+
return preferences;
|
|
18953
20632
|
}
|
|
18954
|
-
|
|
18955
|
-
|
|
18956
|
-
argv: process.argv,
|
|
18957
|
-
env: process.env,
|
|
18958
|
-
moduleUrl
|
|
18959
|
-
});
|
|
18960
|
-
}
|
|
18961
|
-
var init_execution_context = __esm({
|
|
18962
|
-
"src/utils/execution-context.ts"() {
|
|
20633
|
+
var init_mcp_output_format = __esm({
|
|
20634
|
+
"src/cli/mcp-output-format.ts"() {
|
|
18963
20635
|
"use strict";
|
|
20636
|
+
init_errors();
|
|
18964
20637
|
}
|
|
18965
20638
|
});
|
|
18966
20639
|
|
|
@@ -19146,9 +20819,9 @@ var init_shapes = __esm({
|
|
|
19146
20819
|
});
|
|
19147
20820
|
|
|
19148
20821
|
// packages/agent-mcp-config/src/apply.ts
|
|
19149
|
-
import
|
|
20822
|
+
import path34 from "node:path";
|
|
19150
20823
|
function getConfigDirectory(configPath) {
|
|
19151
|
-
return
|
|
20824
|
+
return path34.dirname(configPath);
|
|
19152
20825
|
}
|
|
19153
20826
|
function isConfigObject5(value) {
|
|
19154
20827
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
@@ -19250,7 +20923,7 @@ var init_apply = __esm({
|
|
|
19250
20923
|
});
|
|
19251
20924
|
|
|
19252
20925
|
// packages/agent-mcp-config/src/index.ts
|
|
19253
|
-
var
|
|
20926
|
+
var init_src17 = __esm({
|
|
19254
20927
|
"packages/agent-mcp-config/src/index.ts"() {
|
|
19255
20928
|
"use strict";
|
|
19256
20929
|
init_configs2();
|
|
@@ -19430,7 +21103,7 @@ var init_mcp2 = __esm({
|
|
|
19430
21103
|
init_shared();
|
|
19431
21104
|
init_mcp_output_format();
|
|
19432
21105
|
init_command_not_found();
|
|
19433
|
-
|
|
21106
|
+
init_src17();
|
|
19434
21107
|
init_execution_context();
|
|
19435
21108
|
DEFAULT_MCP_AGENT = "claude-code";
|
|
19436
21109
|
}
|
|
@@ -19438,7 +21111,7 @@ var init_mcp2 = __esm({
|
|
|
19438
21111
|
|
|
19439
21112
|
// packages/agent-skill-config/src/configs.ts
|
|
19440
21113
|
import os2 from "node:os";
|
|
19441
|
-
import
|
|
21114
|
+
import path35 from "node:path";
|
|
19442
21115
|
function resolveAgentSupport2(input, registry = agentSkillConfigs) {
|
|
19443
21116
|
const resolvedId = resolveAgentId(input);
|
|
19444
21117
|
if (!resolvedId) {
|
|
@@ -19630,7 +21303,7 @@ var init_apply2 = __esm({
|
|
|
19630
21303
|
});
|
|
19631
21304
|
|
|
19632
21305
|
// packages/agent-skill-config/src/index.ts
|
|
19633
|
-
var
|
|
21306
|
+
var init_src18 = __esm({
|
|
19634
21307
|
"packages/agent-skill-config/src/index.ts"() {
|
|
19635
21308
|
"use strict";
|
|
19636
21309
|
init_configs3();
|
|
@@ -19855,7 +21528,7 @@ var init_skill = __esm({
|
|
|
19855
21528
|
"src/cli/commands/skill.ts"() {
|
|
19856
21529
|
"use strict";
|
|
19857
21530
|
init_src5();
|
|
19858
|
-
|
|
21531
|
+
init_src18();
|
|
19859
21532
|
init_shared();
|
|
19860
21533
|
init_command_not_found();
|
|
19861
21534
|
DEFAULT_SKILL_AGENT = "claude-code";
|
|
@@ -20524,7 +22197,7 @@ var init_models2 = __esm({
|
|
|
20524
22197
|
});
|
|
20525
22198
|
|
|
20526
22199
|
// src/cli/commands/pipeline.ts
|
|
20527
|
-
import
|
|
22200
|
+
import path36 from "node:path";
|
|
20528
22201
|
import { readFile as readFile9, stat as stat9 } from "node:fs/promises";
|
|
20529
22202
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
20530
22203
|
async function resolvePipelinePlanDirectory(container) {
|
|
@@ -20572,11 +22245,11 @@ function resolveMaxRuns(value) {
|
|
|
20572
22245
|
return parsed;
|
|
20573
22246
|
}
|
|
20574
22247
|
function resolvePipelinePaths(scope, cwd, homeDir) {
|
|
20575
|
-
const rootPath = scope === "global" ?
|
|
22248
|
+
const rootPath = scope === "global" ? path36.join(homeDir, ".poe-code", "pipeline") : path36.join(cwd, ".poe-code", "pipeline");
|
|
20576
22249
|
const displayRoot = scope === "global" ? "~/.poe-code/pipeline" : ".poe-code/pipeline";
|
|
20577
22250
|
return {
|
|
20578
|
-
plansPath:
|
|
20579
|
-
stepsPath:
|
|
22251
|
+
plansPath: path36.join(rootPath, "plans"),
|
|
22252
|
+
stepsPath: path36.join(rootPath, "steps.yaml"),
|
|
20580
22253
|
displayPlansPath: `${displayRoot}/plans`,
|
|
20581
22254
|
displayStepsPath: `${displayRoot}/steps.yaml`
|
|
20582
22255
|
};
|
|
@@ -20587,16 +22260,16 @@ async function loadPipelineTemplates() {
|
|
|
20587
22260
|
}
|
|
20588
22261
|
const packageRoot = await findPackageRoot(fileURLToPath4(import.meta.url));
|
|
20589
22262
|
const templateRoots = [
|
|
20590
|
-
|
|
20591
|
-
|
|
22263
|
+
path36.join(packageRoot, "src", "templates", "pipeline"),
|
|
22264
|
+
path36.join(packageRoot, "dist", "templates", "pipeline")
|
|
20592
22265
|
];
|
|
20593
22266
|
for (const templateRoot of templateRoots) {
|
|
20594
22267
|
if (!await pathExistsOnDisk(templateRoot)) {
|
|
20595
22268
|
continue;
|
|
20596
22269
|
}
|
|
20597
22270
|
const [skillPlan, steps] = await Promise.all([
|
|
20598
|
-
readFile9(
|
|
20599
|
-
readFile9(
|
|
22271
|
+
readFile9(path36.join(templateRoot, "SKILL_plan.md"), "utf8"),
|
|
22272
|
+
readFile9(path36.join(templateRoot, "steps.yaml.hbs"), "utf8")
|
|
20600
22273
|
]);
|
|
20601
22274
|
pipelineTemplatesCache = { skillPlan, steps };
|
|
20602
22275
|
return pipelineTemplatesCache;
|
|
@@ -20615,12 +22288,12 @@ async function pathExistsOnDisk(targetPath) {
|
|
|
20615
22288
|
}
|
|
20616
22289
|
}
|
|
20617
22290
|
async function findPackageRoot(entryFilePath) {
|
|
20618
|
-
let currentPath =
|
|
22291
|
+
let currentPath = path36.dirname(entryFilePath);
|
|
20619
22292
|
while (true) {
|
|
20620
|
-
if (await pathExistsOnDisk(
|
|
22293
|
+
if (await pathExistsOnDisk(path36.join(currentPath, "package.json"))) {
|
|
20621
22294
|
return currentPath;
|
|
20622
22295
|
}
|
|
20623
|
-
const parentPath =
|
|
22296
|
+
const parentPath = path36.dirname(currentPath);
|
|
20624
22297
|
if (parentPath === currentPath) {
|
|
20625
22298
|
throw new Error("Unable to locate package root for Pipeline templates.");
|
|
20626
22299
|
}
|
|
@@ -20911,7 +22584,7 @@ function registerPipelineCommand(program, container) {
|
|
|
20911
22584
|
`Would ${stepsExists ? "overwrite" : "create"}: ${pipelinePaths.displayStepsPath}`
|
|
20912
22585
|
);
|
|
20913
22586
|
} else {
|
|
20914
|
-
await container.fs.mkdir(
|
|
22587
|
+
await container.fs.mkdir(path36.dirname(pipelinePaths.stepsPath), {
|
|
20915
22588
|
recursive: true
|
|
20916
22589
|
});
|
|
20917
22590
|
await container.fs.writeFile(pipelinePaths.stepsPath, templates.steps, {
|
|
@@ -20936,7 +22609,7 @@ var init_pipeline3 = __esm({
|
|
|
20936
22609
|
"use strict";
|
|
20937
22610
|
init_src5();
|
|
20938
22611
|
init_src2();
|
|
20939
|
-
|
|
22612
|
+
init_src18();
|
|
20940
22613
|
init_src4();
|
|
20941
22614
|
init_config3();
|
|
20942
22615
|
init_errors();
|
|
@@ -20950,7 +22623,7 @@ var init_pipeline3 = __esm({
|
|
|
20950
22623
|
});
|
|
20951
22624
|
|
|
20952
22625
|
// src/cli/commands/ralph.ts
|
|
20953
|
-
import
|
|
22626
|
+
import path37 from "node:path";
|
|
20954
22627
|
function formatDuration2(ms) {
|
|
20955
22628
|
const totalSeconds = Math.round(ms / 1e3);
|
|
20956
22629
|
const minutes = Math.floor(totalSeconds / 60);
|
|
@@ -20986,9 +22659,9 @@ function normalizeConfiguredIterations(value) {
|
|
|
20986
22659
|
}
|
|
20987
22660
|
function resolveAbsoluteDocPath4(container, docPath) {
|
|
20988
22661
|
if (docPath.startsWith("~/")) {
|
|
20989
|
-
return
|
|
22662
|
+
return path37.join(container.env.homeDir, docPath.slice(2));
|
|
20990
22663
|
}
|
|
20991
|
-
return
|
|
22664
|
+
return path37.isAbsolute(docPath) ? docPath : path37.resolve(container.env.cwd, docPath);
|
|
20992
22665
|
}
|
|
20993
22666
|
async function resolvePlanDirectory2(container) {
|
|
20994
22667
|
const configDoc = await readMergedDocument(
|
|
@@ -21347,7 +23020,7 @@ var init_ralph3 = __esm({
|
|
|
21347
23020
|
init_src5();
|
|
21348
23021
|
init_src2();
|
|
21349
23022
|
init_src6();
|
|
21350
|
-
|
|
23023
|
+
init_src11();
|
|
21351
23024
|
init_src4();
|
|
21352
23025
|
init_config3();
|
|
21353
23026
|
init_errors();
|
|
@@ -21359,11 +23032,11 @@ var init_ralph3 = __esm({
|
|
|
21359
23032
|
});
|
|
21360
23033
|
|
|
21361
23034
|
// src/cli/commands/experiment.ts
|
|
21362
|
-
import
|
|
23035
|
+
import path38 from "node:path";
|
|
21363
23036
|
import { readFile as readFile10, stat as stat10 } from "node:fs/promises";
|
|
21364
23037
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
21365
23038
|
function resolveExperimentPaths(scope, cwd, homeDir) {
|
|
21366
|
-
const rootPath = scope === "global" ?
|
|
23039
|
+
const rootPath = scope === "global" ? path38.join(homeDir, ".poe-code", "experiments") : path38.join(cwd, ".poe-code", "experiments");
|
|
21367
23040
|
const displayRoot = scope === "global" ? "~/.poe-code/experiments" : ".poe-code/experiments";
|
|
21368
23041
|
return {
|
|
21369
23042
|
experimentsPath: rootPath,
|
|
@@ -21382,12 +23055,12 @@ async function pathExistsOnDisk2(targetPath) {
|
|
|
21382
23055
|
}
|
|
21383
23056
|
}
|
|
21384
23057
|
async function findPackageRoot2(entryFilePath) {
|
|
21385
|
-
let currentPath =
|
|
23058
|
+
let currentPath = path38.dirname(entryFilePath);
|
|
21386
23059
|
while (true) {
|
|
21387
|
-
if (await pathExistsOnDisk2(
|
|
23060
|
+
if (await pathExistsOnDisk2(path38.join(currentPath, "package.json"))) {
|
|
21388
23061
|
return currentPath;
|
|
21389
23062
|
}
|
|
21390
|
-
const parentPath =
|
|
23063
|
+
const parentPath = path38.dirname(currentPath);
|
|
21391
23064
|
if (parentPath === currentPath) {
|
|
21392
23065
|
throw new Error("Unable to locate package root for Experiment templates.");
|
|
21393
23066
|
}
|
|
@@ -21400,16 +23073,16 @@ async function loadExperimentTemplates() {
|
|
|
21400
23073
|
}
|
|
21401
23074
|
const packageRoot = await findPackageRoot2(fileURLToPath5(import.meta.url));
|
|
21402
23075
|
const templateRoots = [
|
|
21403
|
-
|
|
21404
|
-
|
|
23076
|
+
path38.join(packageRoot, "src", "templates", "experiment"),
|
|
23077
|
+
path38.join(packageRoot, "dist", "templates", "experiment")
|
|
21405
23078
|
];
|
|
21406
23079
|
for (const templateRoot of templateRoots) {
|
|
21407
23080
|
if (!await pathExistsOnDisk2(templateRoot)) {
|
|
21408
23081
|
continue;
|
|
21409
23082
|
}
|
|
21410
23083
|
const [skillPlan, runYaml] = await Promise.all([
|
|
21411
|
-
readFile10(
|
|
21412
|
-
readFile10(
|
|
23084
|
+
readFile10(path38.join(templateRoot, "SKILL_experiment.md"), "utf8"),
|
|
23085
|
+
readFile10(path38.join(templateRoot, "run.yaml.hbs"), "utf8")
|
|
21413
23086
|
]);
|
|
21414
23087
|
experimentTemplatesCache = { skillPlan, runYaml };
|
|
21415
23088
|
return experimentTemplatesCache;
|
|
@@ -21487,12 +23160,12 @@ function parseNonNegativeInt(value, fieldName) {
|
|
|
21487
23160
|
}
|
|
21488
23161
|
function resolveAbsoluteDocPath5(container, docPath) {
|
|
21489
23162
|
if (docPath.startsWith("~/")) {
|
|
21490
|
-
return
|
|
23163
|
+
return path38.join(container.env.homeDir, docPath.slice(2));
|
|
21491
23164
|
}
|
|
21492
|
-
return
|
|
23165
|
+
return path38.isAbsolute(docPath) ? docPath : path38.resolve(container.env.cwd, docPath);
|
|
21493
23166
|
}
|
|
21494
23167
|
async function discoverExperimentDocs(container) {
|
|
21495
|
-
const directoryPath =
|
|
23168
|
+
const directoryPath = path38.join(container.env.cwd, EXPERIMENTS_DIRECTORY);
|
|
21496
23169
|
let names;
|
|
21497
23170
|
try {
|
|
21498
23171
|
names = await container.fs.readdir(directoryPath);
|
|
@@ -21507,8 +23180,8 @@ async function discoverExperimentDocs(container) {
|
|
|
21507
23180
|
if (!name.endsWith(".md")) {
|
|
21508
23181
|
continue;
|
|
21509
23182
|
}
|
|
21510
|
-
const relativePath =
|
|
21511
|
-
const absolutePath =
|
|
23183
|
+
const relativePath = path38.join(EXPERIMENTS_DIRECTORY, name);
|
|
23184
|
+
const absolutePath = path38.join(directoryPath, name);
|
|
21512
23185
|
const stat11 = await container.fs.stat(absolutePath);
|
|
21513
23186
|
if (!stat11.isFile()) {
|
|
21514
23187
|
continue;
|
|
@@ -21872,8 +23545,8 @@ function registerExperimentCommand(program, container) {
|
|
|
21872
23545
|
);
|
|
21873
23546
|
}
|
|
21874
23547
|
}
|
|
21875
|
-
const runYamlPath =
|
|
21876
|
-
const runYamlDisplayPath =
|
|
23548
|
+
const runYamlPath = path38.join(experimentPaths.experimentsPath, "run.yaml");
|
|
23549
|
+
const runYamlDisplayPath = path38.join(experimentPaths.displayExperimentsPath, "run.yaml");
|
|
21877
23550
|
if (!await pathExists4(container.fs, runYamlPath)) {
|
|
21878
23551
|
if (flags.dryRun) {
|
|
21879
23552
|
resources.logger.dryRun(`Would create: ${runYamlDisplayPath}`);
|
|
@@ -21898,25 +23571,446 @@ var init_experiment2 = __esm({
|
|
|
21898
23571
|
init_src5();
|
|
21899
23572
|
init_src2();
|
|
21900
23573
|
init_src6();
|
|
21901
|
-
|
|
21902
|
-
|
|
23574
|
+
init_src18();
|
|
23575
|
+
init_src12();
|
|
21903
23576
|
init_errors();
|
|
21904
23577
|
init_shared();
|
|
21905
23578
|
await init_experiment();
|
|
21906
23579
|
DEFAULT_EXPERIMENT_AGENT = "claude-code";
|
|
21907
23580
|
DEFAULT_EXPERIMENT_SCOPE = "local";
|
|
21908
|
-
EXPERIMENTS_DIRECTORY =
|
|
23581
|
+
EXPERIMENTS_DIRECTORY = path38.join(".poe-code", "experiments");
|
|
21909
23582
|
experimentTemplatesCache = null;
|
|
21910
23583
|
}
|
|
21911
23584
|
});
|
|
21912
23585
|
|
|
23586
|
+
// src/cli/commands/launch.ts
|
|
23587
|
+
import { Option } from "commander";
|
|
23588
|
+
function registerLaunchCommand(program, container) {
|
|
23589
|
+
const launch = program.command("launch").description("Manage long-running host and Docker processes.");
|
|
23590
|
+
launch.command("start [id] [commandArgs...]").usage("<id> -- <command> [args...]").description("Start and supervise a managed process.").addOption(createChoiceOption("--restart <policy>", "Restart policy", ["never", "on-failure", "always"], "on-failure")).option("--max-restarts <n>", "Max consecutive restarts", "5").option("--ready-pattern <string>", "Log substring to wait for before reporting running").option("--ready-port <port>", "TCP port to probe for readiness").option("--cwd <dir>", "Working directory for the managed process").option("--env <entry>", "Environment variable (KEY=VALUE)", collectValues, []).option("--image <image>", "Docker image").option("--mount <src:target[:ro]>", "Docker bind mount", collectValues, []).option("--port <host:container>", "Docker port mapping", collectValues, []).option("--network <name>", "Docker network").addOption(createChoiceOption("--engine <engine>", "Container engine", ["docker", "podman"])).action(async function(id, commandArgs) {
|
|
23591
|
+
const spec = await resolveStartSpec({
|
|
23592
|
+
commandArgs,
|
|
23593
|
+
id,
|
|
23594
|
+
options: this.opts(),
|
|
23595
|
+
program
|
|
23596
|
+
});
|
|
23597
|
+
if (spec === null) {
|
|
23598
|
+
return;
|
|
23599
|
+
}
|
|
23600
|
+
await startLaunch({
|
|
23601
|
+
cwd: container.env.cwd,
|
|
23602
|
+
homeDir: container.env.homeDir,
|
|
23603
|
+
spec
|
|
23604
|
+
});
|
|
23605
|
+
});
|
|
23606
|
+
launch.command("stop <id>").description("Stop a managed process.").option("--force", "Stop immediately with SIGKILL / docker kill").action(async function(id) {
|
|
23607
|
+
const result = await stopLaunch({
|
|
23608
|
+
force: Boolean(this.opts().force),
|
|
23609
|
+
homeDir: container.env.homeDir,
|
|
23610
|
+
id
|
|
23611
|
+
});
|
|
23612
|
+
if (result === null) {
|
|
23613
|
+
throw new ValidationError(`Managed process not found: ${id}`);
|
|
23614
|
+
}
|
|
23615
|
+
});
|
|
23616
|
+
launch.command("restart <id>").description("Restart a managed process.").action(async function(id) {
|
|
23617
|
+
await restartLaunch({ homeDir: container.env.homeDir, id });
|
|
23618
|
+
});
|
|
23619
|
+
launch.command("status").description("List managed processes.").action(async function() {
|
|
23620
|
+
const records = await listLaunches({ homeDir: container.env.homeDir });
|
|
23621
|
+
const flags = resolveCommandFlags(program);
|
|
23622
|
+
const resources = createExecutionResources(container, flags, "launch:status");
|
|
23623
|
+
if (records.length === 0) {
|
|
23624
|
+
resources.logger.info("No managed processes.");
|
|
23625
|
+
return;
|
|
23626
|
+
}
|
|
23627
|
+
resources.logger.info(renderTable({
|
|
23628
|
+
columns: [
|
|
23629
|
+
{ name: "ID", title: "ID", alignment: "left", maxLen: 24 },
|
|
23630
|
+
{ name: "RUNTIME", title: "RUNTIME", alignment: "left", maxLen: 8 },
|
|
23631
|
+
{ name: "STATUS", title: "STATUS", alignment: "left", maxLen: 12 },
|
|
23632
|
+
{ name: "PID", title: "PID", alignment: "right", maxLen: 8 },
|
|
23633
|
+
{ name: "RESTARTS", title: "RESTARTS", alignment: "right", maxLen: 10 },
|
|
23634
|
+
{ name: "UPTIME", title: "UPTIME", alignment: "right", maxLen: 12 },
|
|
23635
|
+
{ name: "LAST EXIT", title: "LAST EXIT", alignment: "right", maxLen: 10 }
|
|
23636
|
+
],
|
|
23637
|
+
rows: records.map(formatStatusRow),
|
|
23638
|
+
theme: getTheme()
|
|
23639
|
+
}));
|
|
23640
|
+
});
|
|
23641
|
+
launch.command("logs <id>").description("Show managed process logs.").option("--follow", "Follow log output").option("--lines <n>", "Number of lines to show", "50").option("--stderr", "Show stderr instead of stdout").action(async function(id) {
|
|
23642
|
+
const options = this.opts();
|
|
23643
|
+
const lines = parseNonNegativeInt2(options.lines, "lines") ?? 50;
|
|
23644
|
+
const stream = options.stderr ? "stderr" : "stdout";
|
|
23645
|
+
const flags = resolveCommandFlags(program);
|
|
23646
|
+
const resources = createExecutionResources(container, flags, `launch:logs:${id}`);
|
|
23647
|
+
const initial = await readLaunchLogs({
|
|
23648
|
+
homeDir: container.env.homeDir,
|
|
23649
|
+
id,
|
|
23650
|
+
lines,
|
|
23651
|
+
stream
|
|
23652
|
+
});
|
|
23653
|
+
if (initial.length > 0) {
|
|
23654
|
+
resources.logger.info(initial.join("\n"));
|
|
23655
|
+
}
|
|
23656
|
+
if (!options.follow) {
|
|
23657
|
+
return;
|
|
23658
|
+
}
|
|
23659
|
+
const controller = new AbortController();
|
|
23660
|
+
const stop = () => {
|
|
23661
|
+
controller.abort();
|
|
23662
|
+
};
|
|
23663
|
+
process.once("SIGINT", stop);
|
|
23664
|
+
process.once("SIGTERM", stop);
|
|
23665
|
+
try {
|
|
23666
|
+
for await (const line of followLaunchLogs({
|
|
23667
|
+
homeDir: container.env.homeDir,
|
|
23668
|
+
id,
|
|
23669
|
+
lines,
|
|
23670
|
+
signal: controller.signal,
|
|
23671
|
+
stream
|
|
23672
|
+
})) {
|
|
23673
|
+
resources.logger.info(line);
|
|
23674
|
+
}
|
|
23675
|
+
} finally {
|
|
23676
|
+
process.removeListener("SIGINT", stop);
|
|
23677
|
+
process.removeListener("SIGTERM", stop);
|
|
23678
|
+
}
|
|
23679
|
+
});
|
|
23680
|
+
launch.command("rm <id>").description("Remove managed process state and logs.").action(async function(id) {
|
|
23681
|
+
await removeLaunch({ homeDir: container.env.homeDir, id });
|
|
23682
|
+
});
|
|
23683
|
+
launch.command("__run <id>", { hidden: true }).action(async function(id) {
|
|
23684
|
+
await runLaunchDaemon({ homeDir: container.env.homeDir, id });
|
|
23685
|
+
});
|
|
23686
|
+
return launch;
|
|
23687
|
+
}
|
|
23688
|
+
async function resolveStartSpec(options) {
|
|
23689
|
+
const flags = resolveCommandFlags(options.program);
|
|
23690
|
+
const id = await resolveProcessId(options.id);
|
|
23691
|
+
if (id === null) {
|
|
23692
|
+
return null;
|
|
23693
|
+
}
|
|
23694
|
+
const commandParts = await resolveCommandParts(options.commandArgs);
|
|
23695
|
+
if (commandParts === null) {
|
|
23696
|
+
return null;
|
|
23697
|
+
}
|
|
23698
|
+
if (commandParts.length === 0) {
|
|
23699
|
+
throw new ValidationError("Command to run is required.");
|
|
23700
|
+
}
|
|
23701
|
+
const runtime = await resolveRuntime({
|
|
23702
|
+
assumeYes: flags.assumeYes,
|
|
23703
|
+
hasCommand: commandParts.length > 0,
|
|
23704
|
+
image: options.options.image
|
|
23705
|
+
});
|
|
23706
|
+
if (runtime === null) {
|
|
23707
|
+
return null;
|
|
23708
|
+
}
|
|
23709
|
+
const restart = await resolveRestart(options.options.restart, flags.assumeYes);
|
|
23710
|
+
if (restart === null) {
|
|
23711
|
+
return null;
|
|
23712
|
+
}
|
|
23713
|
+
const spec = {
|
|
23714
|
+
args: commandParts.slice(1),
|
|
23715
|
+
command: commandParts[0],
|
|
23716
|
+
id,
|
|
23717
|
+
restart
|
|
23718
|
+
};
|
|
23719
|
+
const maxRestarts = parseNonNegativeInt2(options.options.maxRestarts, "max-restarts");
|
|
23720
|
+
if (maxRestarts !== void 0) {
|
|
23721
|
+
spec.maxRestarts = maxRestarts;
|
|
23722
|
+
}
|
|
23723
|
+
if (options.options.cwd) {
|
|
23724
|
+
spec.cwd = options.options.cwd;
|
|
23725
|
+
}
|
|
23726
|
+
const envEntries = options.options.env ?? [];
|
|
23727
|
+
if (envEntries.length > 0) {
|
|
23728
|
+
spec.env = parseEnvEntries(envEntries);
|
|
23729
|
+
}
|
|
23730
|
+
const readyCheck = resolveReadyCheck2(options.options);
|
|
23731
|
+
if (readyCheck) {
|
|
23732
|
+
spec.readyCheck = readyCheck;
|
|
23733
|
+
}
|
|
23734
|
+
if (runtime === "docker") {
|
|
23735
|
+
const image = await resolveDockerImage(options.options.image);
|
|
23736
|
+
if (image === null) {
|
|
23737
|
+
return null;
|
|
23738
|
+
}
|
|
23739
|
+
spec.docker = {
|
|
23740
|
+
image,
|
|
23741
|
+
...options.options.engine ? { engine: options.options.engine } : {},
|
|
23742
|
+
...options.options.mount?.length ? { mounts: options.options.mount.map(parseMount) } : {},
|
|
23743
|
+
...options.options.port?.length ? { ports: options.options.port.map(parsePort) } : {},
|
|
23744
|
+
...options.options.network ? { network: options.options.network } : {}
|
|
23745
|
+
};
|
|
23746
|
+
}
|
|
23747
|
+
return spec;
|
|
23748
|
+
}
|
|
23749
|
+
async function resolveProcessId(value) {
|
|
23750
|
+
if (value && value.trim().length > 0) {
|
|
23751
|
+
return value.trim();
|
|
23752
|
+
}
|
|
23753
|
+
const entered = await text3({
|
|
23754
|
+
message: "Process ID"
|
|
23755
|
+
});
|
|
23756
|
+
if (isCancel2(entered)) {
|
|
23757
|
+
cancel2("Launch start cancelled.");
|
|
23758
|
+
return null;
|
|
23759
|
+
}
|
|
23760
|
+
const id = typeof entered === "string" ? entered.trim() : "";
|
|
23761
|
+
if (id.length === 0) {
|
|
23762
|
+
throw new ValidationError("Process ID is required.");
|
|
23763
|
+
}
|
|
23764
|
+
return id;
|
|
23765
|
+
}
|
|
23766
|
+
async function resolveCommandParts(commandArgs) {
|
|
23767
|
+
if (commandArgs.length > 0) {
|
|
23768
|
+
return [...commandArgs];
|
|
23769
|
+
}
|
|
23770
|
+
const entered = await text3({
|
|
23771
|
+
message: "Command to run"
|
|
23772
|
+
});
|
|
23773
|
+
if (isCancel2(entered)) {
|
|
23774
|
+
cancel2("Launch start cancelled.");
|
|
23775
|
+
return null;
|
|
23776
|
+
}
|
|
23777
|
+
const value = typeof entered === "string" ? entered.trim() : "";
|
|
23778
|
+
if (value.length === 0) {
|
|
23779
|
+
throw new ValidationError("Command to run is required.");
|
|
23780
|
+
}
|
|
23781
|
+
return splitCommandLine(value);
|
|
23782
|
+
}
|
|
23783
|
+
async function resolveRuntime(options) {
|
|
23784
|
+
if (options.image) {
|
|
23785
|
+
return "docker";
|
|
23786
|
+
}
|
|
23787
|
+
if (options.hasCommand || options.assumeYes) {
|
|
23788
|
+
return "host";
|
|
23789
|
+
}
|
|
23790
|
+
const selected = await select2({
|
|
23791
|
+
message: "Runtime",
|
|
23792
|
+
options: [
|
|
23793
|
+
{ label: "host", value: "host" },
|
|
23794
|
+
{ label: "docker", value: "docker" }
|
|
23795
|
+
]
|
|
23796
|
+
});
|
|
23797
|
+
if (isCancel2(selected)) {
|
|
23798
|
+
cancel2("Launch start cancelled.");
|
|
23799
|
+
return null;
|
|
23800
|
+
}
|
|
23801
|
+
return selected;
|
|
23802
|
+
}
|
|
23803
|
+
async function resolveDockerImage(value) {
|
|
23804
|
+
if (value && value.trim().length > 0) {
|
|
23805
|
+
return value.trim();
|
|
23806
|
+
}
|
|
23807
|
+
const entered = await text3({
|
|
23808
|
+
message: "Docker image"
|
|
23809
|
+
});
|
|
23810
|
+
if (isCancel2(entered)) {
|
|
23811
|
+
cancel2("Launch start cancelled.");
|
|
23812
|
+
return null;
|
|
23813
|
+
}
|
|
23814
|
+
const image = typeof entered === "string" ? entered.trim() : "";
|
|
23815
|
+
if (image.length === 0) {
|
|
23816
|
+
throw new ValidationError("Docker image is required when runtime is docker.");
|
|
23817
|
+
}
|
|
23818
|
+
return image;
|
|
23819
|
+
}
|
|
23820
|
+
async function resolveRestart(restart, assumeYes) {
|
|
23821
|
+
if (restart) {
|
|
23822
|
+
return restart;
|
|
23823
|
+
}
|
|
23824
|
+
if (assumeYes) {
|
|
23825
|
+
return "on-failure";
|
|
23826
|
+
}
|
|
23827
|
+
const selected = await select2({
|
|
23828
|
+
message: "Restart policy",
|
|
23829
|
+
options: [
|
|
23830
|
+
{ label: "on-failure", value: "on-failure" },
|
|
23831
|
+
{ label: "never", value: "never" },
|
|
23832
|
+
{ label: "always", value: "always" }
|
|
23833
|
+
]
|
|
23834
|
+
});
|
|
23835
|
+
if (isCancel2(selected)) {
|
|
23836
|
+
cancel2("Launch start cancelled.");
|
|
23837
|
+
return null;
|
|
23838
|
+
}
|
|
23839
|
+
return selected;
|
|
23840
|
+
}
|
|
23841
|
+
function resolveReadyCheck2(options) {
|
|
23842
|
+
if (options.readyPattern && options.readyPattern.trim().length > 0) {
|
|
23843
|
+
return { kind: "log-pattern", pattern: options.readyPattern.trim() };
|
|
23844
|
+
}
|
|
23845
|
+
const readyPort = parsePositiveInt2(options.readyPort, "ready-port");
|
|
23846
|
+
if (readyPort !== void 0) {
|
|
23847
|
+
return { kind: "tcp", port: readyPort };
|
|
23848
|
+
}
|
|
23849
|
+
return void 0;
|
|
23850
|
+
}
|
|
23851
|
+
function parseEnvEntries(entries) {
|
|
23852
|
+
const env = {};
|
|
23853
|
+
for (const entry of entries) {
|
|
23854
|
+
const separator = entry.indexOf("=");
|
|
23855
|
+
if (separator <= 0) {
|
|
23856
|
+
throw new ValidationError(`Invalid --env value "${entry}". Expected KEY=VALUE.`);
|
|
23857
|
+
}
|
|
23858
|
+
const key = entry.slice(0, separator).trim();
|
|
23859
|
+
const value = entry.slice(separator + 1);
|
|
23860
|
+
if (key.length === 0) {
|
|
23861
|
+
throw new ValidationError(`Invalid --env value "${entry}". Expected KEY=VALUE.`);
|
|
23862
|
+
}
|
|
23863
|
+
env[key] = value;
|
|
23864
|
+
}
|
|
23865
|
+
return env;
|
|
23866
|
+
}
|
|
23867
|
+
function parseMount(value) {
|
|
23868
|
+
const parts = value.split(":");
|
|
23869
|
+
if (parts.length < 2 || parts.length > 3) {
|
|
23870
|
+
throw new ValidationError(`Invalid --mount value "${value}". Expected src:target[:ro].`);
|
|
23871
|
+
}
|
|
23872
|
+
const mount = {
|
|
23873
|
+
source: parts[0],
|
|
23874
|
+
target: parts[1]
|
|
23875
|
+
};
|
|
23876
|
+
if (parts[2] === "ro") {
|
|
23877
|
+
mount.readonly = true;
|
|
23878
|
+
} else if (parts[2] !== void 0) {
|
|
23879
|
+
throw new ValidationError(`Invalid --mount value "${value}". Only :ro is supported.`);
|
|
23880
|
+
}
|
|
23881
|
+
return mount;
|
|
23882
|
+
}
|
|
23883
|
+
function parsePort(value) {
|
|
23884
|
+
const parts = value.split(":");
|
|
23885
|
+
if (parts.length !== 2) {
|
|
23886
|
+
throw new ValidationError(`Invalid --port value "${value}". Expected host:container.`);
|
|
23887
|
+
}
|
|
23888
|
+
return {
|
|
23889
|
+
container: parseRequiredPositiveInt(parts[1], "port"),
|
|
23890
|
+
host: parseRequiredPositiveInt(parts[0], "port")
|
|
23891
|
+
};
|
|
23892
|
+
}
|
|
23893
|
+
function splitCommandLine(value) {
|
|
23894
|
+
const parts = [];
|
|
23895
|
+
let current = "";
|
|
23896
|
+
let quote = null;
|
|
23897
|
+
for (const char of value) {
|
|
23898
|
+
if (quote !== null) {
|
|
23899
|
+
if (char === quote) {
|
|
23900
|
+
quote = null;
|
|
23901
|
+
} else {
|
|
23902
|
+
current += char;
|
|
23903
|
+
}
|
|
23904
|
+
continue;
|
|
23905
|
+
}
|
|
23906
|
+
if (char === "'" || char === '"') {
|
|
23907
|
+
quote = char;
|
|
23908
|
+
continue;
|
|
23909
|
+
}
|
|
23910
|
+
if (char === " " || char === " ") {
|
|
23911
|
+
if (current.length > 0) {
|
|
23912
|
+
parts.push(current);
|
|
23913
|
+
current = "";
|
|
23914
|
+
}
|
|
23915
|
+
continue;
|
|
23916
|
+
}
|
|
23917
|
+
current += char;
|
|
23918
|
+
}
|
|
23919
|
+
if (quote !== null) {
|
|
23920
|
+
throw new ValidationError("Command contains an unterminated quote.");
|
|
23921
|
+
}
|
|
23922
|
+
if (current.length > 0) {
|
|
23923
|
+
parts.push(current);
|
|
23924
|
+
}
|
|
23925
|
+
return parts;
|
|
23926
|
+
}
|
|
23927
|
+
function formatStatusRow(record) {
|
|
23928
|
+
const state = record.state;
|
|
23929
|
+
const id = record.spec?.id ?? state?.id ?? "-";
|
|
23930
|
+
return {
|
|
23931
|
+
ID: id,
|
|
23932
|
+
"LAST EXIT": state?.lastExitCode == null ? "-" : String(state.lastExitCode),
|
|
23933
|
+
PID: state?.pid == null ? "-" : String(state.pid),
|
|
23934
|
+
RESTARTS: state ? String(state.restartCount) : "0",
|
|
23935
|
+
RUNTIME: state?.runtime ?? (record.spec?.docker ? "docker" : "host"),
|
|
23936
|
+
STATUS: state?.status ?? "stopped",
|
|
23937
|
+
UPTIME: formatUptime(state)
|
|
23938
|
+
};
|
|
23939
|
+
}
|
|
23940
|
+
function formatUptime(state) {
|
|
23941
|
+
if (!state || state.status !== "running" && state.status !== "restarting" || !state.lastStartedAt) {
|
|
23942
|
+
return "-";
|
|
23943
|
+
}
|
|
23944
|
+
const startedAt = Date.parse(state.lastStartedAt);
|
|
23945
|
+
if (!Number.isFinite(startedAt)) {
|
|
23946
|
+
return "-";
|
|
23947
|
+
}
|
|
23948
|
+
const totalSeconds = Math.max(0, Math.floor((Date.now() - startedAt) / 1e3));
|
|
23949
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
23950
|
+
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
23951
|
+
const seconds = totalSeconds % 60;
|
|
23952
|
+
if (hours > 0) {
|
|
23953
|
+
return `${hours}h ${minutes}m`;
|
|
23954
|
+
}
|
|
23955
|
+
if (minutes > 0) {
|
|
23956
|
+
return `${minutes}m ${seconds}s`;
|
|
23957
|
+
}
|
|
23958
|
+
return `${seconds}s`;
|
|
23959
|
+
}
|
|
23960
|
+
function createChoiceOption(flags, description, choices, defaultValue) {
|
|
23961
|
+
const option = new Option(flags, description).choices(choices);
|
|
23962
|
+
if (defaultValue !== void 0) {
|
|
23963
|
+
option.default(defaultValue);
|
|
23964
|
+
}
|
|
23965
|
+
return option;
|
|
23966
|
+
}
|
|
23967
|
+
function parsePositiveInt2(value, fieldName) {
|
|
23968
|
+
if (value == null) {
|
|
23969
|
+
return void 0;
|
|
23970
|
+
}
|
|
23971
|
+
const parsed = Number.parseInt(value, 10);
|
|
23972
|
+
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
23973
|
+
throw new ValidationError(`Invalid ${fieldName} "${value}". Expected a positive integer.`);
|
|
23974
|
+
}
|
|
23975
|
+
return parsed;
|
|
23976
|
+
}
|
|
23977
|
+
function parseRequiredPositiveInt(value, fieldName) {
|
|
23978
|
+
const parsed = parsePositiveInt2(value, fieldName);
|
|
23979
|
+
if (parsed === void 0) {
|
|
23980
|
+
throw new ValidationError(`Invalid ${fieldName} "${value}". Expected a positive integer.`);
|
|
23981
|
+
}
|
|
23982
|
+
return parsed;
|
|
23983
|
+
}
|
|
23984
|
+
function parseNonNegativeInt2(value, fieldName) {
|
|
23985
|
+
if (value == null) {
|
|
23986
|
+
return void 0;
|
|
23987
|
+
}
|
|
23988
|
+
const parsed = Number.parseInt(value, 10);
|
|
23989
|
+
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
23990
|
+
throw new ValidationError(`Invalid ${fieldName} "${value}". Expected a non-negative integer.`);
|
|
23991
|
+
}
|
|
23992
|
+
return parsed;
|
|
23993
|
+
}
|
|
23994
|
+
function collectValues(value, previous) {
|
|
23995
|
+
return [...previous, value];
|
|
23996
|
+
}
|
|
23997
|
+
var init_launch2 = __esm({
|
|
23998
|
+
"src/cli/commands/launch.ts"() {
|
|
23999
|
+
"use strict";
|
|
24000
|
+
init_src5();
|
|
24001
|
+
init_shared();
|
|
24002
|
+
init_errors();
|
|
24003
|
+
init_launch();
|
|
24004
|
+
}
|
|
24005
|
+
});
|
|
24006
|
+
|
|
21913
24007
|
// package.json
|
|
21914
24008
|
var package_default;
|
|
21915
24009
|
var init_package = __esm({
|
|
21916
24010
|
"package.json"() {
|
|
21917
24011
|
package_default = {
|
|
21918
24012
|
name: "poe-code",
|
|
21919
|
-
version: "3.0.
|
|
24013
|
+
version: "3.0.123",
|
|
21920
24014
|
description: "CLI tool to configure Poe API for developer workflows.",
|
|
21921
24015
|
type: "module",
|
|
21922
24016
|
main: "./dist/index.js",
|
|
@@ -22031,7 +24125,9 @@ var init_package = __esm({
|
|
|
22031
24125
|
typescript: "^5.9.3",
|
|
22032
24126
|
"typescript-eslint": "^8.54.0",
|
|
22033
24127
|
vitest: "^4.0.18",
|
|
22034
|
-
"@poe-code/experiment-loop": "*"
|
|
24128
|
+
"@poe-code/experiment-loop": "*",
|
|
24129
|
+
"@poe-code/process-launcher": "*",
|
|
24130
|
+
"@poe-code/process-runner": "*"
|
|
22035
24131
|
},
|
|
22036
24132
|
repository: {
|
|
22037
24133
|
type: "git",
|
|
@@ -22047,7 +24143,7 @@ __export(program_exports, {
|
|
|
22047
24143
|
createProgram: () => createProgram
|
|
22048
24144
|
});
|
|
22049
24145
|
import { basename as basename3 } from "node:path";
|
|
22050
|
-
import { Command as
|
|
24146
|
+
import { Command as Command3 } from "commander";
|
|
22051
24147
|
function formatCommandHeader(cmd) {
|
|
22052
24148
|
const parts = [];
|
|
22053
24149
|
let current = cmd;
|
|
@@ -22069,7 +24165,7 @@ function formatHelpText(input) {
|
|
|
22069
24165
|
name: "install",
|
|
22070
24166
|
aliases: ["i"],
|
|
22071
24167
|
args: "[agent]",
|
|
22072
|
-
description: "Install
|
|
24168
|
+
description: "Install agent binary for a configured agent"
|
|
22073
24169
|
},
|
|
22074
24170
|
{
|
|
22075
24171
|
name: "configure",
|
|
@@ -22099,7 +24195,7 @@ function formatHelpText(input) {
|
|
|
22099
24195
|
name: "auth status",
|
|
22100
24196
|
aliases: [],
|
|
22101
24197
|
args: "",
|
|
22102
|
-
description: "Show login
|
|
24198
|
+
description: "Show login status"
|
|
22103
24199
|
},
|
|
22104
24200
|
{
|
|
22105
24201
|
name: "agent",
|
|
@@ -22144,10 +24240,10 @@ function formatHelpText(input) {
|
|
|
22144
24240
|
description: "Remove Poe MCP configuration from your agent"
|
|
22145
24241
|
},
|
|
22146
24242
|
{
|
|
22147
|
-
name: "
|
|
24243
|
+
name: "experiment install",
|
|
22148
24244
|
aliases: [],
|
|
22149
|
-
args: "",
|
|
22150
|
-
description: "
|
|
24245
|
+
args: "[agent]",
|
|
24246
|
+
description: "Install the experiment skill into agent configuration"
|
|
22151
24247
|
},
|
|
22152
24248
|
{
|
|
22153
24249
|
name: "skill configure",
|
|
@@ -22197,6 +24293,12 @@ function formatHelpText(input) {
|
|
|
22197
24293
|
args: "[doc]",
|
|
22198
24294
|
description: "Display an experiment journal as a formatted table"
|
|
22199
24295
|
},
|
|
24296
|
+
{
|
|
24297
|
+
name: "launch",
|
|
24298
|
+
aliases: [],
|
|
24299
|
+
args: "",
|
|
24300
|
+
description: "Manage long-running host and Docker processes"
|
|
24301
|
+
},
|
|
22200
24302
|
{
|
|
22201
24303
|
name: "usage",
|
|
22202
24304
|
aliases: ["u"],
|
|
@@ -22214,24 +24316,6 @@ function formatHelpText(input) {
|
|
|
22214
24316
|
aliases: [],
|
|
22215
24317
|
args: "",
|
|
22216
24318
|
description: "Show config file paths and usage hints"
|
|
22217
|
-
},
|
|
22218
|
-
{
|
|
22219
|
-
name: "utils config show",
|
|
22220
|
-
aliases: [],
|
|
22221
|
-
args: "",
|
|
22222
|
-
description: "Show config inputs and resolved result"
|
|
22223
|
-
},
|
|
22224
|
-
{
|
|
22225
|
-
name: "utils config init",
|
|
22226
|
-
aliases: [],
|
|
22227
|
-
args: "",
|
|
22228
|
-
description: "Create a project config file"
|
|
22229
|
-
},
|
|
22230
|
-
{
|
|
22231
|
-
name: "utils config edit",
|
|
22232
|
-
aliases: [],
|
|
22233
|
-
args: "",
|
|
22234
|
-
description: "Open a config file in your editor"
|
|
22235
24319
|
}
|
|
22236
24320
|
];
|
|
22237
24321
|
const nameWidth = Math.max(
|
|
@@ -22335,7 +24419,7 @@ function createProgram(dependencies) {
|
|
|
22335
24419
|
return program;
|
|
22336
24420
|
}
|
|
22337
24421
|
function bootstrapProgram(container) {
|
|
22338
|
-
const program = new
|
|
24422
|
+
const program = new Command3();
|
|
22339
24423
|
const executionContext = detectExecutionContext({
|
|
22340
24424
|
argv: process.argv,
|
|
22341
24425
|
env: container.env.variables,
|
|
@@ -22371,6 +24455,7 @@ function bootstrapProgram(container) {
|
|
|
22371
24455
|
registerPipelineCommand(program, container);
|
|
22372
24456
|
registerRalphCommand(program, container);
|
|
22373
24457
|
registerExperimentCommand(program, container);
|
|
24458
|
+
registerLaunchCommand(program, container);
|
|
22374
24459
|
registerUsageCommand(program, container);
|
|
22375
24460
|
registerModelsCommand(program, container);
|
|
22376
24461
|
program.allowExcessArguments().action(function() {
|
|
@@ -22431,6 +24516,7 @@ var init_program = __esm({
|
|
|
22431
24516
|
await init_pipeline3();
|
|
22432
24517
|
await init_ralph3();
|
|
22433
24518
|
await init_experiment2();
|
|
24519
|
+
init_launch2();
|
|
22434
24520
|
init_package();
|
|
22435
24521
|
init_command_not_found();
|
|
22436
24522
|
init_execution_context();
|
|
@@ -22522,7 +24608,7 @@ __export(bootstrap_exports, {
|
|
|
22522
24608
|
createCliMain: () => createCliMain,
|
|
22523
24609
|
isCliInvocation: () => isCliInvocation
|
|
22524
24610
|
});
|
|
22525
|
-
import * as
|
|
24611
|
+
import * as nodeFs4 from "node:fs/promises";
|
|
22526
24612
|
import * as nodeFsSync3 from "node:fs";
|
|
22527
24613
|
import { realpathSync } from "node:fs";
|
|
22528
24614
|
import { homedir as homedir5 } from "node:os";
|
|
@@ -22597,18 +24683,23 @@ var init_bootstrap = __esm({
|
|
|
22597
24683
|
init_error_logger();
|
|
22598
24684
|
init_errors();
|
|
22599
24685
|
init_prompt_runner();
|
|
22600
|
-
fsAdapter =
|
|
24686
|
+
fsAdapter = nodeFs4;
|
|
22601
24687
|
}
|
|
22602
24688
|
});
|
|
22603
24689
|
|
|
22604
24690
|
// src/index.ts
|
|
22605
24691
|
await init_spawn3();
|
|
22606
24692
|
await init_pipeline2();
|
|
22607
|
-
await init_ralph2();
|
|
22608
|
-
await init_experiment();
|
|
22609
24693
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
22610
24694
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
22611
24695
|
|
|
24696
|
+
// src/sdk/process-launcher.ts
|
|
24697
|
+
init_src10();
|
|
24698
|
+
|
|
24699
|
+
// src/index.ts
|
|
24700
|
+
await init_ralph2();
|
|
24701
|
+
await init_experiment();
|
|
24702
|
+
|
|
22612
24703
|
// src/sdk/generate.ts
|
|
22613
24704
|
init_constants();
|
|
22614
24705
|
init_credentials();
|
|
@@ -22708,13 +24799,14 @@ function normalizeBaseUrl(value) {
|
|
|
22708
24799
|
|
|
22709
24800
|
// src/index.ts
|
|
22710
24801
|
init_credentials();
|
|
24802
|
+
init_launch();
|
|
22711
24803
|
|
|
22712
24804
|
// src/cli/poe-agent-main.ts
|
|
22713
24805
|
init_src6();
|
|
22714
24806
|
init_src5();
|
|
22715
24807
|
init_constants();
|
|
22716
24808
|
init_errors();
|
|
22717
|
-
import
|
|
24809
|
+
import path29 from "node:path";
|
|
22718
24810
|
import { Command } from "commander";
|
|
22719
24811
|
function parseMcpSpawnConfig(input) {
|
|
22720
24812
|
if (!input) {
|
|
@@ -22785,10 +24877,10 @@ function resolveWorkingDirectory(baseDir, candidate) {
|
|
|
22785
24877
|
if (!candidate || candidate.trim().length === 0) {
|
|
22786
24878
|
return void 0;
|
|
22787
24879
|
}
|
|
22788
|
-
if (
|
|
24880
|
+
if (path29.isAbsolute(candidate)) {
|
|
22789
24881
|
return candidate;
|
|
22790
24882
|
}
|
|
22791
|
-
return
|
|
24883
|
+
return path29.resolve(baseDir, candidate);
|
|
22792
24884
|
}
|
|
22793
24885
|
function createPoeAgentProgram() {
|
|
22794
24886
|
const program = new Command();
|
|
@@ -22882,18 +24974,30 @@ if (isCliInvocation2(process.argv, import.meta.url)) {
|
|
|
22882
24974
|
void main();
|
|
22883
24975
|
}
|
|
22884
24976
|
export {
|
|
24977
|
+
createLogWriter,
|
|
24978
|
+
createStateStore,
|
|
24979
|
+
createSupervisor,
|
|
24980
|
+
followLaunchLogs,
|
|
22885
24981
|
generate,
|
|
22886
24982
|
generateAudio,
|
|
22887
24983
|
generateImage,
|
|
22888
24984
|
generateVideo,
|
|
22889
24985
|
getPoeApiKey,
|
|
22890
24986
|
isCliInvocation2 as isCliInvocation,
|
|
24987
|
+
listLaunches,
|
|
22891
24988
|
main,
|
|
22892
24989
|
poeAgentMain,
|
|
22893
24990
|
readExperimentJournal,
|
|
24991
|
+
readLaunchLogs,
|
|
24992
|
+
removeLaunch,
|
|
24993
|
+
restartLaunch,
|
|
22894
24994
|
runExperiment,
|
|
24995
|
+
runLaunchDaemon,
|
|
22895
24996
|
runPipeline2 as runPipeline,
|
|
22896
24997
|
runRalph2 as runRalph,
|
|
22897
|
-
spawn4 as spawn
|
|
24998
|
+
spawn4 as spawn,
|
|
24999
|
+
startLaunch,
|
|
25000
|
+
stopLaunch,
|
|
25001
|
+
waitForReady
|
|
22898
25002
|
};
|
|
22899
25003
|
//# sourceMappingURL=index.js.map
|