claudish 14.10.2 → 14.12.0

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 +859 -184
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -5491,7 +5491,7 @@ var init_onepassword_config = __esm(() => {
5491
5491
  });
5492
5492
 
5493
5493
  // src/version.ts
5494
- var VERSION = "14.10.2";
5494
+ var VERSION = "14.12.0";
5495
5495
 
5496
5496
  // src/redact.ts
5497
5497
  function isPlaceholder(value) {
@@ -26267,6 +26267,7 @@ var init_antigravity_token = __esm(() => {
26267
26267
  var exports_antigravity_user = {};
26268
26268
  __export(exports_antigravity_user, {
26269
26269
  antigravityHost: () => antigravityHost,
26270
+ antigravityUserAgentFor: () => antigravityUserAgentFor,
26270
26271
  buildAntigravityUserAgent: () => buildAntigravityUserAgent,
26271
26272
  fetchAntigravityAvailableModelsRaw: () => fetchAntigravityAvailableModelsRaw,
26272
26273
  getAntigravityTierDisplayName: () => getAntigravityTierDisplayName,
@@ -26299,6 +26300,9 @@ function antigravityClientVersion() {
26299
26300
  function userAgentFor(version) {
26300
26301
  return `antigravity/cli/${version} (aidev_client; os_type=${process.platform}; arch=${process.arch}; auth_method=consumer)`;
26301
26302
  }
26303
+ function antigravityUserAgentFor(version) {
26304
+ return userAgentFor(version);
26305
+ }
26302
26306
  function buildAntigravityUserAgent() {
26303
26307
  return userAgentFor(antigravityClientVersion());
26304
26308
  }
@@ -73044,7 +73048,8 @@ var init_contract = __esm(() => {
73044
73048
  "capture_since_seq",
73045
73049
  "capture_spans",
73046
73050
  "resize",
73047
- "allowance"
73051
+ "allowance",
73052
+ "scroll"
73048
73053
  ];
73049
73054
  SLOT_STATES = [
73050
73055
  "STARTING",
@@ -90429,6 +90434,10 @@ ${h("SUBCOMMANDS")}
90429
90434
  ${green("claudish subscription models antigravity")} ${yellow("--raw --json")}
90430
90435
  Print the raw Antigravity fetchAvailableModels
90431
90436
  ${dim("body as one JSON line (for models-index)")}
90437
+ ${green("claudish subscription probe antigravity")} ${yellow("--model <id> --request-file <path> --raw --json")}
90438
+ Send the file's Gemini request once through the
90439
+ Antigravity login (generateContent, no retry, model
90440
+ ${dim("id unchanged); print the raw answer as one JSON line")}
90432
90441
  ${green("claudish update")} Check for updates and install the latest version
90433
90442
 
90434
90443
  ${bold("Profiles:")}
@@ -93465,6 +93474,39 @@ var init_screen_classifier = __esm(() => {
93465
93474
  NON_ANSWER_ROW = /^\s+\u23BF|^\s{2}(Ran|Read|Searched|Wrote|Edited|Listed|Updated) \d+ |^\s*[\u00B7\u2722\u2733\u2736\u273B\u273D*\u25CF\u2217]\s|^\s*\(ctrl\+/;
93466
93475
  });
93467
93476
 
93477
+ // src/pane/scroll-input.ts
93478
+ function isLiveBottom(pos) {
93479
+ return pos.atBottom && pos.lastDirection === null;
93480
+ }
93481
+ function scrollRowsOf(by) {
93482
+ if (!Number.isFinite(by))
93483
+ return 0;
93484
+ return Math.min(Math.abs(Math.trunc(by)), MAX_SCROLL_ROWS);
93485
+ }
93486
+ function planScroll(pos, req) {
93487
+ if ("to" in req)
93488
+ return { bytes: CTRL_END, events: 1, next: LIVE_BOTTOM };
93489
+ const n = scrollRowsOf(req.by);
93490
+ if (n === 0)
93491
+ return { bytes: "", events: 0, next: pos };
93492
+ const dir = req.by < 0 ? "up" : "down";
93493
+ const extra = pos.atBottom || pos.lastDirection !== dir ? 1 : 0;
93494
+ const events = n + extra;
93495
+ return {
93496
+ bytes: (dir === "up" ? WHEEL_UP : WHEEL_DOWN).repeat(events),
93497
+ events,
93498
+ next: { atBottom: false, lastDirection: dir }
93499
+ };
93500
+ }
93501
+ var MAX_SCROLL_ROWS = 200, WHEEL_UP = "\x1B[<64;1;1M", WHEEL_DOWN = "\x1B[<65;1;1M", CTRL_END = "\x1B[1;5F", LIVE_BOTTOM, UNKNOWN_POSITION;
93502
+ var init_scroll_input = __esm(() => {
93503
+ LIVE_BOTTOM = Object.freeze({ atBottom: true, lastDirection: null });
93504
+ UNKNOWN_POSITION = Object.freeze({
93505
+ atBottom: false,
93506
+ lastDirection: null
93507
+ });
93508
+ });
93509
+
93468
93510
  // src/pane/session-registry.ts
93469
93511
  import { readFileSync as readFileSync40, readdirSync as readdirSync6 } from "fs";
93470
93512
  import { join as join48 } from "path";
@@ -94609,6 +94651,9 @@ class PaneSessionImpl {
94609
94651
  resizeQuietFrom = 0;
94610
94652
  resizeQuietUntil = 0;
94611
94653
  activityChangedAt = 0;
94654
+ scrollPos = LIVE_BOTTOM;
94655
+ scrollEndsInFlight = 0;
94656
+ scrollEndConfirmedAt = 0;
94612
94657
  gate = null;
94613
94658
  gateTrusted = false;
94614
94659
  gateInFlight = false;
@@ -95399,8 +95444,8 @@ ${gate}`
95399
95444
  await this.pause(adm, TICK_MS);
95400
95445
  continue;
95401
95446
  }
95402
- if (!this.client || !this.gateTrusted) {
95403
- await this.awaitTrustedClient(adm);
95447
+ if (!this.trustedConnection() || this.needsAdmissionLiveBottom(adm)) {
95448
+ await this.connectionStep(adm);
95404
95449
  continue;
95405
95450
  }
95406
95451
  if (await this.beforeSend(adm) !== "send")
@@ -95412,8 +95457,22 @@ ${gate}`
95412
95457
  adm.inFlight = false;
95413
95458
  }
95414
95459
  }
95460
+ needsAdmissionLiveBottom(adm) {
95461
+ if (adm.liveBottomClient === this.client)
95462
+ return false;
95463
+ adm.liveBottomClient = this.client;
95464
+ return !isLiveBottom(this.scrollPos);
95465
+ }
95466
+ trustedConnection() {
95467
+ return !!this.client && !this.client.isClosed && this.gateTrusted;
95468
+ }
95469
+ connectionStep(adm) {
95470
+ if (!this.trustedConnection())
95471
+ return this.awaitTrustedClient(adm);
95472
+ return this.returnToLiveBottom(Math.max(0, adm.deadline - Date.now()));
95473
+ }
95415
95474
  awaitTrustedClient(adm) {
95416
- return this.waitFor(() => !this.admitting(adm) || !!this.client && this.gateTrusted, Math.max(0, adm.deadline - Date.now()));
95475
+ return this.waitFor(() => !this.admitting(adm) || this.trustedConnection(), Math.max(0, adm.deadline - Date.now()));
95417
95476
  }
95418
95477
  async attemptOnce(adm) {
95419
95478
  const c = this.client;
@@ -95838,6 +95897,7 @@ ${screenTailOf(this.screen)}` });
95838
95897
  accept() {
95839
95898
  this.admission = null;
95840
95899
  this.initialDelivery = false;
95900
+ this.scrollPos = LIVE_BOTTOM;
95841
95901
  const now = Date.now();
95842
95902
  this.lastChatSeenAt = now;
95843
95903
  this.turnAcceptedAt = now;
@@ -95914,6 +95974,7 @@ ${screenTailOf(this.screen)}`
95914
95974
  const d = this.currentDelivery;
95915
95975
  this.turnSource = "screen";
95916
95976
  this.anomaly("degraded_mode");
95977
+ this.returnToLiveBottom(SCROLL_REPLY_MS);
95917
95978
  this.screenTurn = {
95918
95979
  echo: d && d.mode !== "refused" ? d.line : "",
95919
95980
  acceptedAt: at,
@@ -96391,11 +96452,21 @@ ${screenTailOf(this.screen)}`
96391
96452
  const g = this.gateNow();
96392
96453
  if (!g || !g.ready || g.dialog !== null || workingAboveBox(this.screen) === true)
96393
96454
  return false;
96394
- const quiet = this.aboveBoxQuietMs() ?? Date.now() - this.screen.changedAt;
96455
+ let quiet = this.aboveBoxQuietMs() ?? Date.now() - this.screen.changedAt;
96456
+ if (this.scrollEndConfirmedAt > 0)
96457
+ quiet = Math.min(quiet, Date.now() - this.scrollEndConfirmedAt);
96395
96458
  if (view.availability === "off" && quiet >= this.secondaryQuietMs)
96396
96459
  return true;
96397
96460
  return (!!answer || !!apiError) && quiet >= 2 * this.t("screenSettleQuietMs", SCREEN_SETTLE_QUIET_MS);
96398
96461
  }
96462
+ screenViewLive() {
96463
+ if (this.scrollEndsInFlight > 0)
96464
+ return false;
96465
+ if (isLiveBottom(this.scrollPos))
96466
+ return true;
96467
+ this.returnToLiveBottom(SCROLL_REPLY_MS);
96468
+ return false;
96469
+ }
96399
96470
  evalScreenTurn(view) {
96400
96471
  if (this.witnessed(view.current)) {
96401
96472
  this.turnSource = "transcript";
@@ -96410,7 +96481,7 @@ ${screenTailOf(this.screen)}`
96410
96481
  const answer = screenAnswer(this.screen, st.echo);
96411
96482
  const apiError = this.screenApiError(st, answer);
96412
96483
  this.activity = "thinking";
96413
- if (!this.screenSettleReady(view, answer, apiError))
96484
+ if (!this.screenViewLive() || !this.screenSettleReady(view, answer, apiError))
96414
96485
  return;
96415
96486
  this.follower.poll();
96416
96487
  if (this.witnessed(this.follower.view().current))
@@ -96741,6 +96812,69 @@ ${screenTailOf(this.screen)}`
96741
96812
  answer({ ...set, changed: true, seq: this.screen.seq });
96742
96813
  }
96743
96814
  }
96815
+ async scroll(req) {
96816
+ const refusal = this.scrollRefusal();
96817
+ if (refusal)
96818
+ throw new ContractErrorException("scroll_unavailable", refusal);
96819
+ const c = this.client;
96820
+ if (!c || c.isClosed)
96821
+ throw new ContractErrorException("scroll_unavailable", "the pane's socket is reconnecting");
96822
+ const plan = planScroll(this.scrollPos, req);
96823
+ if (plan.bytes === "")
96824
+ return { seq: this.screen.seq };
96825
+ this.scrollPos = plan.next;
96826
+ const seq0 = this.screen.seq;
96827
+ this.extendResizeQuiet();
96828
+ const r = await c.request({ type: "send", pane: 0, text: plan.bytes, enter: false, noGate: true }, SCROLL_REPLY_MS);
96829
+ if (!r.ok) {
96830
+ this.scrollPos = UNKNOWN_POSITION;
96831
+ if (r.code === "client_lost" || r.code === "client_timeout")
96832
+ this.extendResizeQuiet();
96833
+ throw new ContractErrorException("scroll_unavailable", `magmux did not confirm the scroll: ${r.code}${r.error ? `: ${r.error}` : ""}`);
96834
+ }
96835
+ this.extendResizeQuiet();
96836
+ await this.waitFor(() => isTerminalPhase(this.phase) || this.screen.seq !== seq0, this.t("scrollScreenMs", SCROLL_SCREEN_MS));
96837
+ return { seq: this.screen.seq };
96838
+ }
96839
+ screenTurnActive() {
96840
+ if (this.turnSource !== "screen")
96841
+ return false;
96842
+ return this.phase === "RUNNING" || this.phase === "QUESTION" || this.phase === "PERMISSION";
96843
+ }
96844
+ scrollRefusal() {
96845
+ if (isTerminalPhase(this.phase) || this.final)
96846
+ return "the session has finished";
96847
+ if (this.phase === "BOOTING" || this.screen.seq === 0)
96848
+ return "the session is still starting";
96849
+ if (this.phase === "ADMITTING")
96850
+ return "a prompt is being delivered to the session";
96851
+ if (this.screenTurnActive())
96852
+ return "the session's turn is being read from its screen (no transcript)";
96853
+ if (!this.client || this.client.isClosed || !this.gateTrusted)
96854
+ return "the pane's socket is reconnecting";
96855
+ return null;
96856
+ }
96857
+ async returnToLiveBottom(ms) {
96858
+ if (isLiveBottom(this.scrollPos))
96859
+ return;
96860
+ const c = this.client;
96861
+ if (!c || c.isClosed || !this.gateTrusted || ms <= 0)
96862
+ return;
96863
+ this.scrollPos = LIVE_BOTTOM;
96864
+ this.extendResizeQuiet();
96865
+ this.scrollEndsInFlight++;
96866
+ try {
96867
+ const r = await c.request({ type: "send", pane: 0, text: CTRL_END, enter: false, noGate: true }, Math.min(SCROLL_REPLY_MS, ms));
96868
+ if (r.ok) {
96869
+ this.scrollEndConfirmedAt = Date.now();
96870
+ } else {
96871
+ this.scrollPos = UNKNOWN_POSITION;
96872
+ this.anomaly(`scroll_end_unconfirmed:${r.code}`);
96873
+ }
96874
+ } finally {
96875
+ this.scrollEndsInFlight--;
96876
+ }
96877
+ }
96744
96878
  turnAnswer(index) {
96745
96879
  const done = this.answers.get(index);
96746
96880
  if (done !== undefined)
@@ -96993,7 +97127,8 @@ function newAdmission(a) {
96993
97127
  clearAfter: 0,
96994
97128
  lostType: null,
96995
97129
  last: null,
96996
- noted: new Set
97130
+ noted: new Set,
97131
+ liveBottomClient: null
96997
97132
  };
96998
97133
  }
96999
97134
  function markClearFirst(adm) {
@@ -97160,7 +97295,7 @@ async function startPaneSession(o) {
97160
97295
  await session.start({ magmuxBinary: magmux.binary, env: p.magmuxEnv, cwd: p.cwd });
97161
97296
  return session;
97162
97297
  }
97163
- var BOOT_TIMEOUT_MS = 90000, ADMIT_TIMEOUT_MS = 30000, DEGRADED_ENTRY_MS = 1e4, SCREEN_SETTLE_QUIET_MS = 3000, PANEL_SETTLE_MS = 500, SEND_CLIENT_SLACK_MS = 2000, MIN_READY_TIMEOUT_MS = 1000, BUSY_RETRY_MS = 250, MISMATCH_SETTLE_MS = 1000, CLEAR_WAIT_MS = 1000, BOOT_STATIC_MS = 5000, TICK_MS = 250, WATCH_FPS = 4, POLL_BACKSTOP_MS = 1000, TURN_END_MISSING_FACTOR = 3, RESIZE_REPLY_MS = 1e4, RESIZE_SCREEN_MS = 1000, GATE_POLL_MS = 250, GATE_REPLY_MS = 1000, GATE_STALE_MS2 = 1000, GATE_GRACE_MS, GATE_DEAD_BACKSTOP_MS = 1000, EXIT_CODE_QUERY_MS = 2000, EXIT_CODE_RETRY_MS = 50, GATE_KINDLESS_REASONS, RUNTIME_DIALOG_KINDS, REGISTRY_READ_MS = 250, REGISTRY_DISAGREE_MS = 2000, REGISTRY_GATE_BOOT_DISAGREE_MS = 5000, REGISTRY_MISSING_MS = 5000, MAX_ANOMALY_KEYS = 64, KEPT_ANSWERS = 4, DEFAULT_MAX_CONSECUTIVE = 3, EVENT_REASON, VERDICT_EVENT, PaneStartError;
97298
+ var BOOT_TIMEOUT_MS = 90000, ADMIT_TIMEOUT_MS = 30000, DEGRADED_ENTRY_MS = 1e4, SCREEN_SETTLE_QUIET_MS = 3000, PANEL_SETTLE_MS = 500, SEND_CLIENT_SLACK_MS = 2000, MIN_READY_TIMEOUT_MS = 1000, BUSY_RETRY_MS = 250, MISMATCH_SETTLE_MS = 1000, CLEAR_WAIT_MS = 1000, BOOT_STATIC_MS = 5000, TICK_MS = 250, WATCH_FPS = 4, POLL_BACKSTOP_MS = 1000, TURN_END_MISSING_FACTOR = 3, RESIZE_REPLY_MS = 1e4, RESIZE_SCREEN_MS = 1000, SCROLL_REPLY_MS = 5000, SCROLL_SCREEN_MS = 1000, GATE_POLL_MS = 250, GATE_REPLY_MS = 1000, GATE_STALE_MS2 = 1000, GATE_GRACE_MS, GATE_DEAD_BACKSTOP_MS = 1000, EXIT_CODE_QUERY_MS = 2000, EXIT_CODE_RETRY_MS = 50, GATE_KINDLESS_REASONS, RUNTIME_DIALOG_KINDS, REGISTRY_READ_MS = 250, REGISTRY_DISAGREE_MS = 2000, REGISTRY_GATE_BOOT_DISAGREE_MS = 5000, REGISTRY_MISSING_MS = 5000, MAX_ANOMALY_KEYS = 64, KEPT_ANSWERS = 4, DEFAULT_MAX_CONSECUTIVE = 3, EVENT_REASON, VERDICT_EVENT, PaneStartError;
97164
97299
  var init_pane_session = __esm(() => {
97165
97300
  init_queue();
97166
97301
  init_parent_session();
@@ -97177,6 +97312,7 @@ var init_pane_session = __esm(() => {
97177
97312
  init_prompt_delivery();
97178
97313
  init_screen_classifier();
97179
97314
  init_screen_model();
97315
+ init_scroll_input();
97180
97316
  init_session_registry();
97181
97317
  init_settle_rule();
97182
97318
  init_slot_state();
@@ -97231,6 +97367,7 @@ var init_pane = __esm(() => {
97231
97367
  init_pane_launch();
97232
97368
  init_pane_registry();
97233
97369
  init_pane_session();
97370
+ init_scroll_input();
97234
97371
  init_contract();
97235
97372
  });
97236
97373
 
@@ -97959,6 +98096,20 @@ async function resizeTeamSlot(path, slot, cols, rows, runId) {
97959
98096
  return { ...where, cols: DEFAULT_PANE_COLS, rows: DEFAULT_PANE_ROWS, changed: false, seq: 0 };
97960
98097
  return { ...where, ...await e.session.resize(cols, rows) };
97961
98098
  }
98099
+ async function scrollTeamSlot(path, slot, req, runId) {
98100
+ const run = addressRun(path, runId);
98101
+ if (!run)
98102
+ throw unknownRun(path, runId);
98103
+ const e = run.slots.get(slot);
98104
+ if (!e)
98105
+ throw new ContractErrorException("unknown_slot", `run ${run.runId} has no slot ${JSON.stringify(slot)}`);
98106
+ if (!e.session) {
98107
+ const state = run.status.models[e.id]?.state;
98108
+ throw new ContractErrorException("scroll_unavailable", state === undefined || isTerminalState(state) ? "the slot has finished" : "the slot is still starting");
98109
+ }
98110
+ const r = await e.session.scroll(req);
98111
+ return { run_id: run.runId, path: run.path, slot, seq: r.seq };
98112
+ }
97962
98113
  function teamLiveMaps(path, runId) {
97963
98114
  const run = addressRun(path, runId);
97964
98115
  if (!run)
@@ -99999,6 +100150,15 @@ class SessionManager {
99999
100150
  const r = await entry.session.resize(cols, rows);
100000
100151
  return { session_id: sessionId, ...r };
100001
100152
  }
100153
+ async scrollSession(sessionId, req) {
100154
+ const entry = this.liveEntry(sessionId);
100155
+ if (!entry)
100156
+ throw unknownSession(sessionId);
100157
+ if (!entry.session)
100158
+ throw new ContractErrorException("scroll_unavailable", isTerminalState(entry.info.state) ? "the session has finished" : "the session is still starting");
100159
+ const r = await entry.session.scroll(req);
100160
+ return { session_id: sessionId, seq: r.seq };
100161
+ }
100002
100162
  captureSession(sessionId, sinceSeq, spans) {
100003
100163
  const entry = this.liveEntry(sessionId);
100004
100164
  if (!entry)
@@ -100434,7 +100594,7 @@ var NESTED_MCP_TOOL_NAMES, NESTED_INSTRUCTIONS = `Claudish MCP server provides a
100434
100594
 
100435
100595
  ## Nested mode \u2014 no sessions
100436
100596
 
100437
- This server runs inside a session that a claudish MCP server started (CLAUDISH_PANE_CHILD=1). One level of nesting is the limit, so these tools are not registered: create_session, team, send_input, get_output, cancel_session, list_sessions, get_diagnostics, capture_session, preflight, report_error. No channel notifications are sent.
100597
+ This server runs inside a session that a claudish MCP server started (CLAUDISH_PANE_CHILD=1). One level of nesting is the limit, so these tools are not registered: create_session, team, send_input, get_output, cancel_session, list_sessions, get_diagnostics, capture_session, resize_session, scroll_session, preflight, report_error. No channel notifications are sent.
100438
100598
 
100439
100599
  - run_prompt or compare_models: a one-shot answer from another model.
100440
100600
  - list_models, search_models: find a model.
@@ -101531,6 +101691,22 @@ function requiredInteger(raw, name, mode) {
101531
101691
  throw new ContractErrorException("invalid_args", `'${name}' is required${mode ? ` for mode '${mode}'` : ""}`);
101532
101692
  return n;
101533
101693
  }
101694
+ function scrollArgs(args) {
101695
+ const by = optionalInteger(args.by, "by");
101696
+ const to = args.to;
101697
+ if (to !== undefined && to !== null && to !== "end")
101698
+ throw new ContractErrorException("invalid_args", `'to' must be "end"`);
101699
+ const hasTo = to === "end";
101700
+ if (by !== undefined && hasTo)
101701
+ throw new ContractErrorException("invalid_args", "give exactly one of 'by' and 'to', not both");
101702
+ if (hasTo)
101703
+ return { to: "end" };
101704
+ if (by === undefined)
101705
+ throw new ContractErrorException("invalid_args", "one of 'by' and 'to' is required");
101706
+ if (by === 0)
101707
+ throw new ContractErrorException("invalid_args", "'by' must not be 0");
101708
+ return { by };
101709
+ }
101534
101710
  function teamStatusAnswer(path, runId) {
101535
101711
  let row = null;
101536
101712
  if (runId) {
@@ -101575,6 +101751,7 @@ async function teamContractVerb(mode, args) {
101575
101751
  const spans = optionalBoolean(args.spans, "spans");
101576
101752
  const cols = mode === "resize" ? requiredInteger(args.cols, "cols", mode) : undefined;
101577
101753
  const rows = mode === "resize" ? requiredInteger(args.rows, "rows", mode) : undefined;
101754
+ const scroll = mode === "scroll" ? scrollArgs(args) : undefined;
101578
101755
  switch (mode) {
101579
101756
  case "status":
101580
101757
  return contractAnswer(teamStatusAnswer(path, runId));
@@ -101590,6 +101767,11 @@ async function teamContractVerb(mode, args) {
101590
101767
  throw new ContractErrorException("invalid_args", "'slot' is required for mode 'resize'");
101591
101768
  return contractAnswer(await resizeTeamSlot(path, slot, cols, rows, runId));
101592
101769
  }
101770
+ case "scroll": {
101771
+ if (slot === undefined)
101772
+ throw new ContractErrorException("invalid_args", "'slot' is required for mode 'scroll'");
101773
+ return contractAnswer(await scrollTeamSlot(path, slot, scroll, runId));
101774
+ }
101593
101775
  }
101594
101776
  } catch (e) {
101595
101777
  return contractErrorAnswer(e);
@@ -101937,18 +102119,28 @@ This searched OpenRouter's listing only. Subscription wire ids and catalog alias
101937
102119
  });
101938
102120
  tools.push({
101939
102121
  name: "team",
101940
- description: "Run AI models on a task with anonymized outputs and optional blind judging. Every slot is an interactive Claude Code session in its own headless magmux pane. " + "Modes: 'run' (START the models and return once each has taken its prompt \u2014 it does " + "NOT wait for answers), 'status' (per-slot state; read `run.slots`), 'list' (every run this server holds), 'capture' (one slot's screen), 'resize' (set one slot's terminal size), 'cancel' (stop one slot or the whole run), 'judge'(blind-vote on existing outputs), 'run-and-judge' (the blocking pipeline). Poll 'status' (read run.slots) or 'list'. NO SLOT IS EVER KILLED ON A TIMER once its prompt is accepted. A team slot is a full Claude Code session and may work for a long time; a slot inside a build or test suite emits nothing for minutes and is working, not stuck. Judge the silence against the task you set, and use 'cancel' if you decide a slot is wedged. A slot that stops on a question it cannot answer is FAILED 'blocked' (team has no way to answer it). JUDGING A WORKING SLOT: read live_output_bytes_by_slot, idle_seconds_by_slot and activity_by_slot (or each row's idle_seconds and " + "activity). Do NOT use 'outputSize' \u2014 it is the size of the final answer, written " + "only when a slot finishes, so it is 0 for every working slot no matter how much that slot has produced.",
102122
+ description: "Run AI models on a task with anonymized outputs and optional blind judging. Every slot is an interactive Claude Code session in its own headless magmux pane. " + "Modes: 'run' (START the models and return once each has taken its prompt \u2014 it does " + "NOT wait for answers), 'status' (per-slot state; read `run.slots`), 'list' (every run this server holds), 'capture' (one slot's screen), 'resize' (set one slot's terminal size), 'scroll' (scroll one slot's transcript view), 'cancel' (stop one slot or the whole run), 'judge'(blind-vote on existing outputs), 'run-and-judge' (the blocking pipeline). Poll 'status' (read run.slots) or 'list'. NO SLOT IS EVER KILLED ON A TIMER once its prompt is accepted. A team slot is a full Claude Code session and may work for a long time; a slot inside a build or test suite emits nothing for minutes and is working, not stuck. Judge the silence against the task you set, and use 'cancel' if you decide a slot is wedged. A slot that stops on a question it cannot answer is FAILED 'blocked' (team has no way to answer it). JUDGING A WORKING SLOT: read live_output_bytes_by_slot, idle_seconds_by_slot and activity_by_slot (or each row's idle_seconds and " + "activity). Do NOT use 'outputSize' \u2014 it is the size of the final answer, written " + "only when a slot finishes, so it is 0 for every working slot no matter how much that slot has produced.",
101941
102123
  inputSchema: {
101942
102124
  type: "object",
101943
102125
  properties: {
101944
102126
  mode: {
101945
102127
  type: "string",
101946
- enum: ["run", "judge", "run-and-judge", "status", "cancel", "list", "capture", "resize"],
101947
- description: "Operation mode. 'run' STARTS the models and returns once every slot has taken " + "its prompt (or failed to) \u2014 it does not wait for answers. Poll 'status' (read " + "`run.slots`) or 'list' for progress, then 'judge' once the slots have finished. 'capture' returns one slot's screen; 'resize' sets its terminal size. 'run-and-judge' is the blocking pipeline and holds the call open for the whole run. 'cancel' stops one slot or the whole run."
102128
+ enum: [
102129
+ "run",
102130
+ "judge",
102131
+ "run-and-judge",
102132
+ "status",
102133
+ "cancel",
102134
+ "list",
102135
+ "capture",
102136
+ "resize",
102137
+ "scroll"
102138
+ ],
102139
+ description: "Operation mode. 'run' STARTS the models and returns once every slot has taken " + "its prompt (or failed to) \u2014 it does not wait for answers. Poll 'status' (read " + "`run.slots`) or 'list' for progress, then 'judge' once the slots have finished. 'capture' returns one slot's screen; 'resize' sets its terminal size; 'scroll' scrolls its transcript view (`by` or `to`). 'run-and-judge' is the blocking pipeline and holds the call open for the whole run. 'cancel' stops one slot or the whole run."
101948
102140
  },
101949
102141
  slot: {
101950
102142
  type: "string",
101951
- description: "For 'cancel', 'capture' and 'resize': the anonymised slot id (e.g. '02') from the slot map 'run' returned. 'capture' and 'resize' require it; for 'cancel', omit it to stop every slot in the run."
102143
+ description: "For 'cancel', 'capture', 'resize' and 'scroll': the anonymised slot id (e.g. '02') from the slot map 'run' returned. 'capture', 'resize' and 'scroll' require it; for 'cancel', omit it to stop every slot in the run."
101952
102144
  },
101953
102145
  path: {
101954
102146
  type: "string",
@@ -101956,7 +102148,7 @@ This searched OpenRouter's listing only. Subscription wire ids and catalog alias
101956
102148
  },
101957
102149
  run_id: {
101958
102150
  type: "string",
101959
- description: "For 'status', 'cancel', 'capture' and 'resize': the run_id a 'run' answer returned. It addresses THAT run while this server retains it, even after a newer run reused the path. Omit it to address the newest run at 'path'."
102151
+ description: "For 'status', 'cancel', 'capture', 'resize' and 'scroll': the run_id a 'run' answer returned. It addresses THAT run while this server retains it, even after a newer run reused the path. Omit it to address the newest run at 'path'."
101960
102152
  },
101961
102153
  since_seq: {
101962
102154
  type: "number",
@@ -101974,6 +102166,15 @@ This searched OpenRouter's listing only. Subscription wire ids and catalog alias
101974
102166
  type: "integer",
101975
102167
  description: "For 'resize' (required): the terminal height in rows, clamped to 24\u20139999 and to " + "at most 4 000 000 cells (cols \xD7 rows)."
101976
102168
  },
102169
+ by: {
102170
+ type: "integer",
102171
+ description: "For 'scroll': rows to scroll the slot's transcript view; negative = toward older " + `content, positive = toward the live bottom. A target, \xB1 1 row; |by| is capped at ${MAX_SCROLL_ROWS}. Not 0. Give exactly one of 'by' and 'to'. The answer {run_id, path, slot, seq} carries the screen's seq after the scroll.`
102172
+ },
102173
+ to: {
102174
+ type: "string",
102175
+ enum: ["end"],
102176
+ description: `For 'scroll': "end" returns the slot's view to the live bottom. Give exactly one of 'by' and 'to'.`
102177
+ },
101977
102178
  models: {
101978
102179
  type: "array",
101979
102180
  items: { type: "string" },
@@ -102030,7 +102231,7 @@ This searched OpenRouter's listing only. Subscription wire ids and catalog alias
102030
102231
  heartbeat: true,
102031
102232
  handler: async (args, ctx) => {
102032
102233
  const mode = args.mode;
102033
- if (mode === "list" || mode === "status" || mode === "cancel" || mode === "capture" || mode === "resize") {
102234
+ if (mode === "list" || mode === "status" || mode === "cancel" || mode === "capture" || mode === "resize" || mode === "scroll") {
102034
102235
  return teamContractVerb(mode, args);
102035
102236
  }
102036
102237
  try {
@@ -102731,6 +102932,38 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
102731
102932
  }
102732
102933
  }
102733
102934
  });
102935
+ tools.push({
102936
+ name: "scroll_session",
102937
+ description: "Scroll a session's transcript view, as a mouse wheel over the child's Claude Code would: the next capture_session shows the child scrolled. `by` is a signed row count (negative = toward older content, positive = toward the live bottom); it is a " + `target, \xB1 1 row, and |by| is capped at ${MAX_SCROLL_ROWS} per call. \`to:"end"\` returns to the live bottom. Give exactly one of \`by\` and \`to\`; \`by:0\` is refused. It never types into the prompt, submits or answers a dialog, and a prompt claudish delivers next returns the view to the bottom first. The answer {session_id, seq} carries the screen's seq after the scroll (the first changed screen within 1 s, else the current one). Errors are a JSON ContractError: \`scroll_unavailable\` while the session is still starting, finished, delivering a prompt, reading its turn from the screen or reconnecting, or when magmux did not confirm the send (the scroll may still land). Nothing is queued.`,
102938
+ inputSchema: {
102939
+ type: "object",
102940
+ properties: {
102941
+ session_id: { type: "string", description: "Session ID from create_session" },
102942
+ by: {
102943
+ type: "integer",
102944
+ description: `Rows to scroll; negative = older content. Not 0; |by| capped at ${MAX_SCROLL_ROWS}; a target, \xB1 1 row`
102945
+ },
102946
+ to: {
102947
+ type: "string",
102948
+ enum: ["end"],
102949
+ description: '"end" returns the view to the live bottom'
102950
+ }
102951
+ },
102952
+ required: ["session_id"]
102953
+ },
102954
+ group: "session",
102955
+ handler: async (args) => {
102956
+ try {
102957
+ const sessionId = optionalString(args.session_id, "session_id");
102958
+ if (sessionId === undefined)
102959
+ throw new ContractErrorException("invalid_args", "'session_id' is required");
102960
+ const req = scrollArgs(args);
102961
+ return contractAnswer(await sessionManager.scrollSession(sessionId, req));
102962
+ } catch (e) {
102963
+ return contractErrorAnswer(e);
102964
+ }
102965
+ }
102966
+ });
102734
102967
  return tools;
102735
102968
  }
102736
102969
  function resolveToolGroups(mode) {
@@ -102874,7 +103107,7 @@ Each session is an interactive Claude Code running the model in its own headless
102874
103107
  3. send_input may be called at any time; it is queued until the session is idle.
102875
103108
  4. COMPLETED: call get_output for the answer.
102876
103109
  5. FAILED or TIMEOUT \u2014 or COMPLETED with an empty or surprising answer \u2014 call get_diagnostics. It returns the child's final screen, the upstream error bodies, the recent state records, the resolved model chain and the paths to the full records. It needs no re-run and no debug flag.
102877
- 6. capture_session reads a session's current screen; resize_session sets its terminal size (any time, mid-turn included); cancel_session stops it. Nothing stops a session for being idle: a child inside a long build is silent and working.
103110
+ 6. capture_session reads a session's current screen; resize_session sets its terminal size (any time, mid-turn included); scroll_session scrolls the child's transcript view (by rows, or back to the live bottom); cancel_session stops it. Nothing stops a session for being idle: a child inside a long build is silent and working.
102878
103111
 
102879
103112
  The session_id from create_session is the key for every session tool.`, proxyInstance = null, proxyStarting = null, SCORE_TIE_EPSILON = 0.000001, NEXT_STEP, KEEP_EFFORT = "default", USER_REQUIRED_MODEL_DESCRIPTION, sanitize2, TOOL_MODES;
102880
103113
  var init_mcp_server = __esm(() => {
@@ -104456,68 +104689,20 @@ var init_keychain_command = __esm(() => {
104456
104689
  VALUE_FLAGS = new Set(["--config", "--from", "--only"]);
104457
104690
  });
104458
104691
 
104459
- // src/subscription-models-command.ts
104460
- var exports_subscription_models_command = {};
104461
- __export(exports_subscription_models_command, {
104462
- EXIT: () => EXIT,
104463
- FAILURE_CODES: () => FAILURE_CODES,
104464
- INTERNAL_ERROR_MESSAGE: () => INTERNAL_ERROR_MESSAGE,
104465
- SECRET_GUARD_MESSAGE: () => SECRET_GUARD_MESSAGE,
104466
- SUBSCRIPTION_MODELS_USAGE: () => SUBSCRIPTION_MODELS_USAGE,
104467
- SUBSCRIPTION_MODEL_LIST_SCHEMA: () => SUBSCRIPTION_MODEL_LIST_SCHEMA,
104468
- defaultSubscriptionModelsDeps: () => defaultSubscriptionModelsDeps,
104469
- exitCodeFor: () => exitCodeFor,
104470
- parseSubscriptionModelsArgs: () => parseSubscriptionModelsArgs,
104471
- reportSubscriptionInternalError: () => reportSubscriptionInternalError,
104472
- runAntigravityRawModelList: () => runAntigravityRawModelList,
104473
- subscriptionModelsCommand: () => subscriptionModelsCommand
104474
- });
104475
- function exitCodeFor(failure) {
104476
- if (failure.class === "internal")
104477
- return failure.code === "usage" ? EXIT.usage : EXIT.internal;
104478
- return EXIT[failure.class];
104479
- }
104480
- function defaultSubscriptionModelsDeps() {
104481
- return {
104482
- platform: () => process.platform,
104483
- readStore: readAntigravityStoreClassified,
104484
- tokenDeps: defaultAntigravityTokenDeps,
104485
- now: () => Date.now(),
104486
- httpTimeoutMs: 30000,
104487
- keychainDeadlineMs: 1e4,
104488
- writeStdout: (line) => new Promise((resolve, reject) => {
104489
- process.stdout.write(line, (err) => err ? reject(err) : resolve());
104490
- }),
104491
- writeStderr: (line) => {
104492
- process.stderr.write(line);
104493
- }
104494
- };
104495
- }
104496
- function parseSubscriptionModelsArgs(argv) {
104497
- const positionals = argv.filter((a) => !a.startsWith("-"));
104498
- const flags = argv.filter((a) => a.startsWith("-"));
104499
- const positionalsOk = positionals.length === 2 && positionals[0] === "models" && positionals[1] === "antigravity";
104500
- const flagsOk = flags.length === 2 && flags.includes("--raw") && flags.includes("--json");
104501
- return positionalsOk && flagsOk ? { ok: true, provider: "antigravity" } : { ok: false };
104692
+ // src/subscription-antigravity-session.ts
104693
+ function newSecrets() {
104694
+ return { values: new Set };
104502
104695
  }
104503
104696
  function addSecret(secrets, value) {
104504
104697
  if (typeof value === "string" && value.length > 0)
104505
104698
  secrets.values.add(value);
104506
104699
  }
104507
- function buildEnvelope(facts, failure, body) {
104508
- return {
104509
- schema: SUBSCRIPTION_MODEL_LIST_SCHEMA,
104510
- ...facts.provider !== undefined ? { provider: facts.provider } : {},
104511
- claudishVersion: VERSION,
104512
- ...facts.fetchedAt !== undefined ? { fetchedAt: facts.fetchedAt } : {},
104513
- ...facts.sourceUrl !== undefined ? { sourceUrl: facts.sourceUrl } : {},
104514
- ...facts.clientVersion !== undefined ? { clientVersion: facts.clientVersion } : {},
104515
- ...facts.clientVersionSource !== undefined ? { clientVersionSource: facts.clientVersionSource } : {},
104516
- tokenRefreshed: facts.tokenRefreshed,
104517
- ...facts.httpStatus !== undefined ? { httpStatus: facts.httpStatus } : {},
104518
- ...failure ? { failure } : {},
104519
- ...body !== undefined ? { body } : {}
104520
- };
104700
+ function containsSecret(secrets, ...texts) {
104701
+ for (const secret of secrets.values) {
104702
+ if (texts.some((text) => text?.includes(secret)))
104703
+ return true;
104704
+ }
104705
+ return false;
104521
104706
  }
104522
104707
  function failureOf2(cls, code, httpStatus) {
104523
104708
  return { class: cls, code, ...httpStatus !== undefined ? { httpStatus } : {} };
@@ -104532,6 +104717,19 @@ function stripUserinfo(url) {
104532
104717
  return url.replace(/^([a-z][a-z0-9+.-]*:\/\/)[^@/]*@/i, "$1");
104533
104718
  }
104534
104719
  }
104720
+ async function raceTimeout(work, ms) {
104721
+ let timer;
104722
+ const timedOut = new Promise((resolve) => {
104723
+ timer = setTimeout(() => resolve(TIMED_OUT), ms);
104724
+ });
104725
+ work.catch(() => {});
104726
+ try {
104727
+ return await Promise.race([work, timedOut]);
104728
+ } finally {
104729
+ if (timer)
104730
+ clearTimeout(timer);
104731
+ }
104732
+ }
104535
104733
  function storeReadFailure(read) {
104536
104734
  switch (read.kind) {
104537
104735
  case "absent":
@@ -104574,29 +104772,171 @@ function loadCodeAssistFailure(err) {
104574
104772
  return failureOf2("mint_failed", "load_code_assist_no_project");
104575
104773
  return failureOf2("network", "load_code_assist_network_error");
104576
104774
  }
104775
+ async function obtainAccessToken(deps, facts, secrets, preRaw) {
104776
+ const base = deps.tokenDeps();
104777
+ let firstRead = true;
104778
+ let refreshCalled = false;
104779
+ let refreshOutcome = null;
104780
+ const laterReads = [];
104781
+ const observed = {
104782
+ ...base,
104783
+ readStore: () => {
104784
+ if (firstRead) {
104785
+ firstRead = false;
104786
+ return preRaw;
104787
+ }
104788
+ const raw = base.readStore();
104789
+ if (raw)
104790
+ laterReads.push(raw);
104791
+ return raw;
104792
+ },
104793
+ runAgyRefresh: () => {
104794
+ refreshCalled = true;
104795
+ facts.tokenRefreshed = true;
104796
+ refreshOutcome = base.runAgyRefresh();
104797
+ return refreshOutcome;
104798
+ }
104799
+ };
104800
+ let accessToken;
104801
+ try {
104802
+ accessToken = await getValidAntigravityAccessToken(observed);
104803
+ } catch {
104804
+ return { ok: false, failure: tokenFailure(refreshCalled, refreshOutcome) };
104805
+ }
104806
+ addSecret(secrets, accessToken);
104807
+ for (const raw of [preRaw, ...laterReads]) {
104808
+ addSecret(secrets, raw);
104809
+ addSecret(secrets, readSharedAntigravityToken({ ...base, readStore: () => raw })?.refresh_token);
104810
+ }
104811
+ return { ok: true, accessToken };
104812
+ }
104813
+ async function establishAntigravitySession(deps, secrets, facts) {
104814
+ if (deps.platform() !== "darwin") {
104815
+ return { ok: false, failure: failureOf2("credential_missing", "platform_unsupported") };
104816
+ }
104817
+ const read = await deps.readStore(deps.keychainDeadlineMs);
104818
+ if (read.kind !== "present")
104819
+ return { ok: false, failure: storeReadFailure(read) };
104820
+ addSecret(secrets, read.raw);
104821
+ const token = await obtainAccessToken(deps, facts, secrets, read.raw);
104822
+ if (!token.ok)
104823
+ return token;
104824
+ const version = resolveAntigravityClientVersion();
104825
+ facts.clientVersion = version.version;
104826
+ facts.clientVersionSource = version.source;
104827
+ let projectId;
104828
+ let tierId;
104829
+ try {
104830
+ const setup = await raceTimeout(setupAntigravityUser(token.accessToken), deps.httpTimeoutMs);
104831
+ if (setup === TIMED_OUT) {
104832
+ return { ok: false, failure: failureOf2("network", "load_code_assist_timeout") };
104833
+ }
104834
+ projectId = setup.projectId;
104835
+ tierId = setup.tierId;
104836
+ } catch (err) {
104837
+ return { ok: false, failure: loadCodeAssistFailure(err) };
104838
+ }
104839
+ addSecret(secrets, projectId);
104840
+ return { ok: true, accessToken: token.accessToken, projectId, tierId };
104841
+ }
104842
+ var SESSION_FAILURE_CODES, TIMED_OUT;
104843
+ var init_subscription_antigravity_session = __esm(() => {
104844
+ init_antigravity_token();
104845
+ init_antigravity_user();
104846
+ SESSION_FAILURE_CODES = {
104847
+ credential_missing: ["platform_unsupported", "keychain_item_absent", "token_unparseable"],
104848
+ keychain_locked: ["keychain_locked", "keychain_read_timeout", "keychain_read_failed"],
104849
+ mint_failed: [
104850
+ "agy_missing",
104851
+ "agy_refresh_failed",
104852
+ "agy_refresh_timeout",
104853
+ "agy_refresh_no_valid_token",
104854
+ "load_code_assist_4xx",
104855
+ "load_code_assist_no_project",
104856
+ "load_code_assist_bad_body"
104857
+ ],
104858
+ network: [
104859
+ "load_code_assist_network_error",
104860
+ "load_code_assist_429",
104861
+ "load_code_assist_5xx",
104862
+ "load_code_assist_timeout"
104863
+ ]
104864
+ };
104865
+ TIMED_OUT = Symbol("timed-out");
104866
+ });
104867
+
104868
+ // src/subscription-models-command.ts
104869
+ var exports_subscription_models_command = {};
104870
+ __export(exports_subscription_models_command, {
104871
+ EXIT: () => EXIT,
104872
+ FAILURE_CODES: () => FAILURE_CODES,
104873
+ INTERNAL_ERROR_MESSAGE: () => INTERNAL_ERROR_MESSAGE,
104874
+ SECRET_GUARD_MESSAGE: () => SECRET_GUARD_MESSAGE,
104875
+ SUBSCRIPTION_MODELS_USAGE: () => SUBSCRIPTION_MODELS_USAGE,
104876
+ SUBSCRIPTION_MODEL_LIST_SCHEMA: () => SUBSCRIPTION_MODEL_LIST_SCHEMA,
104877
+ defaultSubscriptionModelsDeps: () => defaultSubscriptionModelsDeps,
104878
+ exitCodeFor: () => exitCodeFor,
104879
+ parseSubscriptionModelsArgs: () => parseSubscriptionModelsArgs,
104880
+ reportSubscriptionInternalError: () => reportSubscriptionInternalError,
104881
+ runAntigravityRawModelList: () => runAntigravityRawModelList,
104882
+ subscriptionModelsCommand: () => subscriptionModelsCommand
104883
+ });
104884
+ function exitCodeFor(failure) {
104885
+ if (failure.class === "internal")
104886
+ return failure.code === "usage" ? EXIT.usage : EXIT.internal;
104887
+ return EXIT[failure.class];
104888
+ }
104889
+ function defaultSubscriptionModelsDeps() {
104890
+ return {
104891
+ platform: () => process.platform,
104892
+ readStore: readAntigravityStoreClassified,
104893
+ tokenDeps: defaultAntigravityTokenDeps,
104894
+ now: () => Date.now(),
104895
+ httpTimeoutMs: 30000,
104896
+ keychainDeadlineMs: 1e4,
104897
+ writeStdout: (line) => new Promise((resolve, reject) => {
104898
+ process.stdout.write(line, (err) => err ? reject(err) : resolve());
104899
+ }),
104900
+ writeStderr: (line) => {
104901
+ process.stderr.write(line);
104902
+ }
104903
+ };
104904
+ }
104905
+ function parseSubscriptionModelsArgs(argv) {
104906
+ const positionals = argv.filter((a) => !a.startsWith("-"));
104907
+ const flags = argv.filter((a) => a.startsWith("-"));
104908
+ const positionalsOk = positionals.length === 2 && positionals[0] === "models" && positionals[1] === "antigravity";
104909
+ const flagsOk = flags.length === 2 && flags.includes("--raw") && flags.includes("--json");
104910
+ return positionalsOk && flagsOk ? { ok: true, provider: "antigravity" } : { ok: false };
104911
+ }
104912
+ function buildEnvelope(facts, failure, body) {
104913
+ return {
104914
+ schema: SUBSCRIPTION_MODEL_LIST_SCHEMA,
104915
+ ...facts.provider !== undefined ? { provider: facts.provider } : {},
104916
+ claudishVersion: VERSION,
104917
+ ...facts.fetchedAt !== undefined ? { fetchedAt: facts.fetchedAt } : {},
104918
+ ...facts.sourceUrl !== undefined ? { sourceUrl: facts.sourceUrl } : {},
104919
+ ...facts.clientVersion !== undefined ? { clientVersion: facts.clientVersion } : {},
104920
+ ...facts.clientVersionSource !== undefined ? { clientVersionSource: facts.clientVersionSource } : {},
104921
+ tokenRefreshed: facts.tokenRefreshed,
104922
+ ...facts.httpStatus !== undefined ? { httpStatus: facts.httpStatus } : {},
104923
+ ...failure ? { failure } : {},
104924
+ ...body !== undefined ? { body } : {}
104925
+ };
104926
+ }
104927
+ function failureOf3(cls, code, httpStatus) {
104928
+ return failureOf2(cls, code, httpStatus);
104929
+ }
104577
104930
  function listFailure(value, status) {
104578
104931
  const models = value !== null && typeof value === "object" && !Array.isArray(value) ? value.models : undefined;
104579
104932
  if (models === null || typeof models !== "object" || Array.isArray(models)) {
104580
- return failureOf2("list_incomplete", "models_absent", status);
104933
+ return failureOf3("list_incomplete", "models_absent", status);
104581
104934
  }
104582
104935
  if (Object.keys(models).length === 0) {
104583
- return failureOf2("list_incomplete", "models_empty", status);
104936
+ return failureOf3("list_incomplete", "models_empty", status);
104584
104937
  }
104585
104938
  return null;
104586
104939
  }
104587
- async function raceTimeout(work, ms) {
104588
- let timer;
104589
- const timedOut = new Promise((resolve) => {
104590
- timer = setTimeout(() => resolve(TIMED_OUT), ms);
104591
- });
104592
- work.catch(() => {});
104593
- try {
104594
- return await Promise.race([work, timedOut]);
104595
- } finally {
104596
- if (timer)
104597
- clearTimeout(timer);
104598
- }
104599
- }
104600
104940
  function fail(facts, failure) {
104601
104941
  return { envelope: buildEnvelope(facts, failure), exitCode: exitCodeFor(failure) };
104602
104942
  }
@@ -104604,20 +104944,13 @@ function lineOf(envelope) {
104604
104944
  return `${JSON.stringify(envelope)}
104605
104945
  `;
104606
104946
  }
104607
- function containsSecret(secrets, ...texts) {
104608
- for (const secret of secrets.values) {
104609
- if (texts.some((text) => text?.includes(secret)))
104610
- return true;
104611
- }
104612
- return false;
104613
- }
104614
104947
  function safeStderr(deps, line) {
104615
104948
  try {
104616
104949
  deps.writeStderr(line);
104617
104950
  } catch {}
104618
104951
  }
104619
104952
  async function writeInternalFailure(deps, facts, code, stderrLine, secrets) {
104620
- const failure = failureOf2("internal", code);
104953
+ const failure = failureOf3("internal", code);
104621
104954
  safeStderr(deps, `${stderrLine}
104622
104955
  `);
104623
104956
  const line = lineOf(buildEnvelope(facts, failure));
@@ -104639,51 +104972,13 @@ async function reportSubscriptionInternalError(deps) {
104639
104972
  }
104640
104973
  return writeInternalFailure(resolved, { tokenRefreshed: false }, "internal_error", INTERNAL_ERROR_MESSAGE);
104641
104974
  }
104642
- async function obtainAccessToken(deps, facts, secrets, preRaw) {
104643
- const base = deps.tokenDeps();
104644
- let firstRead = true;
104645
- let refreshCalled = false;
104646
- let refreshOutcome = null;
104647
- const laterReads = [];
104648
- const observed = {
104649
- ...base,
104650
- readStore: () => {
104651
- if (firstRead) {
104652
- firstRead = false;
104653
- return preRaw;
104654
- }
104655
- const raw = base.readStore();
104656
- if (raw)
104657
- laterReads.push(raw);
104658
- return raw;
104659
- },
104660
- runAgyRefresh: () => {
104661
- refreshCalled = true;
104662
- facts.tokenRefreshed = true;
104663
- refreshOutcome = base.runAgyRefresh();
104664
- return refreshOutcome;
104665
- }
104666
- };
104667
- let accessToken;
104668
- try {
104669
- accessToken = await getValidAntigravityAccessToken(observed);
104670
- } catch {
104671
- return { ok: false, result: fail(facts, tokenFailure(refreshCalled, refreshOutcome)) };
104672
- }
104673
- addSecret(secrets, accessToken);
104674
- for (const raw of [preRaw, ...laterReads]) {
104675
- addSecret(secrets, raw);
104676
- addSecret(secrets, readSharedAntigravityToken({ ...base, readStore: () => raw })?.refresh_token);
104677
- }
104678
- return { ok: true, accessToken };
104679
- }
104680
104975
  function classifyAvailableModels(facts, raw, timedOut) {
104681
104976
  facts.sourceUrl = stripUserinfo(raw.url);
104682
104977
  facts.clientVersion = raw.clientVersion;
104683
104978
  facts.clientVersionSource = raw.clientVersionSource;
104684
104979
  const networkCode = timedOut ? "fetch_available_models_timeout" : "fetch_available_models_network_error";
104685
104980
  if (raw.kind === "unreachable")
104686
- return fail(facts, failureOf2("network", networkCode));
104981
+ return fail(facts, failureOf3("network", networkCode));
104687
104982
  facts.fetchedAt = raw.fetchedAt;
104688
104983
  facts.httpStatus = raw.status;
104689
104984
  if (raw.status < 200 || raw.status >= 300) {
@@ -104701,39 +104996,20 @@ function classifyAvailableModels(facts, raw, timedOut) {
104701
104996
  };
104702
104997
  }
104703
104998
  case "not-json":
104704
- return fail(facts, failureOf2("list_incomplete", "body_not_json", raw.status));
104999
+ return fail(facts, failureOf3("list_incomplete", "body_not_json", raw.status));
104705
105000
  default:
104706
- return fail(facts, failureOf2("network", networkCode, raw.status));
105001
+ return fail(facts, failureOf3("network", networkCode, raw.status));
104707
105002
  }
104708
105003
  }
104709
105004
  async function determine(deps, secrets, facts) {
104710
- if (deps.platform() !== "darwin") {
104711
- return fail(facts, failureOf2("credential_missing", "platform_unsupported"));
104712
- }
104713
- const read = await deps.readStore(deps.keychainDeadlineMs);
104714
- if (read.kind !== "present")
104715
- return fail(facts, storeReadFailure(read));
104716
- addSecret(secrets, read.raw);
104717
- const token = await obtainAccessToken(deps, facts, secrets, read.raw);
104718
- if (!token.ok)
104719
- return token.result;
104720
- const version = resolveAntigravityClientVersion();
104721
- facts.clientVersion = version.version;
104722
- facts.clientVersionSource = version.source;
104723
- let projectId;
104724
- try {
104725
- const setup = await raceTimeout(setupAntigravityUser(token.accessToken), deps.httpTimeoutMs);
104726
- if (setup === TIMED_OUT)
104727
- return fail(facts, failureOf2("network", "load_code_assist_timeout"));
104728
- projectId = setup.projectId;
104729
- } catch (err) {
104730
- return fail(facts, loadCodeAssistFailure(err));
104731
- }
104732
- addSecret(secrets, projectId);
105005
+ const session = await establishAntigravitySession(deps, secrets, facts);
105006
+ if (!session.ok)
105007
+ return fail(facts, session.failure);
105008
+ const { accessToken, projectId } = session;
104733
105009
  const controller = new AbortController;
104734
105010
  const timer = setTimeout(() => controller.abort(), deps.httpTimeoutMs);
104735
105011
  try {
104736
- const raw = await fetchAntigravityAvailableModelsRaw(token.accessToken, projectId, {
105012
+ const raw = await fetchAntigravityAvailableModelsRaw(accessToken, projectId, {
104737
105013
  signal: controller.signal,
104738
105014
  now: deps.now
104739
105015
  });
@@ -104743,7 +105019,7 @@ async function determine(deps, secrets, facts) {
104743
105019
  }
104744
105020
  }
104745
105021
  async function runAntigravityRawModelList(deps) {
104746
- const secrets = { values: new Set };
105022
+ const secrets = newSecrets();
104747
105023
  const facts = { provider: "antigravity", tokenRefreshed: false };
104748
105024
  let line;
104749
105025
  let exitCode;
@@ -104774,27 +105050,17 @@ async function subscriptionModelsCommand(argv, deps = defaultSubscriptionModelsD
104774
105050
  }
104775
105051
  return runAntigravityRawModelList(deps);
104776
105052
  }
104777
- var SUBSCRIPTION_MODEL_LIST_SCHEMA = "claudish.subscription-model-list.v1", FAILURE_CODES, EXIT, SUBSCRIPTION_MODELS_USAGE = "usage: claudish subscription models antigravity --raw --json", SECRET_GUARD_MESSAGE = "[claudish subscription] refused: output contained a credential value", INTERNAL_ERROR_MESSAGE = "[claudish subscription] internal error", TIMED_OUT;
105053
+ var SUBSCRIPTION_MODEL_LIST_SCHEMA = "claudish.subscription-model-list.v1", FAILURE_CODES, EXIT, SUBSCRIPTION_MODELS_USAGE = "usage: claudish subscription models antigravity --raw --json", SECRET_GUARD_MESSAGE = "[claudish subscription] refused: output contained a credential value", INTERNAL_ERROR_MESSAGE = "[claudish subscription] internal error";
104778
105054
  var init_subscription_models_command = __esm(() => {
104779
105055
  init_antigravity_token();
104780
105056
  init_antigravity_user();
105057
+ init_subscription_antigravity_session();
104781
105058
  FAILURE_CODES = {
104782
- credential_missing: ["platform_unsupported", "keychain_item_absent", "token_unparseable"],
104783
- keychain_locked: ["keychain_locked", "keychain_read_timeout", "keychain_read_failed"],
104784
- mint_failed: [
104785
- "agy_missing",
104786
- "agy_refresh_failed",
104787
- "agy_refresh_timeout",
104788
- "agy_refresh_no_valid_token",
104789
- "load_code_assist_4xx",
104790
- "load_code_assist_no_project",
104791
- "load_code_assist_bad_body"
104792
- ],
105059
+ credential_missing: SESSION_FAILURE_CODES.credential_missing,
105060
+ keychain_locked: SESSION_FAILURE_CODES.keychain_locked,
105061
+ mint_failed: SESSION_FAILURE_CODES.mint_failed,
104793
105062
  network: [
104794
- "load_code_assist_network_error",
104795
- "load_code_assist_429",
104796
- "load_code_assist_5xx",
104797
- "load_code_assist_timeout",
105063
+ ...SESSION_FAILURE_CODES.network,
104798
105064
  "fetch_available_models_network_error",
104799
105065
  "fetch_available_models_timeout"
104800
105066
  ],
@@ -104811,7 +105077,399 @@ var init_subscription_models_command = __esm(() => {
104811
105077
  network: 6,
104812
105078
  list_incomplete: 7
104813
105079
  };
104814
- TIMED_OUT = Symbol("timed-out");
105080
+ });
105081
+
105082
+ // src/subscription-dispatch.ts
105083
+ function isSubscriptionProbeArgv(argv) {
105084
+ for (let i = 0;i < argv.length; i++) {
105085
+ const token = argv[i];
105086
+ if (token === "--model" || token === "--request-file") {
105087
+ if (argv[i + 1] !== undefined && !argv[i + 1].startsWith("-"))
105088
+ i++;
105089
+ } else if (!token.startsWith("-")) {
105090
+ return token === "probe";
105091
+ }
105092
+ }
105093
+ return false;
105094
+ }
105095
+ function probeLoadFailureLine() {
105096
+ return `${JSON.stringify({
105097
+ schema: SUBSCRIPTION_PROBE_SCHEMA,
105098
+ claudishVersion: VERSION,
105099
+ tokenRefreshed: false,
105100
+ failure: { class: "internal", code: "internal_error" }
105101
+ })}
105102
+ `;
105103
+ }
105104
+ var SUBSCRIPTION_PROBE_SCHEMA = "claudish.subscription-probe.v1";
105105
+ var init_subscription_dispatch = () => {};
105106
+
105107
+ // src/subscription-probe-command.ts
105108
+ var exports_subscription_probe_command = {};
105109
+ __export(exports_subscription_probe_command, {
105110
+ MAX_UNESCAPE_ROUNDS: () => MAX_UNESCAPE_ROUNDS,
105111
+ PROBE_BODY_CAP_BYTES: () => PROBE_BODY_CAP_BYTES,
105112
+ PROBE_EXIT: () => PROBE_EXIT,
105113
+ PROBE_FAILURE_CODES: () => PROBE_FAILURE_CODES,
105114
+ PROBE_REQUEST_FILE_CAP_BYTES: () => PROBE_REQUEST_FILE_CAP_BYTES,
105115
+ PROBE_REQUEST_FILE_MESSAGE: () => PROBE_REQUEST_FILE_MESSAGE,
105116
+ REDACTED: () => REDACTED2,
105117
+ SUBSCRIPTION_PROBE_SCHEMA: () => SUBSCRIPTION_PROBE_SCHEMA,
105118
+ SUBSCRIPTION_PROBE_USAGE: () => SUBSCRIPTION_PROBE_USAGE,
105119
+ buildProbeEnvelopeBody: () => buildProbeEnvelopeBody,
105120
+ defaultSubscriptionProbeDeps: () => defaultSubscriptionProbeDeps,
105121
+ isSubscriptionProbeArgv: () => isSubscriptionProbeArgv,
105122
+ jsonUnescapedForms: () => jsonUnescapedForms,
105123
+ parseSubscriptionProbeArgs: () => parseSubscriptionProbeArgs,
105124
+ probeExitCodeFor: () => probeExitCodeFor,
105125
+ redactSecretValues: () => redactSecretValues,
105126
+ reportProbeInternalError: () => reportProbeInternalError,
105127
+ runAntigravityProbe: () => runAntigravityProbe,
105128
+ subscriptionProbeCommand: () => subscriptionProbeCommand
105129
+ });
105130
+ import { randomUUID as randomUUID10 } from "crypto";
105131
+ import { readFile as readFile8, stat as stat2 } from "fs/promises";
105132
+ function probeExitCodeFor(failure) {
105133
+ if (failure.class === "internal") {
105134
+ return CALLER_CODES.includes(failure.code) ? PROBE_EXIT.usage : PROBE_EXIT.internal;
105135
+ }
105136
+ return PROBE_EXIT[failure.class];
105137
+ }
105138
+ async function defaultReadRequestFile(path) {
105139
+ const info = await stat2(path);
105140
+ if (!info.isFile())
105141
+ throw new Error("not a file");
105142
+ if (info.size > PROBE_REQUEST_FILE_CAP_BYTES)
105143
+ return null;
105144
+ return readFile8(path, "utf8");
105145
+ }
105146
+ function defaultSubscriptionProbeDeps() {
105147
+ return {
105148
+ platform: () => process.platform,
105149
+ readStore: readAntigravityStoreClassified,
105150
+ tokenDeps: defaultAntigravityTokenDeps,
105151
+ now: () => Date.now(),
105152
+ httpTimeoutMs: 30000,
105153
+ keychainDeadlineMs: 1e4,
105154
+ requestTimeoutMs: 300000,
105155
+ readRequestFile: defaultReadRequestFile,
105156
+ writeStdout: (line) => new Promise((resolve, reject) => {
105157
+ process.stdout.write(line, (err) => err ? reject(err) : resolve());
105158
+ }),
105159
+ writeStderr: (line) => {
105160
+ process.stderr.write(line);
105161
+ }
105162
+ };
105163
+ }
105164
+ function parseSubscriptionProbeArgs(argv) {
105165
+ const positionals = [];
105166
+ const values = new Map;
105167
+ const switches = new Set;
105168
+ for (let i = 0;i < argv.length; i++) {
105169
+ const token = argv[i];
105170
+ if (token === "--model" || token === "--request-file") {
105171
+ const value = argv[i + 1];
105172
+ if (values.has(token) || value === undefined || value === "" || value.startsWith("-")) {
105173
+ return { ok: false };
105174
+ }
105175
+ values.set(token, value);
105176
+ i++;
105177
+ } else if (token === "--raw" || token === "--json") {
105178
+ if (switches.has(token))
105179
+ return { ok: false };
105180
+ switches.add(token);
105181
+ } else if (token.startsWith("-")) {
105182
+ return { ok: false };
105183
+ } else {
105184
+ positionals.push(token);
105185
+ }
105186
+ }
105187
+ const model = values.get("--model");
105188
+ const requestFile = values.get("--request-file");
105189
+ if (positionals.length !== 2 || positionals[0] !== "probe" || positionals[1] !== "antigravity" || switches.size !== 2 || model === undefined || requestFile === undefined) {
105190
+ return { ok: false };
105191
+ }
105192
+ return { ok: true, provider: "antigravity", model, requestFile };
105193
+ }
105194
+ function failureOf4(cls, code, httpStatus) {
105195
+ return failureOf2(cls, code, httpStatus);
105196
+ }
105197
+ function buildEnvelope2(facts, failure, body) {
105198
+ return {
105199
+ schema: SUBSCRIPTION_PROBE_SCHEMA,
105200
+ ...facts.provider !== undefined ? { provider: facts.provider } : {},
105201
+ claudishVersion: VERSION,
105202
+ ...facts.model !== undefined ? { model: facts.model } : {},
105203
+ ...facts.fetchedAt !== undefined ? { fetchedAt: facts.fetchedAt } : {},
105204
+ ...facts.sourceUrl !== undefined ? { sourceUrl: facts.sourceUrl } : {},
105205
+ ...facts.clientVersion !== undefined ? { clientVersion: facts.clientVersion } : {},
105206
+ ...facts.clientVersionSource !== undefined ? { clientVersionSource: facts.clientVersionSource } : {},
105207
+ tokenRefreshed: facts.tokenRefreshed,
105208
+ ...facts.httpStatus !== undefined ? { httpStatus: facts.httpStatus } : {},
105209
+ ...failure ? { failure } : {},
105210
+ ...body ? { bodyRedacted: body.redacted, body: body.text } : {}
105211
+ };
105212
+ }
105213
+ function fail2(facts, failure) {
105214
+ return { envelope: buildEnvelope2(facts, failure), exitCode: probeExitCodeFor(failure) };
105215
+ }
105216
+ function lineOf2(envelope) {
105217
+ return `${JSON.stringify(envelope)}
105218
+ `;
105219
+ }
105220
+ function safeStderr2(deps, line) {
105221
+ try {
105222
+ deps.writeStderr(line);
105223
+ } catch {}
105224
+ }
105225
+ async function writeInternalFailure2(deps, facts, code, stderrLine, secrets) {
105226
+ const failure = failureOf4("internal", code);
105227
+ safeStderr2(deps, `${stderrLine}
105228
+ `);
105229
+ let line = lineOf2(buildEnvelope2(facts, failure));
105230
+ if (secrets && containsSecret(secrets, line)) {
105231
+ line = lineOf2(buildEnvelope2({ tokenRefreshed: facts.tokenRefreshed }, failure));
105232
+ }
105233
+ try {
105234
+ await deps.writeStdout(line);
105235
+ } catch {}
105236
+ return probeExitCodeFor(failure);
105237
+ }
105238
+ function redactSecretValues(text, secrets) {
105239
+ let out = text;
105240
+ const values = [...secrets.values].sort((a, b) => b.length - a.length);
105241
+ for (const value of values) {
105242
+ for (const form of new Set([value, value.replaceAll("/", "\\/")])) {
105243
+ if (out.includes(form))
105244
+ out = out.replaceAll(form, REDACTED2);
105245
+ }
105246
+ }
105247
+ return { text: out, redacted: out !== text };
105248
+ }
105249
+ function jsonUnescapedForms(text) {
105250
+ const forms = [];
105251
+ if (text === undefined)
105252
+ return { forms, complete: true };
105253
+ let current = text;
105254
+ for (let round = 0;round < MAX_UNESCAPE_ROUNDS; round++) {
105255
+ const next = current.replace(JSON_ESCAPE, (_match, hex, letter) => hex !== undefined ? String.fromCharCode(Number.parseInt(hex, 16)) : SIMPLE_ESCAPES[letter]);
105256
+ if (next === current)
105257
+ return { forms, complete: true };
105258
+ forms.push(next);
105259
+ current = next;
105260
+ }
105261
+ return { forms, complete: false };
105262
+ }
105263
+ async function readRequest(deps, path) {
105264
+ let text;
105265
+ try {
105266
+ text = await deps.readRequestFile(path);
105267
+ } catch {
105268
+ return { ok: false, code: "request_file_unreadable" };
105269
+ }
105270
+ if (text === null)
105271
+ return { ok: false, code: "request_file_invalid" };
105272
+ let value;
105273
+ try {
105274
+ value = JSON.parse(text);
105275
+ } catch {
105276
+ return { ok: false, code: "request_file_invalid" };
105277
+ }
105278
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
105279
+ return { ok: false, code: "request_file_invalid" };
105280
+ }
105281
+ return { ok: true, text };
105282
+ }
105283
+ function buildProbeEnvelopeBody(model, projectId, tierId, requestText, userPromptId = randomUUID10()) {
105284
+ const head = JSON.stringify({ model, project: projectId, user_prompt_id: userPromptId });
105285
+ const credits = tierId && tierId !== "free-tier" ? `,"enabled_credit_types":${JSON.stringify(["GOOGLE_ONE_AI"])}` : "";
105286
+ return `${head.slice(0, -1)},"request":${requestText}${credits}}`;
105287
+ }
105288
+ function createActivityRequestId3() {
105289
+ return Math.random().toString(36).substring(7);
105290
+ }
105291
+ async function readCapped(res, cap) {
105292
+ if (!res.body)
105293
+ return "";
105294
+ const reader = res.body.getReader();
105295
+ const chunks = [];
105296
+ let size = 0;
105297
+ for (;; ) {
105298
+ const { done, value } = await reader.read();
105299
+ if (done)
105300
+ break;
105301
+ size += value.byteLength;
105302
+ if (size > cap) {
105303
+ await reader.cancel().catch(() => {});
105304
+ return null;
105305
+ }
105306
+ chunks.push(value);
105307
+ }
105308
+ return Buffer.concat(chunks).toString("utf8");
105309
+ }
105310
+ async function determine2(deps, secrets, facts, args) {
105311
+ const request = await readRequest(deps, args.requestFile);
105312
+ if (!request.ok)
105313
+ return fail2(facts, failureOf4("internal", request.code));
105314
+ const session = await establishAntigravitySession(deps, secrets, facts);
105315
+ if (!session.ok)
105316
+ return fail2(facts, session.failure);
105317
+ const url = `${antigravityHost()}/v1internal:generateContent`;
105318
+ const version = resolveAntigravityClientVersion();
105319
+ facts.sourceUrl = stripUserinfo(url);
105320
+ facts.clientVersion = version.version;
105321
+ facts.clientVersionSource = version.source;
105322
+ const controller = new AbortController;
105323
+ const timer = setTimeout(() => controller.abort(), deps.requestTimeoutMs);
105324
+ const networkFailure = () => failureOf4("network", controller.signal.aborted ? "generate_content_timeout" : "generate_content_network_error", facts.httpStatus);
105325
+ try {
105326
+ let res;
105327
+ try {
105328
+ res = await fetch(url, {
105329
+ method: "POST",
105330
+ headers: {
105331
+ Authorization: `Bearer ${session.accessToken}`,
105332
+ "Content-Type": "application/json",
105333
+ "User-Agent": antigravityUserAgentFor(version.version),
105334
+ "x-activity-request-id": createActivityRequestId3()
105335
+ },
105336
+ body: buildProbeEnvelopeBody(args.model, session.projectId, session.tierId, request.text),
105337
+ signal: controller.signal,
105338
+ redirect: "manual"
105339
+ });
105340
+ } catch {
105341
+ return fail2(facts, networkFailure());
105342
+ }
105343
+ facts.fetchedAt = new Date(deps.now()).toISOString();
105344
+ facts.httpStatus = res.status;
105345
+ let text;
105346
+ try {
105347
+ text = await readCapped(res, PROBE_BODY_CAP_BYTES);
105348
+ } catch {
105349
+ return fail2(facts, networkFailure());
105350
+ }
105351
+ if (text === null)
105352
+ return fail2(facts, failureOf4("list_incomplete", "body_too_large", res.status));
105353
+ if (res.ok) {
105354
+ try {
105355
+ JSON.parse(text);
105356
+ } catch {
105357
+ return fail2(facts, failureOf4("list_incomplete", "body_not_json", res.status));
105358
+ }
105359
+ }
105360
+ const body = redactSecretValues(text, secrets);
105361
+ const unescaped = jsonUnescapedForms(body.text);
105362
+ if (!unescaped.complete) {
105363
+ return fail2(facts, failureOf4("list_incomplete", "body_unverifiable", res.status));
105364
+ }
105365
+ return {
105366
+ envelope: buildEnvelope2(facts, undefined, body),
105367
+ exitCode: PROBE_EXIT.ok,
105368
+ bodyText: body.text,
105369
+ bodyForms: unescaped.forms
105370
+ };
105371
+ } finally {
105372
+ clearTimeout(timer);
105373
+ }
105374
+ }
105375
+ async function runAntigravityProbe(deps, args) {
105376
+ const secrets = newSecrets();
105377
+ const facts = { provider: "antigravity", model: args.model, tokenRefreshed: false };
105378
+ let result;
105379
+ try {
105380
+ result = await determine2(deps, secrets, facts, args);
105381
+ } catch {
105382
+ return writeInternalFailure2(deps, { provider: facts.provider, model: facts.model, tokenRefreshed: facts.tokenRefreshed }, "internal_error", INTERNAL_ERROR_MESSAGE2, secrets);
105383
+ }
105384
+ if (result.envelope.failure?.code === "request_file_unreadable" || result.envelope.failure?.code === "request_file_invalid") {
105385
+ safeStderr2(deps, `${PROBE_REQUEST_FILE_MESSAGE}
105386
+ `);
105387
+ }
105388
+ const line = lineOf2(result.envelope);
105389
+ if (containsSecret(secrets, line, result.bodyText, ...result.bodyForms ?? [])) {
105390
+ return writeInternalFailure2(deps, facts, "secret_guard", SECRET_GUARD_MESSAGE2, secrets);
105391
+ }
105392
+ try {
105393
+ await deps.writeStdout(line);
105394
+ } catch {
105395
+ safeStderr2(deps, `${INTERNAL_ERROR_MESSAGE2}
105396
+ `);
105397
+ return PROBE_EXIT.internal;
105398
+ }
105399
+ return result.exitCode;
105400
+ }
105401
+ async function reportProbeInternalError(deps) {
105402
+ let resolved;
105403
+ try {
105404
+ resolved = deps ?? defaultSubscriptionProbeDeps();
105405
+ } catch {
105406
+ process.stderr.write(`${INTERNAL_ERROR_MESSAGE2}
105407
+ `);
105408
+ return PROBE_EXIT.internal;
105409
+ }
105410
+ return writeInternalFailure2(resolved, { tokenRefreshed: false }, "internal_error", INTERNAL_ERROR_MESSAGE2);
105411
+ }
105412
+ async function subscriptionProbeCommand(argv, deps = defaultSubscriptionProbeDeps()) {
105413
+ const args = parseSubscriptionProbeArgs(argv);
105414
+ if (!args.ok) {
105415
+ return writeInternalFailure2(deps, { tokenRefreshed: false }, "usage", SUBSCRIPTION_PROBE_USAGE);
105416
+ }
105417
+ return runAntigravityProbe(deps, args);
105418
+ }
105419
+ var PROBE_FAILURE_CODES, PROBE_EXIT, CALLER_CODES, PROBE_BODY_CAP_BYTES, PROBE_REQUEST_FILE_CAP_BYTES, REDACTED2 = "[REDACTED]", SUBSCRIPTION_PROBE_USAGE = "usage: claudish subscription probe antigravity --model <wire-model-id> --request-file <path> --raw --json", PROBE_REQUEST_FILE_MESSAGE = "[claudish subscription] the request file must hold one JSON object (the inner Gemini request)", SECRET_GUARD_MESSAGE2 = "[claudish subscription] refused: output contained a credential value", INTERNAL_ERROR_MESSAGE2 = "[claudish subscription] internal error", JSON_ESCAPE, SIMPLE_ESCAPES, MAX_UNESCAPE_ROUNDS = 64;
105420
+ var init_subscription_probe_command = __esm(() => {
105421
+ init_antigravity_token();
105422
+ init_antigravity_user();
105423
+ init_subscription_antigravity_session();
105424
+ init_subscription_dispatch();
105425
+ init_subscription_dispatch();
105426
+ PROBE_FAILURE_CODES = {
105427
+ credential_missing: SESSION_FAILURE_CODES.credential_missing,
105428
+ keychain_locked: SESSION_FAILURE_CODES.keychain_locked,
105429
+ mint_failed: SESSION_FAILURE_CODES.mint_failed,
105430
+ network: [
105431
+ ...SESSION_FAILURE_CODES.network,
105432
+ "generate_content_network_error",
105433
+ "generate_content_timeout"
105434
+ ],
105435
+ list_incomplete: ["body_too_large", "body_not_json", "body_unverifiable"],
105436
+ internal: [
105437
+ "usage",
105438
+ "request_file_unreadable",
105439
+ "request_file_invalid",
105440
+ "secret_guard",
105441
+ "internal_error"
105442
+ ]
105443
+ };
105444
+ PROBE_EXIT = {
105445
+ ok: 0,
105446
+ internal: 1,
105447
+ usage: 2,
105448
+ credential_missing: 3,
105449
+ keychain_locked: 4,
105450
+ mint_failed: 5,
105451
+ network: 6,
105452
+ list_incomplete: 7
105453
+ };
105454
+ CALLER_CODES = [
105455
+ "usage",
105456
+ "request_file_unreadable",
105457
+ "request_file_invalid"
105458
+ ];
105459
+ PROBE_BODY_CAP_BYTES = 512 * 1024;
105460
+ PROBE_REQUEST_FILE_CAP_BYTES = 8 * 1024 * 1024;
105461
+ JSON_ESCAPE = /\\(?:u([0-9a-fA-F]{4})|(["\\/bfnrt]))/g;
105462
+ SIMPLE_ESCAPES = {
105463
+ '"': '"',
105464
+ "\\": "\\",
105465
+ "/": "/",
105466
+ b: "\b",
105467
+ f: "\f",
105468
+ n: `
105469
+ `,
105470
+ r: "\r",
105471
+ t: "\t"
105472
+ };
104815
105473
  });
104816
105474
 
104817
105475
  // src/account-forecast-render.ts
@@ -115079,7 +115737,7 @@ var init_terminal_isolation = __esm(() => {
115079
115737
 
115080
115738
  // src/claude-runner.ts
115081
115739
  import { spawn as spawn4, spawnSync as spawnSync4 } from "child_process";
115082
- import { randomUUID as randomUUID10 } from "crypto";
115740
+ import { randomUUID as randomUUID11 } from "crypto";
115083
115741
  import {
115084
115742
  chmodSync as chmodSync5,
115085
115743
  closeSync as closeSync14,
@@ -115651,6 +116309,7 @@ function buildClaudishSettingsOverlay(statusLine, proxyAuthMode, paneChild = isP
115651
116309
  if (paneChild) {
115652
116310
  settings.skipDangerousModePermissionPrompt = true;
115653
116311
  settings.editorMode = "normal";
116312
+ settings.wheelScrollAccelerationEnabled = false;
115654
116313
  }
115655
116314
  return settings;
115656
116315
  }
@@ -115675,6 +116334,9 @@ function mergeUserSettingsIfPresent(config, tempSettingsPath, statusLine, proxyA
115675
116334
  if (paneChild) {
115676
116335
  userSettings.editorMode = "normal";
115677
116336
  }
116337
+ if (paneChild) {
116338
+ userSettings.wheelScrollAccelerationEnabled = false;
116339
+ }
115678
116340
  chmodSync5(tempSettingsPath, 384);
115679
116341
  writeFileSync27(tempSettingsPath, JSON.stringify(userSettings, null, 2), {
115680
116342
  encoding: "utf-8",
@@ -116013,7 +116675,7 @@ Or set CLAUDE_PATH to your custom installation:`);
116013
116675
  const sessionFlags = sessionFlagsOf(config.claudeArgs);
116014
116676
  let driverLaunch = null;
116015
116677
  if (surfaces.driver) {
116016
- const minted = sessionFlags.sessionId || sessionFlags.resumes ? null : randomUUID10();
116678
+ const minted = sessionFlags.sessionId || sessionFlags.resumes ? null : randomUUID11();
116017
116679
  const turnDir = mkdtempSync4(join63(tmpdir3(), "claudish-turns-"));
116018
116680
  chmodSync5(turnDir, 448);
116019
116681
  claudeArgs.unshift(...driverLeadingArgs({ mintedSessionId: minted, turnDir }));
@@ -119200,12 +119862,25 @@ if (isMcpMode) {
119200
119862
  }));
119201
119863
  } else if (isSubscriptionCommand) {
119202
119864
  const subscriptionArgIndex = args.indexOf("subscription");
119865
+ const subscriptionArgv = args.slice(subscriptionArgIndex + 1);
119203
119866
  const subscriptionModule = () => Promise.resolve().then(() => (init_subscription_models_command(), exports_subscription_models_command));
119204
- subscriptionModule().then((m) => m.subscriptionModelsCommand(args.slice(subscriptionArgIndex + 1))).catch(() => subscriptionModule().then((m) => m.reportSubscriptionInternalError()).catch(() => {
119867
+ const probeModule = () => Promise.resolve().then(() => (init_subscription_probe_command(), exports_subscription_probe_command));
119868
+ const writeLine = (line, code) => new Promise((resolve) => {
119869
+ process.stdout.write(line, () => resolve(code));
119870
+ });
119871
+ Promise.resolve().then(() => (init_subscription_dispatch(), {})).then((dispatch) => {
119872
+ const probe = isSubscriptionProbeArgv(subscriptionArgv);
119873
+ const run = probe ? probeModule().then((m) => m.subscriptionProbeCommand(subscriptionArgv)) : subscriptionModule().then((m) => m.subscriptionModelsCommand(subscriptionArgv));
119874
+ return run.catch(() => probe ? probeModule().then((m) => m.reportProbeInternalError()).catch(() => {
119875
+ process.stderr.write(`[claudish subscription] internal error
119876
+ `);
119877
+ return writeLine(probeLoadFailureLine(), 1);
119878
+ }) : subscriptionModule().then((m) => m.reportSubscriptionInternalError()));
119879
+ }).catch(() => {
119205
119880
  process.stderr.write(`[claudish subscription] internal error
119206
119881
  `);
119207
119882
  return 1;
119208
- })).then((code) => process.exit(code));
119883
+ }).then((code) => process.exit(code));
119209
119884
  } else if (isAccountCommand) {
119210
119885
  const accountArgIndex = args.indexOf("account");
119211
119886
  Promise.resolve().then(() => (init_account_command(), {})).then((m) => accountCommand(args.slice(accountArgIndex + 1)).catch((e) => {