@rallycry/conveyor-agent 7.0.2 → 7.0.3
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.
|
@@ -141,25 +141,7 @@ var AgentConnection = class {
|
|
|
141
141
|
});
|
|
142
142
|
this.socket.io.on("reconnect", () => {
|
|
143
143
|
process.stderr.write("[conveyor-agent] Reconnected\n");
|
|
144
|
-
|
|
145
|
-
for (const msg of pendingMessages) {
|
|
146
|
-
if (msg.content) {
|
|
147
|
-
if (this.messageCallback) {
|
|
148
|
-
this.messageCallback({ content: msg.content, userId: msg.userId });
|
|
149
|
-
} else {
|
|
150
|
-
this.earlyMessages.push({ content: msg.content, userId: msg.userId });
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}).catch(() => {
|
|
155
|
-
});
|
|
156
|
-
if (this.lastEmittedStatus) {
|
|
157
|
-
void this.call("reportAgentStatus", {
|
|
158
|
-
sessionId: this.config.sessionId,
|
|
159
|
-
status: this.lastEmittedStatus
|
|
160
|
-
}).catch(() => {
|
|
161
|
-
});
|
|
162
|
-
}
|
|
144
|
+
void this.reconnectToSession();
|
|
163
145
|
});
|
|
164
146
|
this.socket.io.on("reconnect_attempt", () => {
|
|
165
147
|
});
|
|
@@ -174,6 +156,53 @@ var AgentConnection = class {
|
|
|
174
156
|
this.socket = null;
|
|
175
157
|
}
|
|
176
158
|
}
|
|
159
|
+
// ── Reconnect with retry ────────────────────────────────────────────
|
|
160
|
+
async reconnectToSession() {
|
|
161
|
+
const maxRetries = 5;
|
|
162
|
+
const baseDelayMs = 2e3;
|
|
163
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
164
|
+
try {
|
|
165
|
+
const { pendingMessages } = await this.call("connectAgent", {
|
|
166
|
+
sessionId: this.config.sessionId
|
|
167
|
+
});
|
|
168
|
+
this.drainPendingMessages(pendingMessages);
|
|
169
|
+
process.stderr.write("[conveyor-agent] Reconnected to session successfully\n");
|
|
170
|
+
if (this.lastEmittedStatus) {
|
|
171
|
+
void this.call("reportAgentStatus", {
|
|
172
|
+
sessionId: this.config.sessionId,
|
|
173
|
+
status: this.lastEmittedStatus
|
|
174
|
+
}).catch(() => {
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
return;
|
|
178
|
+
} catch (err) {
|
|
179
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
180
|
+
const delayMs = baseDelayMs * 2 ** (attempt - 1);
|
|
181
|
+
process.stderr.write(
|
|
182
|
+
`[conveyor-agent] connectAgent failed (attempt ${attempt}/${maxRetries}): ${errMsg} \u2014 retrying in ${delayMs / 1e3}s
|
|
183
|
+
`
|
|
184
|
+
);
|
|
185
|
+
await new Promise((resolve2) => {
|
|
186
|
+
setTimeout(resolve2, delayMs);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
process.stderr.write(
|
|
191
|
+
`[conveyor-agent] Failed to reconnect to session after ${maxRetries} attempts, exiting
|
|
192
|
+
`
|
|
193
|
+
);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
drainPendingMessages(messages) {
|
|
197
|
+
for (const msg of messages) {
|
|
198
|
+
if (!msg.content) continue;
|
|
199
|
+
if (this.messageCallback) {
|
|
200
|
+
this.messageCallback({ content: msg.content, userId: msg.userId });
|
|
201
|
+
} else {
|
|
202
|
+
this.earlyMessages.push({ content: msg.content, userId: msg.userId });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
177
206
|
// ── Callback registration with early-buffer draining ───────────────
|
|
178
207
|
onMessage(callback) {
|
|
179
208
|
this.messageCallback = callback;
|
|
@@ -2305,6 +2334,7 @@ Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>`;
|
|
|
2305
2334
|
}
|
|
2306
2335
|
}
|
|
2307
2336
|
const result = await connection.call("createPullRequest", {
|
|
2337
|
+
sessionId: connection.sessionId,
|
|
2308
2338
|
title,
|
|
2309
2339
|
body,
|
|
2310
2340
|
head: branch,
|
|
@@ -4657,6 +4687,9 @@ function handleAutoToolAccess(toolName, input, hasExitedPlanMode, isParentTask)
|
|
|
4657
4687
|
return { behavior: "allow", updatedInput: input };
|
|
4658
4688
|
}
|
|
4659
4689
|
async function handleExitPlanMode(host, input) {
|
|
4690
|
+
if (host.hasExitedPlanMode) {
|
|
4691
|
+
return { behavior: "allow", updatedInput: input };
|
|
4692
|
+
}
|
|
4660
4693
|
try {
|
|
4661
4694
|
host.syncPlanFile();
|
|
4662
4695
|
const taskProps = await host.connection.getTaskProperties();
|
|
@@ -5223,6 +5256,8 @@ var QueryBridge = class {
|
|
|
5223
5256
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5224
5257
|
logger2.error("Query execution failed", { error: msg });
|
|
5225
5258
|
this.connection.sendEvent({ type: "error", message: msg });
|
|
5259
|
+
} finally {
|
|
5260
|
+
this.mode.pendingModeRestart = false;
|
|
5226
5261
|
}
|
|
5227
5262
|
}
|
|
5228
5263
|
// ── QueryHost construction ──────────────────────────────────────────
|
|
@@ -5431,6 +5466,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
5431
5466
|
if (!this.stopped && this.pendingMessages.length === 0) {
|
|
5432
5467
|
await this.maybeSendPRNudge();
|
|
5433
5468
|
}
|
|
5469
|
+
this.hasCompleted = true;
|
|
5434
5470
|
if (!this.stopped) await this.setState("idle");
|
|
5435
5471
|
} else if (this._state === "error") {
|
|
5436
5472
|
await this.setState("idle");
|
|
@@ -6624,7 +6660,7 @@ var ProjectRunner = class {
|
|
|
6624
6660
|
}
|
|
6625
6661
|
// ── Event wiring ───────────────────────────────────────────────────────
|
|
6626
6662
|
wireEventHandlers() {
|
|
6627
|
-
this.connection.onTaskAssignment((assignment) => this.handleAssignment(assignment));
|
|
6663
|
+
this.connection.onTaskAssignment((assignment) => void this.handleAssignment(assignment));
|
|
6628
6664
|
this.connection.onStopTask((data) => this.handleStopTask(data.taskId));
|
|
6629
6665
|
this.connection.onShutdown(() => void this.stop());
|
|
6630
6666
|
this.connection.onChatMessage((msg) => {
|
|
@@ -6682,13 +6718,42 @@ var ProjectRunner = class {
|
|
|
6682
6718
|
}
|
|
6683
6719
|
}
|
|
6684
6720
|
// ── Task management ────────────────────────────────────────────────────
|
|
6685
|
-
|
|
6721
|
+
async killAgent(agent, taskId) {
|
|
6722
|
+
const shortId = taskId.slice(0, 8);
|
|
6723
|
+
if (agent.process.exitCode !== null) {
|
|
6724
|
+
logger6.info("Agent process already exited", { taskId: shortId });
|
|
6725
|
+
return;
|
|
6726
|
+
}
|
|
6727
|
+
logger6.info("Killing agent process", { taskId: shortId });
|
|
6728
|
+
agent.process.kill("SIGTERM");
|
|
6729
|
+
await new Promise((resolve2) => {
|
|
6730
|
+
const timer = setTimeout(() => {
|
|
6731
|
+
if (agent.process.exitCode === null) {
|
|
6732
|
+
logger6.warn("Agent did not exit after SIGTERM, sending SIGKILL", { taskId: shortId });
|
|
6733
|
+
agent.process.kill("SIGKILL");
|
|
6734
|
+
}
|
|
6735
|
+
resolve2();
|
|
6736
|
+
}, STOP_TIMEOUT_MS);
|
|
6737
|
+
agent.process.on("exit", () => {
|
|
6738
|
+
clearTimeout(timer);
|
|
6739
|
+
resolve2();
|
|
6740
|
+
});
|
|
6741
|
+
});
|
|
6742
|
+
}
|
|
6743
|
+
// oxlint-disable-next-line max-lines-per-function -- re-assignment logic requires sequential checks
|
|
6744
|
+
async handleAssignment(assignment) {
|
|
6686
6745
|
const { taskId, mode } = assignment;
|
|
6687
6746
|
const shortId = taskId.slice(0, 8);
|
|
6688
6747
|
const agentKey = assignment.agentMode === "code-review" ? `${taskId}:code-review` : taskId;
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6748
|
+
const existing = this.activeAgents.get(agentKey);
|
|
6749
|
+
if (existing) {
|
|
6750
|
+
if (existing.process.exitCode === null) {
|
|
6751
|
+
logger6.info("Re-assignment received, killing existing agent", { taskId: shortId });
|
|
6752
|
+
await this.killAgent(existing, taskId);
|
|
6753
|
+
} else {
|
|
6754
|
+
logger6.info("Stale agent entry (process already exited), cleaning up", { taskId: shortId });
|
|
6755
|
+
}
|
|
6756
|
+
this.activeAgents.delete(agentKey);
|
|
6692
6757
|
}
|
|
6693
6758
|
if (this.activeAgents.size >= MAX_CONCURRENT) {
|
|
6694
6759
|
logger6.warn("Max concurrent agents reached", { maxConcurrent: MAX_CONCURRENT });
|
|
@@ -6730,16 +6795,11 @@ var ProjectRunner = class {
|
|
|
6730
6795
|
}
|
|
6731
6796
|
}
|
|
6732
6797
|
handleStopTask(taskId) {
|
|
6733
|
-
|
|
6734
|
-
|
|
6798
|
+
const agentKey = this.activeAgents.has(taskId) ? taskId : `${taskId}:code-review`;
|
|
6799
|
+
const agent = this.activeAgents.get(agentKey);
|
|
6735
6800
|
if (!agent) return;
|
|
6736
6801
|
logger6.info("Stopping task", { taskId: taskId.slice(0, 8) });
|
|
6737
|
-
agent.
|
|
6738
|
-
const timer = setTimeout(() => {
|
|
6739
|
-
if (this.activeAgents.has(taskId)) agent.process.kill("SIGKILL");
|
|
6740
|
-
}, STOP_TIMEOUT_MS);
|
|
6741
|
-
agent.process.on("exit", () => {
|
|
6742
|
-
clearTimeout(timer);
|
|
6802
|
+
void this.killAgent(agent, taskId).then(() => {
|
|
6743
6803
|
if (agent.usesWorktree) {
|
|
6744
6804
|
try {
|
|
6745
6805
|
removeWorktree(this.projectDir, taskId);
|
|
@@ -7027,4 +7087,4 @@ export {
|
|
|
7027
7087
|
removeWorktree,
|
|
7028
7088
|
ProjectRunner
|
|
7029
7089
|
};
|
|
7030
|
-
//# sourceMappingURL=chunk-
|
|
7090
|
+
//# sourceMappingURL=chunk-L7ZH423N.js.map
|