@rallycry/conveyor-agent 10.7.2 → 10.7.4
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/{chunk-DDDLYATP.js → chunk-WJWMLZKR.js} +253 -77
- package/dist/chunk-WJWMLZKR.js.map +1 -0
- package/dist/cli.js +376 -130
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +11 -4
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/runtime/entrypoint.sh +9 -2
- package/dist/chunk-DDDLYATP.js.map +0 -1
|
@@ -1540,52 +1540,6 @@ async function backupOtherBranches(cwd, currentBranch) {
|
|
|
1540
1540
|
return count;
|
|
1541
1541
|
}
|
|
1542
1542
|
|
|
1543
|
-
// src/setup/git-ready.ts
|
|
1544
|
-
import { access, stat } from "fs/promises";
|
|
1545
|
-
var DEFAULT_FAILED_PATH = "/workspaces/.conveyor-git-failed";
|
|
1546
|
-
var DEFAULT_TIMEOUT_MS = 6e5;
|
|
1547
|
-
var DEFAULT_POLL_MS = 200;
|
|
1548
|
-
async function fileExists(path4) {
|
|
1549
|
-
try {
|
|
1550
|
-
await access(path4);
|
|
1551
|
-
const s = await stat(path4);
|
|
1552
|
-
return s.isFile();
|
|
1553
|
-
} catch {
|
|
1554
|
-
return false;
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
function awaitGitReady(opts = {}) {
|
|
1558
|
-
const markerPath = opts.markerPath ?? process.env.CONVEYOR_GIT_READY_MARKER;
|
|
1559
|
-
if (!markerPath) {
|
|
1560
|
-
return Promise.resolve("not-gated");
|
|
1561
|
-
}
|
|
1562
|
-
const failedPath = opts.failedPath ?? process.env.CONVEYOR_GIT_FAILED_MARKER ?? DEFAULT_FAILED_PATH;
|
|
1563
|
-
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
1564
|
-
const pollMs = opts.pollMs ?? DEFAULT_POLL_MS;
|
|
1565
|
-
opts.onLog?.(`waiting for workspace git (marker=${markerPath})`);
|
|
1566
|
-
return pollForMarkers(markerPath, failedPath, timeoutMs, pollMs, opts.onLog);
|
|
1567
|
-
}
|
|
1568
|
-
async function pollForMarkers(markerPath, failedPath, timeoutMs, pollMs, onLog) {
|
|
1569
|
-
const deadline = Date.now() + timeoutMs;
|
|
1570
|
-
for (; ; ) {
|
|
1571
|
-
if (await fileExists(markerPath)) {
|
|
1572
|
-
onLog?.("workspace git ready");
|
|
1573
|
-
return "ready";
|
|
1574
|
-
}
|
|
1575
|
-
if (await fileExists(failedPath)) {
|
|
1576
|
-
onLog?.("workspace git preparation failed (marker present)");
|
|
1577
|
-
return "failed";
|
|
1578
|
-
}
|
|
1579
|
-
if (Date.now() >= deadline) {
|
|
1580
|
-
onLog?.(`workspace git not ready after ${timeoutMs}ms \u2014 giving up`);
|
|
1581
|
-
return "timeout";
|
|
1582
|
-
}
|
|
1583
|
-
await new Promise((resolve) => {
|
|
1584
|
-
setTimeout(resolve, pollMs);
|
|
1585
|
-
});
|
|
1586
|
-
}
|
|
1587
|
-
}
|
|
1588
|
-
|
|
1589
1543
|
// src/runner/work-preservation/index.ts
|
|
1590
1544
|
import { rm as rm3 } from "fs/promises";
|
|
1591
1545
|
|
|
@@ -1599,7 +1553,7 @@ function selectRestoreSource(probe) {
|
|
|
1599
1553
|
// src/runner/work-preservation/snapshot-tar.ts
|
|
1600
1554
|
import { execFile as execFile2 } from "child_process";
|
|
1601
1555
|
import { createReadStream, createWriteStream } from "fs";
|
|
1602
|
-
import { mkdtemp, rm, stat
|
|
1556
|
+
import { mkdtemp, rm, stat, writeFile } from "fs/promises";
|
|
1603
1557
|
import { tmpdir } from "os";
|
|
1604
1558
|
import path from "path";
|
|
1605
1559
|
import { pipeline } from "stream/promises";
|
|
@@ -1691,7 +1645,7 @@ async function buildSnapshotTar(cwd) {
|
|
|
1691
1645
|
const tarPath = path.join(staging, "snapshot.tar.gz");
|
|
1692
1646
|
await pipeline(createReadStream(rawTarPath), createGzip(), createWriteStream(tarPath));
|
|
1693
1647
|
await rm(rawTarPath, { force: true });
|
|
1694
|
-
const { size } = await
|
|
1648
|
+
const { size } = await stat(tarPath);
|
|
1695
1649
|
return {
|
|
1696
1650
|
tarPath,
|
|
1697
1651
|
sizeBytes: size,
|
|
@@ -1937,6 +1891,7 @@ async function restoreOnBoot(bundle, cwd) {
|
|
|
1937
1891
|
import { z } from "zod";
|
|
1938
1892
|
import { z as z2 } from "zod";
|
|
1939
1893
|
var DEFAULT_SONNET_MODEL = "claude-sonnet-5";
|
|
1894
|
+
var FABLE_MODEL = "claude-fable-5";
|
|
1940
1895
|
var TUI_KINDS = ["claude-code", "opencode"];
|
|
1941
1896
|
var MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024;
|
|
1942
1897
|
var EMBED_THRESHOLD_IMAGES = 5 * 1024 * 1024;
|
|
@@ -2502,7 +2457,7 @@ var ListMyLiveSessionsRequestSchema = z2.object({
|
|
|
2502
2457
|
/** Admin-only: list another member's sessions instead of the caller's. */
|
|
2503
2458
|
targetUserId: z2.string().optional()
|
|
2504
2459
|
});
|
|
2505
|
-
var
|
|
2460
|
+
var ListProjectSessionGroupsRequestSchema = z2.object({
|
|
2506
2461
|
projectId: z2.string()
|
|
2507
2462
|
});
|
|
2508
2463
|
var GetProjectAvailableTuisRequestSchema = z2.object({
|
|
@@ -4239,7 +4194,50 @@ function seedWorkspaceTrust(config, trustCwd) {
|
|
|
4239
4194
|
config.projects = projects;
|
|
4240
4195
|
return true;
|
|
4241
4196
|
}
|
|
4242
|
-
|
|
4197
|
+
var FABLE_MODEL_OPTION = {
|
|
4198
|
+
value: `${FABLE_MODEL}[1m]`,
|
|
4199
|
+
label: "Fable",
|
|
4200
|
+
description: "Fable 5 - most capable for your hardest and longest-running tasks"
|
|
4201
|
+
};
|
|
4202
|
+
function seedFableModelOption(config) {
|
|
4203
|
+
const cache = Array.isArray(config.additionalModelOptionsCache) ? config.additionalModelOptionsCache : [];
|
|
4204
|
+
const hasFable = cache.some((entry) => {
|
|
4205
|
+
if (typeof entry !== "object" || entry === null) return false;
|
|
4206
|
+
const value = entry.value;
|
|
4207
|
+
return typeof value === "string" && value.toLowerCase().includes("fable");
|
|
4208
|
+
});
|
|
4209
|
+
if (hasFable) return false;
|
|
4210
|
+
config.additionalModelOptionsCache = [...cache, { ...FABLE_MODEL_OPTION }];
|
|
4211
|
+
return true;
|
|
4212
|
+
}
|
|
4213
|
+
function normalizeOauthIdentity(record) {
|
|
4214
|
+
const organizationUuid = typeof record.organizationUuid === "string" && record.organizationUuid !== "" ? record.organizationUuid : void 0;
|
|
4215
|
+
const accountUuid = typeof record.accountUuid === "string" && record.accountUuid !== "" ? record.accountUuid : void 0;
|
|
4216
|
+
if (!organizationUuid && !accountUuid) return null;
|
|
4217
|
+
return { organizationUuid, accountUuid };
|
|
4218
|
+
}
|
|
4219
|
+
function extractOauthIdentity(config) {
|
|
4220
|
+
return normalizeOauthIdentity(asRecord(config.oauthAccount));
|
|
4221
|
+
}
|
|
4222
|
+
function seedFableConsent(config, fallbackIdentity) {
|
|
4223
|
+
const identity = extractOauthIdentity(config) ?? fallbackIdentity;
|
|
4224
|
+
if (!identity) return false;
|
|
4225
|
+
const consent = asRecord(config.fableOverageConsentV2);
|
|
4226
|
+
let changed = false;
|
|
4227
|
+
const keys = [
|
|
4228
|
+
...identity.organizationUuid ? [identity.organizationUuid] : [],
|
|
4229
|
+
...identity.accountUuid ? [`acct:${identity.accountUuid}`] : []
|
|
4230
|
+
];
|
|
4231
|
+
for (const key of keys) {
|
|
4232
|
+
if (consent[key] !== true) {
|
|
4233
|
+
consent[key] = true;
|
|
4234
|
+
changed = true;
|
|
4235
|
+
}
|
|
4236
|
+
}
|
|
4237
|
+
if (changed) config.fableOverageConsentV2 = consent;
|
|
4238
|
+
return changed;
|
|
4239
|
+
}
|
|
4240
|
+
function planClaudeJsonSeed(existingRaw, trustCwd, oauthIdentity) {
|
|
4243
4241
|
const config = parseClaudeJson(existingRaw);
|
|
4244
4242
|
const isFresh = Object.keys(config).length === 0;
|
|
4245
4243
|
let changed = false;
|
|
@@ -4258,13 +4256,56 @@ function planClaudeJsonSeed(existingRaw, trustCwd) {
|
|
|
4258
4256
|
if (trustCwd && seedWorkspaceTrust(config, trustCwd)) {
|
|
4259
4257
|
changed = true;
|
|
4260
4258
|
}
|
|
4259
|
+
if (seedFableModelOption(config)) {
|
|
4260
|
+
changed = true;
|
|
4261
|
+
}
|
|
4262
|
+
if (seedFableConsent(config, oauthIdentity ?? null)) {
|
|
4263
|
+
changed = true;
|
|
4264
|
+
}
|
|
4261
4265
|
return changed ? JSON.stringify(config) : null;
|
|
4262
4266
|
}
|
|
4267
|
+
function conveyorOauthMarkerPath() {
|
|
4268
|
+
return join3(claudeConfigHome(), "conveyor-oauth-account.json");
|
|
4269
|
+
}
|
|
4270
|
+
function parseOauthIdentity(raw) {
|
|
4271
|
+
if (!raw || raw.trim() === "") return null;
|
|
4272
|
+
try {
|
|
4273
|
+
return normalizeOauthIdentity(asRecord(JSON.parse(raw)));
|
|
4274
|
+
} catch {
|
|
4275
|
+
return null;
|
|
4276
|
+
}
|
|
4277
|
+
}
|
|
4278
|
+
async function persistOauthIdentityMarker(configIdentity, markerIdentity) {
|
|
4279
|
+
try {
|
|
4280
|
+
if (!configIdentity) return;
|
|
4281
|
+
if (markerIdentity !== null && markerIdentity.organizationUuid === configIdentity.organizationUuid && markerIdentity.accountUuid === configIdentity.accountUuid) {
|
|
4282
|
+
return;
|
|
4283
|
+
}
|
|
4284
|
+
await mkdir2(claudeConfigHome(), { recursive: true });
|
|
4285
|
+
const verified = await writeWithReadBackRetry(
|
|
4286
|
+
fsWriteIo(conveyorOauthMarkerPath()),
|
|
4287
|
+
JSON.stringify(configIdentity)
|
|
4288
|
+
);
|
|
4289
|
+
if (verified) {
|
|
4290
|
+
process.stderr.write("[conveyor-agent] persisted oauth identity marker for fable consent\n");
|
|
4291
|
+
}
|
|
4292
|
+
} catch (err) {
|
|
4293
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4294
|
+
process.stderr.write(`[conveyor-agent] oauth identity marker write failed: ${message}
|
|
4295
|
+
`);
|
|
4296
|
+
}
|
|
4297
|
+
}
|
|
4263
4298
|
async function ensureClaudeOnboarding(env = process.env, trustCwd) {
|
|
4264
4299
|
try {
|
|
4265
4300
|
if (!isConveyorCloudEnv(env)) return;
|
|
4266
4301
|
const path4 = claudeJsonPath();
|
|
4267
|
-
const
|
|
4302
|
+
const existingRaw = await readRaw(path4);
|
|
4303
|
+
const markerIdentity = parseOauthIdentity(await readRaw(conveyorOauthMarkerPath()));
|
|
4304
|
+
await persistOauthIdentityMarker(
|
|
4305
|
+
extractOauthIdentity(parseClaudeJson(existingRaw)),
|
|
4306
|
+
markerIdentity
|
|
4307
|
+
);
|
|
4308
|
+
const contents = planClaudeJsonSeed(existingRaw, trustCwd, markerIdentity);
|
|
4268
4309
|
if (contents === null) return;
|
|
4269
4310
|
const verified = await writeWithReadBackRetry(fsWriteIo(path4), contents);
|
|
4270
4311
|
if (verified) {
|
|
@@ -4302,7 +4343,7 @@ async function removeConveyorCredentials(env = process.env) {
|
|
|
4302
4343
|
}
|
|
4303
4344
|
|
|
4304
4345
|
// src/harness/pty/pty-support.ts
|
|
4305
|
-
import { stat as
|
|
4346
|
+
import { stat as stat2 } from "fs/promises";
|
|
4306
4347
|
var MAX_DIAGNOSTIC_OUTPUT = 4e3;
|
|
4307
4348
|
var MAX_BETWEEN_TURN_BUFFER = 500;
|
|
4308
4349
|
var SUBMIT_SETTLE_MS = 300;
|
|
@@ -4401,7 +4442,7 @@ function sleep3(ms) {
|
|
|
4401
4442
|
}
|
|
4402
4443
|
async function transcriptSize(path4) {
|
|
4403
4444
|
try {
|
|
4404
|
-
return (await
|
|
4445
|
+
return (await stat2(path4)).size;
|
|
4405
4446
|
} catch {
|
|
4406
4447
|
return 0;
|
|
4407
4448
|
}
|
|
@@ -5519,7 +5560,7 @@ function formatIncidents(incidents) {
|
|
|
5519
5560
|
}
|
|
5520
5561
|
|
|
5521
5562
|
// src/execution/tag-context-resolver.ts
|
|
5522
|
-
import { readFile as readFile2, readdir, stat as
|
|
5563
|
+
import { readFile as readFile2, readdir, stat as stat3 } from "fs/promises";
|
|
5523
5564
|
var TYPE_PRIORITY = { rule: 0, file: 1, folder: 2, doc: 3 };
|
|
5524
5565
|
var SUMMARY_SCAN_CHARS = 4e3;
|
|
5525
5566
|
var SUMMARY_MAX_CHARS = 160;
|
|
@@ -5593,7 +5634,7 @@ async function readFileSummary(filePath) {
|
|
|
5593
5634
|
if (isBinaryPath(filePath)) return null;
|
|
5594
5635
|
let mtimeMs;
|
|
5595
5636
|
try {
|
|
5596
|
-
const st = await
|
|
5637
|
+
const st = await stat3(filePath);
|
|
5597
5638
|
mtimeMs = st.mtimeMs;
|
|
5598
5639
|
} catch {
|
|
5599
5640
|
return null;
|
|
@@ -5615,7 +5656,7 @@ async function readFolderListing(folderPath) {
|
|
|
5615
5656
|
try {
|
|
5616
5657
|
let mtimeMs;
|
|
5617
5658
|
try {
|
|
5618
|
-
const st = await
|
|
5659
|
+
const st = await stat3(folderPath);
|
|
5619
5660
|
mtimeMs = st.mtimeMs;
|
|
5620
5661
|
} catch {
|
|
5621
5662
|
return null;
|
|
@@ -7219,7 +7260,7 @@ function buildMutationTools(connection, config) {
|
|
|
7219
7260
|
}
|
|
7220
7261
|
|
|
7221
7262
|
// src/tools/attachment-tools.ts
|
|
7222
|
-
import { readFile as readFile3, stat as
|
|
7263
|
+
import { readFile as readFile3, stat as stat4 } from "fs/promises";
|
|
7223
7264
|
import { basename, extname, isAbsolute, join as join5 } from "path";
|
|
7224
7265
|
import { z as z7 } from "zod";
|
|
7225
7266
|
var IMAGE_MIME_BY_EXT = {
|
|
@@ -7246,7 +7287,7 @@ function buildUploadAttachmentTool(connection, config) {
|
|
|
7246
7287
|
`Unsupported file type "${extname(filePath) || "(none)"}". Supported: ${Object.keys(IMAGE_MIME_BY_EXT).join(", ")}`
|
|
7247
7288
|
);
|
|
7248
7289
|
}
|
|
7249
|
-
const info = await
|
|
7290
|
+
const info = await stat4(filePath).catch(() => null);
|
|
7250
7291
|
if (!info?.isFile()) {
|
|
7251
7292
|
return textResult(`File not found: ${filePath}`);
|
|
7252
7293
|
}
|
|
@@ -9647,6 +9688,76 @@ async function sampleKeyUsage(token, probe = runUsageProbe) {
|
|
|
9647
9688
|
}
|
|
9648
9689
|
}
|
|
9649
9690
|
|
|
9691
|
+
// src/setup/git-ready.ts
|
|
9692
|
+
import { access, stat as stat5 } from "fs/promises";
|
|
9693
|
+
var DEFAULT_FAILED_PATH = "/workspaces/.conveyor-git-failed";
|
|
9694
|
+
var DEFAULT_TIMEOUT_MS = 6e5;
|
|
9695
|
+
var DEFAULT_POLL_MS = 200;
|
|
9696
|
+
async function fileExists(path4) {
|
|
9697
|
+
try {
|
|
9698
|
+
await access(path4);
|
|
9699
|
+
const s = await stat5(path4);
|
|
9700
|
+
return s.isFile();
|
|
9701
|
+
} catch {
|
|
9702
|
+
return false;
|
|
9703
|
+
}
|
|
9704
|
+
}
|
|
9705
|
+
function awaitGitReady(opts = {}) {
|
|
9706
|
+
if (opts.signal?.aborted) return Promise.reject(abortError());
|
|
9707
|
+
const markerPath = opts.markerPath ?? process.env.CONVEYOR_GIT_READY_MARKER;
|
|
9708
|
+
if (!markerPath) {
|
|
9709
|
+
return Promise.resolve("not-gated");
|
|
9710
|
+
}
|
|
9711
|
+
const failedPath = opts.failedPath ?? process.env.CONVEYOR_GIT_FAILED_MARKER ?? DEFAULT_FAILED_PATH;
|
|
9712
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
9713
|
+
const pollMs = opts.pollMs ?? DEFAULT_POLL_MS;
|
|
9714
|
+
opts.onLog?.(`waiting for workspace git (marker=${markerPath})`);
|
|
9715
|
+
return pollForMarkers(markerPath, failedPath, timeoutMs, pollMs, opts.onLog, opts.signal);
|
|
9716
|
+
}
|
|
9717
|
+
function abortError() {
|
|
9718
|
+
const error = new Error("Operation aborted");
|
|
9719
|
+
error.name = "AbortError";
|
|
9720
|
+
return error;
|
|
9721
|
+
}
|
|
9722
|
+
function abortableDelay(ms, signal) {
|
|
9723
|
+
if (!signal) {
|
|
9724
|
+
return new Promise((resolve) => {
|
|
9725
|
+
setTimeout(resolve, ms);
|
|
9726
|
+
});
|
|
9727
|
+
}
|
|
9728
|
+
if (signal.aborted) return Promise.reject(abortError());
|
|
9729
|
+
return new Promise((resolve, reject) => {
|
|
9730
|
+
const timer = setTimeout(() => {
|
|
9731
|
+
signal.removeEventListener("abort", onAbort);
|
|
9732
|
+
resolve();
|
|
9733
|
+
}, ms);
|
|
9734
|
+
const onAbort = () => {
|
|
9735
|
+
clearTimeout(timer);
|
|
9736
|
+
reject(abortError());
|
|
9737
|
+
};
|
|
9738
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
9739
|
+
});
|
|
9740
|
+
}
|
|
9741
|
+
async function pollForMarkers(markerPath, failedPath, timeoutMs, pollMs, onLog, signal) {
|
|
9742
|
+
const deadline = Date.now() + timeoutMs;
|
|
9743
|
+
for (; ; ) {
|
|
9744
|
+
if (signal?.aborted) throw abortError();
|
|
9745
|
+
if (await fileExists(markerPath)) {
|
|
9746
|
+
onLog?.("workspace git ready");
|
|
9747
|
+
return "ready";
|
|
9748
|
+
}
|
|
9749
|
+
if (await fileExists(failedPath)) {
|
|
9750
|
+
onLog?.("workspace git preparation failed (marker present)");
|
|
9751
|
+
return "failed";
|
|
9752
|
+
}
|
|
9753
|
+
if (Date.now() >= deadline) {
|
|
9754
|
+
onLog?.(`workspace git not ready after ${timeoutMs}ms \u2014 giving up`);
|
|
9755
|
+
return "timeout";
|
|
9756
|
+
}
|
|
9757
|
+
await abortableDelay(pollMs, signal);
|
|
9758
|
+
}
|
|
9759
|
+
}
|
|
9760
|
+
|
|
9650
9761
|
// src/runner/port-discovery.ts
|
|
9651
9762
|
import { readFile as readFile4 } from "fs/promises";
|
|
9652
9763
|
import { execFile as execFile3 } from "child_process";
|
|
@@ -9760,6 +9871,7 @@ var PortDiscovery = class {
|
|
|
9760
9871
|
timer = null;
|
|
9761
9872
|
ticking = false;
|
|
9762
9873
|
disabled = false;
|
|
9874
|
+
stopped = false;
|
|
9763
9875
|
/** Set when the confirmed set changed (or a report failed) — cleared only
|
|
9764
9876
|
* after a successful report, so transient RPC failures retry next tick. */
|
|
9765
9877
|
reportPending = false;
|
|
@@ -9777,8 +9889,9 @@ var PortDiscovery = class {
|
|
|
9777
9889
|
}
|
|
9778
9890
|
/** Take the baseline scan and start polling. Safe to call once. */
|
|
9779
9891
|
async start() {
|
|
9780
|
-
if (this.timer || this.disabled) return;
|
|
9892
|
+
if (this.timer || this.disabled || this.stopped) return;
|
|
9781
9893
|
const baseline = await this.scanSafe();
|
|
9894
|
+
if (this.stopped) return;
|
|
9782
9895
|
if (baseline === null) {
|
|
9783
9896
|
this.disabled = true;
|
|
9784
9897
|
this.log("Port discovery disabled: no listening-socket source available");
|
|
@@ -9789,6 +9902,7 @@ var PortDiscovery = class {
|
|
|
9789
9902
|
this.timer.unref?.();
|
|
9790
9903
|
}
|
|
9791
9904
|
stop() {
|
|
9905
|
+
this.stopped = true;
|
|
9792
9906
|
if (this.timer) {
|
|
9793
9907
|
clearInterval(this.timer);
|
|
9794
9908
|
this.timer = null;
|
|
@@ -9984,13 +10098,16 @@ var SessionRunner = class _SessionRunner {
|
|
|
9984
10098
|
/** Max consecutive gate-deferred ticks (~2 min each) before flushing anyway. */
|
|
9985
10099
|
static MAX_GATE_SKIPS = 10;
|
|
9986
10100
|
/** Runtime preview-port poller (v3 dynamic port discovery). */
|
|
9987
|
-
portDiscovery
|
|
10101
|
+
portDiscovery;
|
|
9988
10102
|
/** Main event-loop lag measurement, shared with the heartbeat worker. */
|
|
9989
10103
|
loopLag = new LoopLagMonitor();
|
|
9990
|
-
constructor(config, callbacks) {
|
|
10104
|
+
constructor(config, callbacks, deps = {}) {
|
|
9991
10105
|
this.config = config;
|
|
9992
10106
|
this.callbacks = callbacks;
|
|
9993
10107
|
this.connection = new AgentConnection(config.connection);
|
|
10108
|
+
this.portDiscovery = deps.portDiscovery ?? new PortDiscovery({
|
|
10109
|
+
report: (ports) => this.connection.reportDiscoveredPorts(ports)
|
|
10110
|
+
});
|
|
9994
10111
|
const initialMode = config.agentMode ?? (config.runnerMode === "pm" ? config.isAuto ? "auto" : "discovery" : "building");
|
|
9995
10112
|
this.mode = new ModeController(initialMode, config.runnerMode, config.isAuto);
|
|
9996
10113
|
const lifecycleConfig = { ...DEFAULT_LIFECYCLE_CONFIG, ...config.lifecycle };
|
|
@@ -10055,16 +10172,18 @@ var SessionRunner = class _SessionRunner {
|
|
|
10055
10172
|
this.pendingMessages.push({ content: msg.content, userId: msg.userId });
|
|
10056
10173
|
}
|
|
10057
10174
|
}
|
|
10058
|
-
this.
|
|
10059
|
-
|
|
10060
|
-
|
|
10061
|
-
|
|
10062
|
-
}
|
|
10175
|
+
if (this.stopped) return false;
|
|
10176
|
+
try {
|
|
10177
|
+
await this.portDiscovery.start();
|
|
10178
|
+
} catch {
|
|
10179
|
+
}
|
|
10180
|
+
if (this.stopped) return false;
|
|
10063
10181
|
const agentVersion = readAgentVersion();
|
|
10064
10182
|
if (agentVersion) {
|
|
10065
10183
|
this.connection.call("notifyAgentVersion", { sessionId: this.sessionId, agentVersion }).catch(() => {
|
|
10066
10184
|
});
|
|
10067
10185
|
}
|
|
10186
|
+
return true;
|
|
10068
10187
|
}
|
|
10069
10188
|
/**
|
|
10070
10189
|
* Run the main agent lifecycle: fetch context, resolve mode, execute, loop.
|
|
@@ -10180,7 +10299,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
10180
10299
|
}
|
|
10181
10300
|
/** Convenience wrapper: connect() then run(). */
|
|
10182
10301
|
async start() {
|
|
10183
|
-
await this.connect();
|
|
10302
|
+
if (!await this.connect()) return;
|
|
10184
10303
|
await this.run();
|
|
10185
10304
|
}
|
|
10186
10305
|
// ── Core loop ──────────────────────────────────────────────────────
|
|
@@ -10574,7 +10693,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
10574
10693
|
this.queryBridge?.stop();
|
|
10575
10694
|
void this.queryBridge?.dispose().catch(() => {
|
|
10576
10695
|
});
|
|
10577
|
-
this.portDiscovery
|
|
10696
|
+
this.portDiscovery.stop();
|
|
10578
10697
|
this.loopLag.stop();
|
|
10579
10698
|
this.lifecycle.destroy();
|
|
10580
10699
|
this.connection.disconnect();
|
|
@@ -10786,7 +10905,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
10786
10905
|
process.stderr.write(`[conveyor-agent] Shutdown: reason=${finalState}
|
|
10787
10906
|
`);
|
|
10788
10907
|
this.connection.sendEvent({ type: "shutdown", reason: finalState });
|
|
10789
|
-
this.portDiscovery
|
|
10908
|
+
this.portDiscovery.stop();
|
|
10790
10909
|
this.loopLag.stop();
|
|
10791
10910
|
this.lifecycle.destroy();
|
|
10792
10911
|
try {
|
|
@@ -10885,28 +11004,83 @@ function loadConveyorConfig() {
|
|
|
10885
11004
|
|
|
10886
11005
|
// src/setup/commands.ts
|
|
10887
11006
|
import { spawn as spawn2, execSync } from "child_process";
|
|
10888
|
-
|
|
11007
|
+
var PROCESS_TERMINATION_GRACE_MS = 5e3;
|
|
11008
|
+
function abortError2() {
|
|
11009
|
+
const error = new Error("Operation aborted");
|
|
11010
|
+
error.name = "AbortError";
|
|
11011
|
+
return error;
|
|
11012
|
+
}
|
|
11013
|
+
function signalProcessGroup(child, signal) {
|
|
11014
|
+
try {
|
|
11015
|
+
if (child.pid) process.kill(-child.pid, signal);
|
|
11016
|
+
else child.kill(signal);
|
|
11017
|
+
} catch {
|
|
11018
|
+
try {
|
|
11019
|
+
child.kill(signal);
|
|
11020
|
+
} catch {
|
|
11021
|
+
}
|
|
11022
|
+
}
|
|
11023
|
+
}
|
|
11024
|
+
function terminateProcessGroup(child, graceMs = PROCESS_TERMINATION_GRACE_MS) {
|
|
11025
|
+
if (child.exitCode !== null) return Promise.resolve();
|
|
11026
|
+
return new Promise((resolve) => {
|
|
11027
|
+
let settled = false;
|
|
11028
|
+
const finish = () => {
|
|
11029
|
+
if (settled) return;
|
|
11030
|
+
settled = true;
|
|
11031
|
+
clearTimeout(timer);
|
|
11032
|
+
child.removeListener("exit", finish);
|
|
11033
|
+
resolve();
|
|
11034
|
+
};
|
|
11035
|
+
const timer = setTimeout(() => {
|
|
11036
|
+
signalProcessGroup(child, "SIGKILL");
|
|
11037
|
+
finish();
|
|
11038
|
+
}, graceMs);
|
|
11039
|
+
timer.unref();
|
|
11040
|
+
child.once("exit", finish);
|
|
11041
|
+
signalProcessGroup(child, "SIGTERM");
|
|
11042
|
+
});
|
|
11043
|
+
}
|
|
11044
|
+
function runSetupCommand(cmd, cwd, onOutput, signal) {
|
|
11045
|
+
if (signal?.aborted) return Promise.reject(abortError2());
|
|
10889
11046
|
return new Promise((resolve, reject) => {
|
|
10890
11047
|
const child = spawn2("sh", ["-c", cmd], {
|
|
10891
11048
|
cwd,
|
|
10892
11049
|
stdio: ["ignore", "pipe", "pipe"],
|
|
11050
|
+
detached: true,
|
|
10893
11051
|
env: { ...process.env }
|
|
10894
11052
|
});
|
|
11053
|
+
let settled = false;
|
|
11054
|
+
let aborting = false;
|
|
11055
|
+
const cleanup = () => signal?.removeEventListener("abort", onAbort);
|
|
11056
|
+
const settle = (error) => {
|
|
11057
|
+
if (settled) return;
|
|
11058
|
+
settled = true;
|
|
11059
|
+
cleanup();
|
|
11060
|
+
if (error) reject(error);
|
|
11061
|
+
else resolve();
|
|
11062
|
+
};
|
|
11063
|
+
const onAbort = () => {
|
|
11064
|
+
if (settled || aborting) return;
|
|
11065
|
+
aborting = true;
|
|
11066
|
+
void terminateProcessGroup(child).then(() => settle(abortError2()));
|
|
11067
|
+
};
|
|
11068
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
11069
|
+
if (signal?.aborted) onAbort();
|
|
10895
11070
|
child.stdout.on("data", (chunk) => {
|
|
11071
|
+
if (aborting || signal?.aborted) return;
|
|
10896
11072
|
onOutput("stdout", chunk.toString());
|
|
10897
11073
|
});
|
|
10898
11074
|
child.stderr.on("data", (chunk) => {
|
|
11075
|
+
if (aborting || signal?.aborted) return;
|
|
10899
11076
|
onOutput("stderr", chunk.toString());
|
|
10900
11077
|
});
|
|
10901
11078
|
child.on("close", (code) => {
|
|
10902
|
-
if (
|
|
10903
|
-
|
|
10904
|
-
} else {
|
|
10905
|
-
reject(new Error(`Setup command exited with code ${code}`));
|
|
10906
|
-
}
|
|
11079
|
+
if (aborting) return;
|
|
11080
|
+
settle(code === 0 ? void 0 : new Error(`Setup command exited with code ${code}`));
|
|
10907
11081
|
});
|
|
10908
11082
|
child.on("error", (err) => {
|
|
10909
|
-
|
|
11083
|
+
if (!aborting) settle(err);
|
|
10910
11084
|
});
|
|
10911
11085
|
});
|
|
10912
11086
|
}
|
|
@@ -10983,6 +11157,7 @@ export {
|
|
|
10983
11157
|
resolveSessionStart,
|
|
10984
11158
|
sampleKeyUsage,
|
|
10985
11159
|
awaitGitReady,
|
|
11160
|
+
PortDiscovery,
|
|
10986
11161
|
uploadSnapshotToGcs,
|
|
10987
11162
|
captureSnapshot,
|
|
10988
11163
|
startPeriodic,
|
|
@@ -10993,9 +11168,10 @@ export {
|
|
|
10993
11168
|
loadForwardPorts,
|
|
10994
11169
|
buildSessionPreviewPorts,
|
|
10995
11170
|
loadConveyorConfig,
|
|
11171
|
+
terminateProcessGroup,
|
|
10996
11172
|
runSetupCommand,
|
|
10997
11173
|
runAuthTokenCommand,
|
|
10998
11174
|
runStartCommand,
|
|
10999
11175
|
unshallowRepo
|
|
11000
11176
|
};
|
|
11001
|
-
//# sourceMappingURL=chunk-
|
|
11177
|
+
//# sourceMappingURL=chunk-WJWMLZKR.js.map
|