@rallycry/conveyor-agent 11.0.19 → 11.0.20
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-4ZNOCKFZ.js → boot-Z3EBJ7GX.js} +2 -2
- package/dist/{chunk-SR66HQKB.js → chunk-37J5MMQT.js} +1 -1
- package/dist/{chunk-WS7QRB37.js → chunk-JBGPARLG.js} +1 -1
- package/dist/{chunk-N5LEVAGA.js → chunk-POK3QCGN.js} +338 -98
- package/dist/{chunk-GL2DIQEQ.js → chunk-Q4FQOJ7D.js} +23 -4
- package/dist/{chunk-GZRZGBIK.js → chunk-SKTNJNXQ.js} +2 -2
- package/dist/cli.js +7 -7
- package/dist/index.js +4 -4
- package/dist/{serve-boot-RU5BYIK4.js → serve-boot-4BUN4U44.js} +3 -3
- package/package.json +1 -1
|
@@ -11,14 +11,14 @@ import {
|
|
|
11
11
|
readAgentVersion,
|
|
12
12
|
refreshSkillsAfterCheckout,
|
|
13
13
|
runPreReadyBinds
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-37J5MMQT.js";
|
|
15
15
|
import "./chunk-W5INK3NE.js";
|
|
16
16
|
import {
|
|
17
17
|
GitPrepJob,
|
|
18
18
|
defaultGit,
|
|
19
19
|
ensureDir,
|
|
20
20
|
reportBootMilestone
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-Q4FQOJ7D.js";
|
|
22
22
|
import "./chunk-W4LZ7R6Z.js";
|
|
23
23
|
import "./chunk-372R6E4C.js";
|
|
24
24
|
import "./chunk-SQM2BQ7H.js";
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
mapChatHistory,
|
|
3
3
|
readAgentVersion,
|
|
4
4
|
refreshSkillsAfterCheckout
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-37J5MMQT.js";
|
|
6
6
|
import {
|
|
7
7
|
MAX_BETWEEN_TURN_BUFFER,
|
|
8
8
|
MAX_DIAGNOSTIC_OUTPUT,
|
|
@@ -59,11 +59,11 @@ import {
|
|
|
59
59
|
statWorkspacePath,
|
|
60
60
|
updateRemoteToken,
|
|
61
61
|
verifyGitCredential
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-JBGPARLG.js";
|
|
63
63
|
import {
|
|
64
64
|
registerBootMilestoneSocketFallback,
|
|
65
65
|
reportBootMilestone
|
|
66
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-Q4FQOJ7D.js";
|
|
67
67
|
import {
|
|
68
68
|
describeTokenFile,
|
|
69
69
|
ghHostsExternallyOwned,
|
|
@@ -4847,7 +4847,8 @@ var ClaudeTuiAdapter = class {
|
|
|
4847
4847
|
structuredEvents: true,
|
|
4848
4848
|
prefill: true,
|
|
4849
4849
|
passiveTurns: true,
|
|
4850
|
-
rawPromptGate: false
|
|
4850
|
+
rawPromptGate: false,
|
|
4851
|
+
prewarm: true
|
|
4851
4852
|
};
|
|
4852
4853
|
resolveBinary(env = process.env) {
|
|
4853
4854
|
return env.CONVEYOR_CLAUDE_BIN ?? "claude";
|
|
@@ -4942,7 +4943,6 @@ var PtySession = class {
|
|
|
4942
4943
|
// Raw-TUI input detection (see awaitRawTuiInputLive). `probeWindow`, when
|
|
4943
4944
|
// non-null, accumulates raw output so a probe can look for its own sentinel
|
|
4944
4945
|
// coming back.
|
|
4945
|
-
spawnedAt = 0;
|
|
4946
4946
|
// Set once the child writes a DEC private mode — it owns the tty from then on,
|
|
4947
4947
|
// so the kernel no longer echoes our keystrokes and a sentinel coming back is
|
|
4948
4948
|
// attributable to the app's own repaint.
|
|
@@ -5002,6 +5002,8 @@ var PtySession = class {
|
|
|
5002
5002
|
turn;
|
|
5003
5003
|
codexPromptInArgv = false;
|
|
5004
5004
|
codexInitialPrompt;
|
|
5005
|
+
/** A fresh CLI intentionally started without input for checkout overlap. */
|
|
5006
|
+
prewarmed = false;
|
|
5005
5007
|
codexSource = null;
|
|
5006
5008
|
adapterCleanupPaths = [];
|
|
5007
5009
|
onIdle(listener) {
|
|
@@ -5095,7 +5097,7 @@ var PtySession = class {
|
|
|
5095
5097
|
* never set) keeps the Claude semantics byte-identical.
|
|
5096
5098
|
*/
|
|
5097
5099
|
canReuse(resume, fingerprint) {
|
|
5098
|
-
const resumeMatches = resume === void 0 ? this.reportedOpenCodeId !== null : resume === this.sessionUuid;
|
|
5100
|
+
const resumeMatches = resume === void 0 ? this.reportedOpenCodeId !== null || this.prewarmed : resume === this.sessionUuid;
|
|
5099
5101
|
return !this._toreDown && !this.exited && this.activeQueue === null && // A parked questionnaire owns the terminal — a fed prompt would type
|
|
5100
5102
|
// into the dialog. Force teardown + respawn instead.
|
|
5101
5103
|
!this.questionnairePending && resumeMatches && fingerprint === this.spawnFingerprint;
|
|
@@ -5125,6 +5127,7 @@ var PtySession = class {
|
|
|
5125
5127
|
if (this.betweenTurnBuffer.length > MAX_BETWEEN_TURN_BUFFER) {
|
|
5126
5128
|
this.betweenTurnBuffer.shift();
|
|
5127
5129
|
}
|
|
5130
|
+
if (this.prewarmed) return;
|
|
5128
5131
|
if (!this.passiveSignaled) {
|
|
5129
5132
|
this.passiveSignaled = true;
|
|
5130
5133
|
this.passiveListener?.();
|
|
@@ -5136,8 +5139,10 @@ var PtySession = class {
|
|
|
5136
5139
|
* the prompt into the live pty. The caller must have verified canReuse().
|
|
5137
5140
|
*/
|
|
5138
5141
|
async beginTurn(prompt, options) {
|
|
5142
|
+
this.prewarmed = false;
|
|
5139
5143
|
this.turnPrompt = prompt;
|
|
5140
5144
|
this.turn = turnOptionsFrom(options);
|
|
5145
|
+
this.attachInput();
|
|
5141
5146
|
this.resetForTurn();
|
|
5142
5147
|
this.betweenTurnBuffer = [];
|
|
5143
5148
|
this.activeQueue = new AsyncEventQueue();
|
|
@@ -5228,13 +5233,24 @@ var PtySession = class {
|
|
|
5228
5233
|
}
|
|
5229
5234
|
}
|
|
5230
5235
|
async start() {
|
|
5236
|
+
await this.startInternal(true);
|
|
5237
|
+
}
|
|
5238
|
+
/** Start the CLI and its event plumbing without allocating a model turn. */
|
|
5239
|
+
async startParked() {
|
|
5240
|
+
this.prewarmed = true;
|
|
5241
|
+
await this.startInternal(false);
|
|
5242
|
+
}
|
|
5243
|
+
// oxlint-disable-next-line complexity -- adapter startup and turn gating share one teardown boundary
|
|
5244
|
+
async startInternal(feedPrompt) {
|
|
5231
5245
|
await this.collectCodexPrompt();
|
|
5232
5246
|
const sessionId = this.resume ?? this.options.sessionId;
|
|
5233
5247
|
if (!sessionId) {
|
|
5234
5248
|
throw new Error("PtySession requires options.sessionId or a resume target");
|
|
5235
5249
|
}
|
|
5236
|
-
|
|
5237
|
-
|
|
5250
|
+
if (feedPrompt) {
|
|
5251
|
+
this.activeQueue = new AsyncEventQueue();
|
|
5252
|
+
this.turnStream = this.activeQueue.drain();
|
|
5253
|
+
}
|
|
5238
5254
|
const signal = this.turn.abortController?.signal;
|
|
5239
5255
|
if (signal?.aborted) {
|
|
5240
5256
|
await this.teardown();
|
|
@@ -5260,7 +5276,7 @@ var PtySession = class {
|
|
|
5260
5276
|
model: this.options.model
|
|
5261
5277
|
});
|
|
5262
5278
|
}
|
|
5263
|
-
if (signal) {
|
|
5279
|
+
if (signal && feedPrompt) {
|
|
5264
5280
|
this.abortHandler = () => {
|
|
5265
5281
|
void this.teardown();
|
|
5266
5282
|
};
|
|
@@ -5271,10 +5287,10 @@ var PtySession = class {
|
|
|
5271
5287
|
}
|
|
5272
5288
|
}
|
|
5273
5289
|
if (this.bridge) {
|
|
5274
|
-
|
|
5290
|
+
if (feedPrompt) this.attachInput();
|
|
5275
5291
|
this.unsubResize = this.bridge.onResize((cols, rows) => this.resizePty(cols, rows));
|
|
5276
5292
|
}
|
|
5277
|
-
await this.feedPrompt();
|
|
5293
|
+
if (feedPrompt) await this.feedPrompt();
|
|
5278
5294
|
} catch (err) {
|
|
5279
5295
|
await this.teardown();
|
|
5280
5296
|
throw err;
|
|
@@ -5314,7 +5330,11 @@ var PtySession = class {
|
|
|
5314
5330
|
session_id: id,
|
|
5315
5331
|
model: this.options.model
|
|
5316
5332
|
});
|
|
5317
|
-
this.sendChatEvent({
|
|
5333
|
+
this.sendChatEvent({
|
|
5334
|
+
kind: "init",
|
|
5335
|
+
model: this.options.model,
|
|
5336
|
+
claudeSessionId: id
|
|
5337
|
+
});
|
|
5318
5338
|
},
|
|
5319
5339
|
(event) => this.sendChatEvent(event)
|
|
5320
5340
|
);
|
|
@@ -5352,7 +5372,11 @@ var PtySession = class {
|
|
|
5352
5372
|
session_id: id,
|
|
5353
5373
|
model: this.options.model
|
|
5354
5374
|
});
|
|
5355
|
-
this.sendChatEvent({
|
|
5375
|
+
this.sendChatEvent({
|
|
5376
|
+
kind: "init",
|
|
5377
|
+
model: this.options.model,
|
|
5378
|
+
claudeSessionId: id
|
|
5379
|
+
});
|
|
5356
5380
|
},
|
|
5357
5381
|
(event) => this.sendChatEvent(event)
|
|
5358
5382
|
);
|
|
@@ -5466,9 +5490,19 @@ var PtySession = class {
|
|
|
5466
5490
|
this.pendingSyntheticQuestionIds = [];
|
|
5467
5491
|
this.questionResultRemap.clear();
|
|
5468
5492
|
for (const toolUseId of orphaned) {
|
|
5469
|
-
this.sendChatEvent({
|
|
5493
|
+
this.sendChatEvent({
|
|
5494
|
+
kind: "tool_result",
|
|
5495
|
+
toolUseId,
|
|
5496
|
+
output: "",
|
|
5497
|
+
isError: false
|
|
5498
|
+
});
|
|
5470
5499
|
}
|
|
5471
5500
|
}
|
|
5501
|
+
/** Attach relay keystrokes only once a Git-gated turn is allowed to accept them. */
|
|
5502
|
+
attachInput() {
|
|
5503
|
+
if (!this.bridge || this.unsubInput) return;
|
|
5504
|
+
this.unsubInput = this.bridge.onInput((data) => this.writeStdin(data));
|
|
5505
|
+
}
|
|
5472
5506
|
writeStdin(text) {
|
|
5473
5507
|
this.pty?.write(text);
|
|
5474
5508
|
}
|
|
@@ -5635,7 +5669,6 @@ var PtySession = class {
|
|
|
5635
5669
|
pty.onExit((event) => {
|
|
5636
5670
|
void this.finalizeOnExit(event.exitCode);
|
|
5637
5671
|
});
|
|
5638
|
-
this.spawnedAt = Date.now();
|
|
5639
5672
|
this.sawTerminalSetup = false;
|
|
5640
5673
|
this.probeWindow = null;
|
|
5641
5674
|
this.wroteToProcess = false;
|
|
@@ -5679,7 +5712,7 @@ var PtySession = class {
|
|
|
5679
5712
|
if (!needsRawReadyGate(this.adapter.capabilities)) return;
|
|
5680
5713
|
const timing = resolveRawTuiProbeTiming();
|
|
5681
5714
|
const { sentinel } = timing;
|
|
5682
|
-
const start =
|
|
5715
|
+
const start = Date.now();
|
|
5683
5716
|
const setupDeadline = start + timing.firstOutputMaxMs;
|
|
5684
5717
|
while (!this._toreDown && Date.now() < setupDeadline) {
|
|
5685
5718
|
if (this.sawTerminalSetup) break;
|
|
@@ -5963,7 +5996,12 @@ var PtySession = class {
|
|
|
5963
5996
|
}
|
|
5964
5997
|
if (!this.adapter.capabilities.structuredEvents) {
|
|
5965
5998
|
if (exitCode === 0) {
|
|
5966
|
-
this.pushEvent({
|
|
5999
|
+
this.pushEvent({
|
|
6000
|
+
type: "result",
|
|
6001
|
+
subtype: "success",
|
|
6002
|
+
result: "",
|
|
6003
|
+
total_cost_usd: 0
|
|
6004
|
+
});
|
|
5967
6005
|
} else {
|
|
5968
6006
|
this.pushEvent({
|
|
5969
6007
|
type: "result",
|
|
@@ -6124,6 +6162,9 @@ var PtyHarness = class _PtyHarness {
|
|
|
6124
6162
|
authNoticeSent = false;
|
|
6125
6163
|
/** Once-per-process guard on the pod-recycle escalation (see escalateToPodRecycle). */
|
|
6126
6164
|
recycleRequested = false;
|
|
6165
|
+
disposed = false;
|
|
6166
|
+
prewarming = null;
|
|
6167
|
+
prewarmInFlight = null;
|
|
6127
6168
|
/**
|
|
6128
6169
|
* Wiggle the live pty's size so the CLI repaints its whole screen. No-op on
|
|
6129
6170
|
* the SDK harness. Falls back to the parked session so an API reconnect while
|
|
@@ -6184,6 +6225,60 @@ var PtyHarness = class _PtyHarness {
|
|
|
6184
6225
|
yield* this.drain(session);
|
|
6185
6226
|
yield* this.recoverFailedDelivery(session, options, want);
|
|
6186
6227
|
}
|
|
6228
|
+
/**
|
|
6229
|
+
* Prepare a fresh TUI while another boot task runs. This deliberately does
|
|
6230
|
+
* not send stdin or create an active event queue, so no model/tool work can
|
|
6231
|
+
* begin before the runner releases its checkout and WIP gates.
|
|
6232
|
+
*/
|
|
6233
|
+
async prewarm(options) {
|
|
6234
|
+
if (this.prewarmInFlight) return this.prewarmInFlight;
|
|
6235
|
+
const pending = this.startPrewarm(options);
|
|
6236
|
+
this.prewarmInFlight = pending;
|
|
6237
|
+
try {
|
|
6238
|
+
return await pending;
|
|
6239
|
+
} finally {
|
|
6240
|
+
this.prewarmInFlight = null;
|
|
6241
|
+
}
|
|
6242
|
+
}
|
|
6243
|
+
async startPrewarm(options) {
|
|
6244
|
+
if (this.disposed || !this.adapter.capabilities.prewarm) return false;
|
|
6245
|
+
const startedAt = Date.now();
|
|
6246
|
+
const prepared = ensureSessionTarget(options, void 0);
|
|
6247
|
+
if (prepared !== options) {
|
|
6248
|
+
_PtyHarness.log.warn("prewarm had no session target \u2014 minted one", {
|
|
6249
|
+
sessionId: prepared.sessionId
|
|
6250
|
+
});
|
|
6251
|
+
}
|
|
6252
|
+
const fingerprint = this.fingerprintOf(prepared);
|
|
6253
|
+
if (this.parked?.canReuse(void 0, fingerprint) && !await this.parkedHomeDied(prepared)) {
|
|
6254
|
+
_PtyHarness.log.info("TUI prewarm reused parked process", {
|
|
6255
|
+
elapsedMs: Date.now() - startedAt
|
|
6256
|
+
});
|
|
6257
|
+
return true;
|
|
6258
|
+
}
|
|
6259
|
+
if (this.parked) {
|
|
6260
|
+
const stale = this.parked;
|
|
6261
|
+
this.parked = null;
|
|
6262
|
+
this.cancelEndedTimer();
|
|
6263
|
+
await stale.teardown();
|
|
6264
|
+
}
|
|
6265
|
+
if (this.disposed) return false;
|
|
6266
|
+
_PtyHarness.log.info("TUI prewarm starting fresh process");
|
|
6267
|
+
const session = await this.spawnSession("", prepared, void 0, true, (created) => {
|
|
6268
|
+
this.prewarming = created;
|
|
6269
|
+
});
|
|
6270
|
+
this.prewarming = null;
|
|
6271
|
+
if (this.disposed) {
|
|
6272
|
+
await session.teardown();
|
|
6273
|
+
this.notifyEnded();
|
|
6274
|
+
return false;
|
|
6275
|
+
}
|
|
6276
|
+
this.park(session);
|
|
6277
|
+
_PtyHarness.log.info("TUI prewarm process started", {
|
|
6278
|
+
elapsedMs: Date.now() - startedAt
|
|
6279
|
+
});
|
|
6280
|
+
return true;
|
|
6281
|
+
}
|
|
6187
6282
|
/**
|
|
6188
6283
|
* Did the shared `~/.claude` mount die while this session sat parked?
|
|
6189
6284
|
*
|
|
@@ -6220,8 +6315,9 @@ var PtyHarness = class _PtyHarness {
|
|
|
6220
6315
|
* environment preparation (config-home health, credential synthesis,
|
|
6221
6316
|
* auth-readiness warning) and registering the parked-death watch.
|
|
6222
6317
|
*/
|
|
6223
|
-
async spawnSession(prompt, options, want) {
|
|
6318
|
+
async spawnSession(prompt, options, want, parked = false, onAllocated) {
|
|
6224
6319
|
const session = new PtySession(prompt, options, want, this.bridge, this.adapter);
|
|
6320
|
+
onAllocated?.(session);
|
|
6225
6321
|
if (this.ownsClaudeConfigHome) {
|
|
6226
6322
|
await ensureUsableClaudeConfigHome(options.cwd, _PtyHarness.log);
|
|
6227
6323
|
}
|
|
@@ -6230,7 +6326,8 @@ var PtyHarness = class _PtyHarness {
|
|
|
6230
6326
|
await this.warnIfAuthNotReady();
|
|
6231
6327
|
}
|
|
6232
6328
|
session.onExit(() => this.handleSessionExit(session));
|
|
6233
|
-
await session.
|
|
6329
|
+
if (parked) await session.startParked();
|
|
6330
|
+
else await session.start();
|
|
6234
6331
|
return session;
|
|
6235
6332
|
}
|
|
6236
6333
|
/**
|
|
@@ -6402,10 +6499,21 @@ var PtyHarness = class _PtyHarness {
|
|
|
6402
6499
|
* the Connected-TUI tab hides promptly.
|
|
6403
6500
|
*/
|
|
6404
6501
|
async dispose() {
|
|
6502
|
+
this.disposed = true;
|
|
6405
6503
|
this.cancelEndedTimer();
|
|
6406
|
-
|
|
6504
|
+
try {
|
|
6505
|
+
await this.prewarmInFlight;
|
|
6506
|
+
} catch (error) {
|
|
6507
|
+
_PtyHarness.log.warn("TUI prewarm failed during disposal", {
|
|
6508
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6509
|
+
});
|
|
6510
|
+
}
|
|
6511
|
+
const toKill = [.../* @__PURE__ */ new Set([this.parked, this.activeSession, this.prewarming])].filter(
|
|
6512
|
+
(s) => s !== null
|
|
6513
|
+
);
|
|
6407
6514
|
this.parked = null;
|
|
6408
6515
|
this.activeSession = null;
|
|
6516
|
+
this.prewarming = null;
|
|
6409
6517
|
for (const session of toKill) {
|
|
6410
6518
|
try {
|
|
6411
6519
|
await session.teardown();
|
|
@@ -6847,7 +6955,8 @@ var OpenCodeTuiAdapter = class {
|
|
|
6847
6955
|
// opencode silently discards early stdin while the TUI paints; the pasted
|
|
6848
6956
|
// text itself is lost, so the readiness probe must gate the first write
|
|
6849
6957
|
// even though structured events exist now.
|
|
6850
|
-
rawPromptGate: true
|
|
6958
|
+
rawPromptGate: true,
|
|
6959
|
+
prewarm: true
|
|
6851
6960
|
};
|
|
6852
6961
|
resolveBinary(env = this.env) {
|
|
6853
6962
|
const override = env.CONVEYOR_OPENCODE_BIN;
|
|
@@ -7011,7 +7120,8 @@ var CodexTuiAdapter = class {
|
|
|
7011
7120
|
structuredEvents: true,
|
|
7012
7121
|
prefill: true,
|
|
7013
7122
|
passiveTurns: true,
|
|
7014
|
-
rawPromptGate: true
|
|
7123
|
+
rawPromptGate: true,
|
|
7124
|
+
prewarm: true
|
|
7015
7125
|
};
|
|
7016
7126
|
resolveBinary(env = this.env) {
|
|
7017
7127
|
const path = findOnPath(env.CONVEYOR_CODEX_BIN ?? "codex", env);
|
|
@@ -8186,6 +8296,7 @@ function buildParentReviewPrompt() {
|
|
|
8186
8296
|
var TYPE_PRIORITY = { rule: 0, doc: 1, file: 2, folder: 3 };
|
|
8187
8297
|
var SUMMARY_SCAN_CHARS = 4e3;
|
|
8188
8298
|
var SUMMARY_MAX_CHARS = 160;
|
|
8299
|
+
var CONTEXT_READ_CONCURRENCY = 4;
|
|
8189
8300
|
var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
8190
8301
|
".png",
|
|
8191
8302
|
".jpg",
|
|
@@ -8288,24 +8399,61 @@ async function readFolderListing(folderPath) {
|
|
|
8288
8399
|
return null;
|
|
8289
8400
|
}
|
|
8290
8401
|
}
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8402
|
+
var ContextReadCoordinator = class {
|
|
8403
|
+
availableSlots = CONTEXT_READ_CONCURRENCY;
|
|
8404
|
+
waitingReaders = [];
|
|
8405
|
+
pendingSummaries = /* @__PURE__ */ new Map();
|
|
8406
|
+
async resolveEntry(entry) {
|
|
8407
|
+
const result = {
|
|
8408
|
+
type: entry.type,
|
|
8409
|
+
path: entry.path,
|
|
8410
|
+
label: entry.label,
|
|
8411
|
+
summary: null
|
|
8412
|
+
};
|
|
8413
|
+
if (entry.label) {
|
|
8414
|
+
result.summary = truncateSummary(entry.label);
|
|
8415
|
+
return result;
|
|
8416
|
+
}
|
|
8417
|
+
result.summary = await this.readSummary(entry);
|
|
8300
8418
|
return result;
|
|
8301
8419
|
}
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
8420
|
+
readSummary(entry) {
|
|
8421
|
+
const kind = entry.type === "folder" ? "folder" : "file";
|
|
8422
|
+
const key = `${kind}:${entry.path}`;
|
|
8423
|
+
const pending = this.pendingSummaries.get(key);
|
|
8424
|
+
if (pending) return pending;
|
|
8425
|
+
const read = this.limit(
|
|
8426
|
+
() => kind === "folder" ? readFolderListing(entry.path) : readFileSummary(entry.path)
|
|
8427
|
+
);
|
|
8428
|
+
this.pendingSummaries.set(key, read);
|
|
8429
|
+
return read;
|
|
8305
8430
|
}
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
|
|
8431
|
+
async limit(read) {
|
|
8432
|
+
await this.acquireSlot();
|
|
8433
|
+
try {
|
|
8434
|
+
return await read();
|
|
8435
|
+
} finally {
|
|
8436
|
+
this.releaseSlot();
|
|
8437
|
+
}
|
|
8438
|
+
}
|
|
8439
|
+
async acquireSlot() {
|
|
8440
|
+
if (this.availableSlots > 0) {
|
|
8441
|
+
this.availableSlots -= 1;
|
|
8442
|
+
return;
|
|
8443
|
+
}
|
|
8444
|
+
await new Promise((resolve) => {
|
|
8445
|
+
this.waitingReaders.push(resolve);
|
|
8446
|
+
});
|
|
8447
|
+
}
|
|
8448
|
+
releaseSlot() {
|
|
8449
|
+
const nextReader = this.waitingReaders.shift();
|
|
8450
|
+
if (nextReader) {
|
|
8451
|
+
nextReader();
|
|
8452
|
+
return;
|
|
8453
|
+
}
|
|
8454
|
+
this.availableSlots += 1;
|
|
8455
|
+
}
|
|
8456
|
+
};
|
|
8309
8457
|
function formatEntry(entry) {
|
|
8310
8458
|
const suffix = entry.summary ? ` \u2014 ${entry.summary}` : "";
|
|
8311
8459
|
return `- \`${entry.path}\`${suffix}`;
|
|
@@ -8360,39 +8508,33 @@ function formatResolvedTags(resolved, subProject, mentioned, runnerMode) {
|
|
|
8360
8508
|
}
|
|
8361
8509
|
return parts.join("\n");
|
|
8362
8510
|
}
|
|
8363
|
-
|
|
8364
|
-
if (!contextPaths?.length) return [];
|
|
8511
|
+
function resolveEntries(contextPaths, coordinator) {
|
|
8512
|
+
if (!contextPaths?.length) return Promise.resolve([]);
|
|
8365
8513
|
const sorted = [...contextPaths].sort(
|
|
8366
8514
|
(a, b) => (TYPE_PRIORITY[a.type] ?? 99) - (TYPE_PRIORITY[b.type] ?? 99)
|
|
8367
8515
|
);
|
|
8368
|
-
|
|
8369
|
-
for (const entry of sorted) {
|
|
8370
|
-
results.push(await resolveEntry(entry));
|
|
8371
|
-
}
|
|
8372
|
-
return results;
|
|
8516
|
+
return Promise.all(sorted.map((entry) => coordinator.resolveEntry(entry)));
|
|
8373
8517
|
}
|
|
8374
8518
|
function countResolved(entries) {
|
|
8375
8519
|
const injected = entries.filter((e) => e.summary !== null).length;
|
|
8376
8520
|
return { injected, skipped: entries.length - injected };
|
|
8377
8521
|
}
|
|
8378
|
-
async function resolveAssignedTags(assignedTags) {
|
|
8379
|
-
const resolved =
|
|
8380
|
-
|
|
8381
|
-
let skipped = 0;
|
|
8382
|
-
for (const tag of assignedTags) {
|
|
8383
|
-
const entries = await resolveEntries(tag.contextPaths);
|
|
8384
|
-
const counts = countResolved(entries);
|
|
8385
|
-
injected += counts.injected;
|
|
8386
|
-
skipped += counts.skipped;
|
|
8387
|
-
resolved.push({
|
|
8522
|
+
async function resolveAssignedTags(assignedTags, coordinator) {
|
|
8523
|
+
const resolved = await Promise.all(
|
|
8524
|
+
assignedTags.map(async (tag) => ({
|
|
8388
8525
|
tagName: tag.name,
|
|
8389
8526
|
description: tag.description,
|
|
8390
|
-
entries,
|
|
8527
|
+
entries: await resolveEntries(tag.contextPaths, coordinator),
|
|
8391
8528
|
hasOverview: tag.hasOverview,
|
|
8392
8529
|
overviewPath: tag.overviewPath ?? null
|
|
8393
|
-
})
|
|
8394
|
-
|
|
8395
|
-
|
|
8530
|
+
}))
|
|
8531
|
+
);
|
|
8532
|
+
const counts = resolved.map((tag) => countResolved(tag.entries));
|
|
8533
|
+
return {
|
|
8534
|
+
resolved,
|
|
8535
|
+
injected: counts.reduce((total, current) => total + current.injected, 0),
|
|
8536
|
+
skipped: counts.reduce((total, current) => total + current.skipped, 0)
|
|
8537
|
+
};
|
|
8396
8538
|
}
|
|
8397
8539
|
async function resolveTagContext(projectTags, taskTagIds, _model, _betas, runnerMode, subProject, mentionedTagIds) {
|
|
8398
8540
|
const taskTagIdSet = new Set(taskTagIds);
|
|
@@ -8406,30 +8548,26 @@ async function resolveTagContext(projectTags, taskTagIds, _model, _betas, runner
|
|
|
8406
8548
|
if (!hasTagPaths && !hasSubProjectPaths && mentionedTags.length === 0) {
|
|
8407
8549
|
return { injectedSection: "", stats: { injected: 0, skipped: 0 } };
|
|
8408
8550
|
}
|
|
8409
|
-
const
|
|
8410
|
-
|
|
8411
|
-
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
|
|
8415
|
-
|
|
8416
|
-
|
|
8417
|
-
|
|
8418
|
-
if (subProject && hasSubProjectPaths) {
|
|
8419
|
-
const entries = await resolveEntries(subProject.contextPaths);
|
|
8420
|
-
const counts = countResolved(entries);
|
|
8421
|
-
subInjected = counts.injected;
|
|
8422
|
-
subSkipped = counts.skipped;
|
|
8423
|
-
subProjectResolved = { name: subProject.name, entries };
|
|
8424
|
-
}
|
|
8551
|
+
const coordinator = new ContextReadCoordinator();
|
|
8552
|
+
const subProjectEntries = subProject && hasSubProjectPaths ? resolveEntries(subProject.contextPaths, coordinator) : Promise.resolve(null);
|
|
8553
|
+
const [assigned, mentioned, subProjectResolvedEntries] = await Promise.all([
|
|
8554
|
+
resolveAssignedTags(assignedTags, coordinator),
|
|
8555
|
+
resolveAssignedTags(mentionedTags, coordinator),
|
|
8556
|
+
subProjectEntries
|
|
8557
|
+
]);
|
|
8558
|
+
const subProjectResolved = subProject && subProjectResolvedEntries ? { name: subProject.name, entries: subProjectResolvedEntries } : null;
|
|
8559
|
+
const subProjectCounts = subProjectResolvedEntries ? countResolved(subProjectResolvedEntries) : { injected: 0, skipped: 0 };
|
|
8425
8560
|
return {
|
|
8426
8561
|
injectedSection: formatResolvedTags(
|
|
8427
|
-
resolved,
|
|
8562
|
+
assigned.resolved,
|
|
8428
8563
|
subProjectResolved,
|
|
8429
|
-
|
|
8564
|
+
mentioned.resolved,
|
|
8430
8565
|
runnerMode
|
|
8431
8566
|
),
|
|
8432
|
-
stats: {
|
|
8567
|
+
stats: {
|
|
8568
|
+
injected: assigned.injected + subProjectCounts.injected,
|
|
8569
|
+
skipped: assigned.skipped + subProjectCounts.skipped
|
|
8570
|
+
}
|
|
8433
8571
|
};
|
|
8434
8572
|
}
|
|
8435
8573
|
|
|
@@ -14207,7 +14345,11 @@ function buildQueryOptions(host, context) {
|
|
|
14207
14345
|
const systemPromptText = buildSystemPrompt(
|
|
14208
14346
|
host.config.mode,
|
|
14209
14347
|
context,
|
|
14210
|
-
{
|
|
14348
|
+
{
|
|
14349
|
+
...host.config,
|
|
14350
|
+
isAuto: host.isAuto,
|
|
14351
|
+
runtimeTui: process.env.CONVEYOR_TUI
|
|
14352
|
+
},
|
|
14211
14353
|
host.setupLog,
|
|
14212
14354
|
mode
|
|
14213
14355
|
);
|
|
@@ -14268,7 +14410,11 @@ function buildMultimodalPrompt(textPrompt, context, skipImages = false) {
|
|
|
14268
14410
|
for (const msg of context.chatHistory) {
|
|
14269
14411
|
for (const f2 of msg.files ?? []) {
|
|
14270
14412
|
if (f2.content && f2.contentEncoding === "base64") {
|
|
14271
|
-
chatImages.push({
|
|
14413
|
+
chatImages.push({
|
|
14414
|
+
fileName: f2.fileName,
|
|
14415
|
+
mimeType: f2.mimeType,
|
|
14416
|
+
content: f2.content
|
|
14417
|
+
});
|
|
14272
14418
|
}
|
|
14273
14419
|
}
|
|
14274
14420
|
}
|
|
@@ -14283,14 +14429,24 @@ function buildMultimodalPrompt(textPrompt, context, skipImages = false) {
|
|
|
14283
14429
|
data: file.content ?? ""
|
|
14284
14430
|
}
|
|
14285
14431
|
});
|
|
14286
|
-
blocks.push({
|
|
14432
|
+
blocks.push({
|
|
14433
|
+
type: "text",
|
|
14434
|
+
text: `[Attached image: ${file.fileName} (${file.mimeType})]`
|
|
14435
|
+
});
|
|
14287
14436
|
}
|
|
14288
14437
|
for (const file of chatImages) {
|
|
14289
14438
|
blocks.push({
|
|
14290
14439
|
type: "image",
|
|
14291
|
-
source: {
|
|
14440
|
+
source: {
|
|
14441
|
+
type: "base64",
|
|
14442
|
+
media_type: file.mimeType,
|
|
14443
|
+
data: file.content
|
|
14444
|
+
}
|
|
14445
|
+
});
|
|
14446
|
+
blocks.push({
|
|
14447
|
+
type: "text",
|
|
14448
|
+
text: `[Chat image: ${file.fileName} (${file.mimeType})]`
|
|
14292
14449
|
});
|
|
14293
|
-
blocks.push({ type: "text", text: `[Chat image: ${file.fileName} (${file.mimeType})]` });
|
|
14294
14450
|
}
|
|
14295
14451
|
return blocks;
|
|
14296
14452
|
}
|
|
@@ -14448,7 +14604,7 @@ async function* watchForParkedTui(inner, host, opts) {
|
|
|
14448
14604
|
function takesPlannerOpeningTurn(host, mode) {
|
|
14449
14605
|
return host.config.mode === "plan" && mode === "discovery";
|
|
14450
14606
|
}
|
|
14451
|
-
async function runSdkQuery(host, context, followUpContent, promptDeliveryOverride) {
|
|
14607
|
+
async function runSdkQuery(host, context, followUpContent, promptDeliveryOverride, freshPrewarmed = false) {
|
|
14452
14608
|
if (host.isStopped()) return;
|
|
14453
14609
|
const mode = host.agentMode;
|
|
14454
14610
|
const isDiscoveryLike = mode === "discovery" || mode === "help";
|
|
@@ -14457,7 +14613,7 @@ async function runSdkQuery(host, context, followUpContent, promptDeliveryOverrid
|
|
|
14457
14613
|
host.config.workspaceDir,
|
|
14458
14614
|
host.config.mode === "code-review" && process.env.CONVEYOR_TUI !== "codex" ? "claude-code" : process.env.CONVEYOR_TUI
|
|
14459
14615
|
);
|
|
14460
|
-
const hasExistingSession = !!sessionStart.resume;
|
|
14616
|
+
const hasExistingSession = !!sessionStart.resume && !freshPrewarmed;
|
|
14461
14617
|
const promptDelivery = promptDeliveryOverride ?? resolvePromptDelivery({
|
|
14462
14618
|
harnessKind: host.harnessKind,
|
|
14463
14619
|
runnerMode: host.config.mode,
|
|
@@ -14479,11 +14635,49 @@ async function runSdkQuery(host, context, followUpContent, promptDeliveryOverrid
|
|
|
14479
14635
|
if (isDiscoveryLike && host.harnessKind === "sdk") {
|
|
14480
14636
|
return;
|
|
14481
14637
|
}
|
|
14482
|
-
if (isDiscoveryLike && resume && !takesPlannerOpeningTurn(host, mode)) {
|
|
14638
|
+
if (isDiscoveryLike && resume && !freshPrewarmed && !takesPlannerOpeningTurn(host, mode)) {
|
|
14483
14639
|
return;
|
|
14484
14640
|
}
|
|
14485
14641
|
await runInitialQuery(host, context, options, resume, promptDelivery);
|
|
14486
14642
|
}
|
|
14643
|
+
async function prewarmInitialTuiQuery(host, context) {
|
|
14644
|
+
if (host.harnessKind !== "pty" || !host.harness.prewarm) return false;
|
|
14645
|
+
const mode = host.agentMode;
|
|
14646
|
+
const sessionStart = resolveSessionStart(
|
|
14647
|
+
sessionLineageKey(context.taskId, mode, host.config.mode),
|
|
14648
|
+
host.config.workspaceDir,
|
|
14649
|
+
host.config.mode === "code-review" && process.env.CONVEYOR_TUI !== "codex" ? "claude-code" : process.env.CONVEYOR_TUI
|
|
14650
|
+
);
|
|
14651
|
+
if (sessionStart.resume) return false;
|
|
14652
|
+
const promptDelivery = resolvePromptDelivery({
|
|
14653
|
+
harnessKind: host.harnessKind,
|
|
14654
|
+
runnerMode: host.config.mode,
|
|
14655
|
+
isAuto: host.isAuto,
|
|
14656
|
+
agentMode: mode,
|
|
14657
|
+
isFollowUp: false,
|
|
14658
|
+
hasExistingSession: false
|
|
14659
|
+
});
|
|
14660
|
+
const options = {
|
|
14661
|
+
...buildQueryOptions(host, context),
|
|
14662
|
+
promptDelivery,
|
|
14663
|
+
...sessionStart.sessionId ? { sessionId: sessionStart.sessionId } : {}
|
|
14664
|
+
};
|
|
14665
|
+
const initialPrompt = await buildInitialPrompt(
|
|
14666
|
+
host.config.mode,
|
|
14667
|
+
context,
|
|
14668
|
+
host.isAuto,
|
|
14669
|
+
host.agentMode,
|
|
14670
|
+
host.config.packExecution
|
|
14671
|
+
);
|
|
14672
|
+
const { appendSystemPrompt } = selectInitialPromptInput(
|
|
14673
|
+
promptDelivery,
|
|
14674
|
+
initialPrompt,
|
|
14675
|
+
context,
|
|
14676
|
+
options.appendSystemPrompt,
|
|
14677
|
+
host.harnessKind
|
|
14678
|
+
);
|
|
14679
|
+
return host.harness.prewarm({ ...options, appendSystemPrompt });
|
|
14680
|
+
}
|
|
14487
14681
|
async function runFollowUpQuery(host, context, options, resume, followUpContent) {
|
|
14488
14682
|
if (options.promptDelivery === "prefill") {
|
|
14489
14683
|
await runPrefilledFollowUp(host, context, options, resume, followUpContent);
|
|
@@ -14809,7 +15003,10 @@ function handleRetryError(error, context, host, options, prevImageError) {
|
|
|
14809
15003
|
return handleAuthError(context, host, options);
|
|
14810
15004
|
}
|
|
14811
15005
|
if (!isRetriableError(error)) throw error;
|
|
14812
|
-
return {
|
|
15006
|
+
return {
|
|
15007
|
+
action: "continue",
|
|
15008
|
+
lastErrorWasImage: classifyImageError(error) || prevImageError
|
|
15009
|
+
};
|
|
14813
15010
|
}
|
|
14814
15011
|
function handleProcessResult(result, context, host, options) {
|
|
14815
15012
|
if (result.modeRestart || host.isStopped()) return { action: "return" };
|
|
@@ -14826,10 +15023,16 @@ function handleProcessResult(result, context, host, options) {
|
|
|
14826
15023
|
};
|
|
14827
15024
|
}
|
|
14828
15025
|
if (result.staleSession && context.claudeSessionId) {
|
|
14829
|
-
return {
|
|
15026
|
+
return {
|
|
15027
|
+
action: "return_promise",
|
|
15028
|
+
promise: handleStaleSession(context, host, options)
|
|
15029
|
+
};
|
|
14830
15030
|
}
|
|
14831
15031
|
if (result.authError) {
|
|
14832
|
-
return {
|
|
15032
|
+
return {
|
|
15033
|
+
action: "return_promise",
|
|
15034
|
+
promise: handleAuthError(context, host, options)
|
|
15035
|
+
};
|
|
14833
15036
|
}
|
|
14834
15037
|
if (!result.retriable) return { action: "return" };
|
|
14835
15038
|
return {
|
|
@@ -14937,6 +15140,7 @@ var QueryBridge = class {
|
|
|
14937
15140
|
_apiOutageDetail = null;
|
|
14938
15141
|
_keyCycleCount = 0;
|
|
14939
15142
|
_abortController = null;
|
|
15143
|
+
freshPrewarmedInitial = false;
|
|
14940
15144
|
/** Called by SessionRunner when ExitPlanMode triggers a mode transition. */
|
|
14941
15145
|
onModeTransition;
|
|
14942
15146
|
/** Called by tool handlers to soft-stop (abort query, keep session alive). */
|
|
@@ -14992,6 +15196,19 @@ var QueryBridge = class {
|
|
|
14992
15196
|
forceRepaint() {
|
|
14993
15197
|
this.harness.forceRepaint?.();
|
|
14994
15198
|
}
|
|
15199
|
+
/** Warm a fresh interactive task TUI only. It receives no input until SessionRunner's Git gate releases. */
|
|
15200
|
+
async prewarmInitial(context) {
|
|
15201
|
+
try {
|
|
15202
|
+
const warmed = await prewarmInitialTuiQuery(this.buildHost(), context);
|
|
15203
|
+
this.freshPrewarmedInitial = warmed;
|
|
15204
|
+
return warmed;
|
|
15205
|
+
} catch (err) {
|
|
15206
|
+
logger6.warn("TUI prewarm failed; continuing with normal startup", {
|
|
15207
|
+
error: err instanceof Error ? err.message : String(err)
|
|
15208
|
+
});
|
|
15209
|
+
return false;
|
|
15210
|
+
}
|
|
15211
|
+
}
|
|
14995
15212
|
stop() {
|
|
14996
15213
|
this._stopped = true;
|
|
14997
15214
|
this._abortController?.abort();
|
|
@@ -15041,7 +15258,7 @@ var QueryBridge = class {
|
|
|
15041
15258
|
isAuto: this.mode.isAuto,
|
|
15042
15259
|
agentMode: this.mode.effectiveMode,
|
|
15043
15260
|
isFollowUp: false,
|
|
15044
|
-
hasExistingSession: hasExistingSessionFile(context.taskId, this.runnerConfig.workspaceDir, {
|
|
15261
|
+
hasExistingSession: !this.freshPrewarmedInitial && hasExistingSessionFile(context.taskId, this.runnerConfig.workspaceDir, {
|
|
15045
15262
|
agentMode: this.mode.effectiveMode,
|
|
15046
15263
|
runnerMode: this.runnerConfig.mode
|
|
15047
15264
|
})
|
|
@@ -15064,7 +15281,9 @@ var QueryBridge = class {
|
|
|
15064
15281
|
this._abortController = new AbortController();
|
|
15065
15282
|
const host = this.buildHost();
|
|
15066
15283
|
try {
|
|
15067
|
-
|
|
15284
|
+
const freshPrewarmed = !followUpContent && this.freshPrewarmedInitial;
|
|
15285
|
+
this.freshPrewarmedInitial = false;
|
|
15286
|
+
await runSdkQuery(host, context, followUpContent, promptDelivery, freshPrewarmed);
|
|
15068
15287
|
} catch (err) {
|
|
15069
15288
|
const msg = err instanceof Error ? err.message : String(err);
|
|
15070
15289
|
const isAbort = this._stopped || /abort/i.test(msg);
|
|
@@ -15781,7 +16000,10 @@ var SessionRunner = class _SessionRunner {
|
|
|
15781
16000
|
});
|
|
15782
16001
|
const initialMode = config.agentMode ?? (config.runnerMode === "pm" ? config.isAuto ? "auto" : "discovery" : "building");
|
|
15783
16002
|
this.mode = new ModeController(initialMode, config.runnerMode, config.isAuto);
|
|
15784
|
-
const lifecycleConfig = {
|
|
16003
|
+
const lifecycleConfig = {
|
|
16004
|
+
...DEFAULT_LIFECYCLE_CONFIG,
|
|
16005
|
+
...config.lifecycle
|
|
16006
|
+
};
|
|
15785
16007
|
this.lifecycle = new Lifecycle(lifecycleConfig, {
|
|
15786
16008
|
onHeartbeat: () => {
|
|
15787
16009
|
const loopStatus = this.refreshLoopStatus();
|
|
@@ -16140,6 +16362,10 @@ var SessionRunner = class _SessionRunner {
|
|
|
16140
16362
|
await this.shutdown("error");
|
|
16141
16363
|
return;
|
|
16142
16364
|
}
|
|
16365
|
+
this.mode.applyServerMode(this.fullContext?.agentMode, this.fullContext?.isAuto);
|
|
16366
|
+
this.mode.resolveInitialMode(this.taskContext);
|
|
16367
|
+
this.queryBridge = this.createQueryBridge();
|
|
16368
|
+
const prewarmInitial = this.queryBridge.prewarmInitial(this.fullContext);
|
|
16143
16369
|
const gitState = await awaitGitReady({
|
|
16144
16370
|
onLog: (m) => process.stderr.write(`[conveyor-agent] ${m}
|
|
16145
16371
|
`)
|
|
@@ -16148,6 +16374,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
16148
16374
|
const message = gitState === "failed" ? "Workspace git preparation failed (see pod logs)" : "Workspace git preparation timed out (see pod logs)";
|
|
16149
16375
|
this.connection.sendEvent({ type: "error", message });
|
|
16150
16376
|
await this.callbacks.onEvent({ type: "error", message });
|
|
16377
|
+
await this.queryBridge.dispose();
|
|
16151
16378
|
await this.shutdown("error");
|
|
16152
16379
|
return;
|
|
16153
16380
|
}
|
|
@@ -16161,8 +16388,8 @@ var SessionRunner = class _SessionRunner {
|
|
|
16161
16388
|
process.stderr.write("[conveyor-agent] WARNING: task-branch checkout failed\n");
|
|
16162
16389
|
}
|
|
16163
16390
|
if (ok) void reportBootMilestone({ key: "branch_ready" });
|
|
16164
|
-
await this.refreshSkillsForCheckout();
|
|
16165
16391
|
}
|
|
16392
|
+
if (this.fullContext?.githubBranch) await this.refreshSkillsForCheckout();
|
|
16166
16393
|
if (!this.stopped) {
|
|
16167
16394
|
this.lifecycle.startGitFlush();
|
|
16168
16395
|
}
|
|
@@ -16177,13 +16404,15 @@ var SessionRunner = class _SessionRunner {
|
|
|
16177
16404
|
}
|
|
16178
16405
|
}
|
|
16179
16406
|
this.workspaceCommands?.notifyWorkspaceReady();
|
|
16180
|
-
this.mode.applyServerMode(this.fullContext?.agentMode, this.fullContext?.isAuto);
|
|
16181
|
-
this.mode.resolveInitialMode(this.taskContext);
|
|
16182
16407
|
if (this.fullContext?.isAuto && PRE_BUILD_TASK_STATUSES.has(this.taskContext.status) && this.mode.isBuildCapable && hasTaskPlan(this.fullContext.plan)) {
|
|
16183
16408
|
void this.connection.triggerIdentification().catch(() => {
|
|
16184
16409
|
});
|
|
16185
16410
|
}
|
|
16186
|
-
|
|
16411
|
+
await prewarmInitial;
|
|
16412
|
+
if (this.stopped) {
|
|
16413
|
+
await this.queryBridge.dispose();
|
|
16414
|
+
return;
|
|
16415
|
+
}
|
|
16187
16416
|
this.logInitialization();
|
|
16188
16417
|
const staleBatch = [...this.pendingMessages];
|
|
16189
16418
|
const didExecuteInitialQuery = await this.executeInitialMode();
|
|
@@ -16376,7 +16605,11 @@ var SessionRunner = class _SessionRunner {
|
|
|
16376
16605
|
}
|
|
16377
16606
|
if (delivery === "prefill") {
|
|
16378
16607
|
await this.setState("waiting_for_input");
|
|
16379
|
-
await this.callbacks.onEvent({
|
|
16608
|
+
await this.callbacks.onEvent({
|
|
16609
|
+
type: "execute_mode",
|
|
16610
|
+
mode: effectiveMode,
|
|
16611
|
+
delivery
|
|
16612
|
+
});
|
|
16380
16613
|
if (this.pendingMessages.length > 0) {
|
|
16381
16614
|
if (!this.stopped) await this.setState("idle");
|
|
16382
16615
|
return false;
|
|
@@ -16389,7 +16622,10 @@ var SessionRunner = class _SessionRunner {
|
|
|
16389
16622
|
}
|
|
16390
16623
|
} else {
|
|
16391
16624
|
await this.setState("running");
|
|
16392
|
-
await this.callbacks.onEvent({
|
|
16625
|
+
await this.callbacks.onEvent({
|
|
16626
|
+
type: "execute_mode",
|
|
16627
|
+
mode: effectiveMode
|
|
16628
|
+
});
|
|
16393
16629
|
await this.executeQuery(void 0, delivery);
|
|
16394
16630
|
await this.requeueWedgedInitialQuery(delivery);
|
|
16395
16631
|
}
|
|
@@ -16872,7 +17108,11 @@ var SessionRunner = class _SessionRunner {
|
|
|
16872
17108
|
const oldMode = this.mode.effectiveMode;
|
|
16873
17109
|
process.stderr.write(`[conveyor-agent] Mode transition: ${oldMode} \u2192 ${newMode}
|
|
16874
17110
|
`);
|
|
16875
|
-
this.connection.sendEvent({
|
|
17111
|
+
this.connection.sendEvent({
|
|
17112
|
+
type: "mode_transition",
|
|
17113
|
+
from: oldMode,
|
|
17114
|
+
to: newMode
|
|
17115
|
+
});
|
|
16876
17116
|
this.mode.pendingModeRestart = true;
|
|
16877
17117
|
this.connection.emitModeChanged(newMode);
|
|
16878
17118
|
this.softStop();
|
|
@@ -128,7 +128,7 @@ function errText(err) {
|
|
|
128
128
|
}
|
|
129
129
|
async function syncTaskBranchToRepo(deps, paths) {
|
|
130
130
|
const { git, log } = deps;
|
|
131
|
-
const { branch
|
|
131
|
+
const { branch } = deps.bundle.gitPlan;
|
|
132
132
|
try {
|
|
133
133
|
await git(["remote", "set-url", "origin", paths.remoteUrl], {
|
|
134
134
|
cwd: paths.repoDir,
|
|
@@ -140,6 +140,18 @@ async function syncTaskBranchToRepo(deps, paths) {
|
|
|
140
140
|
}
|
|
141
141
|
const credentialFailure = await persistCredentialHelper(deps, paths);
|
|
142
142
|
if (credentialFailure) return credentialFailure;
|
|
143
|
+
const [, resetSucceeded] = await Promise.all([
|
|
144
|
+
warmBaseBranch(deps, paths),
|
|
145
|
+
resetTrackedChanges(deps, paths)
|
|
146
|
+
]);
|
|
147
|
+
if (!resetSucceeded) return { state: "failed", reason: "pre-checkout reset failed" };
|
|
148
|
+
log.info(`[boot] Repo remote ready; agent will checkout ${branch}`);
|
|
149
|
+
return { state: "ready" };
|
|
150
|
+
}
|
|
151
|
+
async function warmBaseBranch(deps, paths) {
|
|
152
|
+
const { git, log } = deps;
|
|
153
|
+
const { baseBranch } = deps.bundle.gitPlan;
|
|
154
|
+
const started = performance.now();
|
|
143
155
|
try {
|
|
144
156
|
await git(["fetch", "origin", `+refs/heads/${baseBranch}:refs/remotes/origin/${baseBranch}`], {
|
|
145
157
|
cwd: paths.repoDir,
|
|
@@ -147,17 +159,24 @@ async function syncTaskBranchToRepo(deps, paths) {
|
|
|
147
159
|
});
|
|
148
160
|
} catch (err) {
|
|
149
161
|
log.warn(`[boot] WARN: fetch origin/${baseBranch} failed: ${errText(err)}`);
|
|
162
|
+
} finally {
|
|
163
|
+
log.info(`[boot] step=gitFetchBase ms=${Math.round(performance.now() - started)}`);
|
|
150
164
|
}
|
|
165
|
+
}
|
|
166
|
+
async function resetTrackedChanges(deps, paths) {
|
|
167
|
+
const { git, log } = deps;
|
|
168
|
+
const started = performance.now();
|
|
151
169
|
try {
|
|
152
170
|
await git(["reset", "--hard", "HEAD"], { cwd: paths.repoDir, timeoutMs: QUICK_GIT_TIMEOUT_MS });
|
|
171
|
+
return true;
|
|
153
172
|
} catch (err) {
|
|
154
173
|
log.error(
|
|
155
174
|
`[boot] ERROR: failed to clean tracked repo changes before checkout: ${errText(err)}`
|
|
156
175
|
);
|
|
157
|
-
return
|
|
176
|
+
return false;
|
|
177
|
+
} finally {
|
|
178
|
+
log.info(`[boot] step=gitResetTracked ms=${Math.round(performance.now() - started)}`);
|
|
158
179
|
}
|
|
159
|
-
log.info(`[boot] Repo remote ready; agent will checkout ${branch}`);
|
|
160
|
-
return { state: "ready" };
|
|
161
180
|
}
|
|
162
181
|
async function persistCredentialHelper(deps, paths) {
|
|
163
182
|
try {
|
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
readWorkspaceBytes,
|
|
6
6
|
statWorkspacePath,
|
|
7
7
|
workspacePathExists
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-JBGPARLG.js";
|
|
9
9
|
import {
|
|
10
10
|
reportBootMilestone
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-Q4FQOJ7D.js";
|
|
12
12
|
import {
|
|
13
13
|
runSetupCommand,
|
|
14
14
|
runStartCommand,
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
WorkspaceCommandSupervisor,
|
|
8
8
|
startWorkspaceCommandsAfterConnect,
|
|
9
9
|
stopWorkspaceCommands
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-SKTNJNXQ.js";
|
|
11
11
|
import {
|
|
12
12
|
DEFAULT_SONNET_MODEL,
|
|
13
13
|
PtyHarness,
|
|
@@ -28,8 +28,8 @@ import {
|
|
|
28
28
|
runUsageProbe,
|
|
29
29
|
sampleKeyUsage,
|
|
30
30
|
usesNativeUsageReporting
|
|
31
|
-
} from "./chunk-
|
|
32
|
-
import "./chunk-
|
|
31
|
+
} from "./chunk-POK3QCGN.js";
|
|
32
|
+
import "./chunk-37J5MMQT.js";
|
|
33
33
|
import {
|
|
34
34
|
inheritedEnv,
|
|
35
35
|
resolvePtySpawn,
|
|
@@ -45,8 +45,8 @@ import {
|
|
|
45
45
|
createServiceLogger,
|
|
46
46
|
fetchBootstrap,
|
|
47
47
|
loadConveyorConfig
|
|
48
|
-
} from "./chunk-
|
|
49
|
-
import "./chunk-
|
|
48
|
+
} from "./chunk-JBGPARLG.js";
|
|
49
|
+
import "./chunk-Q4FQOJ7D.js";
|
|
50
50
|
import "./chunk-W4LZ7R6Z.js";
|
|
51
51
|
import "./chunk-372R6E4C.js";
|
|
52
52
|
import "./chunk-IA45XHOA.js";
|
|
@@ -1206,7 +1206,7 @@ function wireSpawnChildren(mode, connection, supervisors, logger7) {
|
|
|
1206
1206
|
|
|
1207
1207
|
// src/cli.ts
|
|
1208
1208
|
if (process.argv[2] === "boot") {
|
|
1209
|
-
const { runBoot } = await import("./boot-
|
|
1209
|
+
const { runBoot } = await import("./boot-Z3EBJ7GX.js");
|
|
1210
1210
|
process.exit(await runBoot(process.argv.slice(3)));
|
|
1211
1211
|
}
|
|
1212
1212
|
if (isLegacyEntrypointLaunch(process.env)) {
|
|
@@ -1459,7 +1459,7 @@ if (!RUNNER_MODES.includes(CONVEYOR_MODE)) {
|
|
|
1459
1459
|
process.exit(1);
|
|
1460
1460
|
}
|
|
1461
1461
|
if (CONVEYOR_MODE === "serving") {
|
|
1462
|
-
const { runServingSession } = await import("./serve-boot-
|
|
1462
|
+
const { runServingSession } = await import("./serve-boot-4BUN4U44.js");
|
|
1463
1463
|
exitContext.runnerMode = "serving";
|
|
1464
1464
|
exitContext.sessionId = process.env.CONVEYOR_SESSION_ID ?? exitContext.sessionId;
|
|
1465
1465
|
const outcome = await runServingSession({
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SessionRunner,
|
|
3
3
|
unshallowRepo
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-POK3QCGN.js";
|
|
5
|
+
import "./chunk-37J5MMQT.js";
|
|
6
6
|
import "./chunk-W5INK3NE.js";
|
|
7
7
|
import {
|
|
8
8
|
AgentConnection,
|
|
@@ -17,8 +17,8 @@ import {
|
|
|
17
17
|
stageAndCommit,
|
|
18
18
|
updateRemoteToken,
|
|
19
19
|
workspacePathExists
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
20
|
+
} from "./chunk-JBGPARLG.js";
|
|
21
|
+
import "./chunk-Q4FQOJ7D.js";
|
|
22
22
|
import {
|
|
23
23
|
runAuthTokenCommand,
|
|
24
24
|
runSetupCommand,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
WorkspaceCommandSupervisor
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SKTNJNXQ.js";
|
|
4
4
|
import {
|
|
5
5
|
AgentConnection,
|
|
6
6
|
CodespacePortVisibility,
|
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
createServiceLogger,
|
|
12
12
|
ensureOnTaskBranch,
|
|
13
13
|
loadConveyorConfig
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-JBGPARLG.js";
|
|
15
|
+
import "./chunk-Q4FQOJ7D.js";
|
|
16
16
|
import "./chunk-W4LZ7R6Z.js";
|
|
17
17
|
import "./chunk-IA45XHOA.js";
|
|
18
18
|
import "./chunk-SQM2BQ7H.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rallycry/conveyor-agent",
|
|
3
|
-
"version": "11.0.
|
|
3
|
+
"version": "11.0.20",
|
|
4
4
|
"description": "Conveyor Agent Runner v10 - PTY harness for the task chat (SDK harness for audit/project-chat). Agent-as-User architecture with BaseService patterns. Works locally too.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|