@tryarcanist/cli 0.1.100 → 0.1.101
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/index.js +49 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -862,6 +862,22 @@ function noChangeOutcomeCopy(reason) {
|
|
|
862
862
|
}
|
|
863
863
|
}
|
|
864
864
|
|
|
865
|
+
// ../../shared/session/transient-disconnect.ts
|
|
866
|
+
var TRANSIENT_DISCONNECT_VISIBILITY_MS = 15e3;
|
|
867
|
+
function nextDisconnectMask(mask, previous, current, now) {
|
|
868
|
+
if (!current || current.sandboxSubstate !== "reconnecting") return null;
|
|
869
|
+
if (mask) return mask;
|
|
870
|
+
if (!previous || previous.sandboxSubstate === "reconnecting") return null;
|
|
871
|
+
return { since: now, heldPhase: previous.phase, heldSubstate: previous.sandboxSubstate ?? "none" };
|
|
872
|
+
}
|
|
873
|
+
function isDisconnectMaskActive(mask, now) {
|
|
874
|
+
return mask !== null && now - mask.since < TRANSIENT_DISCONNECT_VISIBILITY_MS;
|
|
875
|
+
}
|
|
876
|
+
function applyDisconnectMask(view, mask, now) {
|
|
877
|
+
if (!isDisconnectMaskActive(mask, now)) return view;
|
|
878
|
+
return { ...view, phase: mask.heldPhase, sandboxSubstate: mask.heldSubstate };
|
|
879
|
+
}
|
|
880
|
+
|
|
865
881
|
// ../../shared/transcript/malformed-search.ts
|
|
866
882
|
var MALFORMED_SEARCH_BLOCKED_TRANSCRIPT_PREFIX = "Arcanist blocked this malformed search command before execution.";
|
|
867
883
|
var BASH_UNMATCHED_QUOTE_EOF_RE = /\/bin\/bash:\s+-c:\s+line\s+\d+:\s+unexpected EOF while looking for matching [`'"][`'"]?/i;
|
|
@@ -1244,6 +1260,24 @@ function projectRetryStatus(data, index) {
|
|
|
1244
1260
|
...typeof data?.retryAfterMs === "number" ? { retryAfterMs: data.retryAfterMs } : {}
|
|
1245
1261
|
};
|
|
1246
1262
|
}
|
|
1263
|
+
function projectPromptRetrying(data, index) {
|
|
1264
|
+
const attempt = typeof data?.attempt === "number" ? data.attempt : Number(data?.attempt ?? 0);
|
|
1265
|
+
const cap = typeof data?.cap === "number" ? data.cap : void 0;
|
|
1266
|
+
const retryPromptId = typeof data?.retryPromptId === "string" ? data.retryPromptId : resolvePromptId(data);
|
|
1267
|
+
return {
|
|
1268
|
+
type: "retry_status",
|
|
1269
|
+
// Key off retryPromptId (always present in the emitted payload, unique per
|
|
1270
|
+
// retry) rather than the index, so the id is stable across replays. The
|
|
1271
|
+
// event's `timestamp` lives at the top level, not inside `data`.
|
|
1272
|
+
id: `pr-retry-${retryPromptId ?? index}`,
|
|
1273
|
+
...retryPromptId ? { promptId: retryPromptId } : {},
|
|
1274
|
+
attempt,
|
|
1275
|
+
message: "Sandbox dropped mid-task; retrying on a fresh sandbox",
|
|
1276
|
+
scope: "sandbox_disconnect",
|
|
1277
|
+
...cap !== void 0 ? { maxAttempts: cap } : {},
|
|
1278
|
+
...typeof data?.reason === "string" ? { reason: data.reason } : {}
|
|
1279
|
+
};
|
|
1280
|
+
}
|
|
1247
1281
|
function projectBranchChanged(data, index) {
|
|
1248
1282
|
return {
|
|
1249
1283
|
type: "branch_changed",
|
|
@@ -1515,6 +1549,9 @@ function flattenSessionEvents(raw) {
|
|
|
1515
1549
|
case "retry_status":
|
|
1516
1550
|
pushEvent(state, projectRetryStatus(data, state.merged.length));
|
|
1517
1551
|
break;
|
|
1552
|
+
case "prompt_retrying":
|
|
1553
|
+
pushEvent(state, projectPromptRetrying(data, state.merged.length));
|
|
1554
|
+
break;
|
|
1518
1555
|
case "branch_changed":
|
|
1519
1556
|
pushEvent(state, projectBranchChanged(data, state.merged.length));
|
|
1520
1557
|
break;
|
|
@@ -2139,6 +2176,12 @@ function formatStatusLine(status) {
|
|
|
2139
2176
|
if (status.spawnDurationMs != null) details.push(`spawn ${(status.spawnDurationMs / 1e3).toFixed(1)}s`);
|
|
2140
2177
|
return details.length > 0 ? `[status] ${phaseLabel} | ${details.join(" | ")}` : `[status] ${phaseLabel}`;
|
|
2141
2178
|
}
|
|
2179
|
+
function advanceStatusDisconnectMask(status, mask, lastView, now) {
|
|
2180
|
+
const view = status.phase ? { phase: status.phase, sandboxSubstate: status.sandboxSubstate } : null;
|
|
2181
|
+
const nextMask = nextDisconnectMask(mask, lastView, view, now);
|
|
2182
|
+
const displayStatus = view ? { ...status, ...applyDisconnectMask(view, nextMask, now) } : status;
|
|
2183
|
+
return { displayStatus, mask: nextMask, view };
|
|
2184
|
+
}
|
|
2142
2185
|
async function printNoChangeOutcome(config, sessionId) {
|
|
2143
2186
|
try {
|
|
2144
2187
|
const data = await apiFetch(
|
|
@@ -2197,6 +2240,8 @@ async function watchCommand(sessionId, options, command) {
|
|
|
2197
2240
|
let afterSequence = initialAfterSequence;
|
|
2198
2241
|
let lastStatusLine = null;
|
|
2199
2242
|
let textOpen = false;
|
|
2243
|
+
let disconnectMask = null;
|
|
2244
|
+
let lastStatusView = null;
|
|
2200
2245
|
if (!json) console.log(`Watching session ${sessionId}...`);
|
|
2201
2246
|
try {
|
|
2202
2247
|
while (true) {
|
|
@@ -2208,7 +2253,10 @@ async function watchCommand(sessionId, options, command) {
|
|
|
2208
2253
|
const parsed = parseSsePayload(payload);
|
|
2209
2254
|
const receivedFullPage = parsed.events.length >= pageSize;
|
|
2210
2255
|
if (!json && parsed.status) {
|
|
2211
|
-
const
|
|
2256
|
+
const advanced = advanceStatusDisconnectMask(parsed.status, disconnectMask, lastStatusView, Date.now());
|
|
2257
|
+
disconnectMask = advanced.mask;
|
|
2258
|
+
lastStatusView = advanced.view;
|
|
2259
|
+
const nextStatusLine = formatStatusLine(advanced.displayStatus);
|
|
2212
2260
|
if (nextStatusLine !== lastStatusLine) {
|
|
2213
2261
|
if (textOpen) {
|
|
2214
2262
|
process.stdout.write("\n");
|