@tryarcanist/cli 0.1.81 → 0.1.82
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 +100 -24
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -388,19 +388,31 @@ function sleep(ms) {
|
|
|
388
388
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
-
//
|
|
392
|
-
var
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
391
|
+
// ../../shared/session/phase.ts
|
|
392
|
+
var NON_REPO_SESSION_KINDS = /* @__PURE__ */ new Set(["terminal_bench", "swe_bench_pro", "swe_polybench"]);
|
|
393
|
+
function isRepoSession(sessionKind) {
|
|
394
|
+
return !sessionKind || !NON_REPO_SESSION_KINDS.has(sessionKind);
|
|
395
|
+
}
|
|
396
|
+
var TERMINAL_PHASES_ARRAY = [
|
|
397
397
|
"completed",
|
|
398
398
|
"blocked",
|
|
399
399
|
"failed",
|
|
400
400
|
"stopped",
|
|
401
|
-
"stopped_resumable",
|
|
402
401
|
"archived"
|
|
403
|
-
]
|
|
402
|
+
];
|
|
403
|
+
var TERMINAL_PHASES = new Set(TERMINAL_PHASES_ARRAY);
|
|
404
|
+
function isTerminalPhase(phase, sessionKind) {
|
|
405
|
+
if (TERMINAL_PHASES.has(phase)) return true;
|
|
406
|
+
return phase === "idle" && !isRepoSession(sessionKind);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// src/constants/watch.ts
|
|
410
|
+
var MIN_WATCH_POLL_INTERVAL_MS = 1;
|
|
411
|
+
var DEFAULT_WATCH_POLL_INTERVAL_MS = 1e3;
|
|
412
|
+
var WATCH_REPLAY_PAGE_SIZE = 200;
|
|
413
|
+
function isWatchTerminal(phase, sessionKind) {
|
|
414
|
+
return isTerminalPhase(phase, sessionKind);
|
|
415
|
+
}
|
|
404
416
|
|
|
405
417
|
// src/uploads.ts
|
|
406
418
|
import { readFile } from "fs/promises";
|
|
@@ -961,6 +973,15 @@ function mergeMemoryRefs(ids, rawRefs) {
|
|
|
961
973
|
const ref = { id };
|
|
962
974
|
if (typeof record.path === "string" && record.path.trim()) ref.path = record.path.trim();
|
|
963
975
|
if (typeof record.title === "string" && record.title.trim()) ref.title = record.title.trim();
|
|
976
|
+
if (typeof record.selectionRank === "number") ref.selectionRank = record.selectionRank;
|
|
977
|
+
if (typeof record.selectionScore === "number") ref.selectionScore = record.selectionScore;
|
|
978
|
+
if (typeof record.reason === "string" && record.reason.trim()) ref.reason = record.reason.trim();
|
|
979
|
+
if (typeof record.expectedEffect === "string" && record.expectedEffect.trim()) {
|
|
980
|
+
ref.expectedEffect = record.expectedEffect.trim();
|
|
981
|
+
}
|
|
982
|
+
if (typeof record.observedEffect === "string" && record.observedEffect.trim()) {
|
|
983
|
+
ref.observedEffect = record.observedEffect.trim();
|
|
984
|
+
}
|
|
964
985
|
byId.set(id, ref);
|
|
965
986
|
}
|
|
966
987
|
}
|
|
@@ -1402,6 +1423,20 @@ function formatSessionErrorMessage(error, code) {
|
|
|
1402
1423
|
}
|
|
1403
1424
|
|
|
1404
1425
|
// src/utils/session-output.ts
|
|
1426
|
+
var VALID_PHASES = /* @__PURE__ */ new Set([
|
|
1427
|
+
"idle",
|
|
1428
|
+
"running",
|
|
1429
|
+
"waiting_for_input",
|
|
1430
|
+
"finalizing",
|
|
1431
|
+
"completed",
|
|
1432
|
+
"blocked",
|
|
1433
|
+
"failed",
|
|
1434
|
+
"stopped",
|
|
1435
|
+
"archived"
|
|
1436
|
+
]);
|
|
1437
|
+
var VALID_SANDBOX_SUBSTATES = /* @__PURE__ */ new Set(["creating", "reconnecting", "stopping", "none"]);
|
|
1438
|
+
var VALID_STOP_MODES = /* @__PURE__ */ new Set(["user", "resumable", "none"]);
|
|
1439
|
+
var VALID_FINALIZING_STEPS = /* @__PURE__ */ new Set(["post_execution", "publishing", "none"]);
|
|
1405
1440
|
function formatDate(value) {
|
|
1406
1441
|
const date = new Date(value);
|
|
1407
1442
|
if (Number.isNaN(date.getTime())) return value;
|
|
@@ -1601,9 +1636,21 @@ function parseSsePayload(payload) {
|
|
|
1601
1636
|
for (const message of messages) {
|
|
1602
1637
|
const data = message.data ? parseJsonObject(message.data) : {};
|
|
1603
1638
|
if (message.event === "status") {
|
|
1639
|
+
const phaseRaw = data.phase;
|
|
1640
|
+
const phase = typeof phaseRaw === "string" && VALID_PHASES.has(phaseRaw) ? phaseRaw : null;
|
|
1604
1641
|
const entry = {
|
|
1605
|
-
|
|
1642
|
+
phase
|
|
1606
1643
|
};
|
|
1644
|
+
if (typeof data.sandboxSubstate === "string" && VALID_SANDBOX_SUBSTATES.has(data.sandboxSubstate)) {
|
|
1645
|
+
entry.sandboxSubstate = data.sandboxSubstate;
|
|
1646
|
+
}
|
|
1647
|
+
if (typeof data.stopMode === "string" && VALID_STOP_MODES.has(data.stopMode)) {
|
|
1648
|
+
entry.stopMode = data.stopMode;
|
|
1649
|
+
}
|
|
1650
|
+
if (typeof data.finalizingStep === "string" && VALID_FINALIZING_STEPS.has(data.finalizingStep)) {
|
|
1651
|
+
entry.finalizingStep = data.finalizingStep;
|
|
1652
|
+
}
|
|
1653
|
+
if (typeof data.sessionKind === "string") entry.sessionKind = data.sessionKind;
|
|
1607
1654
|
if (typeof data.title === "string") entry.title = data.title;
|
|
1608
1655
|
if (typeof data.spawnDurationMs === "number" || data.spawnDurationMs === null) {
|
|
1609
1656
|
entry.spawnDurationMs = data.spawnDurationMs;
|
|
@@ -1734,10 +1781,16 @@ function parseNonNegativeInteger(raw, name, defaultValue) {
|
|
|
1734
1781
|
return Number(raw);
|
|
1735
1782
|
}
|
|
1736
1783
|
function formatStatusLine(status) {
|
|
1784
|
+
const label = status.phase ?? "unknown";
|
|
1785
|
+
const substate = [];
|
|
1786
|
+
if (status.sandboxSubstate && status.sandboxSubstate !== "none") substate.push(status.sandboxSubstate);
|
|
1787
|
+
if (status.stopMode && status.stopMode !== "none") substate.push(status.stopMode);
|
|
1788
|
+
if (status.finalizingStep && status.finalizingStep !== "none") substate.push(status.finalizingStep);
|
|
1789
|
+
const phaseLabel = substate.length > 0 ? `${label}/${substate.join("/")}` : label;
|
|
1737
1790
|
const details = [];
|
|
1738
1791
|
if (status.title) details.push(status.title);
|
|
1739
1792
|
if (status.spawnDurationMs != null) details.push(`spawn ${(status.spawnDurationMs / 1e3).toFixed(1)}s`);
|
|
1740
|
-
return details.length > 0 ? `[status] ${
|
|
1793
|
+
return details.length > 0 ? `[status] ${phaseLabel} | ${details.join(" | ")}` : `[status] ${phaseLabel}`;
|
|
1741
1794
|
}
|
|
1742
1795
|
async function fetchPromptLabels(config, sessionId) {
|
|
1743
1796
|
const data = await apiFetch(config, `/api/sessions/${sessionId}/prompts`);
|
|
@@ -1817,7 +1870,7 @@ async function watchCommand(sessionId, options, command) {
|
|
|
1817
1870
|
console.log(rendered.line);
|
|
1818
1871
|
}
|
|
1819
1872
|
if (receivedFullPage) continue;
|
|
1820
|
-
if (parsed.status?.
|
|
1873
|
+
if (parsed.status?.phase && isWatchTerminal(parsed.status.phase, parsed.status.sessionKind)) break;
|
|
1821
1874
|
await sleep(effectivePollIntervalMs);
|
|
1822
1875
|
}
|
|
1823
1876
|
} finally {
|
|
@@ -1850,12 +1903,13 @@ function buildPromptFailureError(sessionId, prompt, sessionUrl) {
|
|
|
1850
1903
|
hint: `Inspect with: arcanist sessions transcript ${sessionId}`
|
|
1851
1904
|
});
|
|
1852
1905
|
}
|
|
1853
|
-
function
|
|
1906
|
+
function extractSessionLifecycle(payload) {
|
|
1854
1907
|
const session = payload.session;
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1908
|
+
const root = session && typeof session === "object" ? session : payload;
|
|
1909
|
+
const phaseRaw = root.phase;
|
|
1910
|
+
const phase = typeof phaseRaw === "string" && VALID_PHASES.has(phaseRaw) ? phaseRaw : null;
|
|
1911
|
+
const sessionKind = typeof root.sessionKind === "string" ? root.sessionKind : null;
|
|
1912
|
+
return { phase, sessionKind };
|
|
1859
1913
|
}
|
|
1860
1914
|
async function fetchCreatedPromptStatus(config, sessionId, promptId) {
|
|
1861
1915
|
const promptList = await apiFetch(config, `/api/sessions/${sessionId}/prompts`);
|
|
@@ -1869,7 +1923,8 @@ async function waitForCreatedPromptToSettle(config, sessionId, promptId, pollInt
|
|
|
1869
1923
|
return createdPrompt;
|
|
1870
1924
|
}
|
|
1871
1925
|
const sessionPayload = await apiFetch(config, `/api/sessions/${sessionId}`);
|
|
1872
|
-
|
|
1926
|
+
const lifecycle = extractSessionLifecycle(sessionPayload);
|
|
1927
|
+
if (lifecycle.phase && isWatchTerminal(lifecycle.phase, lifecycle.sessionKind)) {
|
|
1873
1928
|
return fetchCreatedPromptStatus(config, sessionId, promptId);
|
|
1874
1929
|
}
|
|
1875
1930
|
await sleep(effectivePollIntervalMs);
|
|
@@ -2165,17 +2220,38 @@ async function usageCommand(sessionId, options, command) {
|
|
|
2165
2220
|
async function stopCommand(sessionId, options = {}, command) {
|
|
2166
2221
|
const runtime = getRuntimeOptions(command, options);
|
|
2167
2222
|
const config = requireConfig(runtime);
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2223
|
+
let status;
|
|
2224
|
+
try {
|
|
2225
|
+
const response = await apiFetch(config, `/api/sessions/${sessionId}/stop`, {
|
|
2226
|
+
method: "POST"
|
|
2227
|
+
});
|
|
2228
|
+
status = response.status ?? "stopping";
|
|
2229
|
+
} catch (err) {
|
|
2230
|
+
const parsed = parseStopBlocked(err);
|
|
2231
|
+
if (!parsed) throw err;
|
|
2232
|
+
status = parsed.reason;
|
|
2233
|
+
}
|
|
2172
2234
|
if (isJson(command, options)) {
|
|
2173
2235
|
writeJson({ sessionId, status });
|
|
2174
2236
|
return;
|
|
2175
2237
|
}
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
)
|
|
2238
|
+
if (status === "already_stopped") {
|
|
2239
|
+
console.log(`Session ${sessionId} is already stopped.`);
|
|
2240
|
+
} else if (status === "stopping" || status === "stopped") {
|
|
2241
|
+
console.log(`Stop requested for session ${sessionId}.`);
|
|
2242
|
+
} else {
|
|
2243
|
+
console.log(`Session ${sessionId} cannot be stopped from phase=${status}.`);
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
function parseStopBlocked(err) {
|
|
2247
|
+
if (!(err instanceof ApiError) || err.status !== 409) return null;
|
|
2248
|
+
try {
|
|
2249
|
+
const body = JSON.parse(err.body);
|
|
2250
|
+
if (body.error !== "session_not_stoppable") return null;
|
|
2251
|
+
return { reason: body.reason ?? "not_stoppable" };
|
|
2252
|
+
} catch {
|
|
2253
|
+
return null;
|
|
2254
|
+
}
|
|
2179
2255
|
}
|
|
2180
2256
|
|
|
2181
2257
|
// src/commands/test-creds.ts
|