@tryarcanist/cli 0.1.148 → 0.1.149
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 +4 -1
- package/dist/index.js +79 -34
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -119,6 +119,7 @@ Creates a new session and sends the initial prompt.
|
|
|
119
119
|
```bash
|
|
120
120
|
arcanist sessions create https://github.com/your-org/your-repo "fix the login bug"
|
|
121
121
|
arcanist sessions create your-org/your-repo "continue this work" --start-branch wip/resume-me
|
|
122
|
+
arcanist sessions create your-org/your-repo "finish this PR" --continue-pr https://github.com/your-org/your-repo/pull/123
|
|
122
123
|
printf "add tests" | arcanist sessions create your-org/your-repo --prompt-stdin --json
|
|
123
124
|
printf "add tests" | arcanist sessions create your-org/your-repo --prompt-stdin --wait
|
|
124
125
|
arcanist sessions create your-org/your-repo - --model gpt-5.5
|
|
@@ -138,6 +139,8 @@ Use `--base-branch <branch>` to target a non-default base branch. The CLI only v
|
|
|
138
139
|
|
|
139
140
|
Use `--start-branch <branch>` to resume an existing branch with its history instead of forking a fresh branch off base; the control plane verifies the branch exists on the remote and fails closed if it does not.
|
|
140
141
|
|
|
142
|
+
Use `--continue-pr <url>` to continue an open same-repo pull request. The control plane checks out the PR head branch before the prompt runs. `--continue-mode update-pr` updates the referenced PR; `--continue-mode new-pr` starts from that PR head but leaves publish free to open a fresh PR. `auto` is the default and currently resolves to same-PR update for supported open same-repo PRs.
|
|
143
|
+
|
|
141
144
|
Repeatable `--uploaded-file <path>` flags attach local UTF-8 text files to the prompt. Uploaded file names come from the local basename; directory components are not sent.
|
|
142
145
|
|
|
143
146
|
`--cold` is a deprecated no-op retained for backward compatibility. Sessions always start from a fresh sandbox (the warm sandbox pool was removed), so the flag has no effect.
|
|
@@ -146,7 +149,7 @@ Repeatable `--uploaded-file <path>` flags attach local UTF-8 text files to the p
|
|
|
146
149
|
|
|
147
150
|
`--onboarding` creates an onboarding session: the agent authors the repo's `.arcanist.json`, `.arcanist/` runtime files, `ARCANIST.md`, and conditionally `.arcanist/sandbox.yaml` + `.arcanist/sandbox.layer.Dockerfile` (when the base sandbox lacks a needed toolchain), proves what it can inside its sandbox, and opens the setup PR ready for review. The onboarding behavior is driven by the bridge's canonical onboarding playbook, not the prompt, so `--onboarding` needs no prompt: `arcanist sessions create <repo> --onboarding --wait`. Any prompt supplied alongside `--onboarding` is ignored. Team use; not part of the external API surface.
|
|
148
151
|
|
|
149
|
-
JSON mode returns `{sessionId, sessionUrl?, repoUrl, model?, agentRuntimeBackend?, reasoningEffort?, baseBranch?, startBranch?, onboarding?, promptId?}`. `sessionUrl` is emitted only when the server returns it; `agentRuntimeBackend` only when `--backend` is passed. With `--wait`, JSON mode also includes best-effort result fields when available: `prUrl?`, `publishedBranch?`, and `lastBranch?`.
|
|
152
|
+
JSON mode returns `{sessionId, sessionUrl?, repoUrl, model?, agentRuntimeBackend?, reasoningEffort?, baseBranch?, startBranch?, continuePrUrl?, continueMode?, onboarding?, promptId?}`. `sessionUrl` is emitted only when the server returns it; `agentRuntimeBackend` only when `--backend` is passed. With `--wait`, JSON mode also includes best-effort result fields when available: `prUrl?`, `publishedBranch?`, and `lastBranch?`.
|
|
150
153
|
|
|
151
154
|
### `arcanist sessions send <session-id> [prompt]`
|
|
152
155
|
|
package/dist/index.js
CHANGED
|
@@ -568,6 +568,7 @@ var OpenAIModel = {
|
|
|
568
568
|
GPT54Pro: "gpt-5.4-pro",
|
|
569
569
|
GPT54Mini: "gpt-5.4-mini",
|
|
570
570
|
GPT54Nano: "gpt-5.4-nano",
|
|
571
|
+
GPT53CodexSpark: "gpt-5.3-codex-spark",
|
|
571
572
|
GPT53Codex: "gpt-5.3-codex",
|
|
572
573
|
GPT52: "gpt-5.2",
|
|
573
574
|
GPT52ChatLatest: "gpt-5.2-chat-latest",
|
|
@@ -585,17 +586,6 @@ var MODEL_PROVIDERS_SET = /* @__PURE__ */ new Set([
|
|
|
585
586
|
"anthropic",
|
|
586
587
|
"baseten"
|
|
587
588
|
]);
|
|
588
|
-
var SESSION_START_MODEL_IDS_BY_BACKEND = {
|
|
589
|
-
[CODEX_AGENT_RUNTIME_BACKEND]: [OpenAIModel.GPT55, OpenAIModel.GPT54, OpenAIModel.GPT54Nano],
|
|
590
|
-
[CLAUDE_CODE_AGENT_RUNTIME_BACKEND]: [AnthropicModel.Opus48, AnthropicModel.Sonnet46],
|
|
591
|
-
[OPENCODE_AGENT_RUNTIME_BACKEND]: [BasetenModel.GptOss120B]
|
|
592
|
-
};
|
|
593
|
-
var DEFAULT_SESSION_START_MODEL_ID_BY_BACKEND = {
|
|
594
|
-
[CODEX_AGENT_RUNTIME_BACKEND]: OpenAIModel.GPT54,
|
|
595
|
-
[CLAUDE_CODE_AGENT_RUNTIME_BACKEND]: AnthropicModel.Opus48,
|
|
596
|
-
[OPENCODE_AGENT_RUNTIME_BACKEND]: BasetenModel.GptOss120B
|
|
597
|
-
};
|
|
598
|
-
var DEFAULT_SESSION_START_MODEL_ID = DEFAULT_SESSION_START_MODEL_ID_BY_BACKEND[CODEX_AGENT_RUNTIME_BACKEND];
|
|
599
589
|
var MODEL_REGISTRY = [
|
|
600
590
|
{
|
|
601
591
|
id: OpenAIModel.GPT54,
|
|
@@ -616,7 +606,8 @@ var MODEL_REGISTRY = [
|
|
|
616
606
|
outputPerMillion: 22.5,
|
|
617
607
|
cacheReadPerMillion: 0.5
|
|
618
608
|
}
|
|
619
|
-
}
|
|
609
|
+
},
|
|
610
|
+
sessionStart: { eligible: true, isDefault: true }
|
|
620
611
|
},
|
|
621
612
|
{
|
|
622
613
|
id: OpenAIModel.GPT55,
|
|
@@ -635,7 +626,8 @@ var MODEL_REGISTRY = [
|
|
|
635
626
|
outputPerMillion: 45,
|
|
636
627
|
cacheReadPerMillion: 1
|
|
637
628
|
}
|
|
638
|
-
}
|
|
629
|
+
},
|
|
630
|
+
sessionStart: { eligible: true }
|
|
639
631
|
},
|
|
640
632
|
{
|
|
641
633
|
id: OpenAIModel.GPT54Mini,
|
|
@@ -662,7 +654,20 @@ var MODEL_REGISTRY = [
|
|
|
662
654
|
backends: [CODEX_AGENT_RUNTIME_BACKEND],
|
|
663
655
|
contextWindow: 4e5,
|
|
664
656
|
reasoning: { efforts: ["none", "low", "medium", "high", "xhigh"], default: void 0 },
|
|
665
|
-
pricing: { inputPerMillion: 0.2, outputPerMillion: 1.25, cacheReadPerMillion: 0.02 }
|
|
657
|
+
pricing: { inputPerMillion: 0.2, outputPerMillion: 1.25, cacheReadPerMillion: 0.02 },
|
|
658
|
+
sessionStart: { eligible: true }
|
|
659
|
+
},
|
|
660
|
+
{
|
|
661
|
+
id: OpenAIModel.GPT53CodexSpark,
|
|
662
|
+
name: "GPT-5.3 Codex Spark",
|
|
663
|
+
provider: "openai",
|
|
664
|
+
backends: [CODEX_AGENT_RUNTIME_BACKEND],
|
|
665
|
+
contextWindow: 128e3,
|
|
666
|
+
reasoning: { efforts: ["low", "medium", "high", "xhigh"], default: "high" },
|
|
667
|
+
costTracked: false,
|
|
668
|
+
requiresCodexSubscriptionAuth: true,
|
|
669
|
+
sessionStart: { eligible: true },
|
|
670
|
+
visibility: "internal_probe"
|
|
666
671
|
},
|
|
667
672
|
{
|
|
668
673
|
id: OpenAIModel.GPT53Codex,
|
|
@@ -713,7 +718,8 @@ var MODEL_REGISTRY = [
|
|
|
713
718
|
// Bridge cost-ESTIMATE only; NOT authoritative for control-plane Anthropic
|
|
714
719
|
// billing. `anthropic/cost.ts` ANTHROPIC_MESSAGES_MODEL_PRICING owns that
|
|
715
720
|
// and is intentionally ~3x divergent until Phase 5.
|
|
716
|
-
pricing: { inputPerMillion: 5, outputPerMillion: 25, cacheReadPerMillion: 0.5, cacheWritePerMillion: 6.25 }
|
|
721
|
+
pricing: { inputPerMillion: 5, outputPerMillion: 25, cacheReadPerMillion: 0.5, cacheWritePerMillion: 6.25 },
|
|
722
|
+
sessionStart: { eligible: true, isDefault: true }
|
|
717
723
|
},
|
|
718
724
|
{
|
|
719
725
|
id: AnthropicModel.Sonnet46,
|
|
@@ -727,7 +733,8 @@ var MODEL_REGISTRY = [
|
|
|
727
733
|
// Bridge cost-ESTIMATE only; NOT authoritative for control-plane Anthropic
|
|
728
734
|
// billing. `anthropic/cost.ts` ANTHROPIC_MESSAGES_MODEL_PRICING owns that
|
|
729
735
|
// and is intentionally ~3x divergent until Phase 5.
|
|
730
|
-
pricing: { inputPerMillion: 3, outputPerMillion: 15, cacheReadPerMillion: 0.3, cacheWritePerMillion: 3.75 }
|
|
736
|
+
pricing: { inputPerMillion: 3, outputPerMillion: 15, cacheReadPerMillion: 0.3, cacheWritePerMillion: 3.75 },
|
|
737
|
+
sessionStart: { eligible: true }
|
|
731
738
|
},
|
|
732
739
|
{
|
|
733
740
|
id: BasetenModel.GptOss120B,
|
|
@@ -741,7 +748,8 @@ var MODEL_REGISTRY = [
|
|
|
741
748
|
// Internal cold-spawn bridge ESTIMATE, NOT authoritative Baseten API
|
|
742
749
|
// billing. `baseten/cost.ts` BASETEN_MODEL_API_PRICING (wire-id keyed)
|
|
743
750
|
// owns real billing.
|
|
744
|
-
pricing: { inputPerMillion: 0, outputPerMillion: 0 }
|
|
751
|
+
pricing: { inputPerMillion: 0, outputPerMillion: 0 },
|
|
752
|
+
sessionStart: { eligible: true, isDefault: true }
|
|
745
753
|
}
|
|
746
754
|
];
|
|
747
755
|
var MODEL_PROVIDER_NAMES = {
|
|
@@ -749,6 +757,32 @@ var MODEL_PROVIDER_NAMES = {
|
|
|
749
757
|
anthropic: "Anthropic",
|
|
750
758
|
baseten: "Baseten"
|
|
751
759
|
};
|
|
760
|
+
function buildSessionStartModelIdsByBackend() {
|
|
761
|
+
const byBackend = Object.fromEntries(AGENT_RUNTIME_BACKENDS.map((backend) => [backend, []]));
|
|
762
|
+
for (const model of MODEL_REGISTRY) {
|
|
763
|
+
if (!model.sessionStart?.eligible) continue;
|
|
764
|
+
for (const backend of model.backends) {
|
|
765
|
+
byBackend[backend].push(model.id);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
return byBackend;
|
|
769
|
+
}
|
|
770
|
+
function buildDefaultSessionStartModelIdByBackend() {
|
|
771
|
+
const defaults = {};
|
|
772
|
+
for (const backend of AGENT_RUNTIME_BACKENDS) {
|
|
773
|
+
const backendDefaults = MODEL_REGISTRY.filter(
|
|
774
|
+
(model) => model.sessionStart?.eligible && model.sessionStart.isDefault === true && model.backends.includes(backend)
|
|
775
|
+
);
|
|
776
|
+
if (backendDefaults.length !== 1) {
|
|
777
|
+
throw new Error(`Expected exactly one default session-start model for ${backend}, got ${backendDefaults.length}`);
|
|
778
|
+
}
|
|
779
|
+
defaults[backend] = backendDefaults[0].id;
|
|
780
|
+
}
|
|
781
|
+
return defaults;
|
|
782
|
+
}
|
|
783
|
+
var SESSION_START_MODEL_IDS_BY_BACKEND = buildSessionStartModelIdsByBackend();
|
|
784
|
+
var DEFAULT_SESSION_START_MODEL_ID_BY_BACKEND = buildDefaultSessionStartModelIdByBackend();
|
|
785
|
+
var DEFAULT_SESSION_START_MODEL_ID = DEFAULT_SESSION_START_MODEL_ID_BY_BACKEND[CODEX_AGENT_RUNTIME_BACKEND];
|
|
752
786
|
var VALID_MODEL_IDS = new Set(MODEL_REGISTRY.map((model) => model.id));
|
|
753
787
|
var VALID_SESSION_START_MODEL_IDS_BY_BACKEND = {
|
|
754
788
|
[CODEX_AGENT_RUNTIME_BACKEND]: new Set(SESSION_START_MODEL_IDS_BY_BACKEND[CODEX_AGENT_RUNTIME_BACKEND]),
|
|
@@ -813,21 +847,6 @@ function getSessionStartModelIdsForBackend(backend) {
|
|
|
813
847
|
function isSessionStartModelAllowedForBackend(modelId, backend) {
|
|
814
848
|
return VALID_SESSION_START_MODEL_IDS_BY_BACKEND[backend].has(modelId);
|
|
815
849
|
}
|
|
816
|
-
var MODEL_TIER_BY_ID = {
|
|
817
|
-
[OpenAIModel.GPT55]: "frontier",
|
|
818
|
-
[OpenAIModel.GPT54]: "mid",
|
|
819
|
-
[OpenAIModel.GPT54Nano]: "mid",
|
|
820
|
-
[AnthropicModel.Opus48]: "frontier",
|
|
821
|
-
[AnthropicModel.Sonnet46]: "mid",
|
|
822
|
-
[BasetenModel.GptOss120B]: "mid"
|
|
823
|
-
};
|
|
824
|
-
var CODEX_MODEL_ID_BY_TIER = {
|
|
825
|
-
// Single source of truth: the frontier codex model follows the codex default,
|
|
826
|
-
// so changing the default propagates here automatically. Only used for
|
|
827
|
-
// non-codex (e.g. claude) parents — codex parents verify on their own model.
|
|
828
|
-
frontier: DEFAULT_SESSION_START_MODEL_ID_BY_BACKEND[CODEX_AGENT_RUNTIME_BACKEND],
|
|
829
|
-
mid: OpenAIModel.GPT54
|
|
830
|
-
};
|
|
831
850
|
function getProviderForModel(modelId) {
|
|
832
851
|
return MODEL_PROVIDERS[modelId] ?? "openai";
|
|
833
852
|
}
|
|
@@ -884,6 +903,11 @@ var PUBLIC_SESSION_START_MODEL_PROVIDER_GROUPS = buildModelProviderGroups(
|
|
|
884
903
|
(model) => SESSION_START_MODEL_ID_SET_ANY_BACKEND.has(model.id) && model.visibility !== "internal_probe"
|
|
885
904
|
)
|
|
886
905
|
);
|
|
906
|
+
var CODEX_SUBSCRIPTION_SESSION_START_MODEL_PROVIDER_GROUPS = buildModelProviderGroups(
|
|
907
|
+
MODEL_REGISTRY.filter(
|
|
908
|
+
(model) => SESSION_START_MODEL_ID_SET_ANY_BACKEND.has(model.id) && (model.visibility !== "internal_probe" || model.requiresCodexSubscriptionAuth === true)
|
|
909
|
+
)
|
|
910
|
+
);
|
|
887
911
|
|
|
888
912
|
// ../../shared/utils/timing.ts
|
|
889
913
|
function sleep(ms) {
|
|
@@ -2601,6 +2625,7 @@ function validateRepoUrl(url) {
|
|
|
2601
2625
|
}
|
|
2602
2626
|
var PROMPT_TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "failed"]);
|
|
2603
2627
|
var RESULT_FETCH_ATTEMPTS = 5;
|
|
2628
|
+
var SESSION_CREATE_PROMPT_PREVIEW_MAX_CHARS = 4e3;
|
|
2604
2629
|
var ONBOARDING_PROMPT = "Onboard this repository onto Arcanist.";
|
|
2605
2630
|
function selectCreatedPrompt(prompts, promptId) {
|
|
2606
2631
|
if (prompts.length === 0) return null;
|
|
@@ -2616,6 +2641,11 @@ function buildPromptFailureError(sessionId, prompt, sessionUrl) {
|
|
|
2616
2641
|
hint: `Inspect with: arcanist sessions transcript ${sessionId}`
|
|
2617
2642
|
});
|
|
2618
2643
|
}
|
|
2644
|
+
function buildSessionCreatePromptPreview(prompt) {
|
|
2645
|
+
const trimmed = prompt.trim();
|
|
2646
|
+
if (!trimmed) return void 0;
|
|
2647
|
+
return trimmed.length > SESSION_CREATE_PROMPT_PREVIEW_MAX_CHARS ? trimmed.slice(0, SESSION_CREATE_PROMPT_PREVIEW_MAX_CHARS).trimEnd() : trimmed;
|
|
2648
|
+
}
|
|
2619
2649
|
async function fetchCreatedPromptStatus(config, sessionId, promptId) {
|
|
2620
2650
|
const promptList = await apiFetch(config, `/api/sessions/${sessionId}/prompts`);
|
|
2621
2651
|
return selectCreatedPrompt(promptList.prompts, promptId);
|
|
@@ -2719,6 +2749,14 @@ async function createCommand(repoUrl, promptArg, options, command) {
|
|
|
2719
2749
|
if (options.startBranch !== void 0 && !startBranch) {
|
|
2720
2750
|
throw new CliError("user", "--start-branch must not be empty.");
|
|
2721
2751
|
}
|
|
2752
|
+
const continuePr = options.continuePr?.trim();
|
|
2753
|
+
if (options.continuePr !== void 0 && !continuePr) {
|
|
2754
|
+
throw new CliError("user", "--continue-pr must not be empty.");
|
|
2755
|
+
}
|
|
2756
|
+
const continueMode = options.continueMode?.trim();
|
|
2757
|
+
if (options.continueMode !== void 0 && !continueMode) {
|
|
2758
|
+
throw new CliError("user", "--continue-mode must not be empty.");
|
|
2759
|
+
}
|
|
2722
2760
|
const uploadedFiles = await resolveUploadedFileOptions(options.uploadedFile);
|
|
2723
2761
|
const idempotencyKey = options.idempotencyKey ?? randomIdempotencyKey();
|
|
2724
2762
|
const sessionIdempotencyKey = `${idempotencyKey}:session`;
|
|
@@ -2727,8 +2765,12 @@ async function createCommand(repoUrl, promptArg, options, command) {
|
|
|
2727
2765
|
if (options.model) body.model = options.model;
|
|
2728
2766
|
if (options.backend) body.agentRuntimeBackend = agentRuntimeBackend;
|
|
2729
2767
|
if (options.reasoningEffort) body.reasoningEffort = options.reasoningEffort;
|
|
2768
|
+
const promptPreview = buildSessionCreatePromptPreview(prompt);
|
|
2769
|
+
if (promptPreview) body.prompt = promptPreview;
|
|
2730
2770
|
if (baseBranch) body.baseBranch = baseBranch;
|
|
2731
2771
|
if (startBranch) body.startBranch = startBranch;
|
|
2772
|
+
if (continuePr) body.continuePrUrl = continuePr;
|
|
2773
|
+
if (continueMode) body.continueMode = continueMode;
|
|
2732
2774
|
if (options.cold) body.cold = true;
|
|
2733
2775
|
if (options.onboarding) body.onboarding = true;
|
|
2734
2776
|
const sessionData = await apiFetch(config, "/api/sessions", {
|
|
@@ -2792,6 +2834,8 @@ async function createCommand(repoUrl, promptArg, options, command) {
|
|
|
2792
2834
|
if (options.reasoningEffort) output.reasoningEffort = options.reasoningEffort;
|
|
2793
2835
|
if (baseBranch) output.baseBranch = baseBranch;
|
|
2794
2836
|
if (startBranch) output.startBranch = startBranch;
|
|
2837
|
+
if (continuePr) output.continuePrUrl = continuePr;
|
|
2838
|
+
if (continueMode) output.continueMode = continueMode;
|
|
2795
2839
|
if (options.onboarding) output.onboarding = true;
|
|
2796
2840
|
if (promptId) output.promptId = promptId;
|
|
2797
2841
|
Object.assign(output, waitResultFields);
|
|
@@ -4470,7 +4514,7 @@ function addCreateOptions(cmd) {
|
|
|
4470
4514
|
return cmd.argument("<repo-url>", "Repository URL").argument("[prompt]", "Prompt to send, or '-' to read stdin").option("--model <model>", "Model to use").option("--backend <backend>", "Agent runtime backend: codex (default), claude_code, or opencode").option("--reasoning-effort <effort>", "Reasoning effort to use for models that support it").option("--base-branch <branch>", "Base branch to create the session against (defaults to the repo default branch)").option(
|
|
4471
4515
|
"--start-branch <branch>",
|
|
4472
4516
|
"Resume an existing branch with its history instead of forking a new one off base"
|
|
4473
|
-
).option("--prompt-stdin", "Read prompt from stdin").option(
|
|
4517
|
+
).option("--continue-pr <url>", "Continue from an existing same-repo pull request").option("--continue-mode <mode>", "Continuation mode: auto (default), update-pr, or new-pr").option("--prompt-stdin", "Read prompt from stdin").option(
|
|
4474
4518
|
"--uploaded-file <path>",
|
|
4475
4519
|
"Attach a local text file to the prompt as uploadedFiles; repeat for multiple files",
|
|
4476
4520
|
collectUploadedFileOption
|
|
@@ -4483,13 +4527,14 @@ function addCreateOptions(cmd) {
|
|
|
4483
4527
|
`
|
|
4484
4528
|
Examples:
|
|
4485
4529
|
arcanist sessions create https://github.com/org/repo "fix bug"
|
|
4530
|
+
arcanist sessions create https://github.com/org/repo "finish this PR" --continue-pr https://github.com/org/repo/pull/123
|
|
4486
4531
|
arcanist sessions create https://github.com/org/repo "review this trace" --uploaded-file trace.txt
|
|
4487
4532
|
printf "fix bug" | arcanist sessions create https://github.com/org/repo --prompt-stdin --json
|
|
4488
4533
|
printf "fix bug" | arcanist sessions create https://github.com/org/repo --prompt-stdin --wait
|
|
4489
4534
|
arcanist sessions create https://github.com/org/repo - --json | jq -r .sessionId | xargs -I{} arcanist sessions events {} --follow --json
|
|
4490
4535
|
|
|
4491
4536
|
JSON:
|
|
4492
|
-
JSON mode returns {sessionId, sessionUrl?, repoUrl, model?, agentRuntimeBackend?, reasoningEffort?, baseBranch?, startBranch?, onboarding?, promptId?}
|
|
4537
|
+
JSON mode returns {sessionId, sessionUrl?, repoUrl, model?, agentRuntimeBackend?, reasoningEffort?, baseBranch?, startBranch?, continuePrUrl?, continueMode?, onboarding?, promptId?}
|
|
4493
4538
|
--wait --json also includes best-effort result fields when available: prUrl?, publishedBranch?, lastBranch?
|
|
4494
4539
|
Follow async progress with: arcanist sessions events <session-id> --follow --json
|
|
4495
4540
|
`
|