@tryarcanist/cli 0.1.287 → 0.1.289

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.
Files changed (2) hide show
  1. package/dist/index.js +104 -15
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8524,6 +8524,19 @@ async function egressValidateCommand(path = EGRESS_ALLOWLIST_SOURCE_PATH, option
8524
8524
  });
8525
8525
  }
8526
8526
 
8527
+ // src/commands/hades.ts
8528
+ async function hadesCommand(options = {}, command) {
8529
+ assertArcanistSessionMutationAllowed("hades");
8530
+ const { config } = resolveBusinessContext(command, options);
8531
+ const result = await apiFetch(config, "/api/hades-runs", {
8532
+ method: "POST",
8533
+ body: "{}"
8534
+ });
8535
+ emit(command, options, result, (payload) => {
8536
+ console.log(`Started Hades run ${payload.runId} (${payload.jobId}).`);
8537
+ });
8538
+ }
8539
+
8527
8540
  // src/commands/login.ts
8528
8541
  async function loginCommand(options, command) {
8529
8542
  const runtime = getRuntimeOptions(command, options);
@@ -8593,6 +8606,10 @@ var OpenAIModel = {
8593
8606
  GPT52ChatLatest: "gpt-5.2-chat-latest",
8594
8607
  GPT52Codex: "gpt-5.2-codex"
8595
8608
  };
8609
+ var DeepSeekModel = {
8610
+ V4Flash: "deepseek-v4-flash",
8611
+ V4Pro: "deepseek-v4-pro"
8612
+ };
8596
8613
  var MODEL_PROVIDERS_SET = /* @__PURE__ */ new Set(["openai", "anthropic"]);
8597
8614
  var BACKEND_DESKTOP_IMAGE_FEEDBACK_CONFIGS = {
8598
8615
  [CODEX_AGENT_RUNTIME_BACKEND]: {
@@ -8839,6 +8856,67 @@ var MODEL_REGISTRY = [
8839
8856
  contextWindow: 4e5,
8840
8857
  reasoning: { efforts: ["low", "medium", "high", "xhigh"], default: "high" },
8841
8858
  pricing: { inputPerMillion: 1.75, outputPerMillion: 14, cacheReadPerMillion: 0.175 }
8859
+ },
8860
+ {
8861
+ id: DeepSeekModel.V4Flash,
8862
+ name: "DeepSeek V4 Flash",
8863
+ // `provider` names the WIRE PROTOCOL the gateway speaks (OpenAI Responses),
8864
+ // not the vendor. DeepSeek V4 is served by Baseten: the gateway maps these
8865
+ // registry ids to Baseten wire ids and swaps the upstream host, while every
8866
+ // request/response stays OpenAI-shaped. Do NOT "fix" this to a new
8867
+ // "baseten" provider — `ModelProvider` is what review-model validation, the
8868
+ // credential gate (`PROVIDER_ENV_VAR` / spawn credential resolution), and
8869
+ // the sandbox bridge's model guard all key off, so a new provider value
8870
+ // silently fails those closed instead of routing anywhere.
8871
+ provider: "openai",
8872
+ backends: [CODEX_AGENT_RUNTIME_BACKEND],
8873
+ // Required for codex session-start eligibility: the codex backend is the
8874
+ // sole consumer of this flag and drops any model without it from the
8875
+ // session-start set (see modelSupportsRequiredSessionStartCapabilities).
8876
+ capabilities: { codexToolSearch: true },
8877
+ contextWindow: 1048576,
8878
+ // Only the effort our live Baseten probes actually proved. Registry efforts
8879
+ // are treated as supported capabilities and are selectable by other paths
8880
+ // (isValidReasoningEffort, review config, CLI overrides), so widen this list
8881
+ // only after probing each added value end-to-end against Baseten.
8882
+ reasoning: { efforts: ["high"], default: "high" },
8883
+ // Verified against https://www.baseten.co/pricing on 2026-08-11 (Model APIs
8884
+ // token pricing, row `deepseek-ai/DeepSeek-V4-Flash-0731`): $0.13/M input,
8885
+ // $0.028/M cached input, $0.26/M output. Baseten publishes a cached-input
8886
+ // rate for this model, so cacheReadPerMillion carries it rather than
8887
+ // mirroring the input rate. No longContext and no flex: both are OpenAI-only
8888
+ // pricing axes and Baseten prices a single flat tier.
8889
+ pricing: { inputPerMillion: 0.13, outputPerMillion: 0.26, cacheReadPerMillion: 0.028 },
8890
+ sessionStart: { eligible: true },
8891
+ visibility: "internal_probe"
8892
+ // Deliberately no overloadFallback. A Baseten 429 must not silently re-run
8893
+ // an A/B arm on a different model; with no fallback the loop retries the
8894
+ // same model, which is what an A/B comparison requires.
8895
+ },
8896
+ {
8897
+ id: DeepSeekModel.V4Pro,
8898
+ name: "DeepSeek V4 Pro",
8899
+ // See the DeepSeek V4 Flash entry above: "openai" is the wire protocol
8900
+ // (OpenAI Responses), not the vendor. Changing it to a "baseten" provider
8901
+ // breaks review-model validation, the credential gate, and the sandbox
8902
+ // bridge's model guard.
8903
+ provider: "openai",
8904
+ backends: [CODEX_AGENT_RUNTIME_BACKEND],
8905
+ // Required for codex session-start eligibility (sole consumer of the flag).
8906
+ capabilities: { codexToolSearch: true },
8907
+ contextWindow: 262144,
8908
+ // Only the probed effort; widen only after probing each value against
8909
+ // Baseten, since registry efforts are selectable capabilities.
8910
+ reasoning: { efforts: ["high"], default: "high" },
8911
+ // Verified against https://www.baseten.co/pricing on 2026-08-11 (Model APIs
8912
+ // token pricing, row `DeepSeek V4 Pro`): $1.74/M input, $0.145/M cached
8913
+ // input, $3.48/M output. Cached-input rate is published, so it is carried
8914
+ // verbatim. No longContext and no flex (OpenAI-only axes).
8915
+ pricing: { inputPerMillion: 1.74, outputPerMillion: 3.48, cacheReadPerMillion: 0.145 },
8916
+ sessionStart: { eligible: true },
8917
+ visibility: "internal_probe"
8918
+ // Deliberately no overloadFallback — see DeepSeek V4 Flash: an A/B arm must
8919
+ // retry the same model on a Baseten 429, never silently swap models.
8842
8920
  }
8843
8921
  ];
8844
8922
  var MODEL_PROVIDER_NAMES = {
@@ -8931,6 +9009,7 @@ function extractModelId(raw) {
8931
9009
  function getProviderForModel(modelId) {
8932
9010
  return MODEL_PROVIDERS[modelId] ?? "openai";
8933
9011
  }
9012
+ var BASETEN_SERVED_MODEL_IDS = new Set(Object.values(DeepSeekModel));
8934
9013
  function toModelSelection(raw) {
8935
9014
  const modelID = extractModelId(raw);
8936
9015
  if (!modelID) return void 0;
@@ -10286,7 +10365,7 @@ function getRawSessionEventPromptId(event) {
10286
10365
  if (isCanonicalRawSessionEvent(event)) {
10287
10366
  return canonicalPromptId(event);
10288
10367
  }
10289
- return typeof event.data?.promptId === "string" && event.data.promptId.length > 0 ? event.data.promptId : void 0;
10368
+ return isRecord(event.data) && typeof event.data.promptId === "string" && event.data.promptId.length > 0 ? event.data.promptId : void 0;
10290
10369
  }
10291
10370
  function getRawSessionEventKind(event) {
10292
10371
  if (!isCanonicalRawSessionEvent(event)) return event.type;
@@ -10332,7 +10411,7 @@ function getRawSessionEventTimestamp(event) {
10332
10411
  if (isCanonicalRawSessionEvent(event)) {
10333
10412
  return Number.isFinite(event.timestampMs) && Number.isFinite(new Date(event.timestampMs).getTime()) ? new Date(event.timestampMs).toISOString() : void 0;
10334
10413
  }
10335
- const dataTimestamp = event.data?.timestamp;
10414
+ const dataTimestamp = isRecord(event.data) ? event.data.timestamp : void 0;
10336
10415
  if (typeof dataTimestamp === "string" && dataTimestamp.length > 0 || typeof dataTimestamp === "number") {
10337
10416
  const parsed = new Date(dataTimestamp);
10338
10417
  if (Number.isFinite(parsed.getTime())) return parsed.toISOString();
@@ -10411,6 +10490,7 @@ function getRawSessionEventData(event) {
10411
10490
  ...base,
10412
10491
  error: payload.message,
10413
10492
  ...typeof payload.code === "string" ? { code: payload.code } : {},
10493
+ ...typeof payload.command === "string" ? { command: payload.command } : {},
10414
10494
  ...payload.details !== void 0 ? { errorDetails: payload.details } : {}
10415
10495
  });
10416
10496
  case "bridge.event":
@@ -10695,21 +10775,20 @@ function mergeMemoryRefs(ids, rawRefs) {
10695
10775
  const byId = /* @__PURE__ */ new Map();
10696
10776
  if (Array.isArray(rawRefs)) {
10697
10777
  for (const entry of rawRefs) {
10698
- if (!entry || typeof entry !== "object") continue;
10699
- const record = entry;
10700
- const id = typeof record.id === "string" ? record.id.trim() : "";
10778
+ if (!isRecord(entry)) continue;
10779
+ const id = typeof entry.id === "string" ? entry.id.trim() : "";
10701
10780
  if (!id) continue;
10702
10781
  const ref = { id };
10703
- if (typeof record.path === "string" && record.path.trim()) ref.path = record.path.trim();
10704
- if (typeof record.title === "string" && record.title.trim()) ref.title = record.title.trim();
10705
- if (typeof record.selectionRank === "number") ref.selectionRank = record.selectionRank;
10706
- if (typeof record.selectionScore === "number") ref.selectionScore = record.selectionScore;
10707
- if (typeof record.reason === "string" && record.reason.trim()) ref.reason = record.reason.trim();
10708
- if (typeof record.expectedEffect === "string" && record.expectedEffect.trim()) {
10709
- ref.expectedEffect = record.expectedEffect.trim();
10782
+ if (typeof entry.path === "string" && entry.path.trim()) ref.path = entry.path.trim();
10783
+ if (typeof entry.title === "string" && entry.title.trim()) ref.title = entry.title.trim();
10784
+ if (typeof entry.selectionRank === "number") ref.selectionRank = entry.selectionRank;
10785
+ if (typeof entry.selectionScore === "number") ref.selectionScore = entry.selectionScore;
10786
+ if (typeof entry.reason === "string" && entry.reason.trim()) ref.reason = entry.reason.trim();
10787
+ if (typeof entry.expectedEffect === "string" && entry.expectedEffect.trim()) {
10788
+ ref.expectedEffect = entry.expectedEffect.trim();
10710
10789
  }
10711
- if (typeof record.observedEffect === "string" && record.observedEffect.trim()) {
10712
- ref.observedEffect = record.observedEffect.trim();
10790
+ if (typeof entry.observedEffect === "string" && entry.observedEffect.trim()) {
10791
+ ref.observedEffect = entry.observedEffect.trim();
10713
10792
  }
10714
10793
  byId.set(id, ref);
10715
10794
  }
@@ -10758,7 +10837,8 @@ function projectSessionError(data, index) {
10758
10837
  id: resolveEventId(data, "err", index),
10759
10838
  error: typeof data?.error === "string" ? data.error : "Unknown error",
10760
10839
  ...resolvePromptId(data) ? { promptId: resolvePromptId(data) } : {},
10761
- ...typeof data?.code === "string" ? { code: data.code } : {}
10840
+ ...typeof data?.code === "string" ? { code: data.code } : {},
10841
+ ...typeof data?.command === "string" ? { command: data.command } : {}
10762
10842
  };
10763
10843
  }
10764
10844
  function recordMalformedSearchBlock(data, state) {
@@ -11273,6 +11353,7 @@ var ERROR_CODES = [
11273
11353
  "api_error",
11274
11354
  "model_overloaded",
11275
11355
  "config_error",
11356
+ "github_pr_context",
11276
11357
  "github_app_permission",
11277
11358
  "failed_edits",
11278
11359
  // No producer since the memory subsystem was removed. Retained because the code is
@@ -11319,6 +11400,7 @@ var ERROR_CODE_LABELS = {
11319
11400
  api_error: "Model service error",
11320
11401
  model_overloaded: "Model at capacity",
11321
11402
  config_error: "Configuration error",
11403
+ github_pr_context: "GitHub pull request context unavailable",
11322
11404
  github_app_permission: "GitHub App permissions missing",
11323
11405
  failed_edits: "Edit failure",
11324
11406
  memory_enforcement_failed: "Memory enforcement failed",
@@ -12329,6 +12411,13 @@ The result is posted as a PR comment marked arcanist-anubis:v1.
12329
12411
  Anubis requires a write-scoped CLI token and repository write access.
12330
12412
  `
12331
12413
  ).action((prUrl, options, command) => anubisCommand(prUrl, options, command));
12414
+ program.command("hades").description("Start an internal Hades adversarial Zeus probe").addHelpText(
12415
+ "after",
12416
+ `
12417
+ Hades is internal-only. It creates one proved adversarial patch in tryarcanist/arcanist;
12418
+ the control plane opens the draft pull request and triggers Zeus.
12419
+ `
12420
+ ).action((options, command) => hadesCommand(options, command));
12332
12421
  sessions.command("stop").description("Stop the active run for a session").argument("<session-id>", "Session ID").addHelpText(
12333
12422
  "after",
12334
12423
  `
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tryarcanist/cli",
3
- "version": "0.1.287",
3
+ "version": "0.1.289",
4
4
  "description": "CLI for Arcanist - create and manage coding agent sessions",
5
5
  "type": "module",
6
6
  "bin": {