@tryarcanist/cli 0.1.132 → 0.1.133
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/README.md +15 -1
- package/dist/index.js +44 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -131,7 +131,7 @@ arcanist sessions create your-org/your-repo "retry-safe create" --idempotency-ke
|
|
|
131
131
|
|
|
132
132
|
`--backend` picks the agent runtime backend: `codex` (default) or `claude_code`. `--model` must be valid for the chosen backend — codex runs OpenAI models (`gpt-5.4` default, `gpt-5.5`), `claude_code` runs Anthropic models (`claude-opus-4-8` default, `claude-sonnet-4-6`) — and the CLI rejects a mismatch before any network call. `claude_code` sessions require an Anthropic API key configured in Settings.
|
|
133
133
|
|
|
134
|
-
`--wait` blocks until the created prompt finishes and exits non-zero if the prompt finishes with `status: failed`, making it suitable for cron or other schedulers that alert on command failure. `--poll-interval <ms>` tunes the completion check frequency.
|
|
134
|
+
`--wait` blocks until the created prompt finishes, prints the resulting PR/branch line in human-readable mode when it is already available, and exits non-zero if the prompt finishes with `status: failed`, making it suitable for cron or other schedulers that alert on command failure. `--poll-interval <ms>` tunes the completion check frequency.
|
|
135
135
|
|
|
136
136
|
Use `--base-branch <branch>` to target a non-default base branch. The CLI only validates that the branch value is non-empty; branch existence is checked later by the session runtime.
|
|
137
137
|
|
|
@@ -176,6 +176,8 @@ arcanist sessions get abc123
|
|
|
176
176
|
arcanist sessions get abc123 --json
|
|
177
177
|
```
|
|
178
178
|
|
|
179
|
+
Human-readable output includes `PR: <url> (<branch>)` when the session has opened a PR, or `Branch: <branch>` when a produced branch is known but no PR URL is present yet. If publishing is still settling, rerun `sessions get`; JSON mode returns the raw session payload, with result fields at `.session.prUrl`, `.session.publishedBranch`, and `.session.lastBranch`.
|
|
180
|
+
|
|
179
181
|
### `arcanist sessions list`
|
|
180
182
|
|
|
181
183
|
```bash
|
|
@@ -324,6 +326,18 @@ arcanist sessions create your-org/your-repo "verify the new rate limiter is acti
|
|
|
324
326
|
|
|
325
327
|
For cron, prefer `ARCANIST_TOKEN` or a logged-in `~/.arcanist/config.json` over passing `--token` on the command line.
|
|
326
328
|
|
|
329
|
+
To capture the PR URL after a successful run, use `create --wait` for the exit code, then read the session state:
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
SESSION_ID=$(arcanist sessions create your-org/your-repo "fix the flaky test" --wait --json | jq -r .sessionId)
|
|
333
|
+
for _ in {1..20}; do
|
|
334
|
+
PR_URL=$(arcanist sessions get "$SESSION_ID" --json | jq -r '.session.prUrl // empty')
|
|
335
|
+
[ -n "$PR_URL" ] && break
|
|
336
|
+
sleep 5
|
|
337
|
+
done
|
|
338
|
+
[ -n "$PR_URL" ] || { echo "PR URL not ready for $SESSION_ID" >&2; exit 1; }
|
|
339
|
+
```
|
|
340
|
+
|
|
327
341
|
## Troubleshooting
|
|
328
342
|
|
|
329
343
|
- **401 on login verification**: token may be invalid or expired. Regenerate in **Settings > CLI Tokens**.
|
package/dist/index.js
CHANGED
|
@@ -1023,22 +1023,6 @@ function noChangeOutcomeCopy(reason) {
|
|
|
1023
1023
|
}
|
|
1024
1024
|
}
|
|
1025
1025
|
|
|
1026
|
-
// ../../shared/session/transient-disconnect.ts
|
|
1027
|
-
var TRANSIENT_DISCONNECT_VISIBILITY_MS = 15e3;
|
|
1028
|
-
function nextDisconnectMask(mask, previous, current, now) {
|
|
1029
|
-
if (!current || current.sandboxSubstate !== "reconnecting") return null;
|
|
1030
|
-
if (mask) return mask;
|
|
1031
|
-
if (!previous || previous.sandboxSubstate === "reconnecting") return null;
|
|
1032
|
-
return { since: now, heldPhase: previous.phase, heldSubstate: previous.sandboxSubstate ?? "none" };
|
|
1033
|
-
}
|
|
1034
|
-
function isDisconnectMaskActive(mask, now) {
|
|
1035
|
-
return mask !== null && now - mask.since < TRANSIENT_DISCONNECT_VISIBILITY_MS;
|
|
1036
|
-
}
|
|
1037
|
-
function applyDisconnectMask(view, mask, now) {
|
|
1038
|
-
if (!isDisconnectMaskActive(mask, now)) return view;
|
|
1039
|
-
return { ...view, phase: mask.heldPhase, sandboxSubstate: mask.heldSubstate };
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
1026
|
// ../../shared/transcript/malformed-search.ts
|
|
1043
1027
|
var MALFORMED_SEARCH_BLOCKED_TRANSCRIPT_PREFIX = "Arcanist blocked this malformed search command before execution.";
|
|
1044
1028
|
var BASH_UNMATCHED_QUOTE_EOF_RE = /\/bin\/bash:\s+-c:\s+line\s+\d+:\s+unexpected EOF while looking for matching [`'"][`'"]?/i;
|
|
@@ -2063,6 +2047,23 @@ ${event.answer ? `**Answer:** ${event.answer}
|
|
|
2063
2047
|
function formatNumber(value) {
|
|
2064
2048
|
return value.toLocaleString();
|
|
2065
2049
|
}
|
|
2050
|
+
function stringField(value) {
|
|
2051
|
+
return typeof value === "string" && value.trim() ? value : null;
|
|
2052
|
+
}
|
|
2053
|
+
function formatSessionResult(session) {
|
|
2054
|
+
const prUrl = stringField(session.prUrl);
|
|
2055
|
+
const publishedBranch = stringField(session.publishedBranch);
|
|
2056
|
+
const lastBranch = stringField(session.lastBranch);
|
|
2057
|
+
const baseBranch = stringField(session.baseBranch);
|
|
2058
|
+
const branch = publishedBranch ?? (lastBranch && lastBranch !== baseBranch ? lastBranch : null);
|
|
2059
|
+
if (prUrl) {
|
|
2060
|
+
return `PR: ${prUrl}${branch ? ` (${branch})` : ""}`;
|
|
2061
|
+
}
|
|
2062
|
+
if (branch) {
|
|
2063
|
+
return `Branch: ${branch}`;
|
|
2064
|
+
}
|
|
2065
|
+
return null;
|
|
2066
|
+
}
|
|
2066
2067
|
function latestCompletedPromptResult(prompts) {
|
|
2067
2068
|
for (let i = prompts.length - 1; i >= 0; i--) {
|
|
2068
2069
|
if (prompts[i].status === "completed") return prompts[i].result;
|
|
@@ -2314,6 +2315,22 @@ function renderWatchEvent(event, state) {
|
|
|
2314
2315
|
}
|
|
2315
2316
|
}
|
|
2316
2317
|
|
|
2318
|
+
// ../../shared/session/transient-disconnect.ts
|
|
2319
|
+
var TRANSIENT_DISCONNECT_VISIBILITY_MS = 15e3;
|
|
2320
|
+
function nextDisconnectMask(mask, previous, current, now) {
|
|
2321
|
+
if (!current || current.sandboxSubstate !== "reconnecting") return null;
|
|
2322
|
+
if (mask) return mask;
|
|
2323
|
+
if (!previous || previous.sandboxSubstate === "reconnecting") return null;
|
|
2324
|
+
return { since: now, heldPhase: previous.phase, heldSubstate: previous.sandboxSubstate ?? "none" };
|
|
2325
|
+
}
|
|
2326
|
+
function isDisconnectMaskActive(mask, now) {
|
|
2327
|
+
return mask !== null && now - mask.since < TRANSIENT_DISCONNECT_VISIBILITY_MS;
|
|
2328
|
+
}
|
|
2329
|
+
function applyDisconnectMask(view, mask, now) {
|
|
2330
|
+
if (!isDisconnectMaskActive(mask, now)) return view;
|
|
2331
|
+
return { ...view, phase: mask.heldPhase, sandboxSubstate: mask.heldSubstate };
|
|
2332
|
+
}
|
|
2333
|
+
|
|
2317
2334
|
// src/commands/watch.ts
|
|
2318
2335
|
function parsePollInterval(raw) {
|
|
2319
2336
|
if (!raw) return DEFAULT_WATCH_POLL_INTERVAL_MS;
|
|
@@ -2621,6 +2638,15 @@ async function createCommand(repoUrl, promptArg, options, command) {
|
|
|
2621
2638
|
if (sessionData.sessionUrl) console.log(`URL: ${sessionData.sessionUrl}`);
|
|
2622
2639
|
}
|
|
2623
2640
|
await waitForCreatedPrompt(sessionId, promptId, sessionData.sessionUrl, waitPollIntervalMs, runtime, command);
|
|
2641
|
+
if (!isJson(command, options)) {
|
|
2642
|
+
try {
|
|
2643
|
+
const sessionPayload = await apiFetch(config, `/api/sessions/${sessionId}`);
|
|
2644
|
+
const sessionState = sessionPayload.session && typeof sessionPayload.session === "object" ? sessionPayload.session : sessionPayload;
|
|
2645
|
+
const resultLine = formatSessionResult(sessionState);
|
|
2646
|
+
if (resultLine) console.log(resultLine);
|
|
2647
|
+
} catch {
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2624
2650
|
}
|
|
2625
2651
|
if (isJson(command, options)) {
|
|
2626
2652
|
const output = { sessionId };
|
|
@@ -3846,6 +3872,8 @@ async function getSessionCommand(sessionId, options, command) {
|
|
|
3846
3872
|
console.log(`Status: ${String(session.phase ?? session.status ?? "unknown")}`);
|
|
3847
3873
|
if (session.repoUrl) console.log(`Repo: ${String(session.repoUrl)}`);
|
|
3848
3874
|
if (session.title) console.log(`Title: ${String(session.title)}`);
|
|
3875
|
+
const resultLine = formatSessionResult(session);
|
|
3876
|
+
if (resultLine) console.log(resultLine);
|
|
3849
3877
|
}
|
|
3850
3878
|
async function sessionEventsCommand(sessionId, options, command) {
|
|
3851
3879
|
const afterSequence = resolveSequenceOption(options.afterSequence, options.after, "--after-sequence", "--after");
|