@rallycry/conveyor-agent 10.13.71 → 11.0.0
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-PKHZUDAC.js → boot-PKQ2I66D.js} +56 -5
- package/dist/chunk-3F4ZZKCA.js +291 -0
- package/dist/{chunk-QU53HND5.js → chunk-GL2DIQEQ.js} +116 -47
- package/dist/chunk-JQVAWRVL.js +697 -0
- package/dist/chunk-N4WSUTGV.js +2564 -0
- package/dist/{chunk-7MMECTTJ.js → chunk-PEEGCZAR.js} +2257 -3701
- package/dist/{chunk-DOB2XE2I.js → chunk-UBDSLM44.js} +4 -2
- package/dist/{chunk-GJXAAPJ6.js → chunk-W4LZ7R6Z.js} +117 -400
- package/dist/chunk-XORJ6SII.js +46 -0
- package/dist/cli.js +304 -804
- package/dist/index.d.ts +170 -3
- package/dist/index.js +9 -5
- package/dist/serve-boot-YPAUKENG.js +225 -0
- package/dist/{server-CC7KUJOK.js → server-7XH7RYUX.js} +3 -2
- package/package.json +5 -4
- package/skills/conveyor-build/SKILL.md +262 -0
- package/skills/conveyor-build/references/pack-path.md +224 -0
- package/skills/conveyor-build/references/task-path.md +67 -0
- package/skills/conveyor-consensus/SKILL.md +99 -0
- package/skills/conveyor-consensus/references/doc-template.html +204 -0
- package/skills/conveyor-local-loop/SKILL.md +258 -0
- package/skills/conveyor-meeting-review/SKILL.md +72 -0
- package/skills/conveyor-plan/SKILL.md +177 -0
- package/skills/conveyor-plan/references/plan-format.md +134 -0
- package/skills/conveyor-review/SKILL.md +161 -0
- package/skills/conveyor-start/SKILL.md +106 -0
- package/skills/conveyor-triage/SKILL.md +174 -0
- package/skills/conveyor-workflows/SKILL.md +195 -0
- package/skills/conveyor-workflows/references/mcp-setup.md +43 -0
|
@@ -1,75 +1,122 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return
|
|
8
|
-
}
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (input.permissionMode === "bypassPermissions") {
|
|
18
|
-
args.push("--dangerously-skip-permissions");
|
|
19
|
-
} else {
|
|
20
|
-
args.push("--permission-mode", "plan");
|
|
21
|
-
}
|
|
22
|
-
args.push("--settings", input.settingsPath);
|
|
23
|
-
if (input.appendSystemPrompt) {
|
|
24
|
-
args.push("--append-system-prompt", input.appendSystemPrompt);
|
|
25
|
-
}
|
|
26
|
-
if (input.mcpConfigPath) {
|
|
27
|
-
args.push("--mcp-config", input.mcpConfigPath);
|
|
28
|
-
if (input.strictMcpConfig) {
|
|
29
|
-
args.push("--strict-mcp-config");
|
|
1
|
+
// src/setup/commands.ts
|
|
2
|
+
import { spawn, execSync } from "child_process";
|
|
3
|
+
var PROCESS_TERMINATION_GRACE_MS = 5e3;
|
|
4
|
+
function abortError() {
|
|
5
|
+
const error = new Error("Operation aborted");
|
|
6
|
+
error.name = "AbortError";
|
|
7
|
+
return error;
|
|
8
|
+
}
|
|
9
|
+
function signalProcessGroup(child, signal) {
|
|
10
|
+
try {
|
|
11
|
+
if (child.pid) process.kill(-child.pid, signal);
|
|
12
|
+
else child.kill(signal);
|
|
13
|
+
} catch {
|
|
14
|
+
try {
|
|
15
|
+
child.kill(signal);
|
|
16
|
+
} catch {
|
|
30
17
|
}
|
|
31
18
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
19
|
+
}
|
|
20
|
+
function terminateProcessGroup(child, graceMs = PROCESS_TERMINATION_GRACE_MS) {
|
|
21
|
+
if (child.exitCode !== null) return Promise.resolve();
|
|
22
|
+
return new Promise((resolve) => {
|
|
23
|
+
let settled = false;
|
|
24
|
+
const finish = () => {
|
|
25
|
+
if (settled) return;
|
|
26
|
+
settled = true;
|
|
27
|
+
clearTimeout(timer);
|
|
28
|
+
child.removeListener("exit", finish);
|
|
29
|
+
resolve();
|
|
30
|
+
};
|
|
31
|
+
const timer = setTimeout(() => {
|
|
32
|
+
signalProcessGroup(child, "SIGKILL");
|
|
33
|
+
finish();
|
|
34
|
+
}, graceMs);
|
|
35
|
+
timer.unref();
|
|
36
|
+
child.once("exit", finish);
|
|
37
|
+
signalProcessGroup(child, "SIGTERM");
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function runSetupCommand(cmd, cwd, onOutput, signal) {
|
|
41
|
+
if (signal?.aborted) return Promise.reject(abortError());
|
|
42
|
+
return new Promise((resolve, reject) => {
|
|
43
|
+
const child = spawn("sh", ["-c", cmd], {
|
|
44
|
+
cwd,
|
|
45
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
46
|
+
detached: true,
|
|
47
|
+
env: { ...process.env }
|
|
48
|
+
});
|
|
49
|
+
let settled = false;
|
|
50
|
+
let aborting = false;
|
|
51
|
+
const cleanup = () => signal?.removeEventListener("abort", onAbort);
|
|
52
|
+
const settle = (error) => {
|
|
53
|
+
if (settled) return;
|
|
54
|
+
settled = true;
|
|
55
|
+
cleanup();
|
|
56
|
+
if (error) reject(error);
|
|
57
|
+
else resolve();
|
|
58
|
+
};
|
|
59
|
+
const onAbort = () => {
|
|
60
|
+
if (settled || aborting) return;
|
|
61
|
+
aborting = true;
|
|
62
|
+
void terminateProcessGroup(child).then(() => settle(abortError()));
|
|
63
|
+
};
|
|
64
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
65
|
+
if (signal?.aborted) onAbort();
|
|
66
|
+
child.stdout.on("data", (chunk) => {
|
|
67
|
+
if (aborting || signal?.aborted) return;
|
|
68
|
+
onOutput("stdout", chunk.toString());
|
|
69
|
+
});
|
|
70
|
+
child.stderr.on("data", (chunk) => {
|
|
71
|
+
if (aborting || signal?.aborted) return;
|
|
72
|
+
onOutput("stderr", chunk.toString());
|
|
73
|
+
});
|
|
74
|
+
child.on("close", (code) => {
|
|
75
|
+
if (aborting) return;
|
|
76
|
+
settle(code === 0 ? void 0 : new Error(`Setup command exited with code ${code}`));
|
|
77
|
+
});
|
|
78
|
+
child.on("error", (err) => {
|
|
79
|
+
if (!aborting) settle(err);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
var AUTH_TOKEN_TIMEOUT_MS = 3e4;
|
|
84
|
+
function runAuthTokenCommand(cmd, userEmail, cwd) {
|
|
85
|
+
try {
|
|
86
|
+
const output = execSync(`${cmd} ${JSON.stringify(userEmail)}`, {
|
|
87
|
+
cwd,
|
|
88
|
+
timeout: AUTH_TOKEN_TIMEOUT_MS,
|
|
89
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
90
|
+
env: { ...process.env }
|
|
91
|
+
});
|
|
92
|
+
const token = output.toString().trim();
|
|
93
|
+
return token || null;
|
|
94
|
+
} catch {
|
|
95
|
+
return null;
|
|
71
96
|
}
|
|
72
|
-
|
|
97
|
+
}
|
|
98
|
+
function runStartCommand(cmd, cwd, onOutput) {
|
|
99
|
+
const child = spawn("sh", ["-c", cmd], {
|
|
100
|
+
cwd,
|
|
101
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
102
|
+
detached: true,
|
|
103
|
+
env: { ...process.env }
|
|
104
|
+
});
|
|
105
|
+
child.stdout.on("data", (chunk) => {
|
|
106
|
+
onOutput("stdout", chunk.toString());
|
|
107
|
+
});
|
|
108
|
+
child.stderr.on("data", (chunk) => {
|
|
109
|
+
onOutput("stderr", chunk.toString());
|
|
110
|
+
});
|
|
111
|
+
child.unref();
|
|
112
|
+
return child;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// src/utils/sleep.ts
|
|
116
|
+
function sleep(ms) {
|
|
117
|
+
return new Promise((resolve) => {
|
|
118
|
+
setTimeout(resolve, ms);
|
|
119
|
+
});
|
|
73
120
|
}
|
|
74
121
|
|
|
75
122
|
// src/boot/git-credential.ts
|
|
@@ -289,345 +336,15 @@ function classifyTokenShape(value) {
|
|
|
289
336
|
return "unrecognized prefix";
|
|
290
337
|
}
|
|
291
338
|
|
|
292
|
-
// src/utils/sleep.ts
|
|
293
|
-
function sleep(ms) {
|
|
294
|
-
return new Promise((resolve) => {
|
|
295
|
-
setTimeout(resolve, ms);
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// src/harness/pty/pty-support.ts
|
|
300
|
-
var MAX_DIAGNOSTIC_OUTPUT = 4e3;
|
|
301
|
-
var MAX_BETWEEN_TURN_BUFFER = 500;
|
|
302
|
-
var SUBMIT_SETTLE_MS = 300;
|
|
303
|
-
var SUBMIT_NUDGE_INTERVAL_MS = 2e3;
|
|
304
|
-
var SUBMIT_NUDGE_MAX_PRESSES = 5;
|
|
305
|
-
var SUBMIT_NUDGE_SLOW_INTERVAL_MS = 5e3;
|
|
306
|
-
var SUBMIT_NUDGE_WINDOW_MS = 9e4;
|
|
307
|
-
var SUBMIT_REDELIVERY_MAX_ATTEMPTS = 2;
|
|
308
|
-
var PLAN_DIALOG_FIRST_PRESS_MS = 700;
|
|
309
|
-
var PLAN_DIALOG_INTERVAL_MS = 1500;
|
|
310
|
-
var PLAN_DIALOG_SLOW_INTERVAL_MS = 5e3;
|
|
311
|
-
var PLAN_DIALOG_FAST_WINDOW_MS = 1e4;
|
|
312
|
-
var PLAN_DIALOG_WINDOW_MS = 9e4;
|
|
313
|
-
var RAW_TUI_PROBE_SENTINEL = "zqx";
|
|
314
|
-
var RAW_TUI_PROBE_ACK_MS = 500;
|
|
315
|
-
var RAW_TUI_PROBE_RETRY_MS = 250;
|
|
316
|
-
var RAW_TUI_PROBE_POLL_MS = 20;
|
|
317
|
-
var RAW_TUI_FIRST_OUTPUT_MAX_MS = 1e4;
|
|
318
|
-
var RAW_TUI_INPUT_LIVE_MAX_MS = 2e4;
|
|
319
|
-
function envMs(name, fallback) {
|
|
320
|
-
const raw = Number(process.env[name]);
|
|
321
|
-
return Number.isFinite(raw) && raw > 0 ? raw : fallback;
|
|
322
|
-
}
|
|
323
|
-
function resolveSubmitSettleMs() {
|
|
324
|
-
return envMs("CONVEYOR_PTY_SUBMIT_SETTLE_MS", SUBMIT_SETTLE_MS);
|
|
325
|
-
}
|
|
326
|
-
function resolveRawTuiProbeTiming() {
|
|
327
|
-
const sentinel = process.env.CONVEYOR_PTY_RAW_PROBE_SENTINEL;
|
|
328
|
-
return {
|
|
329
|
-
// A sentinel must be non-empty (it is what we search for) and must stay
|
|
330
|
-
// free of digits and control chars — see the note on menu dialogs above.
|
|
331
|
-
sentinel: sentinel && /^[a-z]{1,8}$/.test(sentinel) ? sentinel : RAW_TUI_PROBE_SENTINEL,
|
|
332
|
-
ackMs: envMs("CONVEYOR_PTY_RAW_PROBE_ACK_MS", RAW_TUI_PROBE_ACK_MS),
|
|
333
|
-
retryMs: envMs("CONVEYOR_PTY_RAW_PROBE_RETRY_MS", RAW_TUI_PROBE_RETRY_MS),
|
|
334
|
-
pollMs: envMs("CONVEYOR_PTY_RAW_PROBE_POLL_MS", RAW_TUI_PROBE_POLL_MS),
|
|
335
|
-
firstOutputMaxMs: envMs("CONVEYOR_PTY_RAW_FIRST_OUTPUT_MAX_MS", RAW_TUI_FIRST_OUTPUT_MAX_MS),
|
|
336
|
-
maxMs: envMs("CONVEYOR_PTY_RAW_INPUT_LIVE_MAX_MS", RAW_TUI_INPUT_LIVE_MAX_MS)
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
function sentinelEchoed(rawOutput, sentinel) {
|
|
340
|
-
return cleanTerminalOutput(rawOutput, Number.MAX_SAFE_INTEGER).includes(sentinel);
|
|
341
|
-
}
|
|
342
|
-
var DEC_PRIVATE_MODE = new RegExp(`${String.fromCharCode(27)}\\[\\?[0-9;]+[hl]`);
|
|
343
|
-
function sawTerminalSetup(rawOutput) {
|
|
344
|
-
return DEC_PRIVATE_MODE.test(rawOutput);
|
|
345
|
-
}
|
|
346
|
-
function needsRawReadyGate(caps) {
|
|
347
|
-
return caps.rawPromptGate;
|
|
348
|
-
}
|
|
349
|
-
function resolveSubmitNudgeTiming() {
|
|
350
|
-
return {
|
|
351
|
-
intervalMs: envMs("CONVEYOR_PTY_NUDGE_INTERVAL_MS", SUBMIT_NUDGE_INTERVAL_MS),
|
|
352
|
-
slowIntervalMs: envMs("CONVEYOR_PTY_NUDGE_SLOW_INTERVAL_MS", SUBMIT_NUDGE_SLOW_INTERVAL_MS),
|
|
353
|
-
maxPresses: SUBMIT_NUDGE_MAX_PRESSES,
|
|
354
|
-
windowMs: envMs("CONVEYOR_PTY_NUDGE_WINDOW_MS", SUBMIT_NUDGE_WINDOW_MS)
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
function resolveSubmitRedeliveryMaxAttempts() {
|
|
358
|
-
const value = process.env.CONVEYOR_PTY_SUBMIT_REDELIVERY_MAX;
|
|
359
|
-
if (!value) return SUBMIT_REDELIVERY_MAX_ATTEMPTS;
|
|
360
|
-
const raw = Number(value);
|
|
361
|
-
return Number.isFinite(raw) && raw >= 0 ? raw : SUBMIT_REDELIVERY_MAX_ATTEMPTS;
|
|
362
|
-
}
|
|
363
|
-
function resolvePlanDialogTiming() {
|
|
364
|
-
return {
|
|
365
|
-
firstPressMs: envMs("CONVEYOR_PTY_PLAN_DIALOG_FIRST_PRESS_MS", PLAN_DIALOG_FIRST_PRESS_MS),
|
|
366
|
-
intervalMs: envMs("CONVEYOR_PTY_PLAN_DIALOG_INTERVAL_MS", PLAN_DIALOG_INTERVAL_MS),
|
|
367
|
-
slowIntervalMs: envMs(
|
|
368
|
-
"CONVEYOR_PTY_PLAN_DIALOG_SLOW_INTERVAL_MS",
|
|
369
|
-
PLAN_DIALOG_SLOW_INTERVAL_MS
|
|
370
|
-
),
|
|
371
|
-
fastWindowMs: envMs("CONVEYOR_PTY_PLAN_DIALOG_FAST_WINDOW_MS", PLAN_DIALOG_FAST_WINDOW_MS),
|
|
372
|
-
windowMs: envMs("CONVEYOR_PTY_PLAN_DIALOG_WINDOW_MS", PLAN_DIALOG_WINDOW_MS)
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
function turnOptionsFrom(options) {
|
|
376
|
-
return {
|
|
377
|
-
canUseTool: options.canUseTool,
|
|
378
|
-
promptDelivery: options.promptDelivery,
|
|
379
|
-
planDialogAutoAccept: options.planDialogAutoAccept,
|
|
380
|
-
abortController: options.abortController
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
var KILL_ESCALATION_MS = 5e3;
|
|
384
|
-
function killPtyWithEscalation(pty, hasExited, escalationMs = KILL_ESCALATION_MS) {
|
|
385
|
-
try {
|
|
386
|
-
pty.kill();
|
|
387
|
-
} catch {
|
|
388
|
-
}
|
|
389
|
-
const timer = setTimeout(() => {
|
|
390
|
-
if (hasExited()) return;
|
|
391
|
-
try {
|
|
392
|
-
pty.kill("SIGKILL");
|
|
393
|
-
} catch {
|
|
394
|
-
}
|
|
395
|
-
}, escalationMs);
|
|
396
|
-
timer.unref?.();
|
|
397
|
-
}
|
|
398
|
-
function isRecord(value) {
|
|
399
|
-
return typeof value === "object" && value !== null;
|
|
400
|
-
}
|
|
401
|
-
function extractSpawn(mod) {
|
|
402
|
-
if (!isRecord(mod)) return null;
|
|
403
|
-
if (typeof mod.spawn === "function") return mod.spawn;
|
|
404
|
-
const def = mod.default;
|
|
405
|
-
if (isRecord(def) && typeof def.spawn === "function") return def.spawn;
|
|
406
|
-
return null;
|
|
407
|
-
}
|
|
408
|
-
async function loadPtySpawn() {
|
|
409
|
-
const mod = await import("node-pty");
|
|
410
|
-
const spawn2 = extractSpawn(mod);
|
|
411
|
-
if (!spawn2) throw new Error("node-pty: spawn export not found");
|
|
412
|
-
return spawn2;
|
|
413
|
-
}
|
|
414
|
-
async function resolvePtySpawn() {
|
|
415
|
-
const { workbenchEnabled } = await import("./mode-ZJSOSLGU.js");
|
|
416
|
-
if (!workbenchEnabled()) return loadPtySpawn();
|
|
417
|
-
const { getWorkbenchClient } = await import("./client-IG6C5F2G.js");
|
|
418
|
-
return (file, args, options) => getWorkbenchClient().spawnPty(file, args, options);
|
|
419
|
-
}
|
|
420
|
-
function sessionTempBase() {
|
|
421
|
-
return process.env.CONVEYOR_SHARED_DIR ?? tmpdir();
|
|
422
|
-
}
|
|
423
|
-
function inheritedEnv(socketPath) {
|
|
424
|
-
const env = {};
|
|
425
|
-
for (const [key, value] of Object.entries(process.env)) {
|
|
426
|
-
if (typeof value === "string") env[key] = value;
|
|
427
|
-
}
|
|
428
|
-
if (env.CLAUDE_CODE_OAUTH_TOKEN) {
|
|
429
|
-
delete env.ANTHROPIC_API_KEY;
|
|
430
|
-
}
|
|
431
|
-
if (ghHostsManagedByConveyor() && env.CONVEYOR_KEEP_GH_TOKEN_ENV !== "1") {
|
|
432
|
-
delete env.GH_TOKEN;
|
|
433
|
-
delete env.GITHUB_TOKEN;
|
|
434
|
-
delete env.CONVEYOR_GITHUB_TOKEN;
|
|
435
|
-
env.CONVEYOR_GITHUB_TOKEN_FILE = githubTokenFilePath();
|
|
436
|
-
}
|
|
437
|
-
if (socketPath) {
|
|
438
|
-
env.CONVEYOR_HOOK_SOCKET = socketPath;
|
|
439
|
-
}
|
|
440
|
-
env.MCP_TIMEOUT ??= "60000";
|
|
441
|
-
env.MCP_TOOL_TIMEOUT ??= "180000";
|
|
442
|
-
return env;
|
|
443
|
-
}
|
|
444
|
-
function buildPromptBytes(text) {
|
|
445
|
-
return `\x1B[200~${text}\x1B[201~`;
|
|
446
|
-
}
|
|
447
|
-
function renderPromptContentText(content) {
|
|
448
|
-
return content.map((block) => {
|
|
449
|
-
const b = block;
|
|
450
|
-
if (b?.type === "text" && typeof b.text === "string") return b.text;
|
|
451
|
-
if (b?.type === "image") {
|
|
452
|
-
return `[Image attachment \u2014 use list_task_files / get_attachment to view]`;
|
|
453
|
-
}
|
|
454
|
-
return JSON.stringify(block);
|
|
455
|
-
}).join("\n\n");
|
|
456
|
-
}
|
|
457
|
-
async function transcriptSize(path) {
|
|
458
|
-
try {
|
|
459
|
-
return (await stat(path)).size;
|
|
460
|
-
} catch {
|
|
461
|
-
return 0;
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
function parseUserQuestions(input) {
|
|
465
|
-
if (!Array.isArray(input.questions)) return [];
|
|
466
|
-
const questions = [];
|
|
467
|
-
for (const entry of input.questions) {
|
|
468
|
-
if (!isRecord(entry)) continue;
|
|
469
|
-
if (typeof entry.question !== "string") continue;
|
|
470
|
-
const options = Array.isArray(entry.options) ? entry.options.filter(isRecord).filter((o) => typeof o.label === "string").map((o) => ({
|
|
471
|
-
label: o.label,
|
|
472
|
-
description: typeof o.description === "string" ? o.description : ""
|
|
473
|
-
})) : [];
|
|
474
|
-
questions.push({
|
|
475
|
-
question: entry.question,
|
|
476
|
-
header: typeof entry.header === "string" ? entry.header : "",
|
|
477
|
-
options,
|
|
478
|
-
...typeof entry.multiSelect === "boolean" ? { multiSelect: entry.multiSelect } : {}
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
return questions;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// src/setup/commands.ts
|
|
485
|
-
import { spawn, execSync } from "child_process";
|
|
486
|
-
var PROCESS_TERMINATION_GRACE_MS = 5e3;
|
|
487
|
-
function abortError() {
|
|
488
|
-
const error = new Error("Operation aborted");
|
|
489
|
-
error.name = "AbortError";
|
|
490
|
-
return error;
|
|
491
|
-
}
|
|
492
|
-
function signalProcessGroup(child, signal) {
|
|
493
|
-
try {
|
|
494
|
-
if (child.pid) process.kill(-child.pid, signal);
|
|
495
|
-
else child.kill(signal);
|
|
496
|
-
} catch {
|
|
497
|
-
try {
|
|
498
|
-
child.kill(signal);
|
|
499
|
-
} catch {
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
function terminateProcessGroup(child, graceMs = PROCESS_TERMINATION_GRACE_MS) {
|
|
504
|
-
if (child.exitCode !== null) return Promise.resolve();
|
|
505
|
-
return new Promise((resolve) => {
|
|
506
|
-
let settled = false;
|
|
507
|
-
const finish = () => {
|
|
508
|
-
if (settled) return;
|
|
509
|
-
settled = true;
|
|
510
|
-
clearTimeout(timer);
|
|
511
|
-
child.removeListener("exit", finish);
|
|
512
|
-
resolve();
|
|
513
|
-
};
|
|
514
|
-
const timer = setTimeout(() => {
|
|
515
|
-
signalProcessGroup(child, "SIGKILL");
|
|
516
|
-
finish();
|
|
517
|
-
}, graceMs);
|
|
518
|
-
timer.unref();
|
|
519
|
-
child.once("exit", finish);
|
|
520
|
-
signalProcessGroup(child, "SIGTERM");
|
|
521
|
-
});
|
|
522
|
-
}
|
|
523
|
-
function runSetupCommand(cmd, cwd, onOutput, signal) {
|
|
524
|
-
if (signal?.aborted) return Promise.reject(abortError());
|
|
525
|
-
return new Promise((resolve, reject) => {
|
|
526
|
-
const child = spawn("sh", ["-c", cmd], {
|
|
527
|
-
cwd,
|
|
528
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
529
|
-
detached: true,
|
|
530
|
-
env: { ...process.env }
|
|
531
|
-
});
|
|
532
|
-
let settled = false;
|
|
533
|
-
let aborting = false;
|
|
534
|
-
const cleanup = () => signal?.removeEventListener("abort", onAbort);
|
|
535
|
-
const settle = (error) => {
|
|
536
|
-
if (settled) return;
|
|
537
|
-
settled = true;
|
|
538
|
-
cleanup();
|
|
539
|
-
if (error) reject(error);
|
|
540
|
-
else resolve();
|
|
541
|
-
};
|
|
542
|
-
const onAbort = () => {
|
|
543
|
-
if (settled || aborting) return;
|
|
544
|
-
aborting = true;
|
|
545
|
-
void terminateProcessGroup(child).then(() => settle(abortError()));
|
|
546
|
-
};
|
|
547
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
548
|
-
if (signal?.aborted) onAbort();
|
|
549
|
-
child.stdout.on("data", (chunk) => {
|
|
550
|
-
if (aborting || signal?.aborted) return;
|
|
551
|
-
onOutput("stdout", chunk.toString());
|
|
552
|
-
});
|
|
553
|
-
child.stderr.on("data", (chunk) => {
|
|
554
|
-
if (aborting || signal?.aborted) return;
|
|
555
|
-
onOutput("stderr", chunk.toString());
|
|
556
|
-
});
|
|
557
|
-
child.on("close", (code) => {
|
|
558
|
-
if (aborting) return;
|
|
559
|
-
settle(code === 0 ? void 0 : new Error(`Setup command exited with code ${code}`));
|
|
560
|
-
});
|
|
561
|
-
child.on("error", (err) => {
|
|
562
|
-
if (!aborting) settle(err);
|
|
563
|
-
});
|
|
564
|
-
});
|
|
565
|
-
}
|
|
566
|
-
var AUTH_TOKEN_TIMEOUT_MS = 3e4;
|
|
567
|
-
function runAuthTokenCommand(cmd, userEmail, cwd) {
|
|
568
|
-
try {
|
|
569
|
-
const output = execSync(`${cmd} ${JSON.stringify(userEmail)}`, {
|
|
570
|
-
cwd,
|
|
571
|
-
timeout: AUTH_TOKEN_TIMEOUT_MS,
|
|
572
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
573
|
-
env: { ...process.env }
|
|
574
|
-
});
|
|
575
|
-
const token = output.toString().trim();
|
|
576
|
-
return token || null;
|
|
577
|
-
} catch {
|
|
578
|
-
return null;
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
function runStartCommand(cmd, cwd, onOutput) {
|
|
582
|
-
const child = spawn("sh", ["-c", cmd], {
|
|
583
|
-
cwd,
|
|
584
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
585
|
-
detached: true,
|
|
586
|
-
env: { ...process.env }
|
|
587
|
-
});
|
|
588
|
-
child.stdout.on("data", (chunk) => {
|
|
589
|
-
onOutput("stdout", chunk.toString());
|
|
590
|
-
});
|
|
591
|
-
child.stderr.on("data", (chunk) => {
|
|
592
|
-
onOutput("stderr", chunk.toString());
|
|
593
|
-
});
|
|
594
|
-
child.unref();
|
|
595
|
-
return child;
|
|
596
|
-
}
|
|
597
|
-
|
|
598
339
|
export {
|
|
599
340
|
sleep,
|
|
600
341
|
gitCredentialHelper,
|
|
601
342
|
writeGitCredential,
|
|
602
343
|
githubTokenFilePath,
|
|
344
|
+
ghHostsManagedByConveyor,
|
|
603
345
|
ghHostsExternallyOwned,
|
|
604
346
|
syncGithubTokenFiles,
|
|
605
347
|
describeTokenFile,
|
|
606
|
-
resolveClaudeBinary,
|
|
607
|
-
buildSpawnArgs,
|
|
608
|
-
spawnOptionsFingerprint,
|
|
609
|
-
cleanTerminalOutput,
|
|
610
|
-
buildExitErrors,
|
|
611
|
-
MAX_DIAGNOSTIC_OUTPUT,
|
|
612
|
-
MAX_BETWEEN_TURN_BUFFER,
|
|
613
|
-
resolveSubmitSettleMs,
|
|
614
|
-
resolveRawTuiProbeTiming,
|
|
615
|
-
sentinelEchoed,
|
|
616
|
-
sawTerminalSetup,
|
|
617
|
-
needsRawReadyGate,
|
|
618
|
-
resolveSubmitNudgeTiming,
|
|
619
|
-
resolveSubmitRedeliveryMaxAttempts,
|
|
620
|
-
resolvePlanDialogTiming,
|
|
621
|
-
turnOptionsFrom,
|
|
622
|
-
killPtyWithEscalation,
|
|
623
|
-
loadPtySpawn,
|
|
624
|
-
resolvePtySpawn,
|
|
625
|
-
sessionTempBase,
|
|
626
|
-
inheritedEnv,
|
|
627
|
-
buildPromptBytes,
|
|
628
|
-
renderPromptContentText,
|
|
629
|
-
transcriptSize,
|
|
630
|
-
parseUserQuestions,
|
|
631
348
|
terminateProcessGroup,
|
|
632
349
|
runSetupCommand,
|
|
633
350
|
runAuthTokenCommand,
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// src/runner/session-runner-helpers.ts
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
import { dirname, join } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
function mapChatHistory(messages) {
|
|
6
|
+
if (!messages) return [];
|
|
7
|
+
return messages.map((m) => ({
|
|
8
|
+
id: m.id,
|
|
9
|
+
role: m.role ?? "user",
|
|
10
|
+
content: m.content ?? "",
|
|
11
|
+
userId: m.userId,
|
|
12
|
+
userName: m.user?.name ?? void 0,
|
|
13
|
+
createdAt: m.createdAt,
|
|
14
|
+
...m.source ? { source: m.source } : {},
|
|
15
|
+
...m.files && m.files.length > 0 ? {
|
|
16
|
+
files: m.files.map((f) => ({
|
|
17
|
+
fileId: f.id,
|
|
18
|
+
fileName: f.fileName,
|
|
19
|
+
mimeType: f.mimeType,
|
|
20
|
+
fileSize: f.fileSize,
|
|
21
|
+
downloadUrl: f.downloadUrl ?? "",
|
|
22
|
+
content: f.content,
|
|
23
|
+
contentEncoding: f.contentEncoding
|
|
24
|
+
}))
|
|
25
|
+
} : {}
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
function readAgentVersion() {
|
|
29
|
+
try {
|
|
30
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
31
|
+
for (const rel of ["../package.json", "../../package.json"]) {
|
|
32
|
+
try {
|
|
33
|
+
const pkg = JSON.parse(readFileSync(join(here, rel), "utf-8"));
|
|
34
|
+
if (pkg.version) return pkg.version;
|
|
35
|
+
} catch {
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
} catch {
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
mapChatHistory,
|
|
45
|
+
readAgentVersion
|
|
46
|
+
};
|