@tryarcanist/cli 0.1.100 → 0.1.102
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 -37
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -212,9 +212,6 @@ function getRuntimeOptions(command, options = {}) {
|
|
|
212
212
|
function isJson(command, options = {}) {
|
|
213
213
|
return getRuntimeOptions(command, options).json === true;
|
|
214
214
|
}
|
|
215
|
-
function isQuiet(command, options = {}) {
|
|
216
|
-
return getRuntimeOptions(command, options).quiet === true;
|
|
217
|
-
}
|
|
218
215
|
function writeJson(value) {
|
|
219
216
|
process.stdout.write(`${JSON.stringify(value)}
|
|
220
217
|
`);
|
|
@@ -318,11 +315,6 @@ async function readHiddenPrompt(prompt) {
|
|
|
318
315
|
stdin.on("error", onError);
|
|
319
316
|
});
|
|
320
317
|
}
|
|
321
|
-
function printDeprecatedAlias(alias, replacement, command, options = {}) {
|
|
322
|
-
if (isQuiet(command, options)) return;
|
|
323
|
-
process.stderr.write(`Warning: \`arcanist ${alias}\` is deprecated; use \`arcanist ${replacement}\`.
|
|
324
|
-
`);
|
|
325
|
-
}
|
|
326
318
|
function applyColorEnvironment(options) {
|
|
327
319
|
if (options.noColor === true || !process.stdout.isTTY) {
|
|
328
320
|
process.env.NO_COLOR = "1";
|
|
@@ -862,6 +854,22 @@ function noChangeOutcomeCopy(reason) {
|
|
|
862
854
|
}
|
|
863
855
|
}
|
|
864
856
|
|
|
857
|
+
// ../../shared/session/transient-disconnect.ts
|
|
858
|
+
var TRANSIENT_DISCONNECT_VISIBILITY_MS = 15e3;
|
|
859
|
+
function nextDisconnectMask(mask, previous, current, now) {
|
|
860
|
+
if (!current || current.sandboxSubstate !== "reconnecting") return null;
|
|
861
|
+
if (mask) return mask;
|
|
862
|
+
if (!previous || previous.sandboxSubstate === "reconnecting") return null;
|
|
863
|
+
return { since: now, heldPhase: previous.phase, heldSubstate: previous.sandboxSubstate ?? "none" };
|
|
864
|
+
}
|
|
865
|
+
function isDisconnectMaskActive(mask, now) {
|
|
866
|
+
return mask !== null && now - mask.since < TRANSIENT_DISCONNECT_VISIBILITY_MS;
|
|
867
|
+
}
|
|
868
|
+
function applyDisconnectMask(view, mask, now) {
|
|
869
|
+
if (!isDisconnectMaskActive(mask, now)) return view;
|
|
870
|
+
return { ...view, phase: mask.heldPhase, sandboxSubstate: mask.heldSubstate };
|
|
871
|
+
}
|
|
872
|
+
|
|
865
873
|
// ../../shared/transcript/malformed-search.ts
|
|
866
874
|
var MALFORMED_SEARCH_BLOCKED_TRANSCRIPT_PREFIX = "Arcanist blocked this malformed search command before execution.";
|
|
867
875
|
var BASH_UNMATCHED_QUOTE_EOF_RE = /\/bin\/bash:\s+-c:\s+line\s+\d+:\s+unexpected EOF while looking for matching [`'"][`'"]?/i;
|
|
@@ -1244,6 +1252,24 @@ function projectRetryStatus(data, index) {
|
|
|
1244
1252
|
...typeof data?.retryAfterMs === "number" ? { retryAfterMs: data.retryAfterMs } : {}
|
|
1245
1253
|
};
|
|
1246
1254
|
}
|
|
1255
|
+
function projectPromptRetrying(data, index) {
|
|
1256
|
+
const attempt = typeof data?.attempt === "number" ? data.attempt : Number(data?.attempt ?? 0);
|
|
1257
|
+
const cap = typeof data?.cap === "number" ? data.cap : void 0;
|
|
1258
|
+
const retryPromptId = typeof data?.retryPromptId === "string" ? data.retryPromptId : resolvePromptId(data);
|
|
1259
|
+
return {
|
|
1260
|
+
type: "retry_status",
|
|
1261
|
+
// Key off retryPromptId (always present in the emitted payload, unique per
|
|
1262
|
+
// retry) rather than the index, so the id is stable across replays. The
|
|
1263
|
+
// event's `timestamp` lives at the top level, not inside `data`.
|
|
1264
|
+
id: `pr-retry-${retryPromptId ?? index}`,
|
|
1265
|
+
...retryPromptId ? { promptId: retryPromptId } : {},
|
|
1266
|
+
attempt,
|
|
1267
|
+
message: "Sandbox dropped mid-task; retrying on a fresh sandbox",
|
|
1268
|
+
scope: "sandbox_disconnect",
|
|
1269
|
+
...cap !== void 0 ? { maxAttempts: cap } : {},
|
|
1270
|
+
...typeof data?.reason === "string" ? { reason: data.reason } : {}
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1247
1273
|
function projectBranchChanged(data, index) {
|
|
1248
1274
|
return {
|
|
1249
1275
|
type: "branch_changed",
|
|
@@ -1515,6 +1541,9 @@ function flattenSessionEvents(raw) {
|
|
|
1515
1541
|
case "retry_status":
|
|
1516
1542
|
pushEvent(state, projectRetryStatus(data, state.merged.length));
|
|
1517
1543
|
break;
|
|
1544
|
+
case "prompt_retrying":
|
|
1545
|
+
pushEvent(state, projectPromptRetrying(data, state.merged.length));
|
|
1546
|
+
break;
|
|
1518
1547
|
case "branch_changed":
|
|
1519
1548
|
pushEvent(state, projectBranchChanged(data, state.merged.length));
|
|
1520
1549
|
break;
|
|
@@ -2139,6 +2168,12 @@ function formatStatusLine(status) {
|
|
|
2139
2168
|
if (status.spawnDurationMs != null) details.push(`spawn ${(status.spawnDurationMs / 1e3).toFixed(1)}s`);
|
|
2140
2169
|
return details.length > 0 ? `[status] ${phaseLabel} | ${details.join(" | ")}` : `[status] ${phaseLabel}`;
|
|
2141
2170
|
}
|
|
2171
|
+
function advanceStatusDisconnectMask(status, mask, lastView, now) {
|
|
2172
|
+
const view = status.phase ? { phase: status.phase, sandboxSubstate: status.sandboxSubstate } : null;
|
|
2173
|
+
const nextMask = nextDisconnectMask(mask, lastView, view, now);
|
|
2174
|
+
const displayStatus = view ? { ...status, ...applyDisconnectMask(view, nextMask, now) } : status;
|
|
2175
|
+
return { displayStatus, mask: nextMask, view };
|
|
2176
|
+
}
|
|
2142
2177
|
async function printNoChangeOutcome(config, sessionId) {
|
|
2143
2178
|
try {
|
|
2144
2179
|
const data = await apiFetch(
|
|
@@ -2197,6 +2232,8 @@ async function watchCommand(sessionId, options, command) {
|
|
|
2197
2232
|
let afterSequence = initialAfterSequence;
|
|
2198
2233
|
let lastStatusLine = null;
|
|
2199
2234
|
let textOpen = false;
|
|
2235
|
+
let disconnectMask = null;
|
|
2236
|
+
let lastStatusView = null;
|
|
2200
2237
|
if (!json) console.log(`Watching session ${sessionId}...`);
|
|
2201
2238
|
try {
|
|
2202
2239
|
while (true) {
|
|
@@ -2208,7 +2245,10 @@ async function watchCommand(sessionId, options, command) {
|
|
|
2208
2245
|
const parsed = parseSsePayload(payload);
|
|
2209
2246
|
const receivedFullPage = parsed.events.length >= pageSize;
|
|
2210
2247
|
if (!json && parsed.status) {
|
|
2211
|
-
const
|
|
2248
|
+
const advanced = advanceStatusDisconnectMask(parsed.status, disconnectMask, lastStatusView, Date.now());
|
|
2249
|
+
disconnectMask = advanced.mask;
|
|
2250
|
+
lastStatusView = advanced.view;
|
|
2251
|
+
const nextStatusLine = formatStatusLine(advanced.displayStatus);
|
|
2212
2252
|
if (nextStatusLine !== lastStatusLine) {
|
|
2213
2253
|
if (textOpen) {
|
|
2214
2254
|
process.stdout.write("\n");
|
|
@@ -2990,34 +3030,6 @@ Examples:
|
|
|
2990
3030
|
`
|
|
2991
3031
|
).action((repo, name, options, command) => setTestCredentialCommand(repo, name, options, command));
|
|
2992
3032
|
testCreds.command("delete").description("Delete a test credential").argument("<repo>", "Repository in 'owner/name' form").argument("<name>", "Credential name").requiredOption("--business <id>", "Business ID that owns the repo").option("--yes", "Confirm deletion without prompting").action((repo, name, options, command) => deleteTestCredentialCommand(repo, name, options, command));
|
|
2993
|
-
program.command("login").description("Authenticate with a personal access token").option("--token-stdin", "Read token from stdin instead of interactive prompt").option("--api-url <url>", "Set custom API URL").action((options, command) => {
|
|
2994
|
-
printDeprecatedAlias("login", "auth login", command);
|
|
2995
|
-
return loginCommand(options, command);
|
|
2996
|
-
});
|
|
2997
|
-
addCreateOptions(program.command("create").description("Create a session and send a prompt")).action(
|
|
2998
|
-
(repoUrl, prompt, options, command) => {
|
|
2999
|
-
printDeprecatedAlias("create", "sessions create", command);
|
|
3000
|
-
return createCommand(repoUrl, prompt, options, command);
|
|
3001
|
-
}
|
|
3002
|
-
);
|
|
3003
|
-
addSendOptions(program.command("message").description("Send a message to an existing session")).action(
|
|
3004
|
-
(sessionId, prompt, options, command) => {
|
|
3005
|
-
printDeprecatedAlias("message", "sessions send", command);
|
|
3006
|
-
return messageCommand(sessionId, prompt, options, command);
|
|
3007
|
-
}
|
|
3008
|
-
);
|
|
3009
|
-
program.command("stop").description("Stop the active run for a session").argument("<session-id>", "Session ID").action((sessionId, options, command) => {
|
|
3010
|
-
printDeprecatedAlias("stop", "sessions stop", command);
|
|
3011
|
-
return stopCommand(sessionId, options, command);
|
|
3012
|
-
});
|
|
3013
|
-
program.command("transcript").description("Render a session transcript").argument("<session-id>", "Session ID").action((sessionId, options, command) => {
|
|
3014
|
-
printDeprecatedAlias("transcript", "sessions transcript", command);
|
|
3015
|
-
return transcriptCommand(sessionId, options, command);
|
|
3016
|
-
});
|
|
3017
|
-
program.command("watch").description("Watch session activity until it becomes idle").argument("<session-id>", "Session ID").option("--poll-interval <ms>", "Polling interval in milliseconds", String(DEFAULT_WATCH_POLL_INTERVAL_MS)).action((sessionId, options, command) => {
|
|
3018
|
-
printDeprecatedAlias("watch", "sessions events --follow", command);
|
|
3019
|
-
return watchCommand(sessionId, options, command);
|
|
3020
|
-
});
|
|
3021
3033
|
async function main() {
|
|
3022
3034
|
try {
|
|
3023
3035
|
await program.parseAsync(process.argv);
|