poe-code 3.0.214 → 3.0.216
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/README.md +0 -2
- package/dist/cli/commands/pipeline.js +72 -3
- package/dist/cli/commands/pipeline.js.map +1 -1
- package/dist/cli/commands/tasks-options.d.ts +19 -0
- package/dist/cli/commands/tasks-options.js +144 -0
- package/dist/cli/commands/tasks-options.js.map +1 -0
- package/dist/cli/commands/tasks.d.ts +3 -0
- package/dist/cli/commands/tasks.js +144 -0
- package/dist/cli/commands/tasks.js.map +1 -0
- package/dist/cli/program.js +92 -1
- package/dist/cli/program.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +41803 -39205
- package/dist/index.js.map +4 -4
- package/dist/prompts/github-issue-opened.md +3 -3
- package/dist/providers/claude-code.js +2800 -2655
- package/dist/providers/claude-code.js.map +4 -4
- package/dist/providers/codex.js +2853 -2708
- package/dist/providers/codex.js.map +4 -4
- package/dist/providers/goose.js +2797 -2652
- package/dist/providers/goose.js.map +4 -4
- package/dist/providers/kimi.js +2800 -2655
- package/dist/providers/kimi.js.map +4 -4
- package/dist/providers/opencode.js +2800 -2655
- package/dist/providers/opencode.js.map +4 -4
- package/dist/providers/poe-agent.js +4926 -2095
- package/dist/providers/poe-agent.js.map +4 -4
- package/package.json +3 -1
- package/packages/memory/dist/index.js +1625 -1482
- package/packages/memory/dist/index.js.map +4 -4
- package/packages/superintendent/dist/commands/run.js +9 -64
|
@@ -611,11 +611,11 @@ function stripBom(content) {
|
|
|
611
611
|
function mergeLayers(layers) {
|
|
612
612
|
return mergeObjectLayers(layers, []);
|
|
613
613
|
}
|
|
614
|
-
function mergeObjectLayers(layers,
|
|
614
|
+
function mergeObjectLayers(layers, path45) {
|
|
615
615
|
const data = {};
|
|
616
616
|
const sources = {};
|
|
617
617
|
for (const key of collectKeys(layers)) {
|
|
618
|
-
const resolved = resolveKey(layers, key,
|
|
618
|
+
const resolved = resolveKey(layers, key, path45);
|
|
619
619
|
if (resolved === void 0) {
|
|
620
620
|
continue;
|
|
621
621
|
}
|
|
@@ -633,7 +633,7 @@ function collectKeys(layers) {
|
|
|
633
633
|
}
|
|
634
634
|
return [...keys];
|
|
635
635
|
}
|
|
636
|
-
function resolveKey(layers, key,
|
|
636
|
+
function resolveKey(layers, key, path45) {
|
|
637
637
|
let winningSource;
|
|
638
638
|
let winningValue;
|
|
639
639
|
const objectLayers = [];
|
|
@@ -663,9 +663,9 @@ function resolveKey(layers, key, path42) {
|
|
|
663
663
|
if (winningSource === void 0) {
|
|
664
664
|
return void 0;
|
|
665
665
|
}
|
|
666
|
-
const fullPath = buildPath(
|
|
666
|
+
const fullPath = buildPath(path45, key);
|
|
667
667
|
if (isPlainObject(winningValue)) {
|
|
668
|
-
const merged = mergeObjectLayers(objectLayers, [...
|
|
668
|
+
const merged = mergeObjectLayers(objectLayers, [...path45, key]);
|
|
669
669
|
return {
|
|
670
670
|
value: merged.data,
|
|
671
671
|
sources: {
|
|
@@ -690,8 +690,8 @@ function isWinningCandidate(key, value) {
|
|
|
690
690
|
}
|
|
691
691
|
return true;
|
|
692
692
|
}
|
|
693
|
-
function buildPath(
|
|
694
|
-
return [...
|
|
693
|
+
function buildPath(path45, key) {
|
|
694
|
+
return [...path45, key].join(".");
|
|
695
695
|
}
|
|
696
696
|
function isPlainObject(value) {
|
|
697
697
|
if (value === null || Array.isArray(value) || typeof value !== "object") {
|
|
@@ -1325,16 +1325,16 @@ function getConfigFormat(pathOrFormat) {
|
|
|
1325
1325
|
}
|
|
1326
1326
|
return formatRegistry[formatName];
|
|
1327
1327
|
}
|
|
1328
|
-
function detectFormat2(
|
|
1329
|
-
const ext = getExtension(
|
|
1328
|
+
function detectFormat2(path45) {
|
|
1329
|
+
const ext = getExtension(path45);
|
|
1330
1330
|
return extensionMap[ext];
|
|
1331
1331
|
}
|
|
1332
|
-
function getExtension(
|
|
1333
|
-
const lastDot =
|
|
1332
|
+
function getExtension(path45) {
|
|
1333
|
+
const lastDot = path45.lastIndexOf(".");
|
|
1334
1334
|
if (lastDot === -1) {
|
|
1335
1335
|
return "";
|
|
1336
1336
|
}
|
|
1337
|
-
return
|
|
1337
|
+
return path45.slice(lastDot).toLowerCase();
|
|
1338
1338
|
}
|
|
1339
1339
|
|
|
1340
1340
|
// packages/config-mutations/src/execution/path-utils.ts
|
|
@@ -2204,7 +2204,7 @@ function mergeScope(scope, baseScope, overrideScope) {
|
|
|
2204
2204
|
...Object.fromEntries(scopeEntries)
|
|
2205
2205
|
};
|
|
2206
2206
|
}
|
|
2207
|
-
function mergeRuntimeScope(baseScope, overrideScope,
|
|
2207
|
+
function mergeRuntimeScope(baseScope, overrideScope, path45 = []) {
|
|
2208
2208
|
const merged = {};
|
|
2209
2209
|
const keys = /* @__PURE__ */ new Set([...Object.keys(baseScope), ...Object.keys(overrideScope)]);
|
|
2210
2210
|
for (const key of keys) {
|
|
@@ -2216,20 +2216,20 @@ function mergeRuntimeScope(baseScope, overrideScope, path42 = []) {
|
|
|
2216
2216
|
}
|
|
2217
2217
|
continue;
|
|
2218
2218
|
}
|
|
2219
|
-
if (isRuntimeConcatenativeArray([...
|
|
2219
|
+
if (isRuntimeConcatenativeArray([...path45, key]) && Array.isArray(baseValue) && Array.isArray(overrideValue)) {
|
|
2220
2220
|
merged[key] = [...baseValue, ...overrideValue];
|
|
2221
2221
|
continue;
|
|
2222
2222
|
}
|
|
2223
2223
|
if (isRecord3(baseValue) && isRecord3(overrideValue)) {
|
|
2224
|
-
merged[key] = mergeRuntimeScope(baseValue, overrideValue, [...
|
|
2224
|
+
merged[key] = mergeRuntimeScope(baseValue, overrideValue, [...path45, key]);
|
|
2225
2225
|
continue;
|
|
2226
2226
|
}
|
|
2227
2227
|
merged[key] = overrideValue;
|
|
2228
2228
|
}
|
|
2229
2229
|
return merged;
|
|
2230
2230
|
}
|
|
2231
|
-
function isRuntimeConcatenativeArray(
|
|
2232
|
-
return
|
|
2231
|
+
function isRuntimeConcatenativeArray(path45) {
|
|
2232
|
+
return path45.join(".") === "mounts" || path45.join(".") === "runner.workspace.exclude";
|
|
2233
2233
|
}
|
|
2234
2234
|
function isRecord3(value) {
|
|
2235
2235
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
@@ -2350,8 +2350,8 @@ function isPidRunning(pid) {
|
|
|
2350
2350
|
}
|
|
2351
2351
|
function createDefaultFs() {
|
|
2352
2352
|
return {
|
|
2353
|
-
open: (
|
|
2354
|
-
readFile: (
|
|
2353
|
+
open: (path45, flags) => fsPromises.open(path45, flags),
|
|
2354
|
+
readFile: (path45, encoding) => fsPromises.readFile(path45, encoding),
|
|
2355
2355
|
stat: fsPromises.stat,
|
|
2356
2356
|
unlink: fsPromises.unlink
|
|
2357
2357
|
};
|
|
@@ -2977,10 +2977,10 @@ function parseSources(value) {
|
|
|
2977
2977
|
if (!isRecord6(item)) {
|
|
2978
2978
|
throw new Error('Invalid "sources" frontmatter. Expected each source to be a string or object.');
|
|
2979
2979
|
}
|
|
2980
|
-
const
|
|
2980
|
+
const path45 = readRequiredString(item.path, "sources[].path");
|
|
2981
2981
|
const startLine = readOptionalPositiveInteger(item.startLine, "sources[].startLine");
|
|
2982
2982
|
const endLine = readOptionalPositiveInteger(item.endLine, "sources[].endLine");
|
|
2983
|
-
return parseSourceRef(serializeSourceRef({ path:
|
|
2983
|
+
return parseSourceRef(serializeSourceRef({ path: path45, ...startLine === void 0 ? {} : { startLine }, ...endLine === void 0 ? {} : { endLine } }));
|
|
2984
2984
|
});
|
|
2985
2985
|
}
|
|
2986
2986
|
function readOptionalString(value, field) {
|
|
@@ -4036,7 +4036,7 @@ function parseOlderThan(value) {
|
|
|
4036
4036
|
|
|
4037
4037
|
// packages/memory/src/ingest.ts
|
|
4038
4038
|
import * as fs11 from "node:fs/promises";
|
|
4039
|
-
import
|
|
4039
|
+
import path38 from "node:path";
|
|
4040
4040
|
|
|
4041
4041
|
// packages/agent-spawn/src/register-factories.ts
|
|
4042
4042
|
import { spawn as spawnChildProcess2 } from "node:child_process";
|
|
@@ -4044,1533 +4044,1676 @@ import { spawn as spawnChildProcess2 } from "node:child_process";
|
|
|
4044
4044
|
// packages/agent-harness-tools/src/paths.ts
|
|
4045
4045
|
import path22 from "node:path";
|
|
4046
4046
|
|
|
4047
|
-
// packages/agent-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
name: "claude-code",
|
|
4051
|
-
label: "Claude Code",
|
|
4052
|
-
summary: "Configure Claude Code to route through Poe.",
|
|
4053
|
-
aliases: ["claude"],
|
|
4054
|
-
binaryName: "claude",
|
|
4055
|
-
configPath: "~/.claude/settings.json",
|
|
4056
|
-
branding: {
|
|
4057
|
-
colors: {
|
|
4058
|
-
dark: "#C15F3C",
|
|
4059
|
-
light: "#C15F3C"
|
|
4060
|
-
}
|
|
4061
|
-
}
|
|
4062
|
-
};
|
|
4047
|
+
// packages/agent-harness-tools/src/plans.ts
|
|
4048
|
+
import * as fsPromises4 from "node:fs/promises";
|
|
4049
|
+
import path27 from "node:path";
|
|
4063
4050
|
|
|
4064
|
-
// packages/
|
|
4065
|
-
|
|
4066
|
-
id: "claude-desktop",
|
|
4067
|
-
name: "claude-desktop",
|
|
4068
|
-
label: "Claude Desktop",
|
|
4069
|
-
summary: "Anthropic's official desktop application for Claude",
|
|
4070
|
-
configPath: "~/.claude/settings.json",
|
|
4071
|
-
branding: {
|
|
4072
|
-
colors: {
|
|
4073
|
-
dark: "#D97757",
|
|
4074
|
-
light: "#D97757"
|
|
4075
|
-
}
|
|
4076
|
-
}
|
|
4077
|
-
};
|
|
4051
|
+
// packages/task-list/src/open.ts
|
|
4052
|
+
import * as fsPromises3 from "node:fs/promises";
|
|
4078
4053
|
|
|
4079
|
-
// packages/
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
label: "Codex",
|
|
4084
|
-
summary: "Configure Codex to use Poe as the model provider.",
|
|
4085
|
-
binaryName: "codex",
|
|
4086
|
-
configPath: "~/.codex/config.toml",
|
|
4087
|
-
branding: {
|
|
4088
|
-
colors: {
|
|
4089
|
-
dark: "#D5D9DF",
|
|
4090
|
-
light: "#7A7F86"
|
|
4091
|
-
}
|
|
4054
|
+
// packages/task-list/src/state-machine.ts
|
|
4055
|
+
function canFireFromState(event, fromState) {
|
|
4056
|
+
if (event.from === "*") {
|
|
4057
|
+
return event.to !== fromState;
|
|
4092
4058
|
}
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
label: "OpenCode CLI",
|
|
4100
|
-
summary: "Configure OpenCode CLI to use the Poe API.",
|
|
4101
|
-
binaryName: "opencode",
|
|
4102
|
-
configPath: "~/.config/opencode/config.json",
|
|
4103
|
-
branding: {
|
|
4104
|
-
colors: {
|
|
4105
|
-
dark: "#4A4F55",
|
|
4106
|
-
light: "#2F3338"
|
|
4107
|
-
}
|
|
4059
|
+
return event.from.includes(fromState);
|
|
4060
|
+
}
|
|
4061
|
+
function findEvent(machine, fromState, eventName) {
|
|
4062
|
+
const event = machine.events[eventName];
|
|
4063
|
+
if (event === void 0) {
|
|
4064
|
+
return void 0;
|
|
4108
4065
|
}
|
|
4109
|
-
|
|
4066
|
+
return canFireFromState(event, fromState) ? event : void 0;
|
|
4067
|
+
}
|
|
4110
4068
|
|
|
4111
|
-
// packages/
|
|
4112
|
-
|
|
4113
|
-
id: "kimi",
|
|
4114
|
-
name: "kimi",
|
|
4115
|
-
label: "Kimi",
|
|
4116
|
-
summary: "Configure Kimi CLI to use Poe API",
|
|
4117
|
-
aliases: ["kimi-cli"],
|
|
4118
|
-
binaryName: "kimi",
|
|
4119
|
-
configPath: "~/.kimi/config.toml",
|
|
4120
|
-
branding: {
|
|
4121
|
-
colors: {
|
|
4122
|
-
dark: "#7B68EE",
|
|
4123
|
-
light: "#6A5ACD"
|
|
4124
|
-
}
|
|
4125
|
-
}
|
|
4126
|
-
};
|
|
4069
|
+
// packages/task-list/src/backends/gh-issues-client.ts
|
|
4070
|
+
import { text } from "node:stream/consumers";
|
|
4127
4071
|
|
|
4128
|
-
// packages/
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4072
|
+
// packages/process-runner/src/docker/context.ts
|
|
4073
|
+
import { execSync } from "node:child_process";
|
|
4074
|
+
function detectContext() {
|
|
4075
|
+
try {
|
|
4076
|
+
const output = execSync("colima list --json", {
|
|
4077
|
+
encoding: "utf-8",
|
|
4078
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
4079
|
+
});
|
|
4080
|
+
const lines = output.trim().split("\n").filter(Boolean);
|
|
4081
|
+
for (const line of lines) {
|
|
4082
|
+
const profile = JSON.parse(line);
|
|
4083
|
+
if (profile.status === "Running" && profile.runtime === "docker") {
|
|
4084
|
+
const name = profile.name ?? profile.profile;
|
|
4085
|
+
if (!name) {
|
|
4086
|
+
continue;
|
|
4087
|
+
}
|
|
4088
|
+
return name === "default" ? "colima" : `colima-${name}`;
|
|
4089
|
+
}
|
|
4140
4090
|
}
|
|
4091
|
+
} catch {
|
|
4092
|
+
return null;
|
|
4141
4093
|
}
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
name: "poe-agent",
|
|
4148
|
-
label: "Poe Agent",
|
|
4149
|
-
summary: "Run one-shot prompts with the built-in Poe agent runtime.",
|
|
4150
|
-
configPath: "~/.poe-code/config.json",
|
|
4151
|
-
branding: {
|
|
4152
|
-
colors: {
|
|
4153
|
-
dark: "#A465F7",
|
|
4154
|
-
light: "#7A3FD3"
|
|
4155
|
-
}
|
|
4094
|
+
return null;
|
|
4095
|
+
}
|
|
4096
|
+
function buildContextArgs(engine, context) {
|
|
4097
|
+
if (engine === "docker" && context) {
|
|
4098
|
+
return ["--context", context];
|
|
4156
4099
|
}
|
|
4157
|
-
|
|
4100
|
+
return [];
|
|
4101
|
+
}
|
|
4158
4102
|
|
|
4159
|
-
// packages/
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
poeAgentAgent
|
|
4168
|
-
];
|
|
4169
|
-
var lookup = /* @__PURE__ */ new Map();
|
|
4170
|
-
for (const agent of allAgents) {
|
|
4171
|
-
const values = [agent.id, agent.name, ...agent.aliases ?? []];
|
|
4172
|
-
for (const value of values) {
|
|
4173
|
-
const normalized = value.toLowerCase();
|
|
4174
|
-
if (!lookup.has(normalized)) {
|
|
4175
|
-
lookup.set(normalized, agent.id);
|
|
4176
|
-
}
|
|
4103
|
+
// packages/process-runner/src/docker/engine.ts
|
|
4104
|
+
import { execSync as execSync2 } from "node:child_process";
|
|
4105
|
+
function detectEngine() {
|
|
4106
|
+
if (isEngineAvailable("docker")) {
|
|
4107
|
+
return "docker";
|
|
4108
|
+
}
|
|
4109
|
+
if (isEngineAvailable("podman")) {
|
|
4110
|
+
return "podman";
|
|
4177
4111
|
}
|
|
4112
|
+
throw new Error(
|
|
4113
|
+
"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"
|
|
4114
|
+
);
|
|
4178
4115
|
}
|
|
4179
|
-
function
|
|
4180
|
-
|
|
4181
|
-
|
|
4116
|
+
function isEngineAvailable(engine) {
|
|
4117
|
+
try {
|
|
4118
|
+
execSync2(`${engine} --version`, {
|
|
4119
|
+
stdio: "ignore"
|
|
4120
|
+
});
|
|
4121
|
+
return true;
|
|
4122
|
+
} catch {
|
|
4123
|
+
return false;
|
|
4182
4124
|
}
|
|
4183
|
-
return lookup.get(input.toLowerCase());
|
|
4184
4125
|
}
|
|
4185
4126
|
|
|
4186
|
-
// packages/
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
);
|
|
4190
|
-
var supportedAgents = loopAgents.map((agent) => agent.id).join(", ");
|
|
4127
|
+
// packages/process-runner/src/docker/docker-runner.ts
|
|
4128
|
+
import * as childProcess from "node:child_process";
|
|
4129
|
+
import { randomBytes } from "node:crypto";
|
|
4191
4130
|
|
|
4192
|
-
// packages/
|
|
4131
|
+
// packages/process-runner/src/docker/args.ts
|
|
4193
4132
|
import path23 from "node:path";
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
var POLL_INTERVAL_MS = 250;
|
|
4199
|
-
function wrapForLogTee(argv, jobId) {
|
|
4200
|
-
if (argv.length === 0) {
|
|
4201
|
-
throw new Error("wrapForLogTee requires argv to contain at least one argument");
|
|
4133
|
+
function buildDockerRunArgs(input) {
|
|
4134
|
+
const args = [input.engine];
|
|
4135
|
+
if (input.engine === "docker" && input.context) {
|
|
4136
|
+
args.push("--context", input.context);
|
|
4202
4137
|
}
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
const exitTmpFile = shellQuote(`${jobExitPath(jobId)}.tmp`);
|
|
4207
|
-
const script = [
|
|
4208
|
-
`mkdir -p ${shellQuote(JOB_DIR)}`,
|
|
4209
|
-
`({ (${command}); echo $? > ${exitTmpFile}; } 2>&1 | tee ${logFile}; mv ${exitTmpFile} ${exitFile})`
|
|
4210
|
-
].join(" && ");
|
|
4211
|
-
return ["sh", "-c", script];
|
|
4212
|
-
}
|
|
4213
|
-
async function* streamLogFile(env, jobId, opts) {
|
|
4214
|
-
const fs14 = env.fs ?? nodeFs2;
|
|
4215
|
-
const file = jobLogPath(jobId);
|
|
4216
|
-
let byteOffset = opts.sinceByte ?? 0;
|
|
4217
|
-
while (true) {
|
|
4218
|
-
if (opts.since !== void 0 && !await wasModifiedSince(fs14, file, opts.since)) {
|
|
4219
|
-
await waitForLogChange(fs14, file);
|
|
4220
|
-
continue;
|
|
4221
|
-
}
|
|
4222
|
-
const result = await readLogChunk(fs14, file, byteOffset);
|
|
4223
|
-
if (result !== null) {
|
|
4224
|
-
byteOffset = result.nextByteOffset;
|
|
4225
|
-
yield result.chunk;
|
|
4226
|
-
continue;
|
|
4227
|
-
}
|
|
4228
|
-
await waitForLogChange(fs14, file);
|
|
4138
|
+
args.push("run");
|
|
4139
|
+
if (input.rm) {
|
|
4140
|
+
args.push("--rm");
|
|
4229
4141
|
}
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
if (fs14.promises.stat === void 0) {
|
|
4233
|
-
return true;
|
|
4142
|
+
if (input.detached) {
|
|
4143
|
+
args.push("-d");
|
|
4234
4144
|
}
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
return stat7.mtimeMs >= since.getTime();
|
|
4238
|
-
} catch (error2) {
|
|
4239
|
-
if (isNodeError(error2) && error2.code === "ENOENT") {
|
|
4240
|
-
return false;
|
|
4241
|
-
}
|
|
4242
|
-
throw error2;
|
|
4145
|
+
if (input.interactive) {
|
|
4146
|
+
args.push("-i");
|
|
4243
4147
|
}
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
const fs14 = env.fs ?? nodeFs2;
|
|
4247
|
-
const file = jobExitPath(jobId);
|
|
4248
|
-
while (true) {
|
|
4249
|
-
throwIfAborted2(opts.signal);
|
|
4250
|
-
const contents = await readTextFileIfExists(fs14, file);
|
|
4251
|
-
if (contents !== null) {
|
|
4252
|
-
const text4 = contents.trim();
|
|
4253
|
-
const exitCode = Number(text4);
|
|
4254
|
-
if (text4.length === 0 || !Number.isInteger(exitCode)) {
|
|
4255
|
-
throw new Error(`Invalid exit code in ${file}: ${contents}`);
|
|
4256
|
-
}
|
|
4257
|
-
return { exitCode };
|
|
4258
|
-
}
|
|
4259
|
-
await sleep3(POLL_INTERVAL_MS, opts.signal);
|
|
4148
|
+
if (input.tty) {
|
|
4149
|
+
args.push("-t");
|
|
4260
4150
|
}
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
}
|
|
4265
|
-
function jobExitPath(jobId) {
|
|
4266
|
-
return `${JOB_DIR}/${jobId}.exit`;
|
|
4267
|
-
}
|
|
4268
|
-
async function readLogChunk(fs14, file, byteOffset) {
|
|
4269
|
-
const contents = await readFileIfExists2(fs14, file);
|
|
4270
|
-
if (contents === null || byteOffset >= contents.byteLength) {
|
|
4271
|
-
return null;
|
|
4151
|
+
args.push("--name", input.containerName);
|
|
4152
|
+
if (input.cwd !== void 0) {
|
|
4153
|
+
args.push("-w", input.cwd);
|
|
4272
4154
|
}
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
byteOffset,
|
|
4276
|
-
data: contents.subarray(byteOffset).toString("utf8")
|
|
4277
|
-
},
|
|
4278
|
-
nextByteOffset: contents.byteLength
|
|
4279
|
-
};
|
|
4280
|
-
}
|
|
4281
|
-
async function readTextFileIfExists(fs14, file) {
|
|
4282
|
-
const contents = await readFileIfExists2(fs14, file);
|
|
4283
|
-
return contents?.toString("utf8") ?? null;
|
|
4284
|
-
}
|
|
4285
|
-
async function readFileIfExists2(fs14, file) {
|
|
4286
|
-
try {
|
|
4287
|
-
const contents = await fs14.promises.readFile(file);
|
|
4288
|
-
return Buffer.isBuffer(contents) ? contents : Buffer.from(contents);
|
|
4289
|
-
} catch (error2) {
|
|
4290
|
-
if (isNodeError(error2) && error2.code === "ENOENT") {
|
|
4291
|
-
return null;
|
|
4292
|
-
}
|
|
4293
|
-
throw error2;
|
|
4155
|
+
for (const [key, value] of Object.entries(input.env ?? {})) {
|
|
4156
|
+
args.push("-e", `${key}=${value}`);
|
|
4294
4157
|
}
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
if (typeof watch !== "function") {
|
|
4299
|
-
await sleep3(POLL_INTERVAL_MS);
|
|
4300
|
-
return;
|
|
4158
|
+
for (const mount of input.mounts) {
|
|
4159
|
+
const volume = `${path23.resolve(mount.source)}:${mount.target}${mount.readonly ? ":ro" : ""}`;
|
|
4160
|
+
args.push("-v", volume);
|
|
4301
4161
|
}
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
function done() {
|
|
4306
|
-
clearTimeout(timer);
|
|
4307
|
-
watcher?.close();
|
|
4308
|
-
resolve2();
|
|
4309
|
-
}
|
|
4310
|
-
try {
|
|
4311
|
-
watcher = watch(file, done);
|
|
4312
|
-
} catch {
|
|
4313
|
-
done();
|
|
4314
|
-
}
|
|
4315
|
-
});
|
|
4316
|
-
}
|
|
4317
|
-
function sleep3(ms, signal) {
|
|
4318
|
-
return new Promise((resolve2, reject) => {
|
|
4319
|
-
let timer = null;
|
|
4320
|
-
const abort = () => {
|
|
4321
|
-
if (timer !== null) {
|
|
4322
|
-
clearTimeout(timer);
|
|
4323
|
-
}
|
|
4324
|
-
reject(new Error("waitForExit aborted."));
|
|
4325
|
-
};
|
|
4326
|
-
if (signal?.aborted) {
|
|
4327
|
-
abort();
|
|
4328
|
-
return;
|
|
4329
|
-
}
|
|
4330
|
-
timer = setTimeout(() => {
|
|
4331
|
-
signal?.removeEventListener("abort", abort);
|
|
4332
|
-
resolve2();
|
|
4333
|
-
}, ms);
|
|
4334
|
-
signal?.addEventListener("abort", abort, { once: true });
|
|
4335
|
-
});
|
|
4336
|
-
}
|
|
4337
|
-
function throwIfAborted2(signal) {
|
|
4338
|
-
if (signal?.aborted) {
|
|
4339
|
-
throw new Error("waitForExit aborted.");
|
|
4162
|
+
for (const port of input.ports) {
|
|
4163
|
+
const mapping = `${port.host}:${port.container}${port.protocol === void 0 || port.protocol === "tcp" ? "" : `/${port.protocol}`}`;
|
|
4164
|
+
args.push("-p", mapping);
|
|
4340
4165
|
}
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
return error2 instanceof Error && "code" in error2;
|
|
4166
|
+
if (input.network !== void 0) {
|
|
4167
|
+
args.push("--network", input.network);
|
|
4168
|
+
}
|
|
4169
|
+
args.push(...input.extraArgs, input.image, input.command, ...input.args);
|
|
4170
|
+
return args;
|
|
4347
4171
|
}
|
|
4348
4172
|
|
|
4349
|
-
// packages/
|
|
4350
|
-
import { randomBytes } from "node:crypto";
|
|
4173
|
+
// packages/process-runner/src/docker/docker-execution-env.ts
|
|
4174
|
+
import { createHash as createHash3, randomBytes as randomBytes2 } from "node:crypto";
|
|
4175
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
4176
|
+
import { readFile as readFile10 } from "node:fs/promises";
|
|
4177
|
+
import { tmpdir } from "node:os";
|
|
4178
|
+
import path24 from "node:path";
|
|
4351
4179
|
|
|
4352
|
-
// packages/
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
args
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4180
|
+
// packages/process-runner/src/host/host-runner.ts
|
|
4181
|
+
import { spawn as spawnChildProcess } from "node:child_process";
|
|
4182
|
+
function createHostRunner(options = {}) {
|
|
4183
|
+
const detached = options.detached === true;
|
|
4184
|
+
return {
|
|
4185
|
+
name: "host",
|
|
4186
|
+
exec(spec) {
|
|
4187
|
+
const stdinMode = spec.stdin ?? "ignore";
|
|
4188
|
+
const stdoutMode = spec.stdout ?? "pipe";
|
|
4189
|
+
const stderrMode = spec.stderr ?? "pipe";
|
|
4190
|
+
const stdio = stdinMode === "inherit" && stdoutMode === "inherit" && stderrMode === "inherit" ? "inherit" : [stdinMode, stdoutMode, stderrMode];
|
|
4191
|
+
const child = spawnChildProcess(spec.command, spec.args ?? [], {
|
|
4192
|
+
cwd: spec.cwd,
|
|
4193
|
+
env: spec.env,
|
|
4194
|
+
stdio,
|
|
4195
|
+
...detached ? { detached: true } : {}
|
|
4196
|
+
});
|
|
4197
|
+
if (detached) {
|
|
4198
|
+
child.unref();
|
|
4199
|
+
}
|
|
4200
|
+
const kill = (signal) => {
|
|
4201
|
+
if (detached && process.platform !== "win32" && child.pid !== void 0) {
|
|
4202
|
+
process.kill(-child.pid, signal);
|
|
4203
|
+
return;
|
|
4204
|
+
}
|
|
4205
|
+
child.kill(signal);
|
|
4206
|
+
};
|
|
4207
|
+
let settled = false;
|
|
4208
|
+
let resolveResult = null;
|
|
4209
|
+
const result = new Promise((resolve2) => {
|
|
4210
|
+
resolveResult = resolve2;
|
|
4211
|
+
});
|
|
4212
|
+
const cleanupAbort = bindAbortSignal(spec.signal, () => {
|
|
4213
|
+
kill("SIGTERM");
|
|
4214
|
+
});
|
|
4215
|
+
child.once("close", (code) => {
|
|
4216
|
+
if (settled) return;
|
|
4217
|
+
settled = true;
|
|
4218
|
+
cleanupAbort();
|
|
4219
|
+
resolveResult?.({ exitCode: code ?? 1 });
|
|
4220
|
+
});
|
|
4221
|
+
child.once("error", () => {
|
|
4222
|
+
if (settled) return;
|
|
4223
|
+
settled = true;
|
|
4224
|
+
cleanupAbort();
|
|
4225
|
+
resolveResult?.({ exitCode: 1 });
|
|
4226
|
+
});
|
|
4227
|
+
return {
|
|
4228
|
+
pid: child.pid ?? null,
|
|
4229
|
+
stdin: child.stdin,
|
|
4230
|
+
stdout: child.stdout,
|
|
4231
|
+
stderr: child.stderr,
|
|
4232
|
+
result,
|
|
4233
|
+
kill
|
|
4234
|
+
};
|
|
4375
4235
|
}
|
|
4376
|
-
|
|
4236
|
+
};
|
|
4237
|
+
}
|
|
4238
|
+
function bindAbortSignal(signal, onAbort) {
|
|
4239
|
+
if (signal === void 0) {
|
|
4240
|
+
return () => {
|
|
4241
|
+
};
|
|
4242
|
+
}
|
|
4243
|
+
if (signal.aborted) {
|
|
4244
|
+
onAbort();
|
|
4245
|
+
return () => {
|
|
4246
|
+
};
|
|
4247
|
+
}
|
|
4248
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
4249
|
+
return () => {
|
|
4250
|
+
signal.removeEventListener("abort", onAbort);
|
|
4251
|
+
};
|
|
4377
4252
|
}
|
|
4378
4253
|
|
|
4379
|
-
// packages/
|
|
4380
|
-
var
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
const opened = opts.factory.open(opts.openSpec);
|
|
4396
|
-
const env = isPromiseLike(opened) ? await opened : opened;
|
|
4397
|
-
let shouldClose = true;
|
|
4398
|
-
try {
|
|
4399
|
-
const upload = env.uploadWorkspace();
|
|
4400
|
-
await Promise.all([pendingJob, upload]);
|
|
4401
|
-
await configureE2bSpawnAgentIfAvailable({
|
|
4402
|
-
env,
|
|
4403
|
-
openSpec: opts.openSpec,
|
|
4404
|
-
factoryType: opts.factory.type
|
|
4405
|
-
});
|
|
4406
|
-
const argv = wrapCommand ? wrapForLogTee(opts.openSpec.jobLabel.argv, jobId) : opts.openSpec.jobLabel.argv;
|
|
4407
|
-
const handle = execution?.tty ? env.shell() : env.exec({
|
|
4408
|
-
command: argv[0],
|
|
4409
|
-
args: argv.slice(1),
|
|
4410
|
-
cwd: opts.openSpec.cwd,
|
|
4411
|
-
env: resolveExecutionEnv(opts.openSpec),
|
|
4412
|
-
stdin: execution?.stdin ?? "inherit",
|
|
4413
|
-
stdout: execution?.stdout ?? "pipe",
|
|
4414
|
-
stderr: execution?.stderr ?? "pipe",
|
|
4415
|
-
signal: opts.signal
|
|
4254
|
+
// packages/process-runner/src/docker/docker-execution-env.ts
|
|
4255
|
+
var containerCommand = ["sh", "-c", "while :; do sleep 3600; done"];
|
|
4256
|
+
var dockerExecutionEnvFactory = {
|
|
4257
|
+
type: "docker",
|
|
4258
|
+
supportsDetach: true,
|
|
4259
|
+
async open(spec) {
|
|
4260
|
+
const runtime = parseDockerRuntime(spec.runtime);
|
|
4261
|
+
const runner = spec.hostRunner ?? createHostRunner();
|
|
4262
|
+
const engine = runtime.engine ?? detectEngine();
|
|
4263
|
+
const context = detectContext();
|
|
4264
|
+
const image = await resolveImage({
|
|
4265
|
+
spec,
|
|
4266
|
+
runtime,
|
|
4267
|
+
runner,
|
|
4268
|
+
engine,
|
|
4269
|
+
context
|
|
4416
4270
|
});
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4271
|
+
const containerName = createContainerName();
|
|
4272
|
+
const runArgs = buildDockerRunArgs({
|
|
4273
|
+
engine,
|
|
4274
|
+
context,
|
|
4275
|
+
image,
|
|
4276
|
+
command: containerCommand[0],
|
|
4277
|
+
args: containerCommand.slice(1),
|
|
4278
|
+
cwd: void 0,
|
|
4279
|
+
env: void 0,
|
|
4280
|
+
mounts: runtime.mounts ?? [],
|
|
4281
|
+
ports: [],
|
|
4282
|
+
network: runtime.network,
|
|
4283
|
+
containerName,
|
|
4284
|
+
detached: true,
|
|
4285
|
+
interactive: true,
|
|
4286
|
+
tty: false,
|
|
4287
|
+
rm: false,
|
|
4288
|
+
extraArgs: runtime.extra_args ?? []
|
|
4425
4289
|
});
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
shouldClose = false;
|
|
4435
|
-
return { kind: "detached", jobId, envId: env.id };
|
|
4436
|
-
}
|
|
4437
|
-
const result = await runSync({
|
|
4438
|
-
env,
|
|
4439
|
-
handle,
|
|
4440
|
-
jobId,
|
|
4441
|
-
openSpec: opts.openSpec,
|
|
4442
|
-
signal: opts.signal,
|
|
4443
|
-
wrapCommand
|
|
4290
|
+
const [command, ...args] = runArgs;
|
|
4291
|
+
const id = (await runAndRead(runner, { command, args, stdout: "pipe", stderr: "pipe" })).trim();
|
|
4292
|
+
return createDockerEnv({
|
|
4293
|
+
id,
|
|
4294
|
+
spec,
|
|
4295
|
+
runner,
|
|
4296
|
+
engine,
|
|
4297
|
+
context
|
|
4444
4298
|
});
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4299
|
+
},
|
|
4300
|
+
async attach(envId, context) {
|
|
4301
|
+
const engine = detectEngine();
|
|
4302
|
+
return createDockerEnv({
|
|
4303
|
+
id: envId,
|
|
4304
|
+
spec: createAttachedSpec(context?.cwd),
|
|
4305
|
+
runner: createHostRunner(),
|
|
4306
|
+
engine,
|
|
4307
|
+
context: detectContext(),
|
|
4308
|
+
attachedJobId: context?.jobId
|
|
4451
4309
|
});
|
|
4452
|
-
return {
|
|
4453
|
-
kind: "sync",
|
|
4454
|
-
exitCode: result.exitCode,
|
|
4455
|
-
download: result.download,
|
|
4456
|
-
...result.stdout !== void 0 ? { stdout: result.stdout } : {},
|
|
4457
|
-
...result.stderr !== void 0 ? { stderr: result.stderr } : {}
|
|
4458
|
-
};
|
|
4459
|
-
} finally {
|
|
4460
|
-
if (shouldClose) {
|
|
4461
|
-
await env.close();
|
|
4462
|
-
}
|
|
4463
4310
|
}
|
|
4311
|
+
};
|
|
4312
|
+
function createDockerEnv(input) {
|
|
4313
|
+
const containerRef = input.id;
|
|
4314
|
+
return {
|
|
4315
|
+
id: containerRef,
|
|
4316
|
+
job: input.attachedJobId === void 0 ? null : createContainerJob(containerRef, input.runner, input.engine, input.context, input.attachedJobId),
|
|
4317
|
+
async uploadWorkspace() {
|
|
4318
|
+
const tempDir = mkdtempSync(path24.join(tmpdir(), "poe-docker-upload-"));
|
|
4319
|
+
const archivePath = path24.join(tempDir, "workspace.tar");
|
|
4320
|
+
try {
|
|
4321
|
+
const excludeArgs = input.spec.uploadIgnoreFiles.flatMap((ignored) => [
|
|
4322
|
+
"--exclude",
|
|
4323
|
+
ignored
|
|
4324
|
+
]);
|
|
4325
|
+
const tarArgs = [...excludeArgs, "-cf", archivePath, "-C", input.spec.cwd, "."];
|
|
4326
|
+
await runOrThrow(input.runner, {
|
|
4327
|
+
command: "tar",
|
|
4328
|
+
args: tarArgs,
|
|
4329
|
+
stdout: "pipe",
|
|
4330
|
+
stderr: "pipe"
|
|
4331
|
+
});
|
|
4332
|
+
await runOrThrow(input.runner, {
|
|
4333
|
+
command: input.engine,
|
|
4334
|
+
args: [
|
|
4335
|
+
...buildContextArgs(input.engine, input.context),
|
|
4336
|
+
"cp",
|
|
4337
|
+
archivePath,
|
|
4338
|
+
`${containerRef}:/tmp/poe-workspace-upload.tar`
|
|
4339
|
+
],
|
|
4340
|
+
stdout: "pipe",
|
|
4341
|
+
stderr: "pipe"
|
|
4342
|
+
});
|
|
4343
|
+
await runOrThrow(input.runner, {
|
|
4344
|
+
command: input.engine,
|
|
4345
|
+
args: [
|
|
4346
|
+
...buildContextArgs(input.engine, input.context),
|
|
4347
|
+
"exec",
|
|
4348
|
+
containerRef,
|
|
4349
|
+
"sh",
|
|
4350
|
+
"-c",
|
|
4351
|
+
`mkdir -p ${shellQuote(input.spec.cwd)} && tar -xf /tmp/poe-workspace-upload.tar -C ${shellQuote(input.spec.cwd)}`
|
|
4352
|
+
],
|
|
4353
|
+
stdout: "pipe",
|
|
4354
|
+
stderr: "pipe"
|
|
4355
|
+
});
|
|
4356
|
+
return { files: 0, bytes: 0, skipped: [] };
|
|
4357
|
+
} finally {
|
|
4358
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
4359
|
+
}
|
|
4360
|
+
},
|
|
4361
|
+
async downloadWorkspace(opts) {
|
|
4362
|
+
const tempDir = mkdtempSync(path24.join(tmpdir(), "poe-docker-download-"));
|
|
4363
|
+
const archivePath = path24.join(tempDir, "workspace.tar");
|
|
4364
|
+
try {
|
|
4365
|
+
await runOrThrow(input.runner, {
|
|
4366
|
+
command: input.engine,
|
|
4367
|
+
args: [
|
|
4368
|
+
...buildContextArgs(input.engine, input.context),
|
|
4369
|
+
"exec",
|
|
4370
|
+
containerRef,
|
|
4371
|
+
"sh",
|
|
4372
|
+
"-c",
|
|
4373
|
+
`tar -cf /tmp/poe-workspace-download.tar -C ${shellQuote(input.spec.cwd)} .`
|
|
4374
|
+
],
|
|
4375
|
+
stdout: "pipe",
|
|
4376
|
+
stderr: "pipe"
|
|
4377
|
+
});
|
|
4378
|
+
await runOrThrow(input.runner, {
|
|
4379
|
+
command: input.engine,
|
|
4380
|
+
args: [
|
|
4381
|
+
...buildContextArgs(input.engine, input.context),
|
|
4382
|
+
"cp",
|
|
4383
|
+
`${containerRef}:/tmp/poe-workspace-download.tar`,
|
|
4384
|
+
archivePath
|
|
4385
|
+
],
|
|
4386
|
+
stdout: "pipe",
|
|
4387
|
+
stderr: "pipe"
|
|
4388
|
+
});
|
|
4389
|
+
const extractMode = opts.conflictPolicy === "refuse" ? "-xkf" : "-xf";
|
|
4390
|
+
await runOrThrow(input.runner, {
|
|
4391
|
+
command: "tar",
|
|
4392
|
+
args: [extractMode, archivePath, "-C", input.spec.cwd],
|
|
4393
|
+
stdout: "pipe",
|
|
4394
|
+
stderr: "pipe"
|
|
4395
|
+
});
|
|
4396
|
+
return { files: 0, bytes: 0, conflicts: [] };
|
|
4397
|
+
} finally {
|
|
4398
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
4399
|
+
}
|
|
4400
|
+
},
|
|
4401
|
+
exec(spec) {
|
|
4402
|
+
return input.runner.exec({
|
|
4403
|
+
command: input.engine,
|
|
4404
|
+
args: [
|
|
4405
|
+
...buildContextArgs(input.engine, input.context),
|
|
4406
|
+
"exec",
|
|
4407
|
+
...spec.stdin === "pipe" || spec.stdin === "inherit" ? ["-i"] : [],
|
|
4408
|
+
...spec.tty === true ? ["-t"] : [],
|
|
4409
|
+
...spec.cwd !== void 0 ? ["-w", spec.cwd] : [],
|
|
4410
|
+
...buildEnvArgs(spec.env),
|
|
4411
|
+
containerRef,
|
|
4412
|
+
spec.command,
|
|
4413
|
+
...spec.args ?? []
|
|
4414
|
+
],
|
|
4415
|
+
stdin: spec.stdin,
|
|
4416
|
+
stdout: spec.stdout,
|
|
4417
|
+
stderr: spec.stderr,
|
|
4418
|
+
tty: spec.tty
|
|
4419
|
+
});
|
|
4420
|
+
},
|
|
4421
|
+
async detach() {
|
|
4422
|
+
return createContainerJob(containerRef, input.runner, input.engine, input.context);
|
|
4423
|
+
},
|
|
4424
|
+
shell() {
|
|
4425
|
+
const shellSpec = input.spec.shellSpec;
|
|
4426
|
+
return this.exec({
|
|
4427
|
+
command: shellSpec?.command ?? input.spec.env.SHELL ?? "sh",
|
|
4428
|
+
...shellSpec?.args ? { args: shellSpec.args } : {},
|
|
4429
|
+
cwd: input.spec.cwd,
|
|
4430
|
+
env: shellSpec && "env" in shellSpec ? shellSpec.env : input.spec.env,
|
|
4431
|
+
stdin: "inherit",
|
|
4432
|
+
stdout: "inherit",
|
|
4433
|
+
stderr: "inherit",
|
|
4434
|
+
tty: true
|
|
4435
|
+
});
|
|
4436
|
+
},
|
|
4437
|
+
async close() {
|
|
4438
|
+
await runOrThrow(input.runner, {
|
|
4439
|
+
command: input.engine,
|
|
4440
|
+
args: [...buildContextArgs(input.engine, input.context), "rm", "-f", containerRef],
|
|
4441
|
+
stdout: "pipe",
|
|
4442
|
+
stderr: "pipe"
|
|
4443
|
+
});
|
|
4444
|
+
}
|
|
4445
|
+
};
|
|
4464
4446
|
}
|
|
4465
|
-
async function
|
|
4466
|
-
if (
|
|
4467
|
-
return;
|
|
4468
|
-
}
|
|
4469
|
-
const agentId = resolveAgentId(opts.openSpec.jobLabel.tool);
|
|
4470
|
-
const agent = allAgents.find((candidate) => candidate.id === agentId);
|
|
4471
|
-
const binaryName = agent?.binaryName;
|
|
4472
|
-
if (!agentId || !binaryName) {
|
|
4473
|
-
return;
|
|
4447
|
+
async function resolveImage(input) {
|
|
4448
|
+
if (input.runtime.image !== void 0) {
|
|
4449
|
+
return input.runtime.image;
|
|
4474
4450
|
}
|
|
4475
|
-
const
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4451
|
+
const result = await buildDockerRuntimeTemplate({
|
|
4452
|
+
cwd: input.spec.cwd,
|
|
4453
|
+
runtime: input.runtime,
|
|
4454
|
+
state: input.spec.state,
|
|
4455
|
+
runner: input.runner
|
|
4480
4456
|
});
|
|
4481
|
-
|
|
4482
|
-
|
|
4457
|
+
return result.image;
|
|
4458
|
+
}
|
|
4459
|
+
async function buildDockerRuntimeTemplate(input) {
|
|
4460
|
+
const runner = input.runner ?? createHostRunner();
|
|
4461
|
+
const engine = input.runtime.engine ?? detectEngine();
|
|
4462
|
+
const context = detectContext();
|
|
4463
|
+
const dockerfilePath = path24.resolve(
|
|
4464
|
+
input.cwd,
|
|
4465
|
+
input.runtime.dockerfile ?? path24.join(".poe-code", "Dockerfile")
|
|
4466
|
+
);
|
|
4467
|
+
const buildContext = path24.resolve(input.cwd, input.runtime.build_context ?? ".");
|
|
4468
|
+
const dockerfileBytes = await readFile10(dockerfilePath);
|
|
4469
|
+
const hash = hashDockerTemplate(dockerfileBytes, input.runtime.build_args ?? {});
|
|
4470
|
+
const cached2 = input.force ? null : await input.state?.templates.get("docker", hash);
|
|
4471
|
+
if (cached2?.image !== void 0) {
|
|
4472
|
+
return {
|
|
4473
|
+
backend: "docker",
|
|
4474
|
+
hash,
|
|
4475
|
+
image: cached2.image,
|
|
4476
|
+
cached: true
|
|
4477
|
+
};
|
|
4483
4478
|
}
|
|
4484
|
-
const
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4479
|
+
const image = `poe-code/local:${hash}`;
|
|
4480
|
+
await buildImage({
|
|
4481
|
+
runner,
|
|
4482
|
+
engine,
|
|
4483
|
+
context,
|
|
4484
|
+
image,
|
|
4485
|
+
dockerfilePath,
|
|
4486
|
+
buildContext,
|
|
4487
|
+
buildArgs: input.runtime.build_args ?? {}
|
|
4489
4488
|
});
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4489
|
+
await input.state?.templates.put("docker", {
|
|
4490
|
+
hash,
|
|
4491
|
+
image,
|
|
4492
|
+
runtime_type: "docker",
|
|
4493
|
+
dockerfile_path: dockerfilePath,
|
|
4494
|
+
built_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
4495
|
+
});
|
|
4496
|
+
return {
|
|
4497
|
+
backend: "docker",
|
|
4498
|
+
hash,
|
|
4499
|
+
image,
|
|
4500
|
+
cached: false
|
|
4501
|
+
};
|
|
4496
4502
|
}
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
}
|
|
4503
|
+
function hashDockerTemplate(dockerfileBytes, buildArgs) {
|
|
4504
|
+
const hash = createHash3("sha256");
|
|
4505
|
+
hash.update(dockerfileBytes);
|
|
4506
|
+
hash.update("\0");
|
|
4507
|
+
for (const [key, value] of sortedBuildArgs(buildArgs)) {
|
|
4508
|
+
hash.update(key);
|
|
4509
|
+
hash.update("=");
|
|
4510
|
+
hash.update(value);
|
|
4511
|
+
hash.update("\0");
|
|
4507
4512
|
}
|
|
4508
|
-
return
|
|
4509
|
-
}
|
|
4510
|
-
function resolveExecutionEnv(openSpec) {
|
|
4511
|
-
const execution = openSpec.execution;
|
|
4512
|
-
return execution?.env ?? openSpec.env;
|
|
4513
|
+
return hash.digest("hex");
|
|
4513
4514
|
}
|
|
4514
|
-
async function
|
|
4515
|
-
|
|
4516
|
-
command:
|
|
4517
|
-
args:
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4515
|
+
async function buildImage(input) {
|
|
4516
|
+
await runOrThrow(input.runner, {
|
|
4517
|
+
command: input.engine,
|
|
4518
|
+
args: [
|
|
4519
|
+
...buildContextArgs(input.engine, input.context),
|
|
4520
|
+
"build",
|
|
4521
|
+
"--tag",
|
|
4522
|
+
input.image,
|
|
4523
|
+
"-f",
|
|
4524
|
+
input.dockerfilePath,
|
|
4525
|
+
...sortedBuildArgs(input.buildArgs).flatMap(([key, value]) => [
|
|
4526
|
+
"--build-arg",
|
|
4527
|
+
`${key}=${value}`
|
|
4528
|
+
]),
|
|
4529
|
+
input.buildContext
|
|
4530
|
+
],
|
|
4521
4531
|
stdout: "pipe",
|
|
4522
4532
|
stderr: "pipe"
|
|
4523
4533
|
});
|
|
4534
|
+
}
|
|
4535
|
+
function parseDockerRuntime(runtime) {
|
|
4536
|
+
if (!runtime || typeof runtime !== "object" || Array.isArray(runtime)) {
|
|
4537
|
+
throw new Error("docker runtime must be an object");
|
|
4538
|
+
}
|
|
4539
|
+
const record = runtime;
|
|
4540
|
+
if (record.type !== "docker") {
|
|
4541
|
+
throw new Error('docker runtime type must be "docker"');
|
|
4542
|
+
}
|
|
4543
|
+
return record;
|
|
4544
|
+
}
|
|
4545
|
+
async function runAndRead(runner, spec) {
|
|
4546
|
+
const handle = runner.exec(spec);
|
|
4524
4547
|
const stdout = readStream(handle.stdout);
|
|
4525
4548
|
const stderr = readStream(handle.stderr);
|
|
4526
4549
|
const result = await handle.result;
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4550
|
+
const output = await stdout;
|
|
4551
|
+
if (result.exitCode !== 0) {
|
|
4552
|
+
const errorOutput = await stderr;
|
|
4553
|
+
throw new Error(
|
|
4554
|
+
`Command failed with exit code ${result.exitCode}: ${spec.command} ${(spec.args ?? []).join(" ")}${errorOutput ? `
|
|
4555
|
+
${errorOutput}` : ""}`
|
|
4556
|
+
);
|
|
4557
|
+
}
|
|
4558
|
+
return output;
|
|
4532
4559
|
}
|
|
4533
|
-
function
|
|
4534
|
-
|
|
4535
|
-
|
|
4560
|
+
async function runOrThrow(runner, spec) {
|
|
4561
|
+
await runAndRead(runner, spec);
|
|
4562
|
+
}
|
|
4563
|
+
async function readStream(stream) {
|
|
4564
|
+
if (stream === null) {
|
|
4565
|
+
return "";
|
|
4536
4566
|
}
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
stream.on("error", reject);
|
|
4544
|
-
stream.on("end", () => resolve2(output));
|
|
4545
|
-
});
|
|
4567
|
+
stream.setEncoding("utf8");
|
|
4568
|
+
const chunks = [];
|
|
4569
|
+
for await (const chunk of stream) {
|
|
4570
|
+
chunks.push(String(chunk));
|
|
4571
|
+
}
|
|
4572
|
+
return chunks.join("");
|
|
4546
4573
|
}
|
|
4547
|
-
function
|
|
4548
|
-
return [
|
|
4549
|
-
`Exit code: ${result.exitCode}`,
|
|
4550
|
-
result.stdout.trim() ? `stdout:
|
|
4551
|
-
${result.stdout.trim()}` : "",
|
|
4552
|
-
result.stderr.trim() ? `stderr:
|
|
4553
|
-
${result.stderr.trim()}` : ""
|
|
4554
|
-
].filter(Boolean).join("\n");
|
|
4574
|
+
function sortedBuildArgs(buildArgs) {
|
|
4575
|
+
return Object.entries(buildArgs).sort(([left], [right]) => left.localeCompare(right));
|
|
4555
4576
|
}
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4577
|
+
function buildEnvArgs(env) {
|
|
4578
|
+
if (env === void 0) {
|
|
4579
|
+
return [];
|
|
4580
|
+
}
|
|
4581
|
+
return Object.entries(env).flatMap(([key, value]) => ["-e", `${key}=${value}`]);
|
|
4582
|
+
}
|
|
4583
|
+
function createContainerName() {
|
|
4584
|
+
return `poe-env-${randomBytes2(6).toString("hex")}`;
|
|
4585
|
+
}
|
|
4586
|
+
function createContainerJob(containerId, runner, engine, context, jobId = containerId) {
|
|
4587
|
+
return {
|
|
4588
|
+
id: jobId,
|
|
4589
|
+
envId: containerId,
|
|
4590
|
+
tool: "docker",
|
|
4591
|
+
argv: ["attach", containerId],
|
|
4592
|
+
async status() {
|
|
4593
|
+
const handle = runner.exec({
|
|
4594
|
+
command: engine,
|
|
4595
|
+
args: [
|
|
4596
|
+
...buildContextArgs(engine, context),
|
|
4597
|
+
"inspect",
|
|
4598
|
+
"-f",
|
|
4599
|
+
"{{.State.Status}}",
|
|
4600
|
+
containerId
|
|
4601
|
+
],
|
|
4602
|
+
stdout: "pipe",
|
|
4603
|
+
stderr: "pipe"
|
|
4604
|
+
});
|
|
4605
|
+
const stdout = await readStream(handle.stdout);
|
|
4606
|
+
const result = await handle.result;
|
|
4607
|
+
if (result.exitCode !== 0) {
|
|
4608
|
+
return "lost";
|
|
4609
|
+
}
|
|
4610
|
+
return stdout.trim() === "running" ? "running" : "exited";
|
|
4611
|
+
},
|
|
4612
|
+
async *stream(opts) {
|
|
4613
|
+
const handle = runner.exec({
|
|
4614
|
+
command: engine,
|
|
4615
|
+
args: [
|
|
4616
|
+
...buildContextArgs(engine, context),
|
|
4617
|
+
"exec",
|
|
4618
|
+
containerId,
|
|
4619
|
+
"sh",
|
|
4620
|
+
"-c",
|
|
4621
|
+
`test -f ${shellQuote(`/tmp/poe-jobs/${jobId}.log`)} && tail -c +${(opts?.sinceByte ?? 0) + 1} ${shellQuote(`/tmp/poe-jobs/${jobId}.log`)} || true`
|
|
4622
|
+
],
|
|
4623
|
+
stdout: "pipe",
|
|
4624
|
+
stderr: "pipe"
|
|
4625
|
+
});
|
|
4626
|
+
const stdout = await readStream(handle.stdout);
|
|
4627
|
+
await handle.result;
|
|
4628
|
+
if (stdout.length > 0) {
|
|
4629
|
+
yield { byteOffset: opts?.sinceByte ?? 0, data: stdout };
|
|
4630
|
+
}
|
|
4631
|
+
},
|
|
4632
|
+
async wait() {
|
|
4633
|
+
const handle = runner.exec({
|
|
4634
|
+
command: engine,
|
|
4635
|
+
args: [...buildContextArgs(engine, context), "wait", containerId],
|
|
4636
|
+
stdout: "pipe",
|
|
4637
|
+
stderr: "pipe"
|
|
4638
|
+
});
|
|
4639
|
+
const stdout = await readStream(handle.stdout);
|
|
4640
|
+
const result = await handle.result;
|
|
4641
|
+
return { exitCode: Number.parseInt(stdout.trim(), 10) || result.exitCode };
|
|
4642
|
+
},
|
|
4643
|
+
async kill(signal) {
|
|
4644
|
+
const args = signal === void 0 || signal === "SIGTERM" ? ["stop", containerId] : ["kill", ...signal === "SIGKILL" ? [] : [`--signal=${signal}`], containerId];
|
|
4645
|
+
await runOrThrow(runner, {
|
|
4646
|
+
command: engine,
|
|
4647
|
+
args: [...buildContextArgs(engine, context), ...args],
|
|
4648
|
+
stdout: "pipe",
|
|
4649
|
+
stderr: "pipe"
|
|
4650
|
+
});
|
|
4569
4651
|
}
|
|
4570
|
-
|
|
4571
|
-
exitCode,
|
|
4572
|
-
download,
|
|
4573
|
-
...capture ? { stdout: streamState.stdout(), stderr: streamState.stderr() } : {}
|
|
4574
|
-
};
|
|
4575
|
-
} finally {
|
|
4576
|
-
abort.dispose();
|
|
4577
|
-
streamState.dispose();
|
|
4578
|
-
}
|
|
4652
|
+
};
|
|
4579
4653
|
}
|
|
4580
|
-
function
|
|
4581
|
-
handle.stdout?.pipe(process.stdout, { end: false });
|
|
4582
|
-
handle.stderr?.pipe(process.stderr, { end: false });
|
|
4654
|
+
function createAttachedSpec(cwd = "/workspace") {
|
|
4583
4655
|
return {
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4656
|
+
cwd,
|
|
4657
|
+
runtime: {
|
|
4658
|
+
type: "docker",
|
|
4659
|
+
image: "attached",
|
|
4660
|
+
build_args: {},
|
|
4661
|
+
mounts: []
|
|
4662
|
+
},
|
|
4663
|
+
env: {},
|
|
4664
|
+
uploadIgnoreFiles: [],
|
|
4665
|
+
jobLabel: {
|
|
4666
|
+
tool: "docker",
|
|
4667
|
+
argv: []
|
|
4589
4668
|
}
|
|
4590
4669
|
};
|
|
4591
4670
|
}
|
|
4592
|
-
function
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4671
|
+
function shellQuote(value) {
|
|
4672
|
+
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
4673
|
+
}
|
|
4674
|
+
|
|
4675
|
+
// packages/process-runner/src/host/host-execution-env.ts
|
|
4676
|
+
var hostExecutionEnvFactory = {
|
|
4677
|
+
type: "host",
|
|
4678
|
+
supportsDetach: false,
|
|
4679
|
+
async open(openSpec) {
|
|
4680
|
+
return {
|
|
4681
|
+
id: "host",
|
|
4682
|
+
job: null,
|
|
4683
|
+
async uploadWorkspace() {
|
|
4684
|
+
return {
|
|
4685
|
+
files: 0,
|
|
4686
|
+
bytes: 0,
|
|
4687
|
+
skipped: []
|
|
4688
|
+
};
|
|
4689
|
+
},
|
|
4690
|
+
async downloadWorkspace() {
|
|
4691
|
+
return {
|
|
4692
|
+
files: 0,
|
|
4693
|
+
bytes: 0,
|
|
4694
|
+
conflicts: []
|
|
4695
|
+
};
|
|
4696
|
+
},
|
|
4697
|
+
exec(spec) {
|
|
4698
|
+
return createHostRunner().exec(spec);
|
|
4699
|
+
},
|
|
4700
|
+
async detach() {
|
|
4701
|
+
throw new Error("host runtime does not support detach because host has no addressable env");
|
|
4702
|
+
},
|
|
4703
|
+
shell() {
|
|
4704
|
+
const shellSpec = openSpec.shellSpec;
|
|
4705
|
+
return createHostRunner().exec({
|
|
4706
|
+
command: shellSpec?.command ?? openSpec.env.SHELL ?? process.env.SHELL ?? "sh",
|
|
4707
|
+
...shellSpec?.args ? { args: shellSpec.args } : {},
|
|
4708
|
+
cwd: openSpec.cwd,
|
|
4709
|
+
env: shellSpec && "env" in shellSpec ? shellSpec.env : openSpec.env,
|
|
4710
|
+
stdin: "inherit",
|
|
4711
|
+
stdout: "inherit",
|
|
4712
|
+
stderr: "inherit",
|
|
4713
|
+
tty: true
|
|
4714
|
+
});
|
|
4715
|
+
},
|
|
4716
|
+
async close() {
|
|
4717
|
+
}
|
|
4602
4718
|
};
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4719
|
+
},
|
|
4720
|
+
async attach() {
|
|
4721
|
+
throw new Error("host runtime does not support reattach");
|
|
4722
|
+
}
|
|
4723
|
+
};
|
|
4724
|
+
|
|
4725
|
+
// packages/process-runner/src/testing/mock-runner.ts
|
|
4726
|
+
import { Readable, Writable } from "node:stream";
|
|
4727
|
+
|
|
4728
|
+
// packages/task-list/src/backends/utils.ts
|
|
4729
|
+
import path25 from "node:path";
|
|
4730
|
+
|
|
4731
|
+
// packages/task-list/src/backends/markdown-dir.ts
|
|
4732
|
+
import path26 from "node:path";
|
|
4733
|
+
import { parseDocument as parseDocument2, stringify as stringify2 } from "yaml";
|
|
4734
|
+
|
|
4735
|
+
// packages/task-list/src/schema/task.schema.json
|
|
4736
|
+
var task_schema_default = {
|
|
4737
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
4738
|
+
$id: "https://poe-platform.github.io/poe-code/schemas/task-list/task.schema.json",
|
|
4739
|
+
title: "Task",
|
|
4740
|
+
description: "Persisted task payload used by task-list backends.",
|
|
4741
|
+
type: "object",
|
|
4742
|
+
properties: {
|
|
4743
|
+
$schema: {
|
|
4744
|
+
type: "string",
|
|
4745
|
+
const: "https://poe-platform.github.io/poe-code/schemas/task-list/task.schema.json"
|
|
4746
|
+
},
|
|
4747
|
+
kind: {
|
|
4748
|
+
type: "string",
|
|
4749
|
+
const: "task"
|
|
4750
|
+
},
|
|
4751
|
+
version: {
|
|
4752
|
+
type: "integer",
|
|
4753
|
+
const: 1
|
|
4754
|
+
},
|
|
4755
|
+
name: {
|
|
4756
|
+
type: "string",
|
|
4757
|
+
minLength: 1
|
|
4758
|
+
},
|
|
4759
|
+
state: {
|
|
4760
|
+
type: "string"
|
|
4761
|
+
},
|
|
4762
|
+
description: {
|
|
4763
|
+
type: "string"
|
|
4764
|
+
}
|
|
4765
|
+
},
|
|
4766
|
+
required: ["name", "state"],
|
|
4767
|
+
additionalProperties: true
|
|
4768
|
+
};
|
|
4769
|
+
|
|
4770
|
+
// packages/task-list/src/state.ts
|
|
4771
|
+
var defaultStateMachine = {
|
|
4772
|
+
initial: "draft",
|
|
4773
|
+
states: ["draft", "planned", "in-progress", "done", "archived"],
|
|
4774
|
+
events: {
|
|
4775
|
+
plan: { from: ["draft"], to: "planned" },
|
|
4776
|
+
start: { from: ["planned"], to: "in-progress" },
|
|
4777
|
+
complete: { from: ["in-progress"], to: "done" },
|
|
4778
|
+
archive: { from: "*", to: "archived" }
|
|
4779
|
+
}
|
|
4780
|
+
};
|
|
4781
|
+
function deriveLegacyTransitions(machine) {
|
|
4782
|
+
const transitions = Object.fromEntries(
|
|
4783
|
+
machine.states.map((state) => [state, /* @__PURE__ */ new Set()])
|
|
4784
|
+
);
|
|
4785
|
+
for (const fromState of machine.states) {
|
|
4786
|
+
for (const eventName of Object.keys(machine.events)) {
|
|
4787
|
+
const event = findEvent(machine, fromState, eventName);
|
|
4788
|
+
if (event !== void 0) {
|
|
4789
|
+
transitions[fromState].add(event.to);
|
|
4622
4790
|
}
|
|
4623
4791
|
}
|
|
4624
|
-
}
|
|
4792
|
+
}
|
|
4793
|
+
const terminalState = machine.events.archive.to;
|
|
4794
|
+
const activeStates = machine.states.filter((state) => state !== terminalState);
|
|
4795
|
+
for (let index = 1; index < activeStates.length; index += 1) {
|
|
4796
|
+
transitions[activeStates[index]].add(activeStates[index - 1]);
|
|
4797
|
+
}
|
|
4798
|
+
return transitions;
|
|
4625
4799
|
}
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4800
|
+
var defaultTransitions = deriveLegacyTransitions(defaultStateMachine);
|
|
4801
|
+
|
|
4802
|
+
// packages/task-list/src/backends/markdown-dir.ts
|
|
4803
|
+
var TASK_SCHEMA_ID = task_schema_default.$id;
|
|
4804
|
+
|
|
4805
|
+
// packages/task-list/src/backends/yaml-file.ts
|
|
4806
|
+
import { isMap, parseDocument as parseDocument3 } from "yaml";
|
|
4807
|
+
|
|
4808
|
+
// packages/task-list/src/schema/store.schema.json
|
|
4809
|
+
var store_schema_default = {
|
|
4810
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
4811
|
+
$id: "https://poe-platform.github.io/poe-code/schemas/task-list/store.schema.json",
|
|
4812
|
+
title: "Task Store",
|
|
4813
|
+
description: "YAML multi-list task store.",
|
|
4814
|
+
type: "object",
|
|
4815
|
+
properties: {
|
|
4816
|
+
$schema: {
|
|
4817
|
+
type: "string",
|
|
4818
|
+
const: "https://poe-platform.github.io/poe-code/schemas/task-list/store.schema.json"
|
|
4819
|
+
},
|
|
4820
|
+
kind: {
|
|
4821
|
+
type: "string",
|
|
4822
|
+
const: "task-store"
|
|
4823
|
+
},
|
|
4824
|
+
version: {
|
|
4825
|
+
type: "integer",
|
|
4826
|
+
const: 1
|
|
4827
|
+
},
|
|
4828
|
+
lists: {
|
|
4829
|
+
type: "object",
|
|
4830
|
+
additionalProperties: {
|
|
4831
|
+
type: "object",
|
|
4832
|
+
additionalProperties: {
|
|
4833
|
+
$ref: "./task.schema.json"
|
|
4646
4834
|
}
|
|
4647
|
-
return result;
|
|
4648
|
-
},
|
|
4649
|
-
resetActivityTimer,
|
|
4650
|
-
dispose() {
|
|
4651
|
-
if (activityTimer) clearTimeout(activityTimer);
|
|
4652
4835
|
}
|
|
4653
|
-
}
|
|
4836
|
+
}
|
|
4837
|
+
},
|
|
4838
|
+
required: ["$schema", "kind", "version", "lists"],
|
|
4839
|
+
additionalProperties: false
|
|
4840
|
+
};
|
|
4841
|
+
|
|
4842
|
+
// packages/task-list/src/backends/yaml-file.ts
|
|
4843
|
+
var STORE_SCHEMA_ID = store_schema_default.$id;
|
|
4844
|
+
var TASK_SCHEMA_ID2 = task_schema_default.$id;
|
|
4845
|
+
|
|
4846
|
+
// packages/agent-defs/src/agents/claude-code.ts
|
|
4847
|
+
var claudeCodeAgent = {
|
|
4848
|
+
id: "claude-code",
|
|
4849
|
+
name: "claude-code",
|
|
4850
|
+
label: "Claude Code",
|
|
4851
|
+
summary: "Configure Claude Code to route through Poe.",
|
|
4852
|
+
aliases: ["claude"],
|
|
4853
|
+
binaryName: "claude",
|
|
4854
|
+
configPath: "~/.claude/settings.json",
|
|
4855
|
+
branding: {
|
|
4856
|
+
colors: {
|
|
4857
|
+
dark: "#C15F3C",
|
|
4858
|
+
light: "#C15F3C"
|
|
4859
|
+
}
|
|
4860
|
+
}
|
|
4861
|
+
};
|
|
4862
|
+
|
|
4863
|
+
// packages/agent-defs/src/agents/claude-desktop.ts
|
|
4864
|
+
var claudeDesktopAgent = {
|
|
4865
|
+
id: "claude-desktop",
|
|
4866
|
+
name: "claude-desktop",
|
|
4867
|
+
label: "Claude Desktop",
|
|
4868
|
+
summary: "Anthropic's official desktop application for Claude",
|
|
4869
|
+
configPath: "~/.claude/settings.json",
|
|
4870
|
+
branding: {
|
|
4871
|
+
colors: {
|
|
4872
|
+
dark: "#D97757",
|
|
4873
|
+
light: "#D97757"
|
|
4874
|
+
}
|
|
4875
|
+
}
|
|
4876
|
+
};
|
|
4877
|
+
|
|
4878
|
+
// packages/agent-defs/src/agents/codex.ts
|
|
4879
|
+
var codexAgent = {
|
|
4880
|
+
id: "codex",
|
|
4881
|
+
name: "codex",
|
|
4882
|
+
label: "Codex",
|
|
4883
|
+
summary: "Configure Codex to use Poe as the model provider.",
|
|
4884
|
+
binaryName: "codex",
|
|
4885
|
+
configPath: "~/.codex/config.toml",
|
|
4886
|
+
branding: {
|
|
4887
|
+
colors: {
|
|
4888
|
+
dark: "#D5D9DF",
|
|
4889
|
+
light: "#7A7F86"
|
|
4890
|
+
}
|
|
4891
|
+
}
|
|
4892
|
+
};
|
|
4893
|
+
|
|
4894
|
+
// packages/agent-defs/src/agents/opencode.ts
|
|
4895
|
+
var openCodeAgent = {
|
|
4896
|
+
id: "opencode",
|
|
4897
|
+
name: "opencode",
|
|
4898
|
+
label: "OpenCode CLI",
|
|
4899
|
+
summary: "Configure OpenCode CLI to use the Poe API.",
|
|
4900
|
+
binaryName: "opencode",
|
|
4901
|
+
configPath: "~/.config/opencode/config.json",
|
|
4902
|
+
branding: {
|
|
4903
|
+
colors: {
|
|
4904
|
+
dark: "#4A4F55",
|
|
4905
|
+
light: "#2F3338"
|
|
4906
|
+
}
|
|
4907
|
+
}
|
|
4908
|
+
};
|
|
4909
|
+
|
|
4910
|
+
// packages/agent-defs/src/agents/kimi.ts
|
|
4911
|
+
var kimiAgent = {
|
|
4912
|
+
id: "kimi",
|
|
4913
|
+
name: "kimi",
|
|
4914
|
+
label: "Kimi",
|
|
4915
|
+
summary: "Configure Kimi CLI to use Poe API",
|
|
4916
|
+
aliases: ["kimi-cli"],
|
|
4917
|
+
binaryName: "kimi",
|
|
4918
|
+
configPath: "~/.kimi/config.toml",
|
|
4919
|
+
branding: {
|
|
4920
|
+
colors: {
|
|
4921
|
+
dark: "#7B68EE",
|
|
4922
|
+
light: "#6A5ACD"
|
|
4923
|
+
}
|
|
4654
4924
|
}
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4925
|
+
};
|
|
4926
|
+
|
|
4927
|
+
// packages/agent-defs/src/agents/goose.ts
|
|
4928
|
+
var gooseAgent = {
|
|
4929
|
+
id: "goose",
|
|
4930
|
+
name: "goose",
|
|
4931
|
+
label: "Goose",
|
|
4932
|
+
summary: "Block's open-source AI agent with ACP support.",
|
|
4933
|
+
binaryName: "goose",
|
|
4934
|
+
configPath: "~/.config/goose/config.yaml",
|
|
4935
|
+
branding: {
|
|
4936
|
+
colors: {
|
|
4937
|
+
dark: "#FF6B35",
|
|
4938
|
+
light: "#E85D26"
|
|
4939
|
+
}
|
|
4669
4940
|
}
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
throw createActivityTimeoutError(activityTimeoutMs);
|
|
4705
|
-
}
|
|
4706
|
-
return result.value;
|
|
4707
|
-
}
|
|
4708
|
-
if (timedOut) {
|
|
4709
|
-
throw createActivityTimeoutError(activityTimeoutMs);
|
|
4710
|
-
}
|
|
4711
|
-
throw createAbortError2();
|
|
4712
|
-
},
|
|
4713
|
-
resetActivityTimer,
|
|
4714
|
-
dispose() {
|
|
4715
|
-
if (activityTimer) clearTimeout(activityTimer);
|
|
4716
|
-
exitWaitController.abort();
|
|
4717
|
-
signal.removeEventListener("abort", kill);
|
|
4941
|
+
};
|
|
4942
|
+
|
|
4943
|
+
// packages/agent-defs/src/agents/poe-agent.ts
|
|
4944
|
+
var poeAgentAgent = {
|
|
4945
|
+
id: "poe-agent",
|
|
4946
|
+
name: "poe-agent",
|
|
4947
|
+
label: "Poe Agent",
|
|
4948
|
+
summary: "Run one-shot prompts with the built-in Poe agent runtime.",
|
|
4949
|
+
configPath: "~/.poe-code/config.json",
|
|
4950
|
+
branding: {
|
|
4951
|
+
colors: {
|
|
4952
|
+
dark: "#A465F7",
|
|
4953
|
+
light: "#7A3FD3"
|
|
4954
|
+
}
|
|
4955
|
+
}
|
|
4956
|
+
};
|
|
4957
|
+
|
|
4958
|
+
// packages/agent-defs/src/registry.ts
|
|
4959
|
+
var allAgents = [
|
|
4960
|
+
claudeCodeAgent,
|
|
4961
|
+
claudeDesktopAgent,
|
|
4962
|
+
codexAgent,
|
|
4963
|
+
openCodeAgent,
|
|
4964
|
+
kimiAgent,
|
|
4965
|
+
gooseAgent,
|
|
4966
|
+
poeAgentAgent
|
|
4967
|
+
];
|
|
4968
|
+
var lookup = /* @__PURE__ */ new Map();
|
|
4969
|
+
for (const agent of allAgents) {
|
|
4970
|
+
const values = [agent.id, agent.name, ...agent.aliases ?? []];
|
|
4971
|
+
for (const value of values) {
|
|
4972
|
+
const normalized = value.toLowerCase();
|
|
4973
|
+
if (!lookup.has(normalized)) {
|
|
4974
|
+
lookup.set(normalized, agent.id);
|
|
4718
4975
|
}
|
|
4719
|
-
};
|
|
4720
|
-
}
|
|
4721
|
-
function toLogStreamEnv(env) {
|
|
4722
|
-
const candidate = env;
|
|
4723
|
-
return candidate.fs === void 0 ? {} : { fs: candidate.fs };
|
|
4724
|
-
}
|
|
4725
|
-
function setDetachedJobContext(env, context) {
|
|
4726
|
-
const candidate = env;
|
|
4727
|
-
candidate.setDetachedJobContext?.(context);
|
|
4728
|
-
}
|
|
4729
|
-
function isPromiseLike(value) {
|
|
4730
|
-
return typeof value.then === "function";
|
|
4731
|
-
}
|
|
4732
|
-
function createAbortError2() {
|
|
4733
|
-
const error2 = new Error("Agent spawn aborted");
|
|
4734
|
-
error2.name = "AbortError";
|
|
4735
|
-
return error2;
|
|
4736
|
-
}
|
|
4737
|
-
function createActivityTimeoutError(timeoutMs) {
|
|
4738
|
-
const error2 = new Error(`Agent spawn timed out after ${timeoutMs / 1e3}s of inactivity`);
|
|
4739
|
-
error2.name = "ActivityTimeoutError";
|
|
4740
|
-
return error2;
|
|
4741
|
-
}
|
|
4742
|
-
function createUlid() {
|
|
4743
|
-
const time = BigInt(Date.now());
|
|
4744
|
-
const random = randomBytes(10);
|
|
4745
|
-
let randomValue = 0n;
|
|
4746
|
-
for (const byte of random) {
|
|
4747
|
-
randomValue = randomValue << 8n | BigInt(byte);
|
|
4748
4976
|
}
|
|
4749
|
-
return encodeBase32(time, 10) + encodeBase32(randomValue, 16);
|
|
4750
4977
|
}
|
|
4751
|
-
function
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
for (let index = length - 1; index >= 0; index -= 1) {
|
|
4755
|
-
chars[index] = ULID_ALPHABET[Number(remaining & 31n)];
|
|
4756
|
-
remaining >>= 5n;
|
|
4978
|
+
function resolveAgentId(input) {
|
|
4979
|
+
if (!input) {
|
|
4980
|
+
return void 0;
|
|
4757
4981
|
}
|
|
4758
|
-
return
|
|
4982
|
+
return lookup.get(input.toLowerCase());
|
|
4759
4983
|
}
|
|
4760
4984
|
|
|
4761
|
-
// packages/agent-harness-tools/src/
|
|
4762
|
-
|
|
4763
|
-
|
|
4985
|
+
// packages/agent-harness-tools/src/select-agent.ts
|
|
4986
|
+
var loopAgents = allAgents.filter(
|
|
4987
|
+
(agent) => agent.binaryName !== void 0 || agent.id === "poe-agent"
|
|
4988
|
+
);
|
|
4989
|
+
var supportedAgents = loopAgents.map((agent) => agent.id).join(", ");
|
|
4764
4990
|
|
|
4765
|
-
// packages/agent-harness-tools/src/
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4991
|
+
// packages/agent-harness-tools/src/run-logs.ts
|
|
4992
|
+
import path28 from "node:path";
|
|
4993
|
+
|
|
4994
|
+
// packages/agent-harness-tools/src/log-stream.ts
|
|
4995
|
+
import nodeFs2 from "node:fs";
|
|
4996
|
+
var JOB_DIR = "/tmp/poe-jobs";
|
|
4997
|
+
var POLL_INTERVAL_MS = 250;
|
|
4998
|
+
function wrapForLogTee(argv, jobId) {
|
|
4999
|
+
if (argv.length === 0) {
|
|
5000
|
+
throw new Error("wrapForLogTee requires argv to contain at least one argument");
|
|
5001
|
+
}
|
|
5002
|
+
const command = argv.map(shellQuote2).join(" ");
|
|
5003
|
+
const logFile = shellQuote2(jobLogPath(jobId));
|
|
5004
|
+
const exitFile = shellQuote2(jobExitPath(jobId));
|
|
5005
|
+
const exitTmpFile = shellQuote2(`${jobExitPath(jobId)}.tmp`);
|
|
5006
|
+
const script = [
|
|
5007
|
+
`mkdir -p ${shellQuote2(JOB_DIR)}`,
|
|
5008
|
+
`({ (${command}); echo $? > ${exitTmpFile}; } 2>&1 | tee ${logFile}; mv ${exitTmpFile} ${exitFile})`
|
|
5009
|
+
].join(" && ");
|
|
5010
|
+
return ["sh", "-c", script];
|
|
4769
5011
|
}
|
|
4770
|
-
function
|
|
4771
|
-
|
|
5012
|
+
async function* streamLogFile(env, jobId, opts) {
|
|
5013
|
+
const fs14 = env.fs ?? nodeFs2;
|
|
5014
|
+
const file = jobLogPath(jobId);
|
|
5015
|
+
let byteOffset = opts.sinceByte ?? 0;
|
|
5016
|
+
while (true) {
|
|
5017
|
+
if (opts.since !== void 0 && !await wasModifiedSince(fs14, file, opts.since)) {
|
|
5018
|
+
await waitForLogChange(fs14, file);
|
|
5019
|
+
continue;
|
|
5020
|
+
}
|
|
5021
|
+
const result = await readLogChunk(fs14, file, byteOffset);
|
|
5022
|
+
if (result !== null) {
|
|
5023
|
+
byteOffset = result.nextByteOffset;
|
|
5024
|
+
yield result.chunk;
|
|
5025
|
+
continue;
|
|
5026
|
+
}
|
|
5027
|
+
await waitForLogChange(fs14, file);
|
|
5028
|
+
}
|
|
4772
5029
|
}
|
|
4773
|
-
function
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
);
|
|
5030
|
+
async function wasModifiedSince(fs14, file, since) {
|
|
5031
|
+
if (fs14.promises.stat === void 0) {
|
|
5032
|
+
return true;
|
|
5033
|
+
}
|
|
5034
|
+
try {
|
|
5035
|
+
const stat7 = await fs14.promises.stat(file);
|
|
5036
|
+
return stat7.mtimeMs >= since.getTime();
|
|
5037
|
+
} catch (error2) {
|
|
5038
|
+
if (isNodeError(error2) && error2.code === "ENOENT") {
|
|
5039
|
+
return false;
|
|
5040
|
+
}
|
|
5041
|
+
throw error2;
|
|
4779
5042
|
}
|
|
4780
|
-
return factory;
|
|
4781
5043
|
}
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
state,
|
|
4796
|
-
openSpec: {
|
|
4797
|
-
cwd: input.cwd,
|
|
4798
|
-
runtimeCwd: runtimeConfigCwd,
|
|
4799
|
-
runtime: resolved.runtime,
|
|
4800
|
-
runner: config.runner,
|
|
4801
|
-
state,
|
|
4802
|
-
env: input.env,
|
|
4803
|
-
uploadIgnoreFiles: config.runner.workspace?.exclude ?? [],
|
|
4804
|
-
jobLabel: {
|
|
4805
|
-
tool: input.tool,
|
|
4806
|
-
argv: input.argv
|
|
4807
|
-
},
|
|
4808
|
-
...input.openSpec
|
|
5044
|
+
async function waitForExit(env, jobId, opts = {}) {
|
|
5045
|
+
const fs14 = env.fs ?? nodeFs2;
|
|
5046
|
+
const file = jobExitPath(jobId);
|
|
5047
|
+
while (true) {
|
|
5048
|
+
throwIfAborted2(opts.signal);
|
|
5049
|
+
const contents = await readTextFileIfExists(fs14, file);
|
|
5050
|
+
if (contents !== null) {
|
|
5051
|
+
const text5 = contents.trim();
|
|
5052
|
+
const exitCode = Number(text5);
|
|
5053
|
+
if (text5.length === 0 || !Number.isInteger(exitCode)) {
|
|
5054
|
+
throw new Error(`Invalid exit code in ${file}: ${contents}`);
|
|
5055
|
+
}
|
|
5056
|
+
return { exitCode };
|
|
4809
5057
|
}
|
|
4810
|
-
|
|
4811
|
-
}
|
|
4812
|
-
function applyRuntimeOverrides(config, overrides, cwd = process.cwd()) {
|
|
4813
|
-
if (!overrides) {
|
|
4814
|
-
return { runtime: config.runtime, runner: config.runner };
|
|
5058
|
+
await sleep3(POLL_INTERVAL_MS, opts.signal);
|
|
4815
5059
|
}
|
|
4816
|
-
const base = "rawScope" in config && config.rawScope ? { ...config.rawScope } : { ...config.runtime };
|
|
4817
|
-
const runtime = parseRuntime({
|
|
4818
|
-
...base,
|
|
4819
|
-
...overrides.runtime !== void 0 ? { type: overrides.runtime } : {},
|
|
4820
|
-
...overrides.runtimeImage !== void 0 ? { image: overrides.runtimeImage } : {},
|
|
4821
|
-
...overrides.runtimeTemplate !== void 0 ? { template_id: overrides.runtimeTemplate } : {},
|
|
4822
|
-
...overrides.mountPoeCode === true ? { mounts: [...config.runtime.mounts, createPoeCodeMount(cwd)] } : {}
|
|
4823
|
-
});
|
|
4824
|
-
return {
|
|
4825
|
-
runtime,
|
|
4826
|
-
runner: {
|
|
4827
|
-
...config.runner,
|
|
4828
|
-
...overrides.detach === true ? { detach: true } : {},
|
|
4829
|
-
...overrides.runnerSync !== void 0 ? { sync: overrides.runnerSync } : {}
|
|
4830
|
-
}
|
|
4831
|
-
};
|
|
4832
5060
|
}
|
|
4833
|
-
function
|
|
4834
|
-
return {
|
|
4835
|
-
source: cwd,
|
|
4836
|
-
target: "/usr/local/lib/poe-code",
|
|
4837
|
-
readonly: true
|
|
4838
|
-
};
|
|
5061
|
+
function jobLogPath(jobId) {
|
|
5062
|
+
return `${JOB_DIR}/${jobId}.log`;
|
|
4839
5063
|
}
|
|
4840
|
-
function
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
);
|
|
4845
|
-
|
|
5064
|
+
function jobExitPath(jobId) {
|
|
5065
|
+
return `${JOB_DIR}/${jobId}.exit`;
|
|
5066
|
+
}
|
|
5067
|
+
async function readLogChunk(fs14, file, byteOffset) {
|
|
5068
|
+
const contents = await readFileIfExists2(fs14, file);
|
|
5069
|
+
if (contents === null || byteOffset >= contents.byteLength) {
|
|
5070
|
+
return null;
|
|
5071
|
+
}
|
|
4846
5072
|
return {
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
5073
|
+
chunk: {
|
|
5074
|
+
byteOffset,
|
|
5075
|
+
data: contents.subarray(byteOffset).toString("utf8")
|
|
5076
|
+
},
|
|
5077
|
+
nextByteOffset: contents.byteLength
|
|
4850
5078
|
};
|
|
4851
5079
|
}
|
|
4852
|
-
function
|
|
4853
|
-
|
|
4854
|
-
|
|
5080
|
+
async function readTextFileIfExists(fs14, file) {
|
|
5081
|
+
const contents = await readFileIfExists2(fs14, file);
|
|
5082
|
+
return contents?.toString("utf8") ?? null;
|
|
5083
|
+
}
|
|
5084
|
+
async function readFileIfExists2(fs14, file) {
|
|
5085
|
+
try {
|
|
5086
|
+
const contents = await fs14.promises.readFile(file);
|
|
5087
|
+
return Buffer.isBuffer(contents) ? contents : Buffer.from(contents);
|
|
5088
|
+
} catch (error2) {
|
|
5089
|
+
if (isNodeError(error2) && error2.code === "ENOENT") {
|
|
5090
|
+
return null;
|
|
5091
|
+
}
|
|
5092
|
+
throw error2;
|
|
4855
5093
|
}
|
|
4856
|
-
return JSON.parse(readFileSync(filePath, "utf8"));
|
|
4857
5094
|
}
|
|
4858
|
-
function
|
|
4859
|
-
|
|
4860
|
-
|
|
5095
|
+
async function waitForLogChange(fs14, file) {
|
|
5096
|
+
const watch = fs14.watch;
|
|
5097
|
+
if (typeof watch !== "function") {
|
|
5098
|
+
await sleep3(POLL_INTERVAL_MS);
|
|
5099
|
+
return;
|
|
4861
5100
|
}
|
|
4862
|
-
|
|
5101
|
+
await new Promise((resolve2) => {
|
|
5102
|
+
let watcher = null;
|
|
5103
|
+
const timer = setTimeout(done, POLL_INTERVAL_MS);
|
|
5104
|
+
function done() {
|
|
5105
|
+
clearTimeout(timer);
|
|
5106
|
+
watcher?.close();
|
|
5107
|
+
resolve2();
|
|
5108
|
+
}
|
|
5109
|
+
try {
|
|
5110
|
+
watcher = watch(file, done);
|
|
5111
|
+
} catch {
|
|
5112
|
+
done();
|
|
5113
|
+
}
|
|
5114
|
+
});
|
|
4863
5115
|
}
|
|
4864
|
-
function
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
},
|
|
4871
|
-
async put() {
|
|
4872
|
-
},
|
|
4873
|
-
async remove() {
|
|
4874
|
-
},
|
|
4875
|
-
async list() {
|
|
4876
|
-
return [];
|
|
4877
|
-
}
|
|
4878
|
-
},
|
|
4879
|
-
jobs: {
|
|
4880
|
-
async get(id) {
|
|
4881
|
-
return jobs.get(id) ?? null;
|
|
4882
|
-
},
|
|
4883
|
-
async put(entry) {
|
|
4884
|
-
jobs.set(entry.id, entry);
|
|
4885
|
-
},
|
|
4886
|
-
async update(id, patch) {
|
|
4887
|
-
const current = jobs.get(id);
|
|
4888
|
-
if (!current) {
|
|
4889
|
-
return null;
|
|
4890
|
-
}
|
|
4891
|
-
const updated = { ...current, ...patch, id };
|
|
4892
|
-
jobs.set(id, updated);
|
|
4893
|
-
return updated;
|
|
4894
|
-
},
|
|
4895
|
-
async list(filter) {
|
|
4896
|
-
const entries = Array.from(jobs.values());
|
|
4897
|
-
if (!filter) {
|
|
4898
|
-
return entries;
|
|
4899
|
-
}
|
|
4900
|
-
return entries.filter(
|
|
4901
|
-
(entry) => Object.entries(filter).every(([key, value]) => entry[key] === value)
|
|
4902
|
-
);
|
|
4903
|
-
},
|
|
4904
|
-
async remove(id) {
|
|
4905
|
-
jobs.delete(id);
|
|
5116
|
+
function sleep3(ms, signal) {
|
|
5117
|
+
return new Promise((resolve2, reject) => {
|
|
5118
|
+
let timer = null;
|
|
5119
|
+
const abort = () => {
|
|
5120
|
+
if (timer !== null) {
|
|
5121
|
+
clearTimeout(timer);
|
|
4906
5122
|
}
|
|
5123
|
+
reject(new Error("waitForExit aborted."));
|
|
5124
|
+
};
|
|
5125
|
+
if (signal?.aborted) {
|
|
5126
|
+
abort();
|
|
5127
|
+
return;
|
|
4907
5128
|
}
|
|
4908
|
-
|
|
5129
|
+
timer = setTimeout(() => {
|
|
5130
|
+
signal?.removeEventListener("abort", abort);
|
|
5131
|
+
resolve2();
|
|
5132
|
+
}, ms);
|
|
5133
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
5134
|
+
});
|
|
5135
|
+
}
|
|
5136
|
+
function throwIfAborted2(signal) {
|
|
5137
|
+
if (signal?.aborted) {
|
|
5138
|
+
throw new Error("waitForExit aborted.");
|
|
5139
|
+
}
|
|
5140
|
+
}
|
|
5141
|
+
function shellQuote2(value) {
|
|
5142
|
+
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
5143
|
+
}
|
|
5144
|
+
function isNodeError(error2) {
|
|
5145
|
+
return error2 instanceof Error && "code" in error2;
|
|
4909
5146
|
}
|
|
4910
5147
|
|
|
4911
|
-
// packages/agent-harness-tools/src/
|
|
4912
|
-
import {
|
|
4913
|
-
import { promises as nodeFs3 } from "node:fs";
|
|
4914
|
-
import path24 from "node:path";
|
|
5148
|
+
// packages/agent-harness-tools/src/run-poe-command.ts
|
|
5149
|
+
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
4915
5150
|
|
|
4916
|
-
// packages/
|
|
4917
|
-
|
|
4918
|
-
|
|
5151
|
+
// packages/agent-harness-tools/src/binary-exists.ts
|
|
5152
|
+
function createBinaryExistsDetectors(binaryName) {
|
|
5153
|
+
const commonPaths = [
|
|
5154
|
+
`/usr/local/bin/${binaryName}`,
|
|
5155
|
+
`/usr/bin/${binaryName}`,
|
|
5156
|
+
`$HOME/.local/bin/${binaryName}`,
|
|
5157
|
+
`$HOME/.claude/local/bin/${binaryName}`
|
|
5158
|
+
];
|
|
5159
|
+
return [
|
|
5160
|
+
{
|
|
5161
|
+
command: "which",
|
|
5162
|
+
args: [binaryName],
|
|
5163
|
+
validate: (result) => result.exitCode === 0
|
|
5164
|
+
},
|
|
5165
|
+
{
|
|
5166
|
+
command: "where",
|
|
5167
|
+
args: [binaryName],
|
|
5168
|
+
validate: (result) => result.exitCode === 0 && result.stdout.trim().length > 0
|
|
5169
|
+
},
|
|
5170
|
+
{
|
|
5171
|
+
command: "sh",
|
|
5172
|
+
args: ["-c", commonPaths.map((p) => `test -f "${p}"`).join(" || ")],
|
|
5173
|
+
validate: (result) => result.exitCode === 0
|
|
5174
|
+
}
|
|
5175
|
+
];
|
|
5176
|
+
}
|
|
5177
|
+
|
|
5178
|
+
// packages/agent-harness-tools/src/run-poe-command.ts
|
|
5179
|
+
var ULID_ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
5180
|
+
async function runPoeCommand(opts) {
|
|
5181
|
+
const jobId = createUlid();
|
|
5182
|
+
const execution = opts.openSpec.execution;
|
|
5183
|
+
const wrapCommand = execution?.wrapForLogTee !== false;
|
|
5184
|
+
const pendingJob = opts.state.jobs.put({
|
|
5185
|
+
id: jobId,
|
|
5186
|
+
env_id: "",
|
|
5187
|
+
env_kind: opts.factory.type,
|
|
5188
|
+
tool: opts.openSpec.jobLabel.tool,
|
|
5189
|
+
argv: opts.openSpec.jobLabel.argv,
|
|
5190
|
+
cwd: opts.openSpec.cwd,
|
|
5191
|
+
started_at: "",
|
|
5192
|
+
status: "pending"
|
|
5193
|
+
});
|
|
5194
|
+
const opened = opts.factory.open(opts.openSpec);
|
|
5195
|
+
const env = isPromiseLike(opened) ? await opened : opened;
|
|
5196
|
+
let shouldClose = true;
|
|
4919
5197
|
try {
|
|
4920
|
-
const
|
|
4921
|
-
|
|
4922
|
-
|
|
5198
|
+
const upload = env.uploadWorkspace();
|
|
5199
|
+
await Promise.all([pendingJob, upload]);
|
|
5200
|
+
await configureE2bSpawnAgentIfAvailable({
|
|
5201
|
+
env,
|
|
5202
|
+
openSpec: opts.openSpec,
|
|
5203
|
+
factoryType: opts.factory.type
|
|
5204
|
+
});
|
|
5205
|
+
const argv = wrapCommand ? wrapForLogTee(opts.openSpec.jobLabel.argv, jobId) : opts.openSpec.jobLabel.argv;
|
|
5206
|
+
const handle = execution?.tty ? env.shell() : env.exec({
|
|
5207
|
+
command: argv[0],
|
|
5208
|
+
args: argv.slice(1),
|
|
5209
|
+
cwd: opts.openSpec.cwd,
|
|
5210
|
+
env: resolveExecutionEnv(opts.openSpec),
|
|
5211
|
+
stdin: execution?.stdin ?? "inherit",
|
|
5212
|
+
stdout: execution?.stdout ?? "pipe",
|
|
5213
|
+
stderr: execution?.stderr ?? "pipe",
|
|
5214
|
+
signal: opts.signal
|
|
5215
|
+
});
|
|
5216
|
+
if (execution?.input !== void 0) {
|
|
5217
|
+
handle.stdin?.setDefaultEncoding("utf8");
|
|
5218
|
+
handle.stdin?.end(execution.input);
|
|
5219
|
+
}
|
|
5220
|
+
const runningJob = opts.state.jobs.update(jobId, {
|
|
5221
|
+
status: "running",
|
|
5222
|
+
env_id: env.id,
|
|
5223
|
+
started_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
5224
|
+
});
|
|
5225
|
+
if (opts.detach) {
|
|
5226
|
+
await runningJob;
|
|
5227
|
+
setDetachedJobContext(env, {
|
|
5228
|
+
id: jobId,
|
|
5229
|
+
tool: opts.openSpec.jobLabel.tool,
|
|
5230
|
+
argv: opts.openSpec.jobLabel.argv
|
|
5231
|
+
});
|
|
5232
|
+
await env.detach();
|
|
5233
|
+
shouldClose = false;
|
|
5234
|
+
return { kind: "detached", jobId, envId: env.id };
|
|
5235
|
+
}
|
|
5236
|
+
const result = await runSync({
|
|
5237
|
+
env,
|
|
5238
|
+
handle,
|
|
5239
|
+
jobId,
|
|
5240
|
+
openSpec: opts.openSpec,
|
|
5241
|
+
signal: opts.signal,
|
|
5242
|
+
wrapCommand
|
|
4923
5243
|
});
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
5244
|
+
await runningJob;
|
|
5245
|
+
shouldClose = false;
|
|
5246
|
+
await opts.state.jobs.update(jobId, {
|
|
5247
|
+
status: "exited",
|
|
5248
|
+
exit_code: result.exitCode,
|
|
5249
|
+
exited_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
5250
|
+
});
|
|
5251
|
+
return {
|
|
5252
|
+
kind: "sync",
|
|
5253
|
+
exitCode: result.exitCode,
|
|
5254
|
+
download: result.download,
|
|
5255
|
+
...result.stdout !== void 0 ? { stdout: result.stdout } : {},
|
|
5256
|
+
...result.stderr !== void 0 ? { stderr: result.stderr } : {}
|
|
5257
|
+
};
|
|
5258
|
+
} finally {
|
|
5259
|
+
if (shouldClose) {
|
|
5260
|
+
await env.close();
|
|
4934
5261
|
}
|
|
4935
|
-
} catch {
|
|
4936
|
-
return null;
|
|
4937
5262
|
}
|
|
4938
|
-
return null;
|
|
4939
5263
|
}
|
|
4940
|
-
function
|
|
4941
|
-
if (
|
|
4942
|
-
return
|
|
5264
|
+
async function configureE2bSpawnAgentIfAvailable(opts) {
|
|
5265
|
+
if (opts.factoryType !== "e2b") {
|
|
5266
|
+
return;
|
|
4943
5267
|
}
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
function detectEngine() {
|
|
4950
|
-
if (isEngineAvailable("docker")) {
|
|
4951
|
-
return "docker";
|
|
5268
|
+
const agentId = resolveAgentId(opts.openSpec.jobLabel.tool);
|
|
5269
|
+
const agent = allAgents.find((candidate) => candidate.id === agentId);
|
|
5270
|
+
const binaryName = agent?.binaryName;
|
|
5271
|
+
if (!agentId || !binaryName) {
|
|
5272
|
+
return;
|
|
4952
5273
|
}
|
|
4953
|
-
|
|
4954
|
-
|
|
5274
|
+
const commandEnv = resolveExecutionEnv(opts.openSpec);
|
|
5275
|
+
const exists = await binaryExists(opts.env, {
|
|
5276
|
+
binaryName,
|
|
5277
|
+
cwd: opts.openSpec.cwd,
|
|
5278
|
+
env: commandEnv
|
|
5279
|
+
});
|
|
5280
|
+
if (!exists) {
|
|
5281
|
+
return;
|
|
5282
|
+
}
|
|
5283
|
+
const result = await runProbeCommand(opts.env, {
|
|
5284
|
+
command: "poe-code",
|
|
5285
|
+
args: ["configure", "--yes", "--provider", "poe", agentId],
|
|
5286
|
+
cwd: opts.openSpec.cwd,
|
|
5287
|
+
env: commandEnv
|
|
5288
|
+
});
|
|
5289
|
+
if (result.exitCode !== 0) {
|
|
5290
|
+
throw new Error(
|
|
5291
|
+
`Failed to configure ${agentId} for Poe inside E2B sandbox.
|
|
5292
|
+
${formatProbeResult(result)}`
|
|
5293
|
+
);
|
|
4955
5294
|
}
|
|
4956
|
-
throw new Error(
|
|
4957
|
-
"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"
|
|
4958
|
-
);
|
|
4959
5295
|
}
|
|
4960
|
-
function
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
5296
|
+
async function binaryExists(env, opts) {
|
|
5297
|
+
for (const detector of createBinaryExistsDetectors(opts.binaryName)) {
|
|
5298
|
+
const result = await runProbeCommand(env, {
|
|
5299
|
+
...detector,
|
|
5300
|
+
cwd: opts.cwd,
|
|
5301
|
+
env: opts.env
|
|
4964
5302
|
});
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
5303
|
+
if (detector.validate(result)) {
|
|
5304
|
+
return true;
|
|
5305
|
+
}
|
|
4968
5306
|
}
|
|
5307
|
+
return false;
|
|
4969
5308
|
}
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
4974
|
-
|
|
4975
|
-
// packages/process-runner/src/docker/args.ts
|
|
4976
|
-
import path25 from "node:path";
|
|
4977
|
-
function buildDockerRunArgs(input) {
|
|
4978
|
-
const args = [input.engine];
|
|
4979
|
-
if (input.engine === "docker" && input.context) {
|
|
4980
|
-
args.push("--context", input.context);
|
|
4981
|
-
}
|
|
4982
|
-
args.push("run");
|
|
4983
|
-
if (input.rm) {
|
|
4984
|
-
args.push("--rm");
|
|
4985
|
-
}
|
|
4986
|
-
if (input.detached) {
|
|
4987
|
-
args.push("-d");
|
|
4988
|
-
}
|
|
4989
|
-
if (input.interactive) {
|
|
4990
|
-
args.push("-i");
|
|
4991
|
-
}
|
|
4992
|
-
if (input.tty) {
|
|
4993
|
-
args.push("-t");
|
|
4994
|
-
}
|
|
4995
|
-
args.push("--name", input.containerName);
|
|
4996
|
-
if (input.cwd !== void 0) {
|
|
4997
|
-
args.push("-w", input.cwd);
|
|
4998
|
-
}
|
|
4999
|
-
for (const [key, value] of Object.entries(input.env ?? {})) {
|
|
5000
|
-
args.push("-e", `${key}=${value}`);
|
|
5001
|
-
}
|
|
5002
|
-
for (const mount of input.mounts) {
|
|
5003
|
-
const volume = `${path25.resolve(mount.source)}:${mount.target}${mount.readonly ? ":ro" : ""}`;
|
|
5004
|
-
args.push("-v", volume);
|
|
5005
|
-
}
|
|
5006
|
-
for (const port of input.ports) {
|
|
5007
|
-
const mapping = `${port.host}:${port.container}${port.protocol === void 0 || port.protocol === "tcp" ? "" : `/${port.protocol}`}`;
|
|
5008
|
-
args.push("-p", mapping);
|
|
5009
|
-
}
|
|
5010
|
-
if (input.network !== void 0) {
|
|
5011
|
-
args.push("--network", input.network);
|
|
5012
|
-
}
|
|
5013
|
-
args.push(...input.extraArgs, input.image, input.command, ...input.args);
|
|
5014
|
-
return args;
|
|
5309
|
+
function resolveExecutionEnv(openSpec) {
|
|
5310
|
+
const execution = openSpec.execution;
|
|
5311
|
+
return execution?.env ?? openSpec.env;
|
|
5015
5312
|
}
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
const
|
|
5313
|
+
async function runProbeCommand(env, spec) {
|
|
5314
|
+
const handle = env.exec({
|
|
5315
|
+
command: spec.command,
|
|
5316
|
+
args: spec.args,
|
|
5317
|
+
cwd: spec.cwd,
|
|
5318
|
+
env: spec.env,
|
|
5319
|
+
stdin: "ignore",
|
|
5320
|
+
stdout: "pipe",
|
|
5321
|
+
stderr: "pipe"
|
|
5322
|
+
});
|
|
5323
|
+
const stdout = readStream2(handle.stdout);
|
|
5324
|
+
const stderr = readStream2(handle.stderr);
|
|
5325
|
+
const result = await handle.result;
|
|
5028
5326
|
return {
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
});
|
|
5071
|
-
return {
|
|
5072
|
-
pid: child.pid ?? null,
|
|
5073
|
-
stdin: child.stdin,
|
|
5074
|
-
stdout: child.stdout,
|
|
5075
|
-
stderr: child.stderr,
|
|
5076
|
-
result,
|
|
5077
|
-
kill
|
|
5078
|
-
};
|
|
5327
|
+
exitCode: result.exitCode,
|
|
5328
|
+
stdout: await stdout,
|
|
5329
|
+
stderr: await stderr
|
|
5330
|
+
};
|
|
5331
|
+
}
|
|
5332
|
+
function readStream2(stream) {
|
|
5333
|
+
if (!stream) {
|
|
5334
|
+
return Promise.resolve("");
|
|
5335
|
+
}
|
|
5336
|
+
return new Promise((resolve2, reject) => {
|
|
5337
|
+
let output = "";
|
|
5338
|
+
stream.setEncoding("utf8");
|
|
5339
|
+
stream.on("data", (chunk) => {
|
|
5340
|
+
output += chunk.toString();
|
|
5341
|
+
});
|
|
5342
|
+
stream.on("error", reject);
|
|
5343
|
+
stream.on("end", () => resolve2(output));
|
|
5344
|
+
});
|
|
5345
|
+
}
|
|
5346
|
+
function formatProbeResult(result) {
|
|
5347
|
+
return [
|
|
5348
|
+
`Exit code: ${result.exitCode}`,
|
|
5349
|
+
result.stdout.trim() ? `stdout:
|
|
5350
|
+
${result.stdout.trim()}` : "",
|
|
5351
|
+
result.stderr.trim() ? `stderr:
|
|
5352
|
+
${result.stderr.trim()}` : ""
|
|
5353
|
+
].filter(Boolean).join("\n");
|
|
5354
|
+
}
|
|
5355
|
+
async function runSync(opts) {
|
|
5356
|
+
const execution = opts.openSpec.execution;
|
|
5357
|
+
const capture = execution?.captureOutput === true;
|
|
5358
|
+
const abort = createAbortSync(opts.signal, opts.handle, execution?.activityTimeoutMs);
|
|
5359
|
+
const streamState = capture ? captureRunStreams(opts.handle, execution, abort.resetActivityTimer) : pipeRunStreams(opts.handle);
|
|
5360
|
+
abort.resetActivityTimer();
|
|
5361
|
+
try {
|
|
5362
|
+
const { exitCode } = opts.wrapCommand ? await abort.waitForExit(opts.env, opts.jobId) : await abort.waitForHandle();
|
|
5363
|
+
const download = await opts.env.downloadWorkspace({
|
|
5364
|
+
conflictPolicy: opts.openSpec.runner?.download_conflict ?? "refuse"
|
|
5365
|
+
});
|
|
5366
|
+
if (opts.closeAfterDownload !== false) {
|
|
5367
|
+
await opts.env.close();
|
|
5079
5368
|
}
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
return () => {
|
|
5085
|
-
};
|
|
5086
|
-
}
|
|
5087
|
-
if (signal.aborted) {
|
|
5088
|
-
onAbort();
|
|
5089
|
-
return () => {
|
|
5369
|
+
return {
|
|
5370
|
+
exitCode,
|
|
5371
|
+
download,
|
|
5372
|
+
...capture ? { stdout: streamState.stdout(), stderr: streamState.stderr() } : {}
|
|
5090
5373
|
};
|
|
5374
|
+
} finally {
|
|
5375
|
+
abort.dispose();
|
|
5376
|
+
streamState.dispose();
|
|
5091
5377
|
}
|
|
5092
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
5093
|
-
return () => {
|
|
5094
|
-
signal.removeEventListener("abort", onAbort);
|
|
5095
|
-
};
|
|
5096
5378
|
}
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
var dockerExecutionEnvFactory = {
|
|
5101
|
-
type: "docker",
|
|
5102
|
-
supportsDetach: true,
|
|
5103
|
-
async open(spec) {
|
|
5104
|
-
const runtime = parseDockerRuntime(spec.runtime);
|
|
5105
|
-
const runner = spec.hostRunner ?? createHostRunner();
|
|
5106
|
-
const engine = runtime.engine ?? detectEngine();
|
|
5107
|
-
const context = detectContext();
|
|
5108
|
-
const image = await resolveImage({
|
|
5109
|
-
spec,
|
|
5110
|
-
runtime,
|
|
5111
|
-
runner,
|
|
5112
|
-
engine,
|
|
5113
|
-
context
|
|
5114
|
-
});
|
|
5115
|
-
const containerName = createContainerName();
|
|
5116
|
-
const runArgs = buildDockerRunArgs({
|
|
5117
|
-
engine,
|
|
5118
|
-
context,
|
|
5119
|
-
image,
|
|
5120
|
-
command: containerCommand[0],
|
|
5121
|
-
args: containerCommand.slice(1),
|
|
5122
|
-
cwd: void 0,
|
|
5123
|
-
env: void 0,
|
|
5124
|
-
mounts: runtime.mounts ?? [],
|
|
5125
|
-
ports: [],
|
|
5126
|
-
network: runtime.network,
|
|
5127
|
-
containerName,
|
|
5128
|
-
detached: true,
|
|
5129
|
-
interactive: true,
|
|
5130
|
-
tty: false,
|
|
5131
|
-
rm: false,
|
|
5132
|
-
extraArgs: runtime.extra_args ?? []
|
|
5133
|
-
});
|
|
5134
|
-
const [command, ...args] = runArgs;
|
|
5135
|
-
const id = (await runAndRead(runner, { command, args, stdout: "pipe", stderr: "pipe" })).trim();
|
|
5136
|
-
return createDockerEnv({
|
|
5137
|
-
id,
|
|
5138
|
-
spec,
|
|
5139
|
-
runner,
|
|
5140
|
-
engine,
|
|
5141
|
-
context
|
|
5142
|
-
});
|
|
5143
|
-
},
|
|
5144
|
-
async attach(envId, context) {
|
|
5145
|
-
const engine = detectEngine();
|
|
5146
|
-
return createDockerEnv({
|
|
5147
|
-
id: envId,
|
|
5148
|
-
spec: createAttachedSpec(context?.cwd),
|
|
5149
|
-
runner: createHostRunner(),
|
|
5150
|
-
engine,
|
|
5151
|
-
context: detectContext(),
|
|
5152
|
-
attachedJobId: context?.jobId
|
|
5153
|
-
});
|
|
5154
|
-
}
|
|
5155
|
-
};
|
|
5156
|
-
function createDockerEnv(input) {
|
|
5157
|
-
const containerRef = input.id;
|
|
5379
|
+
function pipeRunStreams(handle) {
|
|
5380
|
+
handle.stdout?.pipe(process.stdout, { end: false });
|
|
5381
|
+
handle.stderr?.pipe(process.stderr, { end: false });
|
|
5158
5382
|
return {
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
try {
|
|
5165
|
-
const excludeArgs = input.spec.uploadIgnoreFiles.flatMap((ignored) => [
|
|
5166
|
-
"--exclude",
|
|
5167
|
-
ignored
|
|
5168
|
-
]);
|
|
5169
|
-
const tarArgs = [...excludeArgs, "-cf", archivePath, "-C", input.spec.cwd, "."];
|
|
5170
|
-
await runOrThrow(input.runner, {
|
|
5171
|
-
command: "tar",
|
|
5172
|
-
args: tarArgs,
|
|
5173
|
-
stdout: "pipe",
|
|
5174
|
-
stderr: "pipe"
|
|
5175
|
-
});
|
|
5176
|
-
await runOrThrow(input.runner, {
|
|
5177
|
-
command: input.engine,
|
|
5178
|
-
args: [
|
|
5179
|
-
...buildContextArgs(input.engine, input.context),
|
|
5180
|
-
"cp",
|
|
5181
|
-
archivePath,
|
|
5182
|
-
`${containerRef}:/tmp/poe-workspace-upload.tar`
|
|
5183
|
-
],
|
|
5184
|
-
stdout: "pipe",
|
|
5185
|
-
stderr: "pipe"
|
|
5186
|
-
});
|
|
5187
|
-
await runOrThrow(input.runner, {
|
|
5188
|
-
command: input.engine,
|
|
5189
|
-
args: [
|
|
5190
|
-
...buildContextArgs(input.engine, input.context),
|
|
5191
|
-
"exec",
|
|
5192
|
-
containerRef,
|
|
5193
|
-
"sh",
|
|
5194
|
-
"-c",
|
|
5195
|
-
`mkdir -p ${shellQuote2(input.spec.cwd)} && tar -xf /tmp/poe-workspace-upload.tar -C ${shellQuote2(input.spec.cwd)}`
|
|
5196
|
-
],
|
|
5197
|
-
stdout: "pipe",
|
|
5198
|
-
stderr: "pipe"
|
|
5199
|
-
});
|
|
5200
|
-
return { files: 0, bytes: 0, skipped: [] };
|
|
5201
|
-
} finally {
|
|
5202
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
5203
|
-
}
|
|
5204
|
-
},
|
|
5205
|
-
async downloadWorkspace(opts) {
|
|
5206
|
-
const tempDir = mkdtempSync(path26.join(tmpdir(), "poe-docker-download-"));
|
|
5207
|
-
const archivePath = path26.join(tempDir, "workspace.tar");
|
|
5208
|
-
try {
|
|
5209
|
-
await runOrThrow(input.runner, {
|
|
5210
|
-
command: input.engine,
|
|
5211
|
-
args: [
|
|
5212
|
-
...buildContextArgs(input.engine, input.context),
|
|
5213
|
-
"exec",
|
|
5214
|
-
containerRef,
|
|
5215
|
-
"sh",
|
|
5216
|
-
"-c",
|
|
5217
|
-
`tar -cf /tmp/poe-workspace-download.tar -C ${shellQuote2(input.spec.cwd)} .`
|
|
5218
|
-
],
|
|
5219
|
-
stdout: "pipe",
|
|
5220
|
-
stderr: "pipe"
|
|
5221
|
-
});
|
|
5222
|
-
await runOrThrow(input.runner, {
|
|
5223
|
-
command: input.engine,
|
|
5224
|
-
args: [
|
|
5225
|
-
...buildContextArgs(input.engine, input.context),
|
|
5226
|
-
"cp",
|
|
5227
|
-
`${containerRef}:/tmp/poe-workspace-download.tar`,
|
|
5228
|
-
archivePath
|
|
5229
|
-
],
|
|
5230
|
-
stdout: "pipe",
|
|
5231
|
-
stderr: "pipe"
|
|
5232
|
-
});
|
|
5233
|
-
const extractMode = opts.conflictPolicy === "refuse" ? "-xkf" : "-xf";
|
|
5234
|
-
await runOrThrow(input.runner, {
|
|
5235
|
-
command: "tar",
|
|
5236
|
-
args: [extractMode, archivePath, "-C", input.spec.cwd],
|
|
5237
|
-
stdout: "pipe",
|
|
5238
|
-
stderr: "pipe"
|
|
5239
|
-
});
|
|
5240
|
-
return { files: 0, bytes: 0, conflicts: [] };
|
|
5241
|
-
} finally {
|
|
5242
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
5243
|
-
}
|
|
5244
|
-
},
|
|
5245
|
-
exec(spec) {
|
|
5246
|
-
return input.runner.exec({
|
|
5247
|
-
command: input.engine,
|
|
5248
|
-
args: [
|
|
5249
|
-
...buildContextArgs(input.engine, input.context),
|
|
5250
|
-
"exec",
|
|
5251
|
-
...spec.stdin === "pipe" || spec.stdin === "inherit" ? ["-i"] : [],
|
|
5252
|
-
...spec.tty === true ? ["-t"] : [],
|
|
5253
|
-
...spec.cwd !== void 0 ? ["-w", spec.cwd] : [],
|
|
5254
|
-
...buildEnvArgs(spec.env),
|
|
5255
|
-
containerRef,
|
|
5256
|
-
spec.command,
|
|
5257
|
-
...spec.args ?? []
|
|
5258
|
-
],
|
|
5259
|
-
stdin: spec.stdin,
|
|
5260
|
-
stdout: spec.stdout,
|
|
5261
|
-
stderr: spec.stderr,
|
|
5262
|
-
tty: spec.tty
|
|
5263
|
-
});
|
|
5264
|
-
},
|
|
5265
|
-
async detach() {
|
|
5266
|
-
return createContainerJob(containerRef, input.runner, input.engine, input.context);
|
|
5267
|
-
},
|
|
5268
|
-
shell() {
|
|
5269
|
-
const shellSpec = input.spec.shellSpec;
|
|
5270
|
-
return this.exec({
|
|
5271
|
-
command: shellSpec?.command ?? input.spec.env.SHELL ?? "sh",
|
|
5272
|
-
...shellSpec?.args ? { args: shellSpec.args } : {},
|
|
5273
|
-
cwd: input.spec.cwd,
|
|
5274
|
-
env: shellSpec && "env" in shellSpec ? shellSpec.env : input.spec.env,
|
|
5275
|
-
stdin: "inherit",
|
|
5276
|
-
stdout: "inherit",
|
|
5277
|
-
stderr: "inherit",
|
|
5278
|
-
tty: true
|
|
5279
|
-
});
|
|
5280
|
-
},
|
|
5281
|
-
async close() {
|
|
5282
|
-
await runOrThrow(input.runner, {
|
|
5283
|
-
command: input.engine,
|
|
5284
|
-
args: [...buildContextArgs(input.engine, input.context), "rm", "-f", containerRef],
|
|
5285
|
-
stdout: "pipe",
|
|
5286
|
-
stderr: "pipe"
|
|
5287
|
-
});
|
|
5383
|
+
stdout: () => "",
|
|
5384
|
+
stderr: () => "",
|
|
5385
|
+
dispose() {
|
|
5386
|
+
handle.stdout?.unpipe(process.stdout);
|
|
5387
|
+
handle.stderr?.unpipe(process.stderr);
|
|
5288
5388
|
}
|
|
5289
5389
|
};
|
|
5290
5390
|
}
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
const
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5391
|
+
function captureRunStreams(handle, execution, onActivity) {
|
|
5392
|
+
let stdout = "";
|
|
5393
|
+
let stderr = "";
|
|
5394
|
+
const listeners = [];
|
|
5395
|
+
const bind = (stream, onChunk) => {
|
|
5396
|
+
if (!stream) return;
|
|
5397
|
+
stream.setEncoding("utf8");
|
|
5398
|
+
const listener = (chunk) => {
|
|
5399
|
+
onActivity();
|
|
5400
|
+
onChunk(chunk.toString());
|
|
5401
|
+
};
|
|
5402
|
+
stream.on("data", listener);
|
|
5403
|
+
listeners.push(() => {
|
|
5404
|
+
stream.off("data", listener);
|
|
5405
|
+
});
|
|
5406
|
+
};
|
|
5407
|
+
bind(handle.stdout, (chunk) => {
|
|
5408
|
+
stdout += chunk;
|
|
5409
|
+
execution?.onStdout?.(chunk);
|
|
5300
5410
|
});
|
|
5301
|
-
|
|
5411
|
+
bind(handle.stderr, (chunk) => {
|
|
5412
|
+
stderr += chunk;
|
|
5413
|
+
execution?.onStderr?.(chunk);
|
|
5414
|
+
});
|
|
5415
|
+
return {
|
|
5416
|
+
stdout: () => stdout,
|
|
5417
|
+
stderr: () => stderr,
|
|
5418
|
+
dispose() {
|
|
5419
|
+
for (const remove2 of listeners) {
|
|
5420
|
+
remove2();
|
|
5421
|
+
}
|
|
5422
|
+
}
|
|
5423
|
+
};
|
|
5302
5424
|
}
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
const
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5425
|
+
function createAbortSync(signal, handle, activityTimeoutMs) {
|
|
5426
|
+
let activityTimer;
|
|
5427
|
+
let timedOut = false;
|
|
5428
|
+
const resetActivityTimer = activityTimeoutMs ? () => {
|
|
5429
|
+
if (activityTimer) clearTimeout(activityTimer);
|
|
5430
|
+
activityTimer = setTimeout(() => {
|
|
5431
|
+
timedOut = true;
|
|
5432
|
+
handle.kill("SIGTERM");
|
|
5433
|
+
notifyAbort?.();
|
|
5434
|
+
}, activityTimeoutMs);
|
|
5435
|
+
} : () => {
|
|
5436
|
+
};
|
|
5437
|
+
let notifyAbort;
|
|
5438
|
+
if (signal === void 0) {
|
|
5316
5439
|
return {
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5440
|
+
waitForExit: (env, jobId) => waitForExit(toLogStreamEnv(env), jobId),
|
|
5441
|
+
waitForHandle: async () => {
|
|
5442
|
+
const result = await handle.result;
|
|
5443
|
+
if (timedOut) {
|
|
5444
|
+
throw createActivityTimeoutError(activityTimeoutMs);
|
|
5445
|
+
}
|
|
5446
|
+
return result;
|
|
5447
|
+
},
|
|
5448
|
+
resetActivityTimer,
|
|
5449
|
+
dispose() {
|
|
5450
|
+
if (activityTimer) clearTimeout(activityTimer);
|
|
5451
|
+
}
|
|
5321
5452
|
};
|
|
5322
5453
|
}
|
|
5323
|
-
const
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
context,
|
|
5328
|
-
image,
|
|
5329
|
-
dockerfilePath,
|
|
5330
|
-
buildContext,
|
|
5331
|
-
buildArgs: input.runtime.build_args ?? {}
|
|
5332
|
-
});
|
|
5333
|
-
await input.state?.templates.put("docker", {
|
|
5334
|
-
hash,
|
|
5335
|
-
image,
|
|
5336
|
-
runtime_type: "docker",
|
|
5337
|
-
dockerfile_path: dockerfilePath,
|
|
5338
|
-
built_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
5454
|
+
const exitWaitController = new AbortController();
|
|
5455
|
+
let aborted = signal.aborted;
|
|
5456
|
+
const abortedPromise = new Promise((resolve2) => {
|
|
5457
|
+
notifyAbort = resolve2;
|
|
5339
5458
|
});
|
|
5459
|
+
const kill = () => {
|
|
5460
|
+
aborted = true;
|
|
5461
|
+
handle.kill("SIGTERM");
|
|
5462
|
+
notifyAbort?.();
|
|
5463
|
+
};
|
|
5464
|
+
if (signal.aborted) {
|
|
5465
|
+
kill();
|
|
5466
|
+
} else {
|
|
5467
|
+
signal.addEventListener("abort", kill, { once: true });
|
|
5468
|
+
}
|
|
5340
5469
|
return {
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5470
|
+
async waitForExit(env, jobId) {
|
|
5471
|
+
if (aborted) {
|
|
5472
|
+
return handle.result;
|
|
5473
|
+
}
|
|
5474
|
+
const exit = waitForExit(toLogStreamEnv(env), jobId, {
|
|
5475
|
+
signal: exitWaitController.signal
|
|
5476
|
+
}).then(
|
|
5477
|
+
(value) => ({ kind: "exit", value }),
|
|
5478
|
+
(error2) => ({ kind: "error", error: error2 })
|
|
5479
|
+
);
|
|
5480
|
+
const result = await Promise.race([
|
|
5481
|
+
exit,
|
|
5482
|
+
abortedPromise.then(() => ({ kind: "abort" }))
|
|
5483
|
+
]);
|
|
5484
|
+
if (result.kind === "exit") {
|
|
5485
|
+
return result.value;
|
|
5486
|
+
}
|
|
5487
|
+
if (result.kind === "error") {
|
|
5488
|
+
throw result.error;
|
|
5489
|
+
}
|
|
5490
|
+
exitWaitController.abort();
|
|
5491
|
+
return handle.result;
|
|
5492
|
+
},
|
|
5493
|
+
async waitForHandle() {
|
|
5494
|
+
const result = await Promise.race([
|
|
5495
|
+
handle.result.then((value) => ({ kind: "exit", value })),
|
|
5496
|
+
abortedPromise.then(() => ({ kind: "abort" }))
|
|
5497
|
+
]);
|
|
5498
|
+
if (result.kind === "exit") {
|
|
5499
|
+
if (aborted) {
|
|
5500
|
+
throw createAbortError2();
|
|
5501
|
+
}
|
|
5502
|
+
if (timedOut) {
|
|
5503
|
+
throw createActivityTimeoutError(activityTimeoutMs);
|
|
5504
|
+
}
|
|
5505
|
+
return result.value;
|
|
5506
|
+
}
|
|
5507
|
+
if (timedOut) {
|
|
5508
|
+
throw createActivityTimeoutError(activityTimeoutMs);
|
|
5509
|
+
}
|
|
5510
|
+
throw createAbortError2();
|
|
5511
|
+
},
|
|
5512
|
+
resetActivityTimer,
|
|
5513
|
+
dispose() {
|
|
5514
|
+
if (activityTimer) clearTimeout(activityTimer);
|
|
5515
|
+
exitWaitController.abort();
|
|
5516
|
+
signal.removeEventListener("abort", kill);
|
|
5517
|
+
}
|
|
5345
5518
|
};
|
|
5346
5519
|
}
|
|
5347
|
-
function
|
|
5348
|
-
const
|
|
5349
|
-
|
|
5350
|
-
hash.update("\0");
|
|
5351
|
-
for (const [key, value] of sortedBuildArgs(buildArgs)) {
|
|
5352
|
-
hash.update(key);
|
|
5353
|
-
hash.update("=");
|
|
5354
|
-
hash.update(value);
|
|
5355
|
-
hash.update("\0");
|
|
5356
|
-
}
|
|
5357
|
-
return hash.digest("hex");
|
|
5520
|
+
function toLogStreamEnv(env) {
|
|
5521
|
+
const candidate = env;
|
|
5522
|
+
return candidate.fs === void 0 ? {} : { fs: candidate.fs };
|
|
5358
5523
|
}
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
args: [
|
|
5363
|
-
...buildContextArgs(input.engine, input.context),
|
|
5364
|
-
"build",
|
|
5365
|
-
"--tag",
|
|
5366
|
-
input.image,
|
|
5367
|
-
"-f",
|
|
5368
|
-
input.dockerfilePath,
|
|
5369
|
-
...sortedBuildArgs(input.buildArgs).flatMap(([key, value]) => [
|
|
5370
|
-
"--build-arg",
|
|
5371
|
-
`${key}=${value}`
|
|
5372
|
-
]),
|
|
5373
|
-
input.buildContext
|
|
5374
|
-
],
|
|
5375
|
-
stdout: "pipe",
|
|
5376
|
-
stderr: "pipe"
|
|
5377
|
-
});
|
|
5524
|
+
function setDetachedJobContext(env, context) {
|
|
5525
|
+
const candidate = env;
|
|
5526
|
+
candidate.setDetachedJobContext?.(context);
|
|
5378
5527
|
}
|
|
5379
|
-
function
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
const
|
|
5384
|
-
|
|
5385
|
-
|
|
5528
|
+
function isPromiseLike(value) {
|
|
5529
|
+
return typeof value.then === "function";
|
|
5530
|
+
}
|
|
5531
|
+
function createAbortError2() {
|
|
5532
|
+
const error2 = new Error("Agent spawn aborted");
|
|
5533
|
+
error2.name = "AbortError";
|
|
5534
|
+
return error2;
|
|
5535
|
+
}
|
|
5536
|
+
function createActivityTimeoutError(timeoutMs) {
|
|
5537
|
+
const error2 = new Error(`Agent spawn timed out after ${timeoutMs / 1e3}s of inactivity`);
|
|
5538
|
+
error2.name = "ActivityTimeoutError";
|
|
5539
|
+
return error2;
|
|
5540
|
+
}
|
|
5541
|
+
function createUlid() {
|
|
5542
|
+
const time = BigInt(Date.now());
|
|
5543
|
+
const random = randomBytes3(10);
|
|
5544
|
+
let randomValue = 0n;
|
|
5545
|
+
for (const byte of random) {
|
|
5546
|
+
randomValue = randomValue << 8n | BigInt(byte);
|
|
5386
5547
|
}
|
|
5387
|
-
return
|
|
5548
|
+
return encodeBase32(time, 10) + encodeBase32(randomValue, 16);
|
|
5388
5549
|
}
|
|
5389
|
-
|
|
5390
|
-
const
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
if (result.exitCode !== 0) {
|
|
5396
|
-
const errorOutput = await stderr;
|
|
5397
|
-
throw new Error(
|
|
5398
|
-
`Command failed with exit code ${result.exitCode}: ${spec.command} ${(spec.args ?? []).join(" ")}${errorOutput ? `
|
|
5399
|
-
${errorOutput}` : ""}`
|
|
5400
|
-
);
|
|
5550
|
+
function encodeBase32(value, length) {
|
|
5551
|
+
const chars = Array.from({ length }, () => "0");
|
|
5552
|
+
let remaining = value;
|
|
5553
|
+
for (let index = length - 1; index >= 0; index -= 1) {
|
|
5554
|
+
chars[index] = ULID_ALPHABET[Number(remaining & 31n)];
|
|
5555
|
+
remaining >>= 5n;
|
|
5401
5556
|
}
|
|
5402
|
-
return
|
|
5557
|
+
return chars.join("");
|
|
5403
5558
|
}
|
|
5404
|
-
|
|
5405
|
-
|
|
5559
|
+
|
|
5560
|
+
// packages/agent-harness-tools/src/poe-command-execution.ts
|
|
5561
|
+
import { existsSync as existsSync2, readFileSync } from "node:fs";
|
|
5562
|
+
import os3 from "node:os";
|
|
5563
|
+
|
|
5564
|
+
// packages/agent-harness-tools/src/execution-env.ts
|
|
5565
|
+
var executionEnvFactories = /* @__PURE__ */ new Map();
|
|
5566
|
+
function registerExecutionEnvFactory(factory) {
|
|
5567
|
+
executionEnvFactories.set(factory.type, factory);
|
|
5406
5568
|
}
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5569
|
+
function selectExecutionEnv(runtime) {
|
|
5570
|
+
return selectExecutionEnvFactory(runtime.type);
|
|
5571
|
+
}
|
|
5572
|
+
function selectExecutionEnvFactory(type) {
|
|
5573
|
+
const factory = executionEnvFactories.get(type);
|
|
5574
|
+
if (factory === void 0) {
|
|
5575
|
+
throw new Error(
|
|
5576
|
+
`No execution environment factory registered for runtime type "${type}".`
|
|
5577
|
+
);
|
|
5415
5578
|
}
|
|
5416
|
-
return
|
|
5579
|
+
return factory;
|
|
5417
5580
|
}
|
|
5418
|
-
|
|
5419
|
-
|
|
5581
|
+
|
|
5582
|
+
// packages/agent-harness-tools/src/poe-command-execution.ts
|
|
5583
|
+
function resolvePoeCommandExecution(input) {
|
|
5584
|
+
const homeDir = input.context?.homeDir ?? os3.homedir();
|
|
5585
|
+
const runtimeConfigCwd = input.runtimeConfigCwd ?? input.cwd;
|
|
5586
|
+
const loaded = loadRuntimeConfig(runtimeConfigCwd, homeDir);
|
|
5587
|
+
const config = applyRuntimeOverrides(loaded, input.runtime, runtimeConfigCwd);
|
|
5588
|
+
const resolved = resolveRuntime({ cwd: runtimeConfigCwd, config });
|
|
5589
|
+
const factory = selectExecutionEnv(resolved.runtime);
|
|
5590
|
+
const state = input.context?.state ?? loadState(homeDir);
|
|
5591
|
+
return {
|
|
5592
|
+
factory,
|
|
5593
|
+
detach: factory.supportsDetach === true && config.runner.detach,
|
|
5594
|
+
state,
|
|
5595
|
+
openSpec: {
|
|
5596
|
+
cwd: input.cwd,
|
|
5597
|
+
runtimeCwd: runtimeConfigCwd,
|
|
5598
|
+
runtime: resolved.runtime,
|
|
5599
|
+
runner: config.runner,
|
|
5600
|
+
state,
|
|
5601
|
+
env: input.env,
|
|
5602
|
+
uploadIgnoreFiles: config.runner.workspace?.exclude ?? [],
|
|
5603
|
+
jobLabel: {
|
|
5604
|
+
tool: input.tool,
|
|
5605
|
+
argv: input.argv
|
|
5606
|
+
},
|
|
5607
|
+
...input.openSpec
|
|
5608
|
+
}
|
|
5609
|
+
};
|
|
5420
5610
|
}
|
|
5421
|
-
function
|
|
5422
|
-
if (
|
|
5423
|
-
return
|
|
5611
|
+
function applyRuntimeOverrides(config, overrides, cwd = process.cwd()) {
|
|
5612
|
+
if (!overrides) {
|
|
5613
|
+
return { runtime: config.runtime, runner: config.runner };
|
|
5424
5614
|
}
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
}
|
|
5430
|
-
|
|
5615
|
+
const base = "rawScope" in config && config.rawScope ? { ...config.rawScope } : { ...config.runtime };
|
|
5616
|
+
const runtime = parseRuntime({
|
|
5617
|
+
...base,
|
|
5618
|
+
...overrides.runtime !== void 0 ? { type: overrides.runtime } : {},
|
|
5619
|
+
...overrides.runtimeImage !== void 0 ? { image: overrides.runtimeImage } : {},
|
|
5620
|
+
...overrides.runtimeTemplate !== void 0 ? { template_id: overrides.runtimeTemplate } : {},
|
|
5621
|
+
...overrides.mountPoeCode === true ? { mounts: [...config.runtime.mounts, createPoeCodeMount(cwd)] } : {}
|
|
5622
|
+
});
|
|
5431
5623
|
return {
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
const handle = runner.exec({
|
|
5438
|
-
command: engine,
|
|
5439
|
-
args: [
|
|
5440
|
-
...buildContextArgs(engine, context),
|
|
5441
|
-
"inspect",
|
|
5442
|
-
"-f",
|
|
5443
|
-
"{{.State.Status}}",
|
|
5444
|
-
containerId
|
|
5445
|
-
],
|
|
5446
|
-
stdout: "pipe",
|
|
5447
|
-
stderr: "pipe"
|
|
5448
|
-
});
|
|
5449
|
-
const stdout = await readStream2(handle.stdout);
|
|
5450
|
-
const result = await handle.result;
|
|
5451
|
-
if (result.exitCode !== 0) {
|
|
5452
|
-
return "lost";
|
|
5453
|
-
}
|
|
5454
|
-
return stdout.trim() === "running" ? "running" : "exited";
|
|
5455
|
-
},
|
|
5456
|
-
async *stream(opts) {
|
|
5457
|
-
const handle = runner.exec({
|
|
5458
|
-
command: engine,
|
|
5459
|
-
args: [
|
|
5460
|
-
...buildContextArgs(engine, context),
|
|
5461
|
-
"exec",
|
|
5462
|
-
containerId,
|
|
5463
|
-
"sh",
|
|
5464
|
-
"-c",
|
|
5465
|
-
`test -f ${shellQuote2(`/tmp/poe-jobs/${jobId}.log`)} && tail -c +${(opts?.sinceByte ?? 0) + 1} ${shellQuote2(`/tmp/poe-jobs/${jobId}.log`)} || true`
|
|
5466
|
-
],
|
|
5467
|
-
stdout: "pipe",
|
|
5468
|
-
stderr: "pipe"
|
|
5469
|
-
});
|
|
5470
|
-
const stdout = await readStream2(handle.stdout);
|
|
5471
|
-
await handle.result;
|
|
5472
|
-
if (stdout.length > 0) {
|
|
5473
|
-
yield { byteOffset: opts?.sinceByte ?? 0, data: stdout };
|
|
5474
|
-
}
|
|
5475
|
-
},
|
|
5476
|
-
async wait() {
|
|
5477
|
-
const handle = runner.exec({
|
|
5478
|
-
command: engine,
|
|
5479
|
-
args: [...buildContextArgs(engine, context), "wait", containerId],
|
|
5480
|
-
stdout: "pipe",
|
|
5481
|
-
stderr: "pipe"
|
|
5482
|
-
});
|
|
5483
|
-
const stdout = await readStream2(handle.stdout);
|
|
5484
|
-
const result = await handle.result;
|
|
5485
|
-
return { exitCode: Number.parseInt(stdout.trim(), 10) || result.exitCode };
|
|
5486
|
-
},
|
|
5487
|
-
async kill(signal) {
|
|
5488
|
-
const args = signal === void 0 || signal === "SIGTERM" ? ["stop", containerId] : ["kill", ...signal === "SIGKILL" ? [] : [`--signal=${signal}`], containerId];
|
|
5489
|
-
await runOrThrow(runner, {
|
|
5490
|
-
command: engine,
|
|
5491
|
-
args: [...buildContextArgs(engine, context), ...args],
|
|
5492
|
-
stdout: "pipe",
|
|
5493
|
-
stderr: "pipe"
|
|
5494
|
-
});
|
|
5624
|
+
runtime,
|
|
5625
|
+
runner: {
|
|
5626
|
+
...config.runner,
|
|
5627
|
+
...overrides.detach === true ? { detach: true } : {},
|
|
5628
|
+
...overrides.runnerSync !== void 0 ? { sync: overrides.runnerSync } : {}
|
|
5495
5629
|
}
|
|
5496
5630
|
};
|
|
5497
5631
|
}
|
|
5498
|
-
function
|
|
5632
|
+
function createPoeCodeMount(cwd) {
|
|
5499
5633
|
return {
|
|
5500
|
-
cwd,
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
image: "attached",
|
|
5504
|
-
build_args: {},
|
|
5505
|
-
mounts: []
|
|
5506
|
-
},
|
|
5507
|
-
env: {},
|
|
5508
|
-
uploadIgnoreFiles: [],
|
|
5509
|
-
jobLabel: {
|
|
5510
|
-
tool: "docker",
|
|
5511
|
-
argv: []
|
|
5512
|
-
}
|
|
5634
|
+
source: cwd,
|
|
5635
|
+
target: "/usr/local/lib/poe-code",
|
|
5636
|
+
readonly: true
|
|
5513
5637
|
};
|
|
5514
5638
|
}
|
|
5515
|
-
function
|
|
5516
|
-
|
|
5639
|
+
function loadRuntimeConfig(cwd, homeDir) {
|
|
5640
|
+
const document = deepMergeDocuments(
|
|
5641
|
+
readConfigDocument(resolveConfigPath(homeDir)),
|
|
5642
|
+
readConfigDocument(resolveProjectConfigPath(cwd))
|
|
5643
|
+
);
|
|
5644
|
+
const runtimeScope = resolveScope(runtimeConfigScope.schema, document.runtime, process.env);
|
|
5645
|
+
return {
|
|
5646
|
+
rawScope: { ...runtimeScope },
|
|
5647
|
+
runtime: parseRuntime(runtimeScope),
|
|
5648
|
+
runner: runtimeScope.runner
|
|
5649
|
+
};
|
|
5517
5650
|
}
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5651
|
+
function readConfigDocument(filePath) {
|
|
5652
|
+
if (!existsSync2(filePath)) {
|
|
5653
|
+
return {};
|
|
5654
|
+
}
|
|
5655
|
+
return JSON.parse(readFileSync(filePath, "utf8"));
|
|
5656
|
+
}
|
|
5657
|
+
function loadState(homeDir) {
|
|
5658
|
+
if (process.env.VITEST === "true") {
|
|
5659
|
+
return createMemoryStateManager();
|
|
5660
|
+
}
|
|
5661
|
+
return createStateManager(homeDir);
|
|
5662
|
+
}
|
|
5663
|
+
function createMemoryStateManager() {
|
|
5664
|
+
const jobs = /* @__PURE__ */ new Map();
|
|
5665
|
+
return {
|
|
5666
|
+
templates: {
|
|
5667
|
+
async get() {
|
|
5668
|
+
return null;
|
|
5533
5669
|
},
|
|
5534
|
-
async
|
|
5535
|
-
return {
|
|
5536
|
-
files: 0,
|
|
5537
|
-
bytes: 0,
|
|
5538
|
-
conflicts: []
|
|
5539
|
-
};
|
|
5670
|
+
async put() {
|
|
5540
5671
|
},
|
|
5541
|
-
|
|
5542
|
-
return createHostRunner().exec(spec);
|
|
5672
|
+
async remove() {
|
|
5543
5673
|
},
|
|
5544
|
-
async
|
|
5545
|
-
|
|
5674
|
+
async list() {
|
|
5675
|
+
return [];
|
|
5676
|
+
}
|
|
5677
|
+
},
|
|
5678
|
+
jobs: {
|
|
5679
|
+
async get(id) {
|
|
5680
|
+
return jobs.get(id) ?? null;
|
|
5546
5681
|
},
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
return createHostRunner().exec({
|
|
5550
|
-
command: shellSpec?.command ?? openSpec.env.SHELL ?? process.env.SHELL ?? "sh",
|
|
5551
|
-
...shellSpec?.args ? { args: shellSpec.args } : {},
|
|
5552
|
-
cwd: openSpec.cwd,
|
|
5553
|
-
env: shellSpec && "env" in shellSpec ? shellSpec.env : openSpec.env,
|
|
5554
|
-
stdin: "inherit",
|
|
5555
|
-
stdout: "inherit",
|
|
5556
|
-
stderr: "inherit",
|
|
5557
|
-
tty: true
|
|
5558
|
-
});
|
|
5682
|
+
async put(entry) {
|
|
5683
|
+
jobs.set(entry.id, entry);
|
|
5559
5684
|
},
|
|
5560
|
-
async
|
|
5685
|
+
async update(id, patch) {
|
|
5686
|
+
const current = jobs.get(id);
|
|
5687
|
+
if (!current) {
|
|
5688
|
+
return null;
|
|
5689
|
+
}
|
|
5690
|
+
const updated = { ...current, ...patch, id };
|
|
5691
|
+
jobs.set(id, updated);
|
|
5692
|
+
return updated;
|
|
5693
|
+
},
|
|
5694
|
+
async list(filter) {
|
|
5695
|
+
const entries = Array.from(jobs.values());
|
|
5696
|
+
if (!filter) {
|
|
5697
|
+
return entries;
|
|
5698
|
+
}
|
|
5699
|
+
return entries.filter(
|
|
5700
|
+
(entry) => Object.entries(filter).every(([key, value]) => entry[key] === value)
|
|
5701
|
+
);
|
|
5702
|
+
},
|
|
5703
|
+
async remove(id) {
|
|
5704
|
+
jobs.delete(id);
|
|
5561
5705
|
}
|
|
5562
|
-
}
|
|
5563
|
-
}
|
|
5564
|
-
|
|
5565
|
-
throw new Error("host runtime does not support reattach");
|
|
5566
|
-
}
|
|
5567
|
-
};
|
|
5706
|
+
}
|
|
5707
|
+
};
|
|
5708
|
+
}
|
|
5568
5709
|
|
|
5569
|
-
// packages/
|
|
5570
|
-
import {
|
|
5710
|
+
// packages/agent-harness-tools/src/workspace-transfer.ts
|
|
5711
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
5712
|
+
import { promises as nodeFs3 } from "node:fs";
|
|
5713
|
+
import path29 from "node:path";
|
|
5571
5714
|
|
|
5572
5715
|
// packages/runner-e2b/src/factory.ts
|
|
5573
|
-
import
|
|
5716
|
+
import path33 from "node:path";
|
|
5574
5717
|
|
|
5575
5718
|
// packages/runner-e2b/src/sdk.ts
|
|
5576
5719
|
import { Template, Sandbox } from "e2b";
|
|
@@ -5619,7 +5762,7 @@ async function readableToString(stream) {
|
|
|
5619
5762
|
// packages/runner-e2b/src/template-build.ts
|
|
5620
5763
|
import { createHash as createHash5 } from "node:crypto";
|
|
5621
5764
|
import { readdir as readdir4, readFile as readFile11 } from "node:fs/promises";
|
|
5622
|
-
import
|
|
5765
|
+
import path30 from "node:path";
|
|
5623
5766
|
var BUILD_LOG_TAIL_SIZE = 30;
|
|
5624
5767
|
async function buildE2bRuntimeTemplate(input) {
|
|
5625
5768
|
const dockerfileBytes = await readFile11(input.dockerfilePath);
|
|
@@ -5700,10 +5843,10 @@ async function readBuildContextFiles(buildContext) {
|
|
|
5700
5843
|
return files.sort((left, right) => left.relativePath.localeCompare(right.relativePath));
|
|
5701
5844
|
}
|
|
5702
5845
|
async function collectBuildContextFiles(buildContext, relativeDir, files) {
|
|
5703
|
-
const absoluteDir =
|
|
5846
|
+
const absoluteDir = path30.join(buildContext, relativeDir);
|
|
5704
5847
|
const entries = await readdir4(absoluteDir, { withFileTypes: true });
|
|
5705
5848
|
for (const entry of entries) {
|
|
5706
|
-
const relativePath =
|
|
5849
|
+
const relativePath = path30.join(relativeDir, entry.name);
|
|
5707
5850
|
if (entry.isDirectory()) {
|
|
5708
5851
|
await collectBuildContextFiles(buildContext, relativePath, files);
|
|
5709
5852
|
continue;
|
|
@@ -5712,8 +5855,8 @@ async function collectBuildContextFiles(buildContext, relativeDir, files) {
|
|
|
5712
5855
|
continue;
|
|
5713
5856
|
}
|
|
5714
5857
|
files.push({
|
|
5715
|
-
relativePath: relativePath.split(
|
|
5716
|
-
bytes: await readFile11(
|
|
5858
|
+
relativePath: relativePath.split(path30.sep).join("/"),
|
|
5859
|
+
bytes: await readFile11(path30.join(buildContext, relativePath))
|
|
5717
5860
|
});
|
|
5718
5861
|
}
|
|
5719
5862
|
}
|
|
@@ -5722,11 +5865,11 @@ async function collectBuildContextFiles(buildContext, relativeDir, files) {
|
|
|
5722
5865
|
import { mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "node:fs";
|
|
5723
5866
|
import { readFile as readFile12, writeFile as writeFile7 } from "node:fs/promises";
|
|
5724
5867
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
5725
|
-
import
|
|
5868
|
+
import path32 from "node:path";
|
|
5726
5869
|
import { PassThrough, Writable as Writable2 } from "node:stream";
|
|
5727
5870
|
|
|
5728
5871
|
// packages/runner-e2b/src/job-handle.ts
|
|
5729
|
-
import
|
|
5872
|
+
import path31 from "node:path";
|
|
5730
5873
|
var JOB_DIR2 = "/tmp/poe-jobs";
|
|
5731
5874
|
function createE2bJobHandle(input) {
|
|
5732
5875
|
const fs14 = createE2bLogStreamFs(input.sandbox);
|
|
@@ -5784,7 +5927,7 @@ function createE2bLogStreamFs(sandbox) {
|
|
|
5784
5927
|
watch(filePath, listener) {
|
|
5785
5928
|
let closed = false;
|
|
5786
5929
|
let stop = null;
|
|
5787
|
-
void sandbox.files.watchDir(
|
|
5930
|
+
void sandbox.files.watchDir(path31.dirname(filePath), listener, { recursive: false }).then((handle) => {
|
|
5788
5931
|
if (closed) {
|
|
5789
5932
|
void handle.stop();
|
|
5790
5933
|
return;
|
|
@@ -5823,7 +5966,7 @@ async function readExitCode(sandbox, jobId) {
|
|
|
5823
5966
|
var REMOTE_COMMAND_STDERR_TAIL_SIZE = 30;
|
|
5824
5967
|
function createOpenedE2bEnv(input) {
|
|
5825
5968
|
const hostRunner = input.spec.hostRunner ?? createHostRunner();
|
|
5826
|
-
const hostWorkspaceDir =
|
|
5969
|
+
const hostWorkspaceDir = path32.resolve(input.spec.cwd);
|
|
5827
5970
|
const sandboxWorkspaceDir = normalizeSandboxWorkspaceDir(input.runtime.workspace_dir);
|
|
5828
5971
|
let lastProcess = null;
|
|
5829
5972
|
let detachedJobContext = null;
|
|
@@ -5831,7 +5974,7 @@ function createOpenedE2bEnv(input) {
|
|
|
5831
5974
|
if (cwd === void 0) {
|
|
5832
5975
|
return void 0;
|
|
5833
5976
|
}
|
|
5834
|
-
if (
|
|
5977
|
+
if (path32.isAbsolute(cwd) && path32.resolve(cwd) === hostWorkspaceDir) {
|
|
5835
5978
|
return sandboxWorkspaceDir;
|
|
5836
5979
|
}
|
|
5837
5980
|
return cwd;
|
|
@@ -5855,8 +5998,8 @@ function createOpenedE2bEnv(input) {
|
|
|
5855
5998
|
if (input.spec.runner?.sync === "none") {
|
|
5856
5999
|
return { files: 0, bytes: 0, skipped: [] };
|
|
5857
6000
|
}
|
|
5858
|
-
const tempDir = mkdtempSync2(
|
|
5859
|
-
const archivePath =
|
|
6001
|
+
const tempDir = mkdtempSync2(path32.join(tmpdir2(), "poe-e2b-upload-"));
|
|
6002
|
+
const archivePath = path32.join(tempDir, "workspace.tar");
|
|
5860
6003
|
try {
|
|
5861
6004
|
await runOrThrow2(hostRunner, {
|
|
5862
6005
|
command: "tar",
|
|
@@ -5888,8 +6031,8 @@ function createOpenedE2bEnv(input) {
|
|
|
5888
6031
|
if (input.spec.runner?.sync === "upload" || input.spec.runner?.sync === "none") {
|
|
5889
6032
|
return { files: 0, bytes: 0, conflicts: [] };
|
|
5890
6033
|
}
|
|
5891
|
-
const tempDir = mkdtempSync2(
|
|
5892
|
-
const archivePath =
|
|
6034
|
+
const tempDir = mkdtempSync2(path32.join(tmpdir2(), "poe-e2b-download-"));
|
|
6035
|
+
const archivePath = path32.join(tempDir, "workspace.tar");
|
|
5893
6036
|
try {
|
|
5894
6037
|
await runRemoteOrThrow(
|
|
5895
6038
|
input.sandbox,
|
|
@@ -6212,10 +6355,10 @@ function resolveSandboxCommandEnv(env) {
|
|
|
6212
6355
|
}
|
|
6213
6356
|
function normalizeSandboxWorkspaceDir(workspaceDir) {
|
|
6214
6357
|
const resolvedWorkspaceDir = workspaceDir ?? "/workspace";
|
|
6215
|
-
if (!
|
|
6358
|
+
if (!path32.posix.isAbsolute(resolvedWorkspaceDir)) {
|
|
6216
6359
|
throw new Error("E2B runtime workspace_dir must be an absolute sandbox path.");
|
|
6217
6360
|
}
|
|
6218
|
-
let normalized =
|
|
6361
|
+
let normalized = path32.posix.normalize(resolvedWorkspaceDir);
|
|
6219
6362
|
while (normalized.length > 1 && normalized.endsWith("/")) {
|
|
6220
6363
|
normalized = normalized.slice(0, -1);
|
|
6221
6364
|
}
|
|
@@ -6271,11 +6414,11 @@ var e2bExecutionEnvFactory = {
|
|
|
6271
6414
|
const apiKey = await resolveE2bApiKey({ cwd: runtimeCwd });
|
|
6272
6415
|
const templateId = runtime.template_id ?? (await buildE2bRuntimeTemplate({
|
|
6273
6416
|
runtime,
|
|
6274
|
-
dockerfilePath:
|
|
6417
|
+
dockerfilePath: path33.resolve(
|
|
6275
6418
|
runtimeCwd,
|
|
6276
|
-
runtime.dockerfile ??
|
|
6419
|
+
runtime.dockerfile ?? path33.join(".poe-code", "Dockerfile")
|
|
6277
6420
|
),
|
|
6278
|
-
buildContext:
|
|
6421
|
+
buildContext: path33.resolve(runtimeCwd, runtime.build_context ?? "."),
|
|
6279
6422
|
state: spec.state,
|
|
6280
6423
|
apiKey
|
|
6281
6424
|
})).templateId;
|
|
@@ -6716,7 +6859,7 @@ function listMcpSupportedAgents() {
|
|
|
6716
6859
|
|
|
6717
6860
|
// packages/agent-spawn/src/spawn.ts
|
|
6718
6861
|
import { mkdirSync, openSync, writeSync, closeSync } from "node:fs";
|
|
6719
|
-
import
|
|
6862
|
+
import path34 from "node:path";
|
|
6720
6863
|
|
|
6721
6864
|
// packages/agent-spawn/src/configs/resolve-config.ts
|
|
6722
6865
|
function resolveConfig(agentId) {
|
|
@@ -6945,11 +7088,11 @@ function resolveSpawnLogPath(options) {
|
|
|
6945
7088
|
if (!options.logDir || !options.logFileName) {
|
|
6946
7089
|
return void 0;
|
|
6947
7090
|
}
|
|
6948
|
-
return
|
|
7091
|
+
return path34.join(options.logDir, options.logFileName);
|
|
6949
7092
|
}
|
|
6950
7093
|
function openSpawnLog(filePath) {
|
|
6951
7094
|
try {
|
|
6952
|
-
mkdirSync(
|
|
7095
|
+
mkdirSync(path34.dirname(filePath), { recursive: true });
|
|
6953
7096
|
return openSync(filePath, "a");
|
|
6954
7097
|
} catch {
|
|
6955
7098
|
return void 0;
|
|
@@ -6973,36 +7116,36 @@ function closeSpawnLog(fd) {
|
|
|
6973
7116
|
// packages/design-system/src/tokens/colors.ts
|
|
6974
7117
|
import chalk from "chalk";
|
|
6975
7118
|
var dark = {
|
|
6976
|
-
header: (
|
|
6977
|
-
divider: (
|
|
6978
|
-
prompt: (
|
|
6979
|
-
number: (
|
|
6980
|
-
intro: (
|
|
7119
|
+
header: (text5) => chalk.magentaBright.bold(text5),
|
|
7120
|
+
divider: (text5) => chalk.dim(text5),
|
|
7121
|
+
prompt: (text5) => chalk.cyan(text5),
|
|
7122
|
+
number: (text5) => chalk.cyanBright(text5),
|
|
7123
|
+
intro: (text5) => chalk.bgMagenta.white(` Poe - ${text5} `),
|
|
6981
7124
|
resolvedSymbol: chalk.magenta("\u25C7"),
|
|
6982
7125
|
errorSymbol: chalk.red("\u25A0"),
|
|
6983
|
-
accent: (
|
|
6984
|
-
muted: (
|
|
6985
|
-
success: (
|
|
6986
|
-
warning: (
|
|
6987
|
-
error: (
|
|
6988
|
-
info: (
|
|
6989
|
-
badge: (
|
|
7126
|
+
accent: (text5) => chalk.cyan(text5),
|
|
7127
|
+
muted: (text5) => chalk.dim(text5),
|
|
7128
|
+
success: (text5) => chalk.green(text5),
|
|
7129
|
+
warning: (text5) => chalk.yellow(text5),
|
|
7130
|
+
error: (text5) => chalk.red(text5),
|
|
7131
|
+
info: (text5) => chalk.magenta(text5),
|
|
7132
|
+
badge: (text5) => chalk.bgYellow.black(` ${text5} `)
|
|
6990
7133
|
};
|
|
6991
7134
|
var light = {
|
|
6992
|
-
header: (
|
|
6993
|
-
divider: (
|
|
6994
|
-
prompt: (
|
|
6995
|
-
number: (
|
|
6996
|
-
intro: (
|
|
7135
|
+
header: (text5) => chalk.hex("#a200ff").bold(text5),
|
|
7136
|
+
divider: (text5) => chalk.hex("#666666")(text5),
|
|
7137
|
+
prompt: (text5) => chalk.hex("#006699").bold(text5),
|
|
7138
|
+
number: (text5) => chalk.hex("#0077cc").bold(text5),
|
|
7139
|
+
intro: (text5) => chalk.bgHex("#a200ff").white(` Poe - ${text5} `),
|
|
6997
7140
|
resolvedSymbol: chalk.hex("#a200ff")("\u25C7"),
|
|
6998
7141
|
errorSymbol: chalk.hex("#cc0000")("\u25A0"),
|
|
6999
|
-
accent: (
|
|
7000
|
-
muted: (
|
|
7001
|
-
success: (
|
|
7002
|
-
warning: (
|
|
7003
|
-
error: (
|
|
7004
|
-
info: (
|
|
7005
|
-
badge: (
|
|
7142
|
+
accent: (text5) => chalk.hex("#006699").bold(text5),
|
|
7143
|
+
muted: (text5) => chalk.hex("#666666")(text5),
|
|
7144
|
+
success: (text5) => chalk.hex("#008800")(text5),
|
|
7145
|
+
warning: (text5) => chalk.hex("#cc6600")(text5),
|
|
7146
|
+
error: (text5) => chalk.hex("#cc0000")(text5),
|
|
7147
|
+
info: (text5) => chalk.hex("#a200ff")(text5),
|
|
7148
|
+
badge: (text5) => chalk.bgHex("#cc6600").white(` ${text5} `)
|
|
7006
7149
|
};
|
|
7007
7150
|
|
|
7008
7151
|
// packages/design-system/src/tokens/typography.ts
|
|
@@ -7377,7 +7520,7 @@ import chalk16 from "chalk";
|
|
|
7377
7520
|
var DEFAULT_ACTIVITY_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
7378
7521
|
|
|
7379
7522
|
// packages/agent-spawn/src/acp/replay.ts
|
|
7380
|
-
import
|
|
7523
|
+
import path35 from "node:path";
|
|
7381
7524
|
import { homedir as homedir2 } from "node:os";
|
|
7382
7525
|
import { open as open2, readdir as readdir5 } from "node:fs/promises";
|
|
7383
7526
|
import { createInterface } from "node:readline";
|
|
@@ -7391,18 +7534,18 @@ import {
|
|
|
7391
7534
|
} from "node:child_process";
|
|
7392
7535
|
|
|
7393
7536
|
// packages/poe-acp-client/src/run-report.ts
|
|
7394
|
-
import * as
|
|
7537
|
+
import * as fsPromises5 from "node:fs/promises";
|
|
7395
7538
|
import { homedir } from "node:os";
|
|
7396
7539
|
import { join } from "node:path";
|
|
7397
7540
|
|
|
7398
7541
|
// packages/agent-spawn/src/acp/middlewares/spawn-log.ts
|
|
7399
|
-
import
|
|
7542
|
+
import path36 from "node:path";
|
|
7400
7543
|
import { homedir as homedir3 } from "node:os";
|
|
7401
7544
|
import { mkdir as mkdir5, open as open3 } from "node:fs/promises";
|
|
7402
7545
|
|
|
7403
7546
|
// packages/memory/src/tokens.ts
|
|
7404
7547
|
import * as fs10 from "node:fs/promises";
|
|
7405
|
-
import
|
|
7548
|
+
import path37 from "node:path";
|
|
7406
7549
|
|
|
7407
7550
|
// packages/tokenfill/dist/tokenizer.js
|
|
7408
7551
|
import { get_encoding } from "tiktoken";
|
|
@@ -7411,19 +7554,19 @@ function createTokenizer(options = {}) {
|
|
|
7411
7554
|
const encoding = options.encoding ?? DEFAULT_ENCODING;
|
|
7412
7555
|
const tokenizer = get_encoding(encoding);
|
|
7413
7556
|
const utf8Decoder = new TextDecoder();
|
|
7414
|
-
const encode = (
|
|
7557
|
+
const encode = (text5) => tokenizer.encode(text5);
|
|
7415
7558
|
const decode = (tokens) => {
|
|
7416
7559
|
const tokenArray = tokens instanceof Uint32Array ? tokens : Uint32Array.from(tokens);
|
|
7417
7560
|
return utf8Decoder.decode(tokenizer.decode(tokenArray));
|
|
7418
7561
|
};
|
|
7419
|
-
const count = (
|
|
7420
|
-
const truncate2 = (
|
|
7562
|
+
const count = (text5) => encode(text5).length;
|
|
7563
|
+
const truncate2 = (text5, tokenCount) => {
|
|
7421
7564
|
if (tokenCount <= 0) {
|
|
7422
7565
|
return "";
|
|
7423
7566
|
}
|
|
7424
|
-
const tokens = encode(
|
|
7567
|
+
const tokens = encode(text5);
|
|
7425
7568
|
if (tokens.length <= tokenCount) {
|
|
7426
|
-
return
|
|
7569
|
+
return text5;
|
|
7427
7570
|
}
|
|
7428
7571
|
return decode(tokens.slice(0, tokenCount));
|
|
7429
7572
|
};
|
|
@@ -7437,9 +7580,9 @@ function createTokenizer(options = {}) {
|
|
|
7437
7580
|
};
|
|
7438
7581
|
}
|
|
7439
7582
|
var defaultTokenizer;
|
|
7440
|
-
function countTokens(
|
|
7583
|
+
function countTokens(text5) {
|
|
7441
7584
|
defaultTokenizer ??= createTokenizer();
|
|
7442
|
-
return defaultTokenizer.count(
|
|
7585
|
+
return defaultTokenizer.count(text5);
|
|
7443
7586
|
}
|
|
7444
7587
|
|
|
7445
7588
|
// packages/tokenfill/dist/corpus.js
|
|
@@ -7486,11 +7629,11 @@ async function computeTokenStats(root) {
|
|
|
7486
7629
|
}
|
|
7487
7630
|
}
|
|
7488
7631
|
}
|
|
7489
|
-
const repoRoot =
|
|
7632
|
+
const repoRoot = path37.resolve(root, "..", "..");
|
|
7490
7633
|
let sourceTokens = 0;
|
|
7491
7634
|
const missingSources = [];
|
|
7492
7635
|
for (const sourcePath of sourcePaths) {
|
|
7493
|
-
const absPath =
|
|
7636
|
+
const absPath = path37.isAbsolute(sourcePath) ? sourcePath : path37.resolve(repoRoot, sourcePath);
|
|
7494
7637
|
try {
|
|
7495
7638
|
const content = await fs10.readFile(absPath, "utf8");
|
|
7496
7639
|
sourceTokens += countTokens(content);
|
|
@@ -7541,10 +7684,10 @@ function resolveRunners(overrides) {
|
|
|
7541
7684
|
async function ingest(root, opts, runners) {
|
|
7542
7685
|
const resolved = resolveRunners(runners);
|
|
7543
7686
|
const source = await materializeSource(opts.source);
|
|
7544
|
-
const indexMdBytes = await fs11.readFile(
|
|
7687
|
+
const indexMdBytes = await fs11.readFile(path38.join(root, MEMORY_INDEX_RELPATH));
|
|
7545
7688
|
const configOptions = {
|
|
7546
7689
|
fs: fs11,
|
|
7547
|
-
filePath:
|
|
7690
|
+
filePath: path38.join(inferRepoRoot(root), "poe-code.json")
|
|
7548
7691
|
};
|
|
7549
7692
|
const agentId = await resolveAgent(configOptions, opts.agent ?? null) ?? opts.agent ?? "claude-code";
|
|
7550
7693
|
const key = resolved.computeIngestKey({
|
|
@@ -7634,7 +7777,7 @@ async function materializeSource(source) {
|
|
|
7634
7777
|
throw new Error("URL ingest not implemented yet.");
|
|
7635
7778
|
}
|
|
7636
7779
|
function inferRepoRoot(root) {
|
|
7637
|
-
return
|
|
7780
|
+
return path38.resolve(root, "..", "..");
|
|
7638
7781
|
}
|
|
7639
7782
|
async function runWithTimeout(promise, timeoutMs) {
|
|
7640
7783
|
return await new Promise((resolve2, reject) => {
|
|
@@ -7986,8 +8129,8 @@ var File = class _File {
|
|
|
7986
8129
|
const isText = isTextMimeType(mimeType);
|
|
7987
8130
|
return new _File(data, mimeType, isText);
|
|
7988
8131
|
}
|
|
7989
|
-
static fromText(
|
|
7990
|
-
return new _File(
|
|
8132
|
+
static fromText(text5, mimeType = "text/plain") {
|
|
8133
|
+
return new _File(text5, mimeType, true);
|
|
7991
8134
|
}
|
|
7992
8135
|
static fromBase64(base64, mimeType) {
|
|
7993
8136
|
const data = Buffer.from(base64, "base64");
|
|
@@ -7997,18 +8140,18 @@ var File = class _File {
|
|
|
7997
8140
|
toContentBlock() {
|
|
7998
8141
|
const uri = this.name ? `file:///${this.name}` : "file:///data";
|
|
7999
8142
|
if (this.isText) {
|
|
8000
|
-
let
|
|
8143
|
+
let text5;
|
|
8001
8144
|
if (typeof this.data === "string") {
|
|
8002
|
-
|
|
8145
|
+
text5 = this.data;
|
|
8003
8146
|
} else {
|
|
8004
|
-
|
|
8147
|
+
text5 = new TextDecoder("utf-8").decode(this.data);
|
|
8005
8148
|
}
|
|
8006
8149
|
return {
|
|
8007
8150
|
type: "resource",
|
|
8008
8151
|
resource: {
|
|
8009
8152
|
uri,
|
|
8010
8153
|
mimeType: this.mimeType,
|
|
8011
|
-
text:
|
|
8154
|
+
text: text5
|
|
8012
8155
|
}
|
|
8013
8156
|
};
|
|
8014
8157
|
} else {
|
|
@@ -8393,7 +8536,7 @@ function printMcpConfig() {
|
|
|
8393
8536
|
|
|
8394
8537
|
// packages/agent-skill-config/src/configs.ts
|
|
8395
8538
|
import os5 from "node:os";
|
|
8396
|
-
import
|
|
8539
|
+
import path39 from "node:path";
|
|
8397
8540
|
var agentSkillConfigs = {
|
|
8398
8541
|
"claude-code": {
|
|
8399
8542
|
globalSkillDir: "~/.claude/skills",
|
|
@@ -8427,7 +8570,7 @@ function resolveAgentSupport(input, registry = agentSkillConfigs) {
|
|
|
8427
8570
|
|
|
8428
8571
|
// packages/agent-skill-config/src/templates.ts
|
|
8429
8572
|
import { readFile as readFile15, stat as stat6 } from "node:fs/promises";
|
|
8430
|
-
import
|
|
8573
|
+
import path40 from "node:path";
|
|
8431
8574
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
8432
8575
|
|
|
8433
8576
|
// packages/agent-skill-config/src/apply.ts
|
|
@@ -8560,7 +8703,7 @@ function resolveConfigPath2(config, platform) {
|
|
|
8560
8703
|
}
|
|
8561
8704
|
|
|
8562
8705
|
// packages/agent-mcp-config/src/apply.ts
|
|
8563
|
-
import
|
|
8706
|
+
import path41 from "node:path";
|
|
8564
8707
|
import { parse as parseYaml3, stringify as stringifyYaml2 } from "yaml";
|
|
8565
8708
|
|
|
8566
8709
|
// packages/agent-mcp-config/src/shapes.ts
|
|
@@ -8652,7 +8795,7 @@ function getShapeTransformer(shape) {
|
|
|
8652
8795
|
|
|
8653
8796
|
// packages/agent-mcp-config/src/apply.ts
|
|
8654
8797
|
function getConfigDirectory(configPath) {
|
|
8655
|
-
return
|
|
8798
|
+
return path41.dirname(configPath);
|
|
8656
8799
|
}
|
|
8657
8800
|
var UnsupportedAgentError2 = class extends Error {
|
|
8658
8801
|
constructor(agentId) {
|
|
@@ -8678,9 +8821,9 @@ function expandHomePath(configPath, homeDir) {
|
|
|
8678
8821
|
return homeDir;
|
|
8679
8822
|
}
|
|
8680
8823
|
if (configPath.startsWith("~/")) {
|
|
8681
|
-
return
|
|
8824
|
+
return path41.join(homeDir, configPath.slice(2));
|
|
8682
8825
|
}
|
|
8683
|
-
return
|
|
8826
|
+
return path41.join(homeDir, configPath.slice(1));
|
|
8684
8827
|
}
|
|
8685
8828
|
function parseYamlDocument(content) {
|
|
8686
8829
|
if (content.trim() === "") {
|
|
@@ -8713,7 +8856,7 @@ async function writeYamlConfig(configPath, document, options) {
|
|
|
8713
8856
|
return;
|
|
8714
8857
|
}
|
|
8715
8858
|
const absolutePath = expandHomePath(configPath, options.homeDir);
|
|
8716
|
-
const configDir =
|
|
8859
|
+
const configDir = path41.dirname(absolutePath);
|
|
8717
8860
|
await options.fs.mkdir(configDir, { recursive: true });
|
|
8718
8861
|
await options.fs.writeFile(absolutePath, serializeYamlDocument(document), {
|
|
8719
8862
|
encoding: "utf8"
|
|
@@ -8891,7 +9034,7 @@ async function installMemory(options) {
|
|
|
8891
9034
|
|
|
8892
9035
|
// packages/memory/src/query.ts
|
|
8893
9036
|
import * as fs12 from "node:fs/promises";
|
|
8894
|
-
import
|
|
9037
|
+
import path42 from "node:path";
|
|
8895
9038
|
async function queryMemory(root, options) {
|
|
8896
9039
|
const pages = await listPages(root);
|
|
8897
9040
|
if (pages.length === 0) {
|
|
@@ -8905,7 +9048,7 @@ async function queryMemory(root, options) {
|
|
|
8905
9048
|
}
|
|
8906
9049
|
const configOptions = {
|
|
8907
9050
|
fs: fs12,
|
|
8908
|
-
filePath:
|
|
9051
|
+
filePath: path42.join(inferRepoRoot2(root), "poe-code.json")
|
|
8909
9052
|
};
|
|
8910
9053
|
const agentId = await resolveAgent(configOptions, options.agent ?? null) ?? options.agent ?? "claude-code";
|
|
8911
9054
|
const context = await selectQueryContext(root, options.question, options.budget);
|
|
@@ -8920,7 +9063,7 @@ async function queryMemory(root, options) {
|
|
|
8920
9063
|
}
|
|
8921
9064
|
async function selectQueryContext(root, question, budget) {
|
|
8922
9065
|
const [indexText, pages] = await Promise.all([
|
|
8923
|
-
fs12.readFile(
|
|
9066
|
+
fs12.readFile(path42.join(root, MEMORY_INDEX_RELPATH), "utf8"),
|
|
8924
9067
|
listPages(root)
|
|
8925
9068
|
]);
|
|
8926
9069
|
const indexTokens = countTokens(indexText);
|
|
@@ -8950,8 +9093,8 @@ async function selectQueryContext(root, question, budget) {
|
|
|
8950
9093
|
function rankPagesForQuery(pages, question) {
|
|
8951
9094
|
const terms = tokenize(question);
|
|
8952
9095
|
const documents = pages.map((page) => {
|
|
8953
|
-
const
|
|
8954
|
-
const tokens = tokenize(
|
|
9096
|
+
const text5 = [page.relPath, page.frontmatter.name ?? "", page.frontmatter.description ?? "", page.body].join("\n").toLowerCase();
|
|
9097
|
+
const tokens = tokenize(text5);
|
|
8955
9098
|
const counts = /* @__PURE__ */ new Map();
|
|
8956
9099
|
for (const token of tokens) {
|
|
8957
9100
|
counts.set(token, (counts.get(token) ?? 0) + 1);
|
|
@@ -8995,16 +9138,16 @@ function buildQueryPrompt(question, indexText, pages) {
|
|
|
8995
9138
|
function renderPageContext(page) {
|
|
8996
9139
|
return [`FILE: ${page.relPath}`, page.body].join("\n");
|
|
8997
9140
|
}
|
|
8998
|
-
function tokenize(
|
|
8999
|
-
return
|
|
9141
|
+
function tokenize(text5) {
|
|
9142
|
+
return text5.toLowerCase().split(/[^a-z0-9]+/).filter((token) => token.length > 0);
|
|
9000
9143
|
}
|
|
9001
9144
|
function inferRepoRoot2(root) {
|
|
9002
|
-
return
|
|
9145
|
+
return path42.resolve(root, "..", "..");
|
|
9003
9146
|
}
|
|
9004
9147
|
|
|
9005
9148
|
// packages/memory/src/explain.ts
|
|
9006
9149
|
import * as fs13 from "node:fs/promises";
|
|
9007
|
-
import
|
|
9150
|
+
import path43 from "node:path";
|
|
9008
9151
|
async function explainPage(root, options) {
|
|
9009
9152
|
const targetPage = await readPageIfPresent(root, options.relPath);
|
|
9010
9153
|
if (targetPage === void 0) {
|
|
@@ -9027,7 +9170,7 @@ async function explainPage(root, options) {
|
|
|
9027
9170
|
}
|
|
9028
9171
|
const configOptions = {
|
|
9029
9172
|
fs: fs13,
|
|
9030
|
-
filePath:
|
|
9173
|
+
filePath: path43.join(inferRepoRoot3(root), "poe-code.json")
|
|
9031
9174
|
};
|
|
9032
9175
|
const agentId = await resolveAgent(configOptions, options.agent ?? null) ?? options.agent ?? "claude-code";
|
|
9033
9176
|
const response = await spawn3(agentId, { prompt });
|
|
@@ -9076,7 +9219,7 @@ async function readPageIfPresent(root, relPath) {
|
|
|
9076
9219
|
}
|
|
9077
9220
|
}
|
|
9078
9221
|
function inferRepoRoot3(root) {
|
|
9079
|
-
return
|
|
9222
|
+
return path43.resolve(root, "..", "..");
|
|
9080
9223
|
}
|
|
9081
9224
|
|
|
9082
9225
|
// packages/memory/src/explain.cli.ts
|
|
@@ -9089,9 +9232,9 @@ async function runMemoryExplain(input) {
|
|
|
9089
9232
|
}
|
|
9090
9233
|
|
|
9091
9234
|
// packages/memory/src/handle.ts
|
|
9092
|
-
import
|
|
9235
|
+
import path44 from "node:path";
|
|
9093
9236
|
function openMemory(opts) {
|
|
9094
|
-
if (!
|
|
9237
|
+
if (!path44.isAbsolute(opts.root)) {
|
|
9095
9238
|
throw new Error(`openMemory: root must be absolute, got ${opts.root}`);
|
|
9096
9239
|
}
|
|
9097
9240
|
const root = opts.root;
|