@rallycry/conveyor-agent 8.2.0 → 8.3.1
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-W4NCD23G.js → chunk-H3UHIWQF.js} +303 -67
- package/dist/chunk-H3UHIWQF.js.map +1 -0
- package/dist/{chunk-KTNGU2WU.js → chunk-Y7ZVMFJN.js} +108 -3
- package/dist/chunk-Y7ZVMFJN.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -2
- package/dist/{tag-audit-handler-E6BZGVIG.js → tag-audit-handler-FVGEBGSB.js} +2 -2
- package/dist/{task-audit-handler-MXSNTY22.js → task-audit-handler-JNS4NH5O.js} +2 -2
- package/package.json +2 -2
- package/dist/chunk-KTNGU2WU.js.map +0 -1
- package/dist/chunk-W4NCD23G.js.map +0 -1
- /package/dist/{tag-audit-handler-E6BZGVIG.js.map → tag-audit-handler-FVGEBGSB.js.map} +0 -0
- /package/dist/{task-audit-handler-MXSNTY22.js.map → task-audit-handler-JNS4NH5O.js.map} +0 -0
|
@@ -7,8 +7,11 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
createHarness,
|
|
9
9
|
createServiceLogger,
|
|
10
|
-
defineTool
|
|
11
|
-
|
|
10
|
+
defineTool,
|
|
11
|
+
ensureClaudeCredentials,
|
|
12
|
+
removeConveyorCredentials,
|
|
13
|
+
sessionTranscriptPath
|
|
14
|
+
} from "./chunk-Y7ZVMFJN.js";
|
|
12
15
|
|
|
13
16
|
// src/setup/bootstrap.ts
|
|
14
17
|
var BOOTSTRAP_TIMEOUT_MS = 3e4;
|
|
@@ -1154,28 +1157,118 @@ function updateRemoteToken(cwd, token) {
|
|
|
1154
1157
|
} catch {
|
|
1155
1158
|
}
|
|
1156
1159
|
}
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1160
|
+
function wipRefForBranch(branch) {
|
|
1161
|
+
return `conveyor-wip/${branch}`;
|
|
1162
|
+
}
|
|
1163
|
+
var wipRefPushed = /* @__PURE__ */ new Set();
|
|
1164
|
+
function createWipSnapshot(cwd, message) {
|
|
1165
|
+
try {
|
|
1166
|
+
execSync("git add -A", { cwd, stdio: ["ignore", "pipe", "ignore"] });
|
|
1167
|
+
const sha = execSync(`git stash create ${JSON.stringify(message)}`, {
|
|
1168
|
+
cwd,
|
|
1169
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
1170
|
+
}).toString().trim();
|
|
1171
|
+
return sha || null;
|
|
1172
|
+
} catch {
|
|
1173
|
+
return null;
|
|
1174
|
+
} finally {
|
|
1175
|
+
try {
|
|
1176
|
+
execSync("git reset -q", { cwd, stdio: ["ignore", "pipe", "ignore"] });
|
|
1177
|
+
} catch {
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
function tryPushRefspec(cwd, refspec, force = false) {
|
|
1182
|
+
try {
|
|
1183
|
+
execSync(`git push ${force ? "--force " : ""}origin ${JSON.stringify(refspec)}`, {
|
|
1184
|
+
cwd,
|
|
1185
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1186
|
+
timeout: 3e4
|
|
1187
|
+
});
|
|
1188
|
+
return true;
|
|
1189
|
+
} catch {
|
|
1190
|
+
return false;
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
async function refreshRemoteToken(cwd, refreshToken) {
|
|
1194
|
+
if (!refreshToken) return;
|
|
1161
1195
|
try {
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1196
|
+
const token = await refreshToken();
|
|
1197
|
+
if (token) {
|
|
1198
|
+
updateRemoteToken(cwd, token);
|
|
1199
|
+
process.env.GITHUB_TOKEN = token;
|
|
1200
|
+
process.env.GH_TOKEN = token;
|
|
1167
1201
|
}
|
|
1168
1202
|
} catch {
|
|
1169
1203
|
}
|
|
1204
|
+
}
|
|
1205
|
+
function restoreWipSnapshot(cwd, branch) {
|
|
1206
|
+
if (!branch) return "none";
|
|
1207
|
+
const ref = wipRefForBranch(branch);
|
|
1170
1208
|
try {
|
|
1171
|
-
|
|
1172
|
-
|
|
1209
|
+
execSync(`git fetch origin +refs/heads/${ref}:refs/remotes/origin/${ref}`, {
|
|
1210
|
+
cwd,
|
|
1211
|
+
stdio: "ignore",
|
|
1212
|
+
timeout: 6e4
|
|
1213
|
+
});
|
|
1214
|
+
} catch {
|
|
1215
|
+
return "none";
|
|
1216
|
+
}
|
|
1217
|
+
wipRefPushed.add(cwd);
|
|
1218
|
+
try {
|
|
1219
|
+
const sha = execSync(`git rev-parse refs/remotes/origin/${ref}`, {
|
|
1220
|
+
cwd,
|
|
1221
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
1222
|
+
}).toString().trim();
|
|
1223
|
+
const parent = execSync(`git rev-parse "${sha}^"`, {
|
|
1224
|
+
cwd,
|
|
1225
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
1226
|
+
}).toString().trim();
|
|
1227
|
+
const head = execSync("git rev-parse HEAD", { cwd, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
1228
|
+
if (parent !== head) return "stale";
|
|
1229
|
+
execSync(`git stash apply ${sha}`, { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
1230
|
+
return "applied";
|
|
1231
|
+
} catch {
|
|
1232
|
+
return "failed";
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
async function flushPendingChanges(cwd, opts) {
|
|
1236
|
+
let committed = false;
|
|
1237
|
+
let pushed = false;
|
|
1238
|
+
let hadWork = false;
|
|
1239
|
+
try {
|
|
1240
|
+
const branch = getCurrentBranch(cwd);
|
|
1241
|
+
if (!branch) return { committed, pushed, hadWork };
|
|
1242
|
+
const dirty = hasUncommittedChanges(cwd);
|
|
1243
|
+
const unpushed = hasUnpushedCommits(cwd);
|
|
1244
|
+
if (!dirty && !unpushed) {
|
|
1245
|
+
await dropStaleWipRef(cwd, branch, opts?.refreshToken);
|
|
1246
|
+
return { committed, pushed, hadWork };
|
|
1247
|
+
}
|
|
1248
|
+
hadWork = true;
|
|
1249
|
+
await refreshRemoteToken(cwd, opts?.refreshToken);
|
|
1250
|
+
if (unpushed) {
|
|
1173
1251
|
pushed = await pushToOrigin(cwd, opts?.refreshToken);
|
|
1174
1252
|
}
|
|
1253
|
+
if (dirty) {
|
|
1254
|
+
const message = opts?.wipMessage ?? "WIP: conveyor-agent snapshot";
|
|
1255
|
+
const sha = createWipSnapshot(cwd, message);
|
|
1256
|
+
if (sha) {
|
|
1257
|
+
committed = tryPushRefspec(cwd, `${sha}:refs/heads/${wipRefForBranch(branch)}`, true);
|
|
1258
|
+
if (committed) wipRefPushed.add(cwd);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1175
1261
|
} catch {
|
|
1176
1262
|
}
|
|
1177
1263
|
return { committed, pushed, hadWork };
|
|
1178
1264
|
}
|
|
1265
|
+
async function dropStaleWipRef(cwd, branch, refreshToken) {
|
|
1266
|
+
if (!wipRefPushed.has(cwd)) return;
|
|
1267
|
+
await refreshRemoteToken(cwd, refreshToken);
|
|
1268
|
+
if (tryPushRefspec(cwd, `:refs/heads/${wipRefForBranch(branch)}`)) {
|
|
1269
|
+
wipRefPushed.delete(cwd);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1179
1272
|
async function pushToOrigin(cwd, refreshToken) {
|
|
1180
1273
|
try {
|
|
1181
1274
|
const currentBranch = getCurrentBranch(cwd);
|
|
@@ -1302,9 +1395,7 @@ var PlanSync = class {
|
|
|
1302
1395
|
|
|
1303
1396
|
// src/execution/query-executor.ts
|
|
1304
1397
|
import { createHash } from "crypto";
|
|
1305
|
-
import { existsSync } from "fs";
|
|
1306
|
-
import { homedir } from "os";
|
|
1307
|
-
import { join as join3 } from "path";
|
|
1398
|
+
import { existsSync, readFileSync as readFileSync2, truncateSync } from "fs";
|
|
1308
1399
|
|
|
1309
1400
|
// ../shared/dist/index.js
|
|
1310
1401
|
import { z } from "zod";
|
|
@@ -1313,6 +1404,7 @@ import { z as z3 } from "zod";
|
|
|
1313
1404
|
var MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024;
|
|
1314
1405
|
var EMBED_THRESHOLD_IMAGES = 5 * 1024 * 1024;
|
|
1315
1406
|
var EMBED_THRESHOLD_TEXT = 2 * 1024 * 1024;
|
|
1407
|
+
var IDLE_HEARTBEAT_MS = 90 * 1e3;
|
|
1316
1408
|
var AgentHeartbeatSchema = z.object({
|
|
1317
1409
|
sessionId: z.string().optional(),
|
|
1318
1410
|
timestamp: z.string(),
|
|
@@ -6389,19 +6481,63 @@ function buildHooks(host) {
|
|
|
6389
6481
|
]
|
|
6390
6482
|
};
|
|
6391
6483
|
}
|
|
6392
|
-
function taskIdToSessionUuid(
|
|
6393
|
-
const hash = createHash("sha256").update(
|
|
6484
|
+
function taskIdToSessionUuid(lineageKey) {
|
|
6485
|
+
const hash = createHash("sha256").update(lineageKey).digest("hex");
|
|
6394
6486
|
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-8${hash.slice(13, 16)}-a${hash.slice(17, 20)}-${hash.slice(20, 32)}`;
|
|
6395
6487
|
}
|
|
6488
|
+
function sessionLineageKey(taskId, agentMode, runnerMode) {
|
|
6489
|
+
return agentMode === "review" || runnerMode === "code-review" ? `${taskId}:review` : taskId;
|
|
6490
|
+
}
|
|
6396
6491
|
function sessionFileExists(sessionUuid, cwd) {
|
|
6397
6492
|
try {
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
return
|
|
6493
|
+
return existsSync(sessionTranscriptPath(cwd, sessionUuid));
|
|
6494
|
+
} catch {
|
|
6495
|
+
return false;
|
|
6496
|
+
}
|
|
6497
|
+
}
|
|
6498
|
+
function hasExistingSessionFile(taskId, cwd, lineage) {
|
|
6499
|
+
const key = sessionLineageKey(taskId, lineage.agentMode, lineage.runnerMode);
|
|
6500
|
+
return sessionFileExists(taskIdToSessionUuid(key), cwd);
|
|
6501
|
+
}
|
|
6502
|
+
function repairTornSessionFile(path2) {
|
|
6503
|
+
try {
|
|
6504
|
+
if (!existsSync(path2)) return false;
|
|
6505
|
+
const content = readFileSync2(path2, "utf8");
|
|
6506
|
+
if (content.length === 0) return false;
|
|
6507
|
+
let keepEnd = content.length;
|
|
6508
|
+
if (!content.endsWith("\n")) {
|
|
6509
|
+
keepEnd = content.lastIndexOf("\n") + 1;
|
|
6510
|
+
}
|
|
6511
|
+
while (keepEnd > 0) {
|
|
6512
|
+
const prevNewline = content.lastIndexOf("\n", keepEnd - 2);
|
|
6513
|
+
const line = content.slice(prevNewline + 1, keepEnd - 1).trim();
|
|
6514
|
+
if (line.length > 0) {
|
|
6515
|
+
try {
|
|
6516
|
+
JSON.parse(line);
|
|
6517
|
+
break;
|
|
6518
|
+
} catch {
|
|
6519
|
+
}
|
|
6520
|
+
}
|
|
6521
|
+
keepEnd = prevNewline + 1;
|
|
6522
|
+
}
|
|
6523
|
+
if (keepEnd === content.length) return false;
|
|
6524
|
+
truncateSync(path2, Buffer.byteLength(content.slice(0, keepEnd), "utf8"));
|
|
6525
|
+
logger2.warn("Repaired torn transcript before resume", {
|
|
6526
|
+
path: path2,
|
|
6527
|
+
trimmedBytes: content.length - keepEnd
|
|
6528
|
+
});
|
|
6529
|
+
return true;
|
|
6401
6530
|
} catch {
|
|
6402
6531
|
return false;
|
|
6403
6532
|
}
|
|
6404
6533
|
}
|
|
6534
|
+
function resolvePromptDelivery(inputs) {
|
|
6535
|
+
if (inputs.harnessKind !== "pty") return "submit";
|
|
6536
|
+
if ((inputs.runnerMode ?? "task") !== "task") return "submit";
|
|
6537
|
+
if (inputs.isFollowUp || inputs.hasExistingSession) return "submit";
|
|
6538
|
+
if (inputs.isAuto || inputs.agentMode === "auto") return "submit";
|
|
6539
|
+
return "prefill";
|
|
6540
|
+
}
|
|
6405
6541
|
function isReadOnlyMode(mode, hasExitedPlanMode) {
|
|
6406
6542
|
return mode === "discovery" || mode === "help" || mode === "auto" && !hasExitedPlanMode;
|
|
6407
6543
|
}
|
|
@@ -6514,7 +6650,17 @@ ${followUpText}` : followUpText;
|
|
|
6514
6650
|
}
|
|
6515
6651
|
return textPrompt;
|
|
6516
6652
|
}
|
|
6517
|
-
async function
|
|
6653
|
+
async function* notifyOnFirstEvent(inner, onFirst) {
|
|
6654
|
+
let fired = false;
|
|
6655
|
+
for await (const event of inner) {
|
|
6656
|
+
if (!fired && event.type !== "system") {
|
|
6657
|
+
fired = true;
|
|
6658
|
+
await onFirst();
|
|
6659
|
+
}
|
|
6660
|
+
yield event;
|
|
6661
|
+
}
|
|
6662
|
+
}
|
|
6663
|
+
async function runSdkQuery(host, context, followUpContent, promptDeliveryOverride) {
|
|
6518
6664
|
if (host.isStopped()) return;
|
|
6519
6665
|
const mode = host.agentMode;
|
|
6520
6666
|
const isDiscoveryLike = mode === "discovery" || mode === "help";
|
|
@@ -6522,10 +6668,24 @@ async function runSdkQuery(host, context, followUpContent) {
|
|
|
6522
6668
|
if (needsPlanSync) {
|
|
6523
6669
|
host.snapshotPlanFiles();
|
|
6524
6670
|
}
|
|
6525
|
-
const sessionUuid = taskIdToSessionUuid(
|
|
6671
|
+
const sessionUuid = taskIdToSessionUuid(
|
|
6672
|
+
sessionLineageKey(context.taskId, mode, host.config.mode)
|
|
6673
|
+
);
|
|
6526
6674
|
const hasExistingSession = sessionFileExists(sessionUuid, host.config.workspaceDir);
|
|
6675
|
+
if (hasExistingSession) {
|
|
6676
|
+
repairTornSessionFile(sessionTranscriptPath(host.config.workspaceDir, sessionUuid));
|
|
6677
|
+
}
|
|
6678
|
+
const promptDelivery = promptDeliveryOverride ?? resolvePromptDelivery({
|
|
6679
|
+
harnessKind: host.harnessKind,
|
|
6680
|
+
runnerMode: host.config.mode,
|
|
6681
|
+
isAuto: host.isAuto,
|
|
6682
|
+
agentMode: mode,
|
|
6683
|
+
isFollowUp: !!followUpContent,
|
|
6684
|
+
hasExistingSession
|
|
6685
|
+
});
|
|
6527
6686
|
const options = {
|
|
6528
6687
|
...buildQueryOptions(host, context),
|
|
6688
|
+
promptDelivery,
|
|
6529
6689
|
...hasExistingSession ? {} : { sessionId: sessionUuid }
|
|
6530
6690
|
};
|
|
6531
6691
|
const resume = hasExistingSession ? sessionUuid : void 0;
|
|
@@ -6536,33 +6696,45 @@ async function runSdkQuery(host, context, followUpContent) {
|
|
|
6536
6696
|
options: { ...options },
|
|
6537
6697
|
resume
|
|
6538
6698
|
});
|
|
6539
|
-
host
|
|
6540
|
-
|
|
6541
|
-
await runWithRetry(agentQuery, context, host, options);
|
|
6542
|
-
} finally {
|
|
6543
|
-
host.activeQuery = null;
|
|
6544
|
-
}
|
|
6545
|
-
} else if (isDiscoveryLike) {
|
|
6699
|
+
await trackAndRun(host, context, options, agentQuery);
|
|
6700
|
+
} else if (isDiscoveryLike && promptDelivery !== "prefill") {
|
|
6546
6701
|
return;
|
|
6547
6702
|
} else {
|
|
6548
|
-
|
|
6549
|
-
const prompt = buildMultimodalPrompt(initialPrompt, context);
|
|
6550
|
-
const agentQuery = host.harness.executeQuery({
|
|
6551
|
-
prompt: host.createInputStream(prompt),
|
|
6552
|
-
options: { ...options },
|
|
6553
|
-
resume
|
|
6554
|
-
});
|
|
6555
|
-
host.activeQuery = agentQuery;
|
|
6556
|
-
try {
|
|
6557
|
-
await runWithRetry(agentQuery, context, host, options);
|
|
6558
|
-
} finally {
|
|
6559
|
-
host.activeQuery = null;
|
|
6560
|
-
}
|
|
6703
|
+
await runInitialQuery(host, context, options, resume, promptDelivery);
|
|
6561
6704
|
}
|
|
6562
6705
|
if (needsPlanSync) {
|
|
6563
6706
|
await host.syncPlanFile();
|
|
6564
6707
|
}
|
|
6565
6708
|
}
|
|
6709
|
+
async function trackAndRun(host, context, options, agentQuery) {
|
|
6710
|
+
host.activeQuery = agentQuery;
|
|
6711
|
+
try {
|
|
6712
|
+
await runWithRetry(agentQuery, context, host, options);
|
|
6713
|
+
} finally {
|
|
6714
|
+
host.activeQuery = null;
|
|
6715
|
+
}
|
|
6716
|
+
}
|
|
6717
|
+
async function runInitialQuery(host, context, options, resume, promptDelivery) {
|
|
6718
|
+
const initialPrompt = await buildInitialPrompt(
|
|
6719
|
+
host.config.mode,
|
|
6720
|
+
context,
|
|
6721
|
+
host.isAuto,
|
|
6722
|
+
host.agentMode
|
|
6723
|
+
);
|
|
6724
|
+
const prompt = buildMultimodalPrompt(initialPrompt, context);
|
|
6725
|
+
let agentQuery = host.harness.executeQuery({
|
|
6726
|
+
prompt: host.createInputStream(prompt),
|
|
6727
|
+
options: { ...options },
|
|
6728
|
+
resume
|
|
6729
|
+
});
|
|
6730
|
+
if (promptDelivery === "prefill") {
|
|
6731
|
+
agentQuery = notifyOnFirstEvent(agentQuery, async () => {
|
|
6732
|
+
host.connection.emitStatus("running");
|
|
6733
|
+
await host.callbacks.onStatusChange("running");
|
|
6734
|
+
});
|
|
6735
|
+
}
|
|
6736
|
+
await trackAndRun(host, context, options, agentQuery);
|
|
6737
|
+
}
|
|
6566
6738
|
async function buildRetryQuery(host, context, options, lastErrorWasImage) {
|
|
6567
6739
|
if (lastErrorWasImage) {
|
|
6568
6740
|
host.connection.postChatMessage(
|
|
@@ -6901,6 +7073,7 @@ var QueryBridge = class {
|
|
|
6901
7073
|
this.runnerConfig = runnerConfig;
|
|
6902
7074
|
this.callbacks = callbacks;
|
|
6903
7075
|
const harnessKind = resolveHarnessKind();
|
|
7076
|
+
this.harnessKind = harnessKind;
|
|
6904
7077
|
this.harness = createHarness(
|
|
6905
7078
|
harnessKind,
|
|
6906
7079
|
harnessKind === "pty" ? buildPtyBridge(connection) : void 0
|
|
@@ -6913,6 +7086,7 @@ var QueryBridge = class {
|
|
|
6913
7086
|
runnerConfig;
|
|
6914
7087
|
callbacks;
|
|
6915
7088
|
harness;
|
|
7089
|
+
harnessKind;
|
|
6916
7090
|
costTracker;
|
|
6917
7091
|
planSync;
|
|
6918
7092
|
sessionIds = /* @__PURE__ */ new Map();
|
|
@@ -6956,18 +7130,40 @@ var QueryBridge = class {
|
|
|
6956
7130
|
seedCostTracker(totalCostUsd, modelUsage) {
|
|
6957
7131
|
this.costTracker.seed(totalCostUsd, modelUsage);
|
|
6958
7132
|
}
|
|
7133
|
+
/**
|
|
7134
|
+
* How the INITIAL instructions for this task would be delivered — "prefill"
|
|
7135
|
+
* means the TUI input is pre-filled but unsubmitted, awaiting the human.
|
|
7136
|
+
* Mirrors the decision runSdkQuery makes for the initial (non-follow-up)
|
|
7137
|
+
* query so SessionRunner can pick the matching state/timers.
|
|
7138
|
+
*/
|
|
7139
|
+
initialPromptDelivery(context) {
|
|
7140
|
+
return resolvePromptDelivery({
|
|
7141
|
+
harnessKind: this.harnessKind,
|
|
7142
|
+
runnerMode: this.runnerConfig.mode,
|
|
7143
|
+
isAuto: this.mode.isAuto,
|
|
7144
|
+
agentMode: this.mode.effectiveMode,
|
|
7145
|
+
isFollowUp: false,
|
|
7146
|
+
hasExistingSession: hasExistingSessionFile(context.taskId, this.runnerConfig.workspaceDir, {
|
|
7147
|
+
agentMode: this.mode.effectiveMode,
|
|
7148
|
+
runnerMode: this.runnerConfig.mode
|
|
7149
|
+
})
|
|
7150
|
+
});
|
|
7151
|
+
}
|
|
6959
7152
|
/**
|
|
6960
7153
|
* Execute a Claude SDK query.
|
|
6961
7154
|
* Without followUpContent: runs initial mode execution (build/plan).
|
|
6962
7155
|
* With followUpContent: processes a follow-up user message.
|
|
7156
|
+
* `promptDelivery` overrides the executor's submit-vs-prefill resolution —
|
|
7157
|
+
* SessionRunner forces "submit" when pending chat messages already direct
|
|
7158
|
+
* the agent (prefilling would park them until a human touched the TUI).
|
|
6963
7159
|
*/
|
|
6964
|
-
async execute(context, followUpContent) {
|
|
7160
|
+
async execute(context, followUpContent, promptDelivery) {
|
|
6965
7161
|
this._stopped = false;
|
|
6966
7162
|
this._wasRateLimited = false;
|
|
6967
7163
|
this._abortController = new AbortController();
|
|
6968
7164
|
const host = this.buildHost();
|
|
6969
7165
|
try {
|
|
6970
|
-
await runSdkQuery(host, context, followUpContent);
|
|
7166
|
+
await runSdkQuery(host, context, followUpContent, promptDelivery);
|
|
6971
7167
|
} catch (err) {
|
|
6972
7168
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6973
7169
|
const isAbort = this._stopped || /abort/i.test(msg);
|
|
@@ -6990,6 +7186,7 @@ var QueryBridge = class {
|
|
|
6990
7186
|
connection: this.connection,
|
|
6991
7187
|
callbacks: this.callbacks,
|
|
6992
7188
|
harness: this.harness,
|
|
7189
|
+
harnessKind: this.harnessKind,
|
|
6993
7190
|
setupLog: [],
|
|
6994
7191
|
costTracker: this.costTracker,
|
|
6995
7192
|
explorationTracker: bridge.mode.effectiveMode === "discovery" || bridge.mode.effectiveMode === "auto" && !bridge.mode.hasExitedPlanMode ? new ExplorationTracker(bridge._isParentTask) : null,
|
|
@@ -7061,8 +7258,8 @@ var QueryBridge = class {
|
|
|
7061
7258
|
};
|
|
7062
7259
|
|
|
7063
7260
|
// src/runner/session-runner-helpers.ts
|
|
7064
|
-
import { readFileSync as
|
|
7065
|
-
import { dirname, join as
|
|
7261
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
7262
|
+
import { dirname, join as join3 } from "path";
|
|
7066
7263
|
import { fileURLToPath } from "url";
|
|
7067
7264
|
function mapChatHistory(messages) {
|
|
7068
7265
|
if (!messages) return [];
|
|
@@ -7091,7 +7288,7 @@ function readAgentVersion() {
|
|
|
7091
7288
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
7092
7289
|
for (const rel of ["../package.json", "../../package.json"]) {
|
|
7093
7290
|
try {
|
|
7094
|
-
const pkg = JSON.parse(
|
|
7291
|
+
const pkg = JSON.parse(readFileSync3(join3(here, rel), "utf-8"));
|
|
7095
7292
|
if (pkg.version) return pkg.version;
|
|
7096
7293
|
} catch {
|
|
7097
7294
|
}
|
|
@@ -7183,6 +7380,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
7183
7380
|
onIdleTimeout: () => {
|
|
7184
7381
|
process.stderr.write("[conveyor-agent] Idle timeout reached, stopping agent\n");
|
|
7185
7382
|
this.stopped = true;
|
|
7383
|
+
this.queryBridge?.stop();
|
|
7186
7384
|
if (this.inputResolver) {
|
|
7187
7385
|
const resolver = this.inputResolver;
|
|
7188
7386
|
this.inputResolver = null;
|
|
@@ -7192,6 +7390,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
7192
7390
|
onDormantTimeout: () => {
|
|
7193
7391
|
process.stderr.write("[conveyor-agent] Dormant idle timeout reached, shutting down\n");
|
|
7194
7392
|
this.stopped = true;
|
|
7393
|
+
this.queryBridge?.stop();
|
|
7195
7394
|
if (this.inputResolver) {
|
|
7196
7395
|
const resolver = this.inputResolver;
|
|
7197
7396
|
this.inputResolver = null;
|
|
@@ -7276,6 +7475,13 @@ var SessionRunner = class _SessionRunner {
|
|
|
7276
7475
|
syncWithBaseBranch(this.config.workspaceDir, this.fullContext.baseBranch);
|
|
7277
7476
|
}
|
|
7278
7477
|
}
|
|
7478
|
+
if (this.fullContext?.githubBranch) {
|
|
7479
|
+
const restored = restoreWipSnapshot(this.config.workspaceDir, this.fullContext.githubBranch);
|
|
7480
|
+
if (restored !== "none") {
|
|
7481
|
+
process.stderr.write(`[conveyor-agent] WIP snapshot restore: ${restored}
|
|
7482
|
+
`);
|
|
7483
|
+
}
|
|
7484
|
+
}
|
|
7279
7485
|
this.mode.applyServerMode(this.fullContext?.agentMode, this.fullContext?.isAuto);
|
|
7280
7486
|
this.mode.resolveInitialMode(this.taskContext);
|
|
7281
7487
|
if (this.fullContext?.isAuto && this.taskContext.status === "Open" && this.mode.isBuildCapable) {
|
|
@@ -7290,6 +7496,12 @@ var SessionRunner = class _SessionRunner {
|
|
|
7290
7496
|
if (staleMessageCount > 0 && didExecuteInitialQuery) {
|
|
7291
7497
|
this.pendingMessages.splice(0, staleMessageCount);
|
|
7292
7498
|
}
|
|
7499
|
+
if (this.queryBridge?.isDiscoveryCompleted) {
|
|
7500
|
+
process.stderr.write(
|
|
7501
|
+
"[conveyor-agent] Discovery completed during initial query \u2014 entering idle\n"
|
|
7502
|
+
);
|
|
7503
|
+
this.queryBridge.isDiscoveryCompleted = false;
|
|
7504
|
+
}
|
|
7293
7505
|
if (!this.stopped && this.pendingMessages.length === 0) {
|
|
7294
7506
|
await this.maybeSendPRNudge();
|
|
7295
7507
|
}
|
|
@@ -7410,16 +7622,32 @@ var SessionRunner = class _SessionRunner {
|
|
|
7410
7622
|
async executeInitialMode() {
|
|
7411
7623
|
if (!this.taskContext || !this.fullContext) return false;
|
|
7412
7624
|
const effectiveMode = this.mode.effectiveMode;
|
|
7413
|
-
const
|
|
7414
|
-
|
|
7625
|
+
const delivery = this.pendingMessages.length > 0 ? "submit" : this.queryBridge?.initialPromptDelivery(this.fullContext) ?? "submit";
|
|
7626
|
+
const shouldRun = effectiveMode === "building" || effectiveMode === "auto" || effectiveMode === "review" || delivery === "prefill";
|
|
7627
|
+
if (!shouldRun) {
|
|
7628
|
+
await this.setState("idle");
|
|
7629
|
+
return false;
|
|
7630
|
+
}
|
|
7631
|
+
if (delivery === "prefill") {
|
|
7632
|
+
await this.setState("waiting_for_input");
|
|
7633
|
+
await this.callbacks.onEvent({ type: "execute_mode", mode: effectiveMode, delivery });
|
|
7634
|
+
if (this.pendingMessages.length > 0) {
|
|
7635
|
+
if (!this.stopped) await this.setState("idle");
|
|
7636
|
+
return false;
|
|
7637
|
+
}
|
|
7638
|
+
this.lifecycle.startIdleTimer();
|
|
7639
|
+
try {
|
|
7640
|
+
await this.executeQuery(void 0, delivery);
|
|
7641
|
+
} finally {
|
|
7642
|
+
this.lifecycle.cancelIdleTimer();
|
|
7643
|
+
}
|
|
7644
|
+
} else {
|
|
7415
7645
|
await this.setState("running");
|
|
7416
7646
|
await this.callbacks.onEvent({ type: "execute_mode", mode: effectiveMode });
|
|
7417
|
-
await this.executeQuery();
|
|
7418
|
-
if (!this.stopped) await this.setState("idle");
|
|
7419
|
-
return true;
|
|
7647
|
+
await this.executeQuery(void 0, delivery);
|
|
7420
7648
|
}
|
|
7421
|
-
await this.setState("idle");
|
|
7422
|
-
return
|
|
7649
|
+
if (!this.stopped) await this.setState("idle");
|
|
7650
|
+
return true;
|
|
7423
7651
|
}
|
|
7424
7652
|
// ── Message waiting ────────────────────────────────────────────────
|
|
7425
7653
|
waitForMessage() {
|
|
@@ -7438,17 +7666,17 @@ var SessionRunner = class _SessionRunner {
|
|
|
7438
7666
|
resolve2(msg);
|
|
7439
7667
|
} else {
|
|
7440
7668
|
this.pendingMessages.push(msg);
|
|
7441
|
-
if (this._state === "running") {
|
|
7669
|
+
if (this._state === "running" || this._state === "waiting_for_input") {
|
|
7442
7670
|
this.queryBridge?.stop();
|
|
7443
7671
|
}
|
|
7444
7672
|
}
|
|
7445
7673
|
}
|
|
7446
7674
|
// ── Query execution with abort handling ────────────────────────────
|
|
7447
7675
|
/** Run queryBridge.execute, swallowing abort errors from stop/softStop. */
|
|
7448
|
-
async executeQuery(followUpContent) {
|
|
7676
|
+
async executeQuery(followUpContent, promptDelivery) {
|
|
7449
7677
|
if (!this.fullContext || !this.queryBridge) return;
|
|
7450
7678
|
try {
|
|
7451
|
-
await this.queryBridge.execute(this.fullContext, followUpContent);
|
|
7679
|
+
await this.queryBridge.execute(this.fullContext, followUpContent, promptDelivery);
|
|
7452
7680
|
} catch (err) {
|
|
7453
7681
|
if (this.interrupted || this.stopped) {
|
|
7454
7682
|
process.stderr.write("[conveyor-agent] Query aborted by stop/softStop signal\n");
|
|
@@ -7647,7 +7875,13 @@ var SessionRunner = class _SessionRunner {
|
|
|
7647
7875
|
this.mode,
|
|
7648
7876
|
runnerConfig,
|
|
7649
7877
|
{
|
|
7650
|
-
onStatusChange: (status) =>
|
|
7878
|
+
onStatusChange: (status) => {
|
|
7879
|
+
if (status === "running" && this._state === "waiting_for_input") {
|
|
7880
|
+
this._state = "running";
|
|
7881
|
+
this.lifecycle.cancelIdleTimer();
|
|
7882
|
+
}
|
|
7883
|
+
return this.callbacks.onStatusChange(status);
|
|
7884
|
+
},
|
|
7651
7885
|
onEvent: (event) => {
|
|
7652
7886
|
if (event.type === "completed") {
|
|
7653
7887
|
this.completedThisTurn = true;
|
|
@@ -7700,9 +7934,11 @@ var SessionRunner = class _SessionRunner {
|
|
|
7700
7934
|
if (data.isSubscription) {
|
|
7701
7935
|
process.env.CLAUDE_CODE_OAUTH_TOKEN = data.apiKey;
|
|
7702
7936
|
delete process.env.ANTHROPIC_API_KEY;
|
|
7937
|
+
void ensureClaudeCredentials();
|
|
7703
7938
|
} else {
|
|
7704
7939
|
process.env.ANTHROPIC_API_KEY = data.apiKey;
|
|
7705
7940
|
delete process.env.CLAUDE_CODE_OAUTH_TOKEN;
|
|
7941
|
+
void removeConveyorCredentials();
|
|
7706
7942
|
}
|
|
7707
7943
|
});
|
|
7708
7944
|
this.connection.onPullBranch(({ branch }) => {
|
|
@@ -8104,13 +8340,13 @@ var CommitWatcher = class {
|
|
|
8104
8340
|
// src/runner/worktree.ts
|
|
8105
8341
|
import { execSync as execSync4 } from "child_process";
|
|
8106
8342
|
import { existsSync as existsSync2 } from "fs";
|
|
8107
|
-
import { join as
|
|
8343
|
+
import { join as join4 } from "path";
|
|
8108
8344
|
var WORKTREE_DIR = ".worktrees";
|
|
8109
8345
|
function ensureWorktree(projectDir, taskId, branch) {
|
|
8110
8346
|
if (projectDir.includes(`/${WORKTREE_DIR}/`)) {
|
|
8111
8347
|
return projectDir;
|
|
8112
8348
|
}
|
|
8113
|
-
const worktreePath =
|
|
8349
|
+
const worktreePath = join4(projectDir, WORKTREE_DIR, taskId);
|
|
8114
8350
|
if (existsSync2(worktreePath)) {
|
|
8115
8351
|
if (branch) {
|
|
8116
8352
|
if (hasUncommittedChanges(worktreePath)) {
|
|
@@ -8156,7 +8392,7 @@ function detachWorktreeBranch(projectDir, branch) {
|
|
|
8156
8392
|
}
|
|
8157
8393
|
}
|
|
8158
8394
|
function removeWorktree(projectDir, taskId) {
|
|
8159
|
-
const worktreePath =
|
|
8395
|
+
const worktreePath = join4(projectDir, WORKTREE_DIR, taskId);
|
|
8160
8396
|
if (!existsSync2(worktreePath)) return;
|
|
8161
8397
|
try {
|
|
8162
8398
|
execSync4(`git worktree remove "${worktreePath}" --force`, {
|
|
@@ -9838,7 +10074,7 @@ var ProjectRunner = class {
|
|
|
9838
10074
|
async handleAuditTags(request) {
|
|
9839
10075
|
this.connection.emitStatus("busy");
|
|
9840
10076
|
try {
|
|
9841
|
-
const { handleTagAudit } = await import("./tag-audit-handler-
|
|
10077
|
+
const { handleTagAudit } = await import("./tag-audit-handler-FVGEBGSB.js");
|
|
9842
10078
|
await handleTagAudit(request, this.connection, this.projectDir);
|
|
9843
10079
|
} catch (error) {
|
|
9844
10080
|
const msg = parseErrorMessage(error);
|
|
@@ -9861,7 +10097,7 @@ var ProjectRunner = class {
|
|
|
9861
10097
|
async handleAuditTasks(request) {
|
|
9862
10098
|
this.connection.emitStatus("busy");
|
|
9863
10099
|
try {
|
|
9864
|
-
const { handleTaskAudit } = await import("./task-audit-handler-
|
|
10100
|
+
const { handleTaskAudit } = await import("./task-audit-handler-JNS4NH5O.js");
|
|
9865
10101
|
await handleTaskAudit(request, this.connection, this.projectDir);
|
|
9866
10102
|
} catch (error) {
|
|
9867
10103
|
const msg = parseErrorMessage(error);
|
|
@@ -9910,12 +10146,12 @@ var ProjectRunner = class {
|
|
|
9910
10146
|
|
|
9911
10147
|
// src/setup/config.ts
|
|
9912
10148
|
import { readFile as readFile3 } from "fs/promises";
|
|
9913
|
-
import { join as
|
|
10149
|
+
import { join as join5 } from "path";
|
|
9914
10150
|
var DEVCONTAINER_PATH = ".devcontainer/conveyor/devcontainer.json";
|
|
9915
10151
|
var DEVCONTAINER_PORT_DENY_LIST = /* @__PURE__ */ new Set([5432, 6379, 9200]);
|
|
9916
10152
|
async function loadForwardPorts(workspaceDir) {
|
|
9917
10153
|
try {
|
|
9918
|
-
const raw = await readFile3(
|
|
10154
|
+
const raw = await readFile3(join5(workspaceDir, DEVCONTAINER_PATH), "utf-8");
|
|
9919
10155
|
const parsed = JSON.parse(raw);
|
|
9920
10156
|
const ports = (parsed.forwardPorts ?? []).filter(
|
|
9921
10157
|
(p) => typeof p === "number" && !DEVCONTAINER_PORT_DENY_LIST.has(p)
|
|
@@ -10002,4 +10238,4 @@ export {
|
|
|
10002
10238
|
loadConveyorConfig,
|
|
10003
10239
|
unshallowRepo
|
|
10004
10240
|
};
|
|
10005
|
-
//# sourceMappingURL=chunk-
|
|
10241
|
+
//# sourceMappingURL=chunk-H3UHIWQF.js.map
|