@rallycry/conveyor-agent 10.13.50 → 10.13.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{boot-I353EAK6.js → boot-6X5ZZG3B.js} +3 -3
- package/dist/{chunk-3Z4YQNJV.js → chunk-DSP4KR4B.js} +2 -2
- package/dist/{chunk-XR6H326I.js → chunk-UAGIXPYD.js} +109 -1
- package/dist/chunk-UAGIXPYD.js.map +1 -0
- package/dist/{chunk-36VMMHYD.js → chunk-ZTLGCN5G.js} +1070 -209
- package/dist/chunk-ZTLGCN5G.js.map +1 -0
- package/dist/cli.js +73 -241
- package/dist/cli.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{server-NIOBJ46G.js → server-EQUCOLNY.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-36VMMHYD.js.map +0 -1
- package/dist/chunk-XR6H326I.js.map +0 -1
- /package/dist/{boot-I353EAK6.js.map → boot-6X5ZZG3B.js.map} +0 -0
- /package/dist/{chunk-3Z4YQNJV.js.map → chunk-DSP4KR4B.js.map} +0 -0
- /package/dist/{server-NIOBJ46G.js.map → server-EQUCOLNY.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
} from "./chunk-6GS5ADIY.js";
|
|
6
6
|
import {
|
|
7
7
|
AgentConnection,
|
|
8
|
-
ClaudeTuiAdapter,
|
|
9
8
|
CodespacePortVisibility,
|
|
10
9
|
DEFAULT_LIFECYCLE_CONFIG,
|
|
11
10
|
DEFAULT_SONNET_MODEL,
|
|
@@ -13,28 +12,26 @@ import {
|
|
|
13
12
|
PortDiscovery,
|
|
14
13
|
PtyHarness,
|
|
15
14
|
SessionRunner,
|
|
16
|
-
TUI_KINDS,
|
|
17
|
-
TuiUnavailableError,
|
|
18
15
|
applyBootstrapToEnv,
|
|
19
16
|
awaitGitReady,
|
|
20
17
|
buildProjectTools,
|
|
21
18
|
buildSessionPreviewPorts,
|
|
22
19
|
buildSynthesizedCredentials,
|
|
23
20
|
claudeJsonPath,
|
|
24
|
-
cleanTerminalOutput,
|
|
25
21
|
createServiceLogger,
|
|
26
22
|
fetchBootstrap,
|
|
27
|
-
findOnPath,
|
|
28
23
|
isPermissionDeniedError,
|
|
29
24
|
loadConveyorConfig,
|
|
30
25
|
loadForwardPorts,
|
|
31
26
|
parseUsageGauges,
|
|
32
27
|
resolvePlaywrightMcpServer,
|
|
33
28
|
resolveSessionStart,
|
|
29
|
+
resolveTuiAdapter,
|
|
30
|
+
resolveTuiKindFromEnv,
|
|
34
31
|
runUsageProbe,
|
|
35
32
|
sampleKeyUsage,
|
|
36
33
|
workspacePathExists
|
|
37
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-ZTLGCN5G.js";
|
|
38
35
|
import {
|
|
39
36
|
reportBootMilestone
|
|
40
37
|
} from "./chunk-KCB7CSWJ.js";
|
|
@@ -46,19 +43,18 @@ import {
|
|
|
46
43
|
workbenchEnabled
|
|
47
44
|
} from "./chunk-4VUQ2NPF.js";
|
|
48
45
|
import {
|
|
49
|
-
buildPromptBytes,
|
|
50
46
|
inheritedEnv,
|
|
51
47
|
resolvePtySpawn,
|
|
52
48
|
runSetupCommand,
|
|
53
49
|
runStartCommand,
|
|
54
50
|
sessionTempBase,
|
|
55
51
|
terminateProcessGroup
|
|
56
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-UAGIXPYD.js";
|
|
57
53
|
import "./chunk-JIGG755T.js";
|
|
58
54
|
|
|
59
55
|
// src/cli.ts
|
|
60
56
|
import { readFileSync } from "fs";
|
|
61
|
-
import { join as
|
|
57
|
+
import { join as join3, dirname as dirname2 } from "path";
|
|
62
58
|
import { fileURLToPath } from "url";
|
|
63
59
|
|
|
64
60
|
// src/setup/sidecars.ts
|
|
@@ -567,14 +563,14 @@ var WorkspaceCommandSupervisor = class {
|
|
|
567
563
|
|
|
568
564
|
// src/utils/session-identity.ts
|
|
569
565
|
async function checkSessionTaskIdentity(params) {
|
|
570
|
-
const { sessionId, taskId, fetchSessionTaskId, logger:
|
|
566
|
+
const { sessionId, taskId, fetchSessionTaskId, logger: logger6 } = params;
|
|
571
567
|
if (!sessionId || sessionId === taskId) return "skipped";
|
|
572
568
|
let sessionTaskId;
|
|
573
569
|
try {
|
|
574
570
|
sessionTaskId = await fetchSessionTaskId(sessionId);
|
|
575
571
|
} catch (err) {
|
|
576
572
|
const message = err instanceof Error ? err.message : String(err);
|
|
577
|
-
|
|
573
|
+
logger6.warn("Could not verify session/task identity \u2014 continuing (defense-in-depth only)", {
|
|
578
574
|
sessionId,
|
|
579
575
|
taskId,
|
|
580
576
|
error: message
|
|
@@ -582,7 +578,7 @@ async function checkSessionTaskIdentity(params) {
|
|
|
582
578
|
return "error";
|
|
583
579
|
}
|
|
584
580
|
if (sessionTaskId !== taskId) {
|
|
585
|
-
|
|
581
|
+
logger6.warn(
|
|
586
582
|
"!!! CONVEYOR_SESSION_ID is bound to a different task than CONVEYOR_TASK_ID \u2014 server-side guards should still block mutations, but this indicates a misconfiguration or replayed token.",
|
|
587
583
|
{ sessionId, envTaskId: taskId, sessionTaskId }
|
|
588
584
|
);
|
|
@@ -834,167 +830,6 @@ async function probeKeysUsage(keys, deps = {}) {
|
|
|
834
830
|
return results;
|
|
835
831
|
}
|
|
836
832
|
|
|
837
|
-
// src/harness/pty/adapters/opencode-auth.ts
|
|
838
|
-
import { promises as fs } from "fs";
|
|
839
|
-
import { dirname as dirname2, join as join3 } from "path";
|
|
840
|
-
import { homedir } from "os";
|
|
841
|
-
var logger2 = createServiceLogger("opencode-auth");
|
|
842
|
-
var OPENCODE_CODEX_PLUGIN = "opencode-openai-codex-auth@4.4.0";
|
|
843
|
-
var PLUGIN_PACKAGE = "opencode-openai-codex-auth";
|
|
844
|
-
function opencodeAuthPath(env) {
|
|
845
|
-
const dataHome = env.XDG_DATA_HOME ?? join3(env.HOME ?? homedir(), ".local", "share");
|
|
846
|
-
return join3(dataHome, "opencode", "auth.json");
|
|
847
|
-
}
|
|
848
|
-
function opencodeConfigPath(env) {
|
|
849
|
-
const configHome = env.XDG_CONFIG_HOME ?? join3(env.HOME ?? homedir(), ".config");
|
|
850
|
-
return join3(configHome, "opencode", "opencode.json");
|
|
851
|
-
}
|
|
852
|
-
function parseOauthSeed(b64) {
|
|
853
|
-
if (!b64) return null;
|
|
854
|
-
try {
|
|
855
|
-
const parsed = JSON.parse(Buffer.from(b64, "base64").toString("utf8"));
|
|
856
|
-
if (typeof parsed.access === "string" && typeof parsed.refresh === "string" && typeof parsed.expires === "number") {
|
|
857
|
-
return { access: parsed.access, refresh: parsed.refresh, expires: parsed.expires };
|
|
858
|
-
}
|
|
859
|
-
return null;
|
|
860
|
-
} catch {
|
|
861
|
-
return null;
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
function shouldSeed(existingEntry, seed) {
|
|
865
|
-
if (!existingEntry || typeof existingEntry !== "object") return true;
|
|
866
|
-
const entry = existingEntry;
|
|
867
|
-
if (entry.type !== "oauth") return true;
|
|
868
|
-
if (typeof entry.access !== "string" || typeof entry.refresh !== "string") return true;
|
|
869
|
-
if (typeof entry.expires !== "number") return true;
|
|
870
|
-
return entry.expires < seed.expires;
|
|
871
|
-
}
|
|
872
|
-
async function readJsonFile(path) {
|
|
873
|
-
try {
|
|
874
|
-
return JSON.parse(await fs.readFile(path, "utf8"));
|
|
875
|
-
} catch {
|
|
876
|
-
return {};
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
async function writeJsonFile(path, value) {
|
|
880
|
-
await fs.mkdir(dirname2(path), { recursive: true });
|
|
881
|
-
await fs.writeFile(path, `${JSON.stringify(value, null, 2)}
|
|
882
|
-
`, { mode: 384 });
|
|
883
|
-
}
|
|
884
|
-
async function ensureAuthEntry(env, seed) {
|
|
885
|
-
const path = opencodeAuthPath(env);
|
|
886
|
-
const store = await readJsonFile(path);
|
|
887
|
-
if (!shouldSeed(store.openai, seed)) {
|
|
888
|
-
logger2.info("opencode oauth store is fresher than the seed; leaving it alone");
|
|
889
|
-
return;
|
|
890
|
-
}
|
|
891
|
-
store.openai = {
|
|
892
|
-
type: "oauth",
|
|
893
|
-
access: seed.access,
|
|
894
|
-
refresh: seed.refresh,
|
|
895
|
-
expires: seed.expires
|
|
896
|
-
};
|
|
897
|
-
await writeJsonFile(path, store);
|
|
898
|
-
logger2.info("seeded opencode oauth store entry");
|
|
899
|
-
}
|
|
900
|
-
async function ensurePluginConfig(env) {
|
|
901
|
-
const path = opencodeConfigPath(env);
|
|
902
|
-
const config = await readJsonFile(path);
|
|
903
|
-
const plugins = Array.isArray(config.plugin) ? config.plugin : [];
|
|
904
|
-
const isOurs = (p) => typeof p === "string" && (p === PLUGIN_PACKAGE || p.startsWith(`${PLUGIN_PACKAGE}@`));
|
|
905
|
-
const hasExactPin = plugins.includes(OPENCODE_CODEX_PLUGIN);
|
|
906
|
-
const hasStalePin = plugins.some((p) => isOurs(p) && p !== OPENCODE_CODEX_PLUGIN);
|
|
907
|
-
if (hasExactPin && !hasStalePin) return;
|
|
908
|
-
const kept = plugins.filter((p) => !isOurs(p));
|
|
909
|
-
config.plugin = [...kept, OPENCODE_CODEX_PLUGIN];
|
|
910
|
-
await writeJsonFile(path, config);
|
|
911
|
-
logger2.info("ensured opencode codex-auth plugin in config");
|
|
912
|
-
}
|
|
913
|
-
async function seedOpenCodeOauth(env) {
|
|
914
|
-
const seed = parseOauthSeed(env.CONVEYOR_OPENCODE_OAUTH);
|
|
915
|
-
if (!seed) return;
|
|
916
|
-
try {
|
|
917
|
-
await ensureAuthEntry(env, seed);
|
|
918
|
-
await ensurePluginConfig(env);
|
|
919
|
-
} catch (err) {
|
|
920
|
-
logger2.warn(
|
|
921
|
-
`failed to seed opencode oauth store: ${err instanceof Error ? err.message : String(err)}`
|
|
922
|
-
);
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
|
|
926
|
-
// src/harness/pty/adapters/opencode.ts
|
|
927
|
-
var PROVIDER_KEY_ENV = {
|
|
928
|
-
openai: "OPENAI_API_KEY",
|
|
929
|
-
anthropic: "ANTHROPIC_API_KEY"
|
|
930
|
-
};
|
|
931
|
-
var OpenCodeTuiAdapter = class {
|
|
932
|
-
constructor(env = process.env) {
|
|
933
|
-
this.env = env;
|
|
934
|
-
}
|
|
935
|
-
env;
|
|
936
|
-
id = "opencode";
|
|
937
|
-
capabilities = {
|
|
938
|
-
resume: false,
|
|
939
|
-
structuredEvents: false,
|
|
940
|
-
prefill: false,
|
|
941
|
-
passiveTurns: false
|
|
942
|
-
};
|
|
943
|
-
resolveBinary(env = this.env) {
|
|
944
|
-
const override = env.CONVEYOR_OPENCODE_BIN;
|
|
945
|
-
const found = override ? findOnPath(override, env) : findOnPath("opencode", env);
|
|
946
|
-
if (!found) {
|
|
947
|
-
throw new TuiUnavailableError(
|
|
948
|
-
"opencode",
|
|
949
|
-
"The opencode CLI is not available in this environment. It must be baked into the pod image (see Dockerfile.base) \u2014 re-run Build Image for this project, or set CONVEYOR_OPENCODE_BIN to its absolute path."
|
|
950
|
-
);
|
|
951
|
-
}
|
|
952
|
-
return found;
|
|
953
|
-
}
|
|
954
|
-
buildSpawn(input) {
|
|
955
|
-
const env = { ...inheritedEnv() };
|
|
956
|
-
delete env.CONVEYOR_AGENT_KEY;
|
|
957
|
-
delete env.CONVEYOR_OPENCODE_OAUTH;
|
|
958
|
-
const oauthActive = Boolean(this.env.CONVEYOR_OPENCODE_OAUTH);
|
|
959
|
-
const key = this.env.CONVEYOR_AGENT_KEY;
|
|
960
|
-
const provider = this.env.CONVEYOR_AGENT_PROVIDER ?? "openai";
|
|
961
|
-
const keyEnvVar = PROVIDER_KEY_ENV[provider];
|
|
962
|
-
if (key && keyEnvVar && !oauthActive) env[keyEnvVar] = key;
|
|
963
|
-
const model = this.env.CONVEYOR_AGENT_MODEL ?? input.options.model;
|
|
964
|
-
const args = [];
|
|
965
|
-
if (model) args.push("--model", model.includes("/") ? model : `${provider}/${model}`);
|
|
966
|
-
return { file: this.resolveBinary(), args, env };
|
|
967
|
-
}
|
|
968
|
-
async prepareEnvironment() {
|
|
969
|
-
await seedOpenCodeOauth(this.env);
|
|
970
|
-
}
|
|
971
|
-
spawnFingerprint(input) {
|
|
972
|
-
return JSON.stringify(["opencode", input.model, input.cwd]);
|
|
973
|
-
}
|
|
974
|
-
encodePromptBytes(text) {
|
|
975
|
-
return buildPromptBytes(text);
|
|
976
|
-
}
|
|
977
|
-
buildExitErrors(exitCode, rawOutput) {
|
|
978
|
-
const errors = [`opencode exited (code ${exitCode}) without a result`];
|
|
979
|
-
const tail = cleanTerminalOutput(rawOutput);
|
|
980
|
-
if (tail) errors.push(`Last terminal output before exit:
|
|
981
|
-
${tail}`);
|
|
982
|
-
return errors;
|
|
983
|
-
}
|
|
984
|
-
};
|
|
985
|
-
|
|
986
|
-
// src/harness/pty/adapters/index.ts
|
|
987
|
-
function resolveTuiAdapter(kind = "claude-code") {
|
|
988
|
-
switch (kind) {
|
|
989
|
-
case "claude-code":
|
|
990
|
-
return new ClaudeTuiAdapter();
|
|
991
|
-
case "opencode":
|
|
992
|
-
return new OpenCodeTuiAdapter();
|
|
993
|
-
default:
|
|
994
|
-
throw new Error(`Unknown TUI kind: ${kind}`);
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
|
|
998
833
|
// src/runner/adhoc-session-runner.ts
|
|
999
834
|
var ADHOC_SYSTEM_NOTE = "You are running in an ad-hoc Conveyor scratch pod \u2014 an interactive terminal on the project's repository checked out at its default branch. There is no task or plan; help the human with whatever they ask directly.";
|
|
1000
835
|
var HEADLESS_SYSTEM_NOTE = "You are running a HEADLESS Conveyor session on the project's repository \u2014 your instructions were auto-submitted as the first message. Work them to completion autonomously and never wait for user input; a human may attach to this terminal to watch or interject, but none is required.";
|
|
@@ -1008,11 +843,7 @@ function resolveInitialPrompt(env = process.env) {
|
|
|
1008
843
|
return null;
|
|
1009
844
|
}
|
|
1010
845
|
}
|
|
1011
|
-
|
|
1012
|
-
const raw = env.CONVEYOR_TUI ?? "claude-code";
|
|
1013
|
-
if (TUI_KINDS.includes(raw)) return raw;
|
|
1014
|
-
throw new Error(`Unknown TUI "${raw}" in CONVEYOR_TUI (expected: ${TUI_KINDS.join(", ")})`);
|
|
1015
|
-
}
|
|
846
|
+
var resolveAdhocTui = resolveTuiKindFromEnv;
|
|
1016
847
|
function buildAdhocPtyBridge(connection, onInputActivity) {
|
|
1017
848
|
return {
|
|
1018
849
|
sendOutput: (data, dims) => connection.sendPtyOutput(data, dims),
|
|
@@ -1277,7 +1108,7 @@ var AdhocSessionRunner = class {
|
|
|
1277
1108
|
import { spawn as nodeSpawn, execFile } from "child_process";
|
|
1278
1109
|
import { promisify } from "util";
|
|
1279
1110
|
var execFileAsync = promisify(execFile);
|
|
1280
|
-
var
|
|
1111
|
+
var logger2 = createServiceLogger("ReviewChild");
|
|
1281
1112
|
var SPAWN_FAILURE_GRACE_MS = 15e3;
|
|
1282
1113
|
var KILL_WAIT_MS = 5e3;
|
|
1283
1114
|
function buildReviewChildEnv(baseEnv, data) {
|
|
@@ -1293,6 +1124,7 @@ function buildReviewChildEnv(baseEnv, data) {
|
|
|
1293
1124
|
delete env.CONVEYOR_GIT_READY_MARKER;
|
|
1294
1125
|
delete env.CONVEYOR_AGENT_MODE;
|
|
1295
1126
|
delete env.CONVEYOR_IS_AUTO;
|
|
1127
|
+
delete env.CONVEYOR_TUI;
|
|
1296
1128
|
return env;
|
|
1297
1129
|
}
|
|
1298
1130
|
var ReviewChildSupervisor = class {
|
|
@@ -1308,7 +1140,7 @@ var ReviewChildSupervisor = class {
|
|
|
1308
1140
|
childSessionId = null;
|
|
1309
1141
|
/** Spawn (or replace) the review child for a `session:spawnReview` push. */
|
|
1310
1142
|
async spawn(data) {
|
|
1311
|
-
|
|
1143
|
+
logger2.info("Spawning same-pod review child", {
|
|
1312
1144
|
reviewSessionId: data.sessionId,
|
|
1313
1145
|
branch: data.branch ?? void 0,
|
|
1314
1146
|
prNumber: data.prNumber ?? void 0
|
|
@@ -1351,7 +1183,7 @@ var ReviewChildSupervisor = class {
|
|
|
1351
1183
|
process.stderr.write(`[review-child] ${chunk.toString()}`);
|
|
1352
1184
|
});
|
|
1353
1185
|
child.on("error", (err) => {
|
|
1354
|
-
|
|
1186
|
+
logger2.error("Review child spawn error", { error: err.message });
|
|
1355
1187
|
if (this.child === child) {
|
|
1356
1188
|
this.child = null;
|
|
1357
1189
|
this.childSessionId = null;
|
|
@@ -1364,7 +1196,7 @@ var ReviewChildSupervisor = class {
|
|
|
1364
1196
|
this.child = null;
|
|
1365
1197
|
this.childSessionId = null;
|
|
1366
1198
|
}
|
|
1367
|
-
|
|
1199
|
+
logger2.info("Review child exited", { code, signal, reviewSessionId: data.sessionId });
|
|
1368
1200
|
const withinGrace = Date.now() - spawnedAt < SPAWN_FAILURE_GRACE_MS;
|
|
1369
1201
|
if (wasCurrent && withinGrace && code !== null && code !== 0) {
|
|
1370
1202
|
reportOnce(`review child exited with code ${code} within startup grace`);
|
|
@@ -1382,7 +1214,7 @@ var ReviewChildSupervisor = class {
|
|
|
1382
1214
|
this.childSessionId = null;
|
|
1383
1215
|
return;
|
|
1384
1216
|
}
|
|
1385
|
-
|
|
1217
|
+
logger2.info("Stopping review child", { reason, reviewSessionId: this.childSessionId });
|
|
1386
1218
|
this.child = null;
|
|
1387
1219
|
this.childSessionId = null;
|
|
1388
1220
|
await new Promise((resolve) => {
|
|
@@ -1424,7 +1256,7 @@ var ReviewChildSupervisor = class {
|
|
|
1424
1256
|
timeout: 3e4
|
|
1425
1257
|
});
|
|
1426
1258
|
} catch (err) {
|
|
1427
|
-
|
|
1259
|
+
logger2.warn("Review checkout freshen skipped", {
|
|
1428
1260
|
branch,
|
|
1429
1261
|
error: err instanceof Error ? err.message : String(err)
|
|
1430
1262
|
});
|
|
@@ -1434,7 +1266,7 @@ var ReviewChildSupervisor = class {
|
|
|
1434
1266
|
|
|
1435
1267
|
// src/runner/session-child.ts
|
|
1436
1268
|
import { spawn as nodeSpawn2 } from "child_process";
|
|
1437
|
-
var
|
|
1269
|
+
var logger3 = createServiceLogger("SessionChild");
|
|
1438
1270
|
function buildSpawnedChildEnv(baseEnv, data) {
|
|
1439
1271
|
const env = { ...baseEnv };
|
|
1440
1272
|
env.CONVEYOR_TASK_TOKEN = data.sessionJwt;
|
|
@@ -1464,7 +1296,7 @@ var SessionChildSupervisor = class {
|
|
|
1464
1296
|
}
|
|
1465
1297
|
/** Spawn a TUI/shell child for a `session:spawnTui` push. Additive per session. */
|
|
1466
1298
|
async spawn(data) {
|
|
1467
|
-
|
|
1299
|
+
logger3.info("Spawning same-pod session child", {
|
|
1468
1300
|
spawnedSessionId: data.sessionId,
|
|
1469
1301
|
mode: data.mode
|
|
1470
1302
|
});
|
|
@@ -1505,7 +1337,7 @@ var SessionChildSupervisor = class {
|
|
|
1505
1337
|
process.stderr.write(`${prefix} ${chunk.toString()}`);
|
|
1506
1338
|
});
|
|
1507
1339
|
child.on("error", (err) => {
|
|
1508
|
-
|
|
1340
|
+
logger3.error("Session child spawn error", { error: err.message });
|
|
1509
1341
|
if (this.children.get(data.sessionId) === child) {
|
|
1510
1342
|
this.children.delete(data.sessionId);
|
|
1511
1343
|
}
|
|
@@ -1514,7 +1346,7 @@ var SessionChildSupervisor = class {
|
|
|
1514
1346
|
child.on("exit", (code, signal) => {
|
|
1515
1347
|
const wasCurrent = this.children.get(data.sessionId) === child;
|
|
1516
1348
|
if (wasCurrent) this.children.delete(data.sessionId);
|
|
1517
|
-
|
|
1349
|
+
logger3.info("Session child exited", {
|
|
1518
1350
|
code,
|
|
1519
1351
|
signal,
|
|
1520
1352
|
spawnedSessionId: data.sessionId,
|
|
@@ -1535,7 +1367,7 @@ var SessionChildSupervisor = class {
|
|
|
1535
1367
|
const child = this.children.get(sessionId);
|
|
1536
1368
|
this.children.delete(sessionId);
|
|
1537
1369
|
if (!child || child.exitCode !== null || child.killed) return;
|
|
1538
|
-
|
|
1370
|
+
logger3.info("Stopping session child", { reason, spawnedSessionId: sessionId });
|
|
1539
1371
|
await new Promise((resolve) => {
|
|
1540
1372
|
const timer = setTimeout(() => {
|
|
1541
1373
|
try {
|
|
@@ -1683,7 +1515,7 @@ var ShellSessionRunner = class {
|
|
|
1683
1515
|
};
|
|
1684
1516
|
|
|
1685
1517
|
// src/runner/spawned-child-boot.ts
|
|
1686
|
-
var
|
|
1518
|
+
var logger4 = createServiceLogger("SpawnedChildBoot");
|
|
1687
1519
|
function createSpawnedChildRunner(inputs) {
|
|
1688
1520
|
if (inputs.mode === "shell") {
|
|
1689
1521
|
return new ShellSessionRunner({
|
|
@@ -1713,7 +1545,7 @@ function createSpawnedChildRunner(inputs) {
|
|
|
1713
1545
|
},
|
|
1714
1546
|
{
|
|
1715
1547
|
onEvent: (event) => {
|
|
1716
|
-
|
|
1548
|
+
logger4.info("Spawned TUI event", { eventType: event.type });
|
|
1717
1549
|
}
|
|
1718
1550
|
}
|
|
1719
1551
|
);
|
|
@@ -1726,7 +1558,7 @@ function hostsSpawnedChildren(mode) {
|
|
|
1726
1558
|
|
|
1727
1559
|
// src/cli.ts
|
|
1728
1560
|
if (process.argv[2] === "boot") {
|
|
1729
|
-
const { runBoot } = await import("./boot-
|
|
1561
|
+
const { runBoot } = await import("./boot-6X5ZZG3B.js");
|
|
1730
1562
|
process.exit(await runBoot(process.argv.slice(3)));
|
|
1731
1563
|
}
|
|
1732
1564
|
if (isLegacyEntrypointLaunch(process.env)) {
|
|
@@ -1735,13 +1567,13 @@ if (isLegacyEntrypointLaunch(process.env)) {
|
|
|
1735
1567
|
process.exit(1);
|
|
1736
1568
|
}
|
|
1737
1569
|
if (process.argv.includes("--version")) {
|
|
1738
|
-
const __dirname =
|
|
1739
|
-
const pkgPath =
|
|
1570
|
+
const __dirname = dirname2(fileURLToPath(import.meta.url));
|
|
1571
|
+
const pkgPath = join3(__dirname, "..", "package.json");
|
|
1740
1572
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
1741
1573
|
process.stdout.write(pkg.version + "\n");
|
|
1742
1574
|
process.exit(0);
|
|
1743
1575
|
}
|
|
1744
|
-
var
|
|
1576
|
+
var logger5 = createServiceLogger("CLI");
|
|
1745
1577
|
var exitContext = {};
|
|
1746
1578
|
var exitLogged = false;
|
|
1747
1579
|
var shuttingDown = false;
|
|
@@ -1756,12 +1588,12 @@ function logAgentExit(reason, opts) {
|
|
|
1756
1588
|
uptimeSec: process.uptime(),
|
|
1757
1589
|
identity: exitContext
|
|
1758
1590
|
});
|
|
1759
|
-
|
|
1591
|
+
logger5[exitLogLevel(reason)]("agent_exit", payload);
|
|
1760
1592
|
}
|
|
1761
1593
|
async function bootstrapFromCodespace(apiUrl, instanceName) {
|
|
1762
1594
|
const bootstrapToken = process.env.CONVEYOR_BOOTSTRAP_TOKEN;
|
|
1763
1595
|
const apiUrlFromEnv = Boolean(process.env.CONVEYOR_API_URL);
|
|
1764
|
-
|
|
1596
|
+
logger5.info("Bootstrapping from codespace", {
|
|
1765
1597
|
codespace: instanceName,
|
|
1766
1598
|
apiUrl,
|
|
1767
1599
|
apiUrlFromEnv,
|
|
@@ -1773,7 +1605,7 @@ async function bootstrapFromCodespace(apiUrl, instanceName) {
|
|
|
1773
1605
|
bootstrapToken
|
|
1774
1606
|
});
|
|
1775
1607
|
if (!result.ok) {
|
|
1776
|
-
|
|
1608
|
+
logger5.error("Bootstrap failed after retries", {
|
|
1777
1609
|
reason: result.reason,
|
|
1778
1610
|
attempts: result.attempts,
|
|
1779
1611
|
status: result.status,
|
|
@@ -1786,7 +1618,7 @@ async function bootstrapFromCodespace(apiUrl, instanceName) {
|
|
|
1786
1618
|
process.exit(1);
|
|
1787
1619
|
}
|
|
1788
1620
|
applyBootstrapToEnv(result.config);
|
|
1789
|
-
|
|
1621
|
+
logger5.info("Bootstrap complete", {
|
|
1790
1622
|
taskId: result.config.taskId,
|
|
1791
1623
|
attempts: result.attempts
|
|
1792
1624
|
});
|
|
@@ -1799,7 +1631,7 @@ function isExpectedAbortError(error) {
|
|
|
1799
1631
|
}
|
|
1800
1632
|
function exitOnPermissionDenial(err) {
|
|
1801
1633
|
if (!isPermissionDeniedError(err)) return false;
|
|
1802
|
-
|
|
1634
|
+
logger5.error("Not authorized for this project \u2014 parking instead of crash-looping", {
|
|
1803
1635
|
error: err.message
|
|
1804
1636
|
});
|
|
1805
1637
|
logAgentExit("unauthorized", { exitCode: 0 });
|
|
@@ -1808,48 +1640,48 @@ function exitOnPermissionDenial(err) {
|
|
|
1808
1640
|
process.on("uncaughtException", (err) => {
|
|
1809
1641
|
if (err.code === "EPIPE") return;
|
|
1810
1642
|
if (shuttingDown && isExpectedAbortError(err)) {
|
|
1811
|
-
|
|
1643
|
+
logger5.info("Ignored expected abort after shutdown", { error: err.message, code: err.code });
|
|
1812
1644
|
return;
|
|
1813
1645
|
}
|
|
1814
1646
|
if (exitOnPermissionDenial(err)) return;
|
|
1815
|
-
|
|
1647
|
+
logger5.error("Uncaught exception", { error: err.message, code: err.code });
|
|
1816
1648
|
logAgentExit("uncaught_exception", { exitCode: 1 });
|
|
1817
1649
|
process.exit(1);
|
|
1818
1650
|
});
|
|
1819
1651
|
process.on("unhandledRejection", (reason) => {
|
|
1820
1652
|
const err = reason instanceof Error ? reason : new Error(String(reason));
|
|
1821
1653
|
if (shuttingDown && isExpectedAbortError(err)) {
|
|
1822
|
-
|
|
1654
|
+
logger5.info("Ignored expected abort rejection after shutdown", { error: err.message });
|
|
1823
1655
|
return;
|
|
1824
1656
|
}
|
|
1825
1657
|
if (exitOnPermissionDenial(err)) return;
|
|
1826
|
-
|
|
1658
|
+
logger5.error("Unhandled rejection", { error: err.message });
|
|
1827
1659
|
logAgentExit("unhandled_rejection", { exitCode: 1 });
|
|
1828
1660
|
process.exit(1);
|
|
1829
1661
|
});
|
|
1830
1662
|
if (process.env.CONVEYOR_MODE === "workbench") {
|
|
1831
|
-
const { startWorkbenchServer } = await import("./server-
|
|
1663
|
+
const { startWorkbenchServer } = await import("./server-EQUCOLNY.js");
|
|
1832
1664
|
const { oomWatchdogOptionsFromEnv } = await import("./oom-watchdog-U7JERHA2.js");
|
|
1833
1665
|
const { DEFAULT_WORKBENCH_PORT } = await import("./protocol-QLVS5W6O.js");
|
|
1834
1666
|
const port = Number(process.env.CONVEYOR_WORKBENCH_PORT) || DEFAULT_WORKBENCH_PORT;
|
|
1835
1667
|
const token = process.env.CONVEYOR_WORKBENCH_TOKEN ?? process.env.POD_BOOTSTRAP_TOKEN ?? "";
|
|
1836
1668
|
if (!token) {
|
|
1837
|
-
|
|
1669
|
+
logger5.error("workbench mode requires POD_BOOTSTRAP_TOKEN (or CONVEYOR_WORKBENCH_TOKEN)");
|
|
1838
1670
|
process.exit(1);
|
|
1839
1671
|
}
|
|
1840
|
-
const pkgDir =
|
|
1841
|
-
const pkg = JSON.parse(readFileSync(
|
|
1672
|
+
const pkgDir = dirname2(fileURLToPath(import.meta.url));
|
|
1673
|
+
const pkg = JSON.parse(readFileSync(join3(pkgDir, "..", "package.json"), "utf-8"));
|
|
1842
1674
|
const handle = await startWorkbenchServer({
|
|
1843
1675
|
port,
|
|
1844
1676
|
token,
|
|
1845
1677
|
version: pkg.version ?? "unknown",
|
|
1846
1678
|
oomWatchdog: oomWatchdogOptionsFromEnv({
|
|
1847
|
-
info: (m) =>
|
|
1848
|
-
warn: (m) =>
|
|
1849
|
-
error: (m) =>
|
|
1679
|
+
info: (m) => logger5.info(m),
|
|
1680
|
+
warn: (m) => logger5.warn(m),
|
|
1681
|
+
error: (m) => logger5.error(m)
|
|
1850
1682
|
})
|
|
1851
1683
|
});
|
|
1852
|
-
|
|
1684
|
+
logger5.info(`Workbench launcher listening on 127.0.0.1:${handle.port}`);
|
|
1853
1685
|
process.on("SIGTERM", () => process.exit(0));
|
|
1854
1686
|
await new Promise(() => {
|
|
1855
1687
|
});
|
|
@@ -1859,7 +1691,7 @@ var conveyorApiUrl = process.env.CONVEYOR_API_URL || DEFAULT_CONVEYOR_API_URL;
|
|
|
1859
1691
|
var INSTANCE_NAME = process.env.CODESPACE_NAME || process.env.CLAUDESPACE_NAME;
|
|
1860
1692
|
if (INSTANCE_NAME && !process.env.CONVEYOR_TASK_TOKEN) {
|
|
1861
1693
|
if (!conveyorApiUrl) {
|
|
1862
|
-
|
|
1694
|
+
logger5.error("Could not resolve CONVEYOR_API_URL for codespace bootstrap");
|
|
1863
1695
|
process.exit(1);
|
|
1864
1696
|
}
|
|
1865
1697
|
await bootstrapFromCodespace(conveyorApiUrl, INSTANCE_NAME);
|
|
@@ -1877,7 +1709,7 @@ exitContext.runnerMode = CONVEYOR_MODE;
|
|
|
1877
1709
|
exitContext.sessionId = process.env.CONVEYOR_SESSION_ID ?? CONVEYOR_TASK_ID;
|
|
1878
1710
|
var projectIdentity = resolveProjectRunnerIdentity(process.env);
|
|
1879
1711
|
if (!CONVEYOR_TASK_ID && projectIdentity && CONVEYOR_MODE === "adhoc") {
|
|
1880
|
-
|
|
1712
|
+
logger5.info("Starting ad-hoc agent", { projectId: projectIdentity.projectId });
|
|
1881
1713
|
const adhocRunner = new AdhocSessionRunner(
|
|
1882
1714
|
{
|
|
1883
1715
|
connection: {
|
|
@@ -1896,7 +1728,7 @@ if (!CONVEYOR_TASK_ID && projectIdentity && CONVEYOR_MODE === "adhoc") {
|
|
|
1896
1728
|
},
|
|
1897
1729
|
{
|
|
1898
1730
|
onEvent: (event) => {
|
|
1899
|
-
|
|
1731
|
+
logger5.info("Ad-hoc runner event", { eventType: event.type });
|
|
1900
1732
|
}
|
|
1901
1733
|
}
|
|
1902
1734
|
);
|
|
@@ -1920,7 +1752,7 @@ if (!CONVEYOR_TASK_ID && projectIdentity && CONVEYOR_MODE === "adhoc") {
|
|
|
1920
1752
|
process.exit(adhocError ? 1 : 0);
|
|
1921
1753
|
}
|
|
1922
1754
|
if (!CONVEYOR_TASK_ID && projectIdentity) {
|
|
1923
|
-
|
|
1755
|
+
logger5.info("Starting project agent", { projectId: projectIdentity.projectId });
|
|
1924
1756
|
const projectRunner = new ProjectSessionRunner(
|
|
1925
1757
|
{
|
|
1926
1758
|
connection: {
|
|
@@ -1935,7 +1767,7 @@ if (!CONVEYOR_TASK_ID && projectIdentity) {
|
|
|
1935
1767
|
},
|
|
1936
1768
|
{
|
|
1937
1769
|
onEvent: (event) => {
|
|
1938
|
-
|
|
1770
|
+
logger5.info("Project runner event", { eventType: event.type });
|
|
1939
1771
|
}
|
|
1940
1772
|
}
|
|
1941
1773
|
);
|
|
@@ -1959,22 +1791,22 @@ if (!CONVEYOR_TASK_ID && projectIdentity) {
|
|
|
1959
1791
|
process.exit(projectError ? 1 : 0);
|
|
1960
1792
|
}
|
|
1961
1793
|
if (!CONVEYOR_TASK_TOKEN || !CONVEYOR_TASK_ID) {
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1794
|
+
logger5.error("Missing required environment variables");
|
|
1795
|
+
logger5.error(" CONVEYOR_TASK_TOKEN - JWT token for task authentication");
|
|
1796
|
+
logger5.error(" CONVEYOR_TASK_ID - ID of the task to execute");
|
|
1797
|
+
logger5.error("");
|
|
1798
|
+
logger5.error("CONVEYOR_API_URL is provided via codespace secret or bootstrap.");
|
|
1799
|
+
logger5.error("");
|
|
1800
|
+
logger5.error("Optional:");
|
|
1801
|
+
logger5.error(" CONVEYOR_MODE - Runner mode: 'task' (default), 'pack', or 'pm'");
|
|
1802
|
+
logger5.error(" CONVEYOR_WORKSPACE - Working directory (defaults to cwd)");
|
|
1803
|
+
logger5.error(
|
|
1972
1804
|
" Project pods instead require CONVEYOR_PROJECT_ID + CONVEYOR_SESSION_ID + CONVEYOR_MODE=pm"
|
|
1973
1805
|
);
|
|
1974
1806
|
process.exit(1);
|
|
1975
1807
|
}
|
|
1976
1808
|
if (CONVEYOR_MODE !== "task" && CONVEYOR_MODE !== "pm" && CONVEYOR_MODE !== "code-review" && CONVEYOR_MODE !== "adhoc" && CONVEYOR_MODE !== "pack" && CONVEYOR_MODE !== "shell") {
|
|
1977
|
-
|
|
1809
|
+
logger5.error("Invalid CONVEYOR_MODE", {
|
|
1978
1810
|
mode: CONVEYOR_MODE,
|
|
1979
1811
|
expected: ["task", "pm", "code-review", "adhoc", "pack", "shell"]
|
|
1980
1812
|
});
|
|
@@ -1983,7 +1815,7 @@ if (CONVEYOR_MODE !== "task" && CONVEYOR_MODE !== "pm" && CONVEYOR_MODE !== "cod
|
|
|
1983
1815
|
if (CONVEYOR_MODE === "shell" || CONVEYOR_MODE === "adhoc") {
|
|
1984
1816
|
const spawnedSessionId = process.env.CONVEYOR_SESSION_ID;
|
|
1985
1817
|
if (!spawnedSessionId) {
|
|
1986
|
-
|
|
1818
|
+
logger5.error("Spawned child requires CONVEYOR_SESSION_ID", { mode: CONVEYOR_MODE });
|
|
1987
1819
|
process.exit(1);
|
|
1988
1820
|
}
|
|
1989
1821
|
exitContext.sessionId = spawnedSessionId;
|
|
@@ -1996,7 +1828,7 @@ if (CONVEYOR_MODE === "shell" || CONVEYOR_MODE === "adhoc") {
|
|
|
1996
1828
|
workspaceDir: CONVEYOR_WORKSPACE,
|
|
1997
1829
|
projectId: process.env.CONVEYOR_PROJECT_ID ?? ""
|
|
1998
1830
|
});
|
|
1999
|
-
|
|
1831
|
+
logger5.info("Starting spawned session child", {
|
|
2000
1832
|
mode: CONVEYOR_MODE,
|
|
2001
1833
|
sessionId: spawnedSessionId
|
|
2002
1834
|
});
|
|
@@ -2016,7 +1848,7 @@ if (CONVEYOR_MODE === "shell" || CONVEYOR_MODE === "adhoc") {
|
|
|
2016
1848
|
});
|
|
2017
1849
|
process.exit(childError ? 1 : 0);
|
|
2018
1850
|
}
|
|
2019
|
-
|
|
1851
|
+
logger5.info("Starting agent", { mode: CONVEYOR_MODE });
|
|
2020
1852
|
var lifecycleOverrides = process.env.CLAUDESPACE_NAME ? { idleTimeoutMs: 60 * 60 * 1e3 } : { gitFlushIntervalMs: 0 };
|
|
2021
1853
|
var runner = new SessionRunner(
|
|
2022
1854
|
{
|
|
@@ -2036,12 +1868,12 @@ var runner = new SessionRunner(
|
|
|
2036
1868
|
},
|
|
2037
1869
|
{
|
|
2038
1870
|
onStatusChange: (status) => {
|
|
2039
|
-
|
|
1871
|
+
logger5.info("Status changed", { status });
|
|
2040
1872
|
},
|
|
2041
1873
|
onEvent: (event) => {
|
|
2042
1874
|
const detail = event.message ?? event.content ?? event.summary ?? "";
|
|
2043
1875
|
if (detail) {
|
|
2044
|
-
|
|
1876
|
+
logger5.info(detail, { eventType: event.type });
|
|
2045
1877
|
}
|
|
2046
1878
|
}
|
|
2047
1879
|
}
|
|
@@ -2053,7 +1885,7 @@ var workspaceCommandSupervisor = null;
|
|
|
2053
1885
|
var shutdownCompletion = null;
|
|
2054
1886
|
var shutdownAgent = (signal) => {
|
|
2055
1887
|
shuttingDown = true;
|
|
2056
|
-
|
|
1888
|
+
logger5.info(`Received ${signal}, flushing git and stopping agent`);
|
|
2057
1889
|
const commandShutdown = stopWorkspaceCommands(workspaceCommandSupervisor);
|
|
2058
1890
|
shutdownSignal = signal;
|
|
2059
1891
|
shutdownCompletion ??= (async () => {
|
|
@@ -2070,8 +1902,8 @@ var shutdownAgent = (signal) => {
|
|
|
2070
1902
|
})();
|
|
2071
1903
|
void shutdownCompletion;
|
|
2072
1904
|
setTimeout(() => {
|
|
2073
|
-
|
|
2074
|
-
|
|
1905
|
+
logger5.warn(`Forcing exit after ${signal} timeout`);
|
|
1906
|
+
logger5.warn(
|
|
2075
1907
|
"agent_exit",
|
|
2076
1908
|
buildAgentExitLog({
|
|
2077
1909
|
reason: "force_timeout",
|
|
@@ -2097,7 +1929,7 @@ workspaceCommandSupervisor = await startWorkspaceCommandsAfterConnect({
|
|
|
2097
1929
|
})
|
|
2098
1930
|
});
|
|
2099
1931
|
if (!workspaceCommandSupervisor) {
|
|
2100
|
-
|
|
1932
|
+
logger5.info("Agent stopped before workspace commands were started");
|
|
2101
1933
|
if (shutdownCompletion) await shutdownCompletion;
|
|
2102
1934
|
logAgentExit(shutdownSignal ? "signal" : "clean", {
|
|
2103
1935
|
exitCode: 0,
|
|
@@ -2114,12 +1946,12 @@ void checkSessionTaskIdentity({
|
|
|
2114
1946
|
const ctx = await runner.connection.call("getTaskContext", { sessionId });
|
|
2115
1947
|
return ctx.id;
|
|
2116
1948
|
},
|
|
2117
|
-
logger:
|
|
1949
|
+
logger: logger5
|
|
2118
1950
|
});
|
|
2119
1951
|
if (hostsSpawnedChildren(CONVEYOR_MODE)) {
|
|
2120
1952
|
runner.connection.onSpawnReview((data) => {
|
|
2121
1953
|
void reviewChildren.spawn(data).catch((err) => {
|
|
2122
|
-
|
|
1954
|
+
logger5.error("Review child spawn threw", {
|
|
2123
1955
|
error: err instanceof Error ? err.message : String(err)
|
|
2124
1956
|
});
|
|
2125
1957
|
runner.connection.reportReviewSpawnFailure(
|
|
@@ -2132,7 +1964,7 @@ if (hostsSpawnedChildren(CONVEYOR_MODE)) {
|
|
|
2132
1964
|
if (hostsSpawnedChildren(CONVEYOR_MODE)) {
|
|
2133
1965
|
runner.connection.onSpawnTui((data) => {
|
|
2134
1966
|
void sessionChildren.spawn(data).catch((err) => {
|
|
2135
|
-
|
|
1967
|
+
logger5.error("Session child spawn threw", {
|
|
2136
1968
|
error: err instanceof Error ? err.message : String(err)
|
|
2137
1969
|
});
|
|
2138
1970
|
runner.connection.reportSessionSpawnFailure(
|
|
@@ -2155,7 +1987,7 @@ runner.run().then(async () => {
|
|
|
2155
1987
|
}).catch(async (error) => {
|
|
2156
1988
|
await stopWorkspaceCommands(workspaceCommandSupervisor);
|
|
2157
1989
|
const msg = error instanceof Error ? error.message : String(error);
|
|
2158
|
-
|
|
1990
|
+
logger5.error("Agent runner failed", { error: msg });
|
|
2159
1991
|
logAgentExit("error", { exitCode: 1, finalState: runner.finalState ?? void 0 });
|
|
2160
1992
|
process.exit(1);
|
|
2161
1993
|
});
|