@rallycry/conveyor-agent 6.0.5 → 6.0.7
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.
|
@@ -960,6 +960,7 @@ var RECONNECT_BASE_MS = 1e3;
|
|
|
960
960
|
var RECONNECT_MAX_MS = 3e4;
|
|
961
961
|
var TunnelClient = class _TunnelClient {
|
|
962
962
|
static STABLE_MS = 3e4;
|
|
963
|
+
static MAX_RECONNECT_ATTEMPTS = 10;
|
|
963
964
|
apiUrl;
|
|
964
965
|
token;
|
|
965
966
|
localPort;
|
|
@@ -968,6 +969,7 @@ var TunnelClient = class _TunnelClient {
|
|
|
968
969
|
reconnectAttempts = 0;
|
|
969
970
|
reconnectTimer = null;
|
|
970
971
|
connectedAt = 0;
|
|
972
|
+
loggedNoWebSocket = false;
|
|
971
973
|
constructor(apiUrl, token, localPort) {
|
|
972
974
|
this.apiUrl = apiUrl;
|
|
973
975
|
this.token = token;
|
|
@@ -975,6 +977,13 @@ var TunnelClient = class _TunnelClient {
|
|
|
975
977
|
}
|
|
976
978
|
connect() {
|
|
977
979
|
if (this.stopped) return;
|
|
980
|
+
if (typeof WebSocket === "undefined") {
|
|
981
|
+
if (!this.loggedNoWebSocket) {
|
|
982
|
+
logger2.warn("WebSocket not available in this environment, tunnel disabled");
|
|
983
|
+
this.loggedNoWebSocket = true;
|
|
984
|
+
}
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
978
987
|
const wsUrl = this.apiUrl.replace(/^http/, "ws").replace(/\/$/, "");
|
|
979
988
|
const url = `${wsUrl}/api/tunnel?token=${encodeURIComponent(this.token)}`;
|
|
980
989
|
try {
|
|
@@ -990,7 +999,8 @@ var TunnelClient = class _TunnelClient {
|
|
|
990
999
|
logger2.info("Tunnel connected", { port: this.localPort });
|
|
991
1000
|
});
|
|
992
1001
|
this.ws.addEventListener("close", (event) => {
|
|
993
|
-
|
|
1002
|
+
const closeEvent = event;
|
|
1003
|
+
logger2.info("Tunnel disconnected", { code: closeEvent.code, reason: closeEvent.reason });
|
|
994
1004
|
this.scheduleReconnect();
|
|
995
1005
|
});
|
|
996
1006
|
this.ws.addEventListener("error", (event) => {
|
|
@@ -998,7 +1008,8 @@ var TunnelClient = class _TunnelClient {
|
|
|
998
1008
|
logger2.warn("Tunnel error", { error: msg });
|
|
999
1009
|
});
|
|
1000
1010
|
this.ws.addEventListener("message", (event) => {
|
|
1001
|
-
|
|
1011
|
+
const messageEvent = event;
|
|
1012
|
+
this.handleMessage(messageEvent.data);
|
|
1002
1013
|
});
|
|
1003
1014
|
}
|
|
1004
1015
|
disconnect() {
|
|
@@ -1014,12 +1025,18 @@ var TunnelClient = class _TunnelClient {
|
|
|
1014
1025
|
}
|
|
1015
1026
|
scheduleReconnect() {
|
|
1016
1027
|
if (this.stopped) return;
|
|
1017
|
-
if (Date.now() - this.connectedAt >= _TunnelClient.STABLE_MS) {
|
|
1028
|
+
if (this.connectedAt > 0 && Date.now() - this.connectedAt >= _TunnelClient.STABLE_MS) {
|
|
1018
1029
|
this.reconnectAttempts = 0;
|
|
1019
1030
|
}
|
|
1031
|
+
if (this.reconnectAttempts >= _TunnelClient.MAX_RECONNECT_ATTEMPTS) {
|
|
1032
|
+
logger2.warn("Tunnel gave up after max reconnect attempts", {
|
|
1033
|
+
attempts: this.reconnectAttempts
|
|
1034
|
+
});
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1020
1037
|
const delay = Math.min(RECONNECT_BASE_MS * 2 ** this.reconnectAttempts, RECONNECT_MAX_MS);
|
|
1021
1038
|
this.reconnectAttempts++;
|
|
1022
|
-
logger2.
|
|
1039
|
+
logger2.debug("Tunnel reconnecting", { delay, attempt: this.reconnectAttempts });
|
|
1023
1040
|
this.reconnectTimer = setTimeout(() => this.connect(), delay);
|
|
1024
1041
|
}
|
|
1025
1042
|
// ---------------------------------------------------------------------------
|
|
@@ -1141,7 +1158,8 @@ var TunnelClient = class _TunnelClient {
|
|
|
1141
1158
|
this.send(JSON.stringify({ type: "ws-open", id }));
|
|
1142
1159
|
});
|
|
1143
1160
|
localWs.addEventListener("message", (event) => {
|
|
1144
|
-
const
|
|
1161
|
+
const messageEvent = event;
|
|
1162
|
+
const data = typeof messageEvent.data === "string" ? messageEvent.data : String(messageEvent.data);
|
|
1145
1163
|
this.send(JSON.stringify({ type: "ws-data", id, data }));
|
|
1146
1164
|
});
|
|
1147
1165
|
localWs.addEventListener("close", () => {
|
|
@@ -1228,10 +1246,6 @@ async function processAssistantEvent(event, host, turnToolCalls) {
|
|
|
1228
1246
|
if (turnTextParts.length > 0) {
|
|
1229
1247
|
host.connection.postChatMessage(turnTextParts.join("\n\n"));
|
|
1230
1248
|
}
|
|
1231
|
-
if (turnToolCalls.length > 0) {
|
|
1232
|
-
host.connection.sendEvent({ type: "turn_end", toolCalls: [...turnToolCalls] });
|
|
1233
|
-
turnToolCalls.length = 0;
|
|
1234
|
-
}
|
|
1235
1249
|
}
|
|
1236
1250
|
var API_ERROR_PATTERN = /API Error: [45]\d\d/;
|
|
1237
1251
|
var IMAGE_ERROR_PATTERN = /Could not process image/i;
|
|
@@ -1473,6 +1487,17 @@ var API_ERROR_PATTERN2 = /API Error: [45]\d\d/;
|
|
|
1473
1487
|
function stopTypingIfNeeded(host, isTyping) {
|
|
1474
1488
|
if (isTyping) host.connection.sendTypingStop();
|
|
1475
1489
|
}
|
|
1490
|
+
function flushPendingToolCalls(host, turnToolCalls) {
|
|
1491
|
+
if (turnToolCalls.length === 0) return;
|
|
1492
|
+
for (let i = 0; i < turnToolCalls.length; i++) {
|
|
1493
|
+
if (i < host.pendingToolOutputs.length) {
|
|
1494
|
+
turnToolCalls[i].output = host.pendingToolOutputs[i];
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
host.connection.sendEvent({ type: "turn_end", toolCalls: [...turnToolCalls] });
|
|
1498
|
+
turnToolCalls.length = 0;
|
|
1499
|
+
host.pendingToolOutputs.length = 0;
|
|
1500
|
+
}
|
|
1476
1501
|
async function processSystemCase(event, host, context, state) {
|
|
1477
1502
|
if (event.subtype === "init") {
|
|
1478
1503
|
const stored = await handleSystemEvent(event, host, context, state.sessionIdStored);
|
|
@@ -1509,6 +1534,7 @@ async function processResultCase(event, host, context, startTime, state) {
|
|
|
1509
1534
|
);
|
|
1510
1535
|
if (info.stoppedTyping) state.isTyping = false;
|
|
1511
1536
|
state.retriable = info.retriable;
|
|
1537
|
+
if (!info.retriable) state.sawApiError = false;
|
|
1512
1538
|
state.resultSummary = info.resultSummary;
|
|
1513
1539
|
if (info.staleSession) state.staleSession = true;
|
|
1514
1540
|
if (info.authError) state.authError = true;
|
|
@@ -1531,6 +1557,7 @@ async function processEvents(events, context, host) {
|
|
|
1531
1557
|
};
|
|
1532
1558
|
for await (const event of events) {
|
|
1533
1559
|
if (host.isStopped()) break;
|
|
1560
|
+
flushPendingToolCalls(host, state.turnToolCalls);
|
|
1534
1561
|
const now = Date.now();
|
|
1535
1562
|
if (now - lastStatusEmit >= STATUS_REEMIT_INTERVAL_MS) {
|
|
1536
1563
|
host.connection.emitStatus("running");
|
|
@@ -1560,6 +1587,7 @@ async function processEvents(events, context, host) {
|
|
|
1560
1587
|
break;
|
|
1561
1588
|
}
|
|
1562
1589
|
}
|
|
1590
|
+
flushPendingToolCalls(host, state.turnToolCalls);
|
|
1563
1591
|
stopTypingIfNeeded(host, state.isTyping);
|
|
1564
1592
|
return {
|
|
1565
1593
|
retriable: state.retriable || state.sawApiError,
|
|
@@ -1610,6 +1638,7 @@ function buildPackRunnerSystemPrompt(context, config, setupLog) {
|
|
|
1610
1638
|
`- "Open" \u2014 Ready to execute. Use start_child_cloud_build to fire it.`,
|
|
1611
1639
|
`- "InProgress" \u2014 Currently being worked on by a Task Runner. Wait \u2014 it will move to ReviewPR when done.`,
|
|
1612
1640
|
`- "ReviewPR" \u2014 Task Runner finished and opened a PR. Review and merge it.`,
|
|
1641
|
+
`- "Hold" \u2014 PR exists but is on hold for team review. Do not merge \u2014 skip and move on.`,
|
|
1613
1642
|
`- "ReviewDev" \u2014 PR was merged to dev. This child is complete. Move on.`,
|
|
1614
1643
|
`- "Complete" \u2014 Fully done. Move on.`,
|
|
1615
1644
|
``,
|
|
@@ -1626,6 +1655,7 @@ function buildPackRunnerSystemPrompt(context, config, setupLog) {
|
|
|
1626
1655
|
` - "InProgress": A Task Runner is actively working on this child. Do nothing \u2014 wait for it to finish.`,
|
|
1627
1656
|
` - "Open": This is the next child to execute. Fire it with start_child_cloud_build.`,
|
|
1628
1657
|
` - If it fails because the child is missing story points or an agent: notify the team in chat and go idle.`,
|
|
1658
|
+
` - "Hold": On hold \u2014 team must review before merge. Skip.`,
|
|
1629
1659
|
` - "ReviewDev" / "Complete": Already done. Skip.`,
|
|
1630
1660
|
` - "Planning": Not ready. If this is blocking progress, notify the team.`,
|
|
1631
1661
|
``,
|
|
@@ -1633,7 +1663,7 @@ function buildPackRunnerSystemPrompt(context, config, setupLog) {
|
|
|
1633
1663
|
``,
|
|
1634
1664
|
`4. After firing a child build: report which task you fired to chat, then explicitly state you are going idle. The system will relaunch you when the child completes or changes status.`,
|
|
1635
1665
|
``,
|
|
1636
|
-
`5. When ALL children are in "ReviewDev" or "
|
|
1666
|
+
`5. When ALL children are in "ReviewDev", "Complete", or "Hold" (no "Open", "InProgress", or "ReviewPR" remaining): do a final review, summarize results in chat, and mark this parent task complete with force_update_task_status("Complete").`,
|
|
1637
1667
|
``,
|
|
1638
1668
|
`## Important Rules`,
|
|
1639
1669
|
`- Process children ONE at a time, in ordinal order.`,
|
|
@@ -2615,7 +2645,7 @@ function buildForceUpdateTaskStatusTool(connection) {
|
|
|
2615
2645
|
"force_update_task_status",
|
|
2616
2646
|
"EMERGENCY ONLY: Force-override a task's Kanban status. Status transitions happen automatically (building sets InProgress, PR creation sets ReviewPR, merge sets ReviewDev). Only use this if an automatic transition failed or a task is stuck in the wrong status. Omit task_id to update the current task, or provide a child task ID.",
|
|
2617
2647
|
{
|
|
2618
|
-
status: z.enum(["InProgress", "ReviewPR", "ReviewDev", "Complete"]).describe("The new status for the task"),
|
|
2648
|
+
status: z.enum(["InProgress", "ReviewPR", "Hold", "ReviewDev", "Complete"]).describe("The new status for the task"),
|
|
2619
2649
|
task_id: z.string().optional().describe("Child task ID to update. Omit to update the current task.")
|
|
2620
2650
|
},
|
|
2621
2651
|
async ({ status, task_id }) => {
|
|
@@ -3399,7 +3429,8 @@ async function injectTelemetry(cdpClient) {
|
|
|
3399
3429
|
return { success: false, error: result.value };
|
|
3400
3430
|
}
|
|
3401
3431
|
try {
|
|
3402
|
-
|
|
3432
|
+
let parsed = JSON.parse(result.value);
|
|
3433
|
+
if (typeof parsed === "string") parsed = JSON.parse(parsed);
|
|
3403
3434
|
return {
|
|
3404
3435
|
success: parsed.success === true,
|
|
3405
3436
|
patches: parsed.patches
|
|
@@ -4569,6 +4600,7 @@ function buildHooks(host) {
|
|
|
4569
4600
|
output,
|
|
4570
4601
|
isError: false
|
|
4571
4602
|
});
|
|
4603
|
+
host.pendingToolOutputs.push(output);
|
|
4572
4604
|
}
|
|
4573
4605
|
return await Promise.resolve({ continue: true });
|
|
4574
4606
|
}
|
|
@@ -4930,7 +4962,6 @@ var CostTracker = class {
|
|
|
4930
4962
|
|
|
4931
4963
|
// src/runner/plan-sync.ts
|
|
4932
4964
|
import { readdirSync, statSync, readFileSync } from "fs";
|
|
4933
|
-
import { homedir } from "os";
|
|
4934
4965
|
import { join as join3 } from "path";
|
|
4935
4966
|
var PlanSync = class {
|
|
4936
4967
|
planFileSnapshot = /* @__PURE__ */ new Map();
|
|
@@ -4945,7 +4976,7 @@ var PlanSync = class {
|
|
|
4945
4976
|
this.workspaceDir = workspaceDir;
|
|
4946
4977
|
}
|
|
4947
4978
|
getPlanDirs() {
|
|
4948
|
-
return [join3(
|
|
4979
|
+
return [join3(this.workspaceDir, ".claude", "plans")];
|
|
4949
4980
|
}
|
|
4950
4981
|
snapshotPlanFiles() {
|
|
4951
4982
|
this.planFileSnapshot.clear();
|
|
@@ -5300,6 +5331,7 @@ function buildQueryHost(deps) {
|
|
|
5300
5331
|
},
|
|
5301
5332
|
sessionIds: deps.sessionIds,
|
|
5302
5333
|
activeQuery: null,
|
|
5334
|
+
pendingToolOutputs: [],
|
|
5303
5335
|
isStopped: deps.isStopped,
|
|
5304
5336
|
createInputStream: deps.createInputStream,
|
|
5305
5337
|
snapshotPlanFiles: () => deps.planSync.snapshotPlanFiles(),
|
|
@@ -5443,6 +5475,10 @@ var AgentRunner = class {
|
|
|
5443
5475
|
}
|
|
5444
5476
|
this.taskContext._runnerSessionId = randomUUID2();
|
|
5445
5477
|
if (this.taskContext.agentMode) this.agentMode = this.taskContext.agentMode;
|
|
5478
|
+
const pastPlanning = this.taskContext.status !== "Planning" && this.taskContext.status !== "Unidentified";
|
|
5479
|
+
if (this.agentMode === "auto" && pastPlanning) {
|
|
5480
|
+
this.hasExitedPlanMode = true;
|
|
5481
|
+
}
|
|
5446
5482
|
this.logEffectiveSettings();
|
|
5447
5483
|
if (process.env.CODESPACES === "true") unshallowRepo(this.config.workspaceDir);
|
|
5448
5484
|
return true;
|
|
@@ -7308,4 +7344,4 @@ export {
|
|
|
7308
7344
|
ProjectRunner,
|
|
7309
7345
|
FileCache
|
|
7310
7346
|
};
|
|
7311
|
-
//# sourceMappingURL=chunk-
|
|
7347
|
+
//# sourceMappingURL=chunk-ANYHEBDY.js.map
|