claudish 12.3.1 → 12.3.2

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 +214 -62
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -901,7 +901,7 @@ var init_onepassword_config = __esm(() => {
901
901
  });
902
902
 
903
903
  // src/version.ts
904
- var VERSION = "12.3.1";
904
+ var VERSION = "12.3.2";
905
905
 
906
906
  // src/logger.ts
907
907
  import { appendFile, existsSync as existsSync2, mkdirSync, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
@@ -19605,6 +19605,11 @@ Check GOOGLE_APPLICATION_CREDENTIALS path.`);
19605
19605
  }
19606
19606
  }
19607
19607
  }
19608
+ function resetVertexProjectDiscovery() {
19609
+ discoveredProjectPromise = null;
19610
+ discoveredProjectSettled = undefined;
19611
+ syncAdcOrigin = undefined;
19612
+ }
19608
19613
  function describeVertexProjectSource(origin) {
19609
19614
  switch (origin.source) {
19610
19615
  case "env":
@@ -19615,6 +19620,20 @@ function describeVertexProjectSource(origin) {
19615
19620
  return `\`${origin.detail}\``;
19616
19621
  }
19617
19622
  }
19623
+ function describeVertexAccessDenied({
19624
+ status,
19625
+ upstream,
19626
+ projectId,
19627
+ origin,
19628
+ account
19629
+ }) {
19630
+ const segments = [`HTTP ${status}: ${upstream}`];
19631
+ if (account)
19632
+ segments.push(`ADC account ${account}`);
19633
+ segments.push(`project ${projectId}` + (origin ? ` (from ${describeVertexProjectSource(origin)})` : ""));
19634
+ segments.push("to sign in as another account: gcloud auth application-default login");
19635
+ return segments.join(" \xB7 ");
19636
+ }
19618
19637
  function envProjectOrigin() {
19619
19638
  for (const name of VERTEX_PROJECT_ENV_VARS) {
19620
19639
  const value = process.env[name]?.trim();
@@ -19753,6 +19772,9 @@ function buildVertexOAuthEndpoint(config, publisher, model, streaming = true) {
19753
19772
  }
19754
19773
  return `https://aiplatform.googleapis.com/v1/projects/${config.projectId}/locations/global/endpoints/openapi/chat/completions`;
19755
19774
  }
19775
+ function resetVertexAuthManager() {
19776
+ authManagerInstance = null;
19777
+ }
19756
19778
  function getVertexAuthManager() {
19757
19779
  if (!authManagerInstance) {
19758
19780
  authManagerInstance = new VertexAuthManager;
@@ -31177,6 +31199,10 @@ class VertexCredentialProvider {
31177
31199
  const config = await resolveVertexConfig();
31178
31200
  return selectVertexAuthMode({ project: config?.projectId }) !== null;
31179
31201
  }
31202
+ invalidate() {
31203
+ resetVertexAuthManager();
31204
+ resetVertexProjectDiscovery();
31205
+ }
31180
31206
  async getRequestAuth(_ctx) {
31181
31207
  const config = await resolveVertexConfig();
31182
31208
  if (selectVertexAuthMode({ project: config?.projectId }) === "project") {
@@ -40642,6 +40668,10 @@ var init_poe = __esm(() => {
40642
40668
  });
40643
40669
 
40644
40670
  // src/providers/transport/vertex-discovery.ts
40671
+ import { readFile as readFile4 } from "fs/promises";
40672
+ function _clearVertexDiscoveryCache() {
40673
+ _cache3.clear();
40674
+ }
40645
40675
  function isServedByVertex(m) {
40646
40676
  if (!m.publisherModelTemplate)
40647
40677
  return false;
@@ -40698,8 +40728,43 @@ async function listVertexPublisherModels(publisher = VERTEX_DEFAULT_PUBLISHER) {
40698
40728
  signal: AbortSignal.timeout(FETCH_TIMEOUT_MS4)
40699
40729
  });
40700
40730
  if (!response.ok) {
40731
+ log(`[vertex-discovery] HTTP ${response.status} from ${endpoint}`);
40701
40732
  const detail = await response.text().catch(() => "");
40702
- throw new Error(`HTTP ${response.status} from ${endpoint}${detail ? ` \u2014 ${oneLine4(detail)}` : ""}`);
40733
+ const upstream = upstreamErrorMessage(detail);
40734
+ const origin = await resolveVertexProjectOrigin();
40735
+ if (response.status === 401 || response.status === 403) {
40736
+ let account;
40737
+ try {
40738
+ const credPath = process.env.GOOGLE_APPLICATION_CREDENTIALS;
40739
+ if (credPath) {
40740
+ try {
40741
+ const credential = JSON.parse(await readFile4(credPath, "utf-8"));
40742
+ account = str2(credential.client_email);
40743
+ } catch {}
40744
+ }
40745
+ if (!account) {
40746
+ const token = auth.headers.Authorization?.match(/^Bearer\s+(.+)$/i)?.[1];
40747
+ if (token) {
40748
+ const tokeninfo = await fetch(`https://oauth2.googleapis.com/tokeninfo?access_token=${encodeURIComponent(token)}`, { method: "GET", signal: AbortSignal.timeout(3000) });
40749
+ if (tokeninfo.ok) {
40750
+ account = str2((await tokeninfo.json()).email);
40751
+ }
40752
+ }
40753
+ }
40754
+ } catch {}
40755
+ const explanation = describeVertexAccessDenied({
40756
+ status: response.status,
40757
+ upstream,
40758
+ account,
40759
+ origin,
40760
+ projectId: config.projectId
40761
+ });
40762
+ throw new Error(explanation);
40763
+ }
40764
+ throw new Error([
40765
+ `HTTP ${response.status}: ${upstream}`,
40766
+ `project ${config.projectId}` + (origin ? ` (from ${describeVertexProjectSource(origin)})` : "")
40767
+ ].join(" \xB7 "));
40703
40768
  }
40704
40769
  const listed = parsePublisherModels(await response.json());
40705
40770
  const models = listed.filter(isServedByVertex).map((m) => {
@@ -40715,6 +40780,15 @@ function oneLine4(text, max = 200) {
40715
40780
  const flat = text.replace(/\s+/g, " ").trim();
40716
40781
  return flat.length > max ? `${flat.slice(0, max)}\u2026` : flat;
40717
40782
  }
40783
+ function upstreamErrorMessage(detail) {
40784
+ try {
40785
+ const body = JSON.parse(detail);
40786
+ const message = str2(body?.error?.message);
40787
+ if (message)
40788
+ return message;
40789
+ } catch {}
40790
+ return oneLine4(detail) || "(no message)";
40791
+ }
40718
40792
  async function verifyServed(ids, config, headers) {
40719
40793
  const base = `https://${vertexApiHost(config.location)}/v1/` + `projects/${config.projectId}/locations/${config.location}/publishers`;
40720
40794
  return Promise.all(ids.map(async (id) => {
@@ -64053,6 +64127,9 @@ function readProcessTable() {
64053
64127
  return [];
64054
64128
  }
64055
64129
  }
64130
+ function processTableTrusted(table) {
64131
+ return table.some((r) => r.pid === process.pid);
64132
+ }
64056
64133
  function readProcessTableAsync() {
64057
64134
  return new Promise((resolve) => {
64058
64135
  try {
@@ -64989,8 +65066,9 @@ function ownerStartOfSelf() {
64989
65066
  if (ownStart)
64990
65067
  return ownStart;
64991
65068
  const row = readProcessTable().find((r) => r.pid === process.pid);
64992
- ownStart = row?.lstart ?? "";
64993
- return ownStart;
65069
+ if (row)
65070
+ ownStart = row.lstart;
65071
+ return row?.lstart ?? "";
64994
65072
  }
64995
65073
  function ownerAlive(rec, table) {
64996
65074
  const row = table.find((r) => r.pid === rec.ownerPid);
@@ -65244,6 +65322,10 @@ async function killVerified(rec, root) {
65244
65322
  }
65245
65323
  async function sweepRecord(rec, root, out) {
65246
65324
  const table = readProcessTable();
65325
+ if (!processTableTrusted(table)) {
65326
+ out.kept.push(rec.paneId);
65327
+ return;
65328
+ }
65247
65329
  if (ownerAlive(rec, table))
65248
65330
  return;
65249
65331
  const watcher = rec.watcherPid ? table.find((r) => r.pid === rec.watcherPid) : undefined;
@@ -65256,6 +65338,10 @@ async function sweepRecord(rec, root, out) {
65256
65338
  if (anyVerified)
65257
65339
  await killVerified(rec, root);
65258
65340
  const after = readProcessTable();
65341
+ if (!processTableTrusted(after)) {
65342
+ out.kept.push(rec.paneId);
65343
+ return;
65344
+ }
65259
65345
  const stillAlive = t0.group && groupCheck(after, t0.group) || liveEscaped(after, t0.group).length > 0 || t0.mag !== null && isPaneMagmux(t0.mag, rec.paneId, after);
65260
65346
  if (stillAlive) {
65261
65347
  out.kept.push(rec.paneId);
@@ -65288,6 +65374,10 @@ function ownerOfIdAlive(id, table) {
65288
65374
  async function sweepRecordlessSocket(root, name, out) {
65289
65375
  const id = name.slice("magmux-".length, -".sock".length);
65290
65376
  const table = readProcessTable();
65377
+ if (!processTableTrusted(table)) {
65378
+ out.kept.push(id);
65379
+ return;
65380
+ }
65291
65381
  if (ownerOfIdAlive(id, table))
65292
65382
  return;
65293
65383
  const sockPath = join43(root, name);
@@ -65360,7 +65450,7 @@ var init_pane_registry = __esm(() => {
65360
65450
  });
65361
65451
 
65362
65452
  // src/mcp-session/parent-session.ts
65363
- import { readFile as readFile4 } from "fs/promises";
65453
+ import { readFile as readFile5 } from "fs/promises";
65364
65454
  import { join as join44 } from "path";
65365
65455
  function positiveInt(value) {
65366
65456
  if (value === undefined || !/^[1-9][0-9]*$/.test(value))
@@ -65389,7 +65479,7 @@ function claudeConfigDir(env) {
65389
65479
  }
65390
65480
  async function readHostSessionRecord(opts) {
65391
65481
  try {
65392
- const raw = await readFile4(join44(opts.configDir, "sessions", `${opts.hostPid}.json`), "utf-8");
65482
+ const raw = await readFile5(join44(opts.configDir, "sessions", `${opts.hostPid}.json`), "utf-8");
65393
65483
  const parsed = JSON.parse(raw);
65394
65484
  if (!parsed || typeof parsed !== "object")
65395
65485
  return;
@@ -73918,9 +74008,10 @@ async function main() {
73918
74008
  const transport = new StdioServerTransport;
73919
74009
  await server.connect(transport);
73920
74010
  installMcpShutdown(sessionManager);
73921
- ensureSwept(sockRootFor()).catch(() => {
73922
- return;
73923
- });
74011
+ if (!nested)
74012
+ ensureSwept(sockRootFor()).catch(() => {
74013
+ return;
74014
+ });
73924
74015
  }
73925
74016
  function installMcpShutdown(sessionManager) {
73926
74017
  const before = async () => {
@@ -74752,6 +74843,16 @@ var init_source = __esm(() => {
74752
74843
  });
74753
74844
 
74754
74845
  // src/tui/providers.ts
74846
+ function providerLoginAction(p) {
74847
+ if (p.oauthSlug)
74848
+ return { kind: "claudish", slug: p.oauthSlug };
74849
+ if (p.catalogName === "vertex")
74850
+ return { kind: "gcloud-adc" };
74851
+ return;
74852
+ }
74853
+ function providerSetLabel(p) {
74854
+ return p.catalogName === "vertex" ? "project" : "key";
74855
+ }
74755
74856
  function toProviderDef(def) {
74756
74857
  return {
74757
74858
  name: def.name === "google" ? "gemini" : def.name,
@@ -74796,7 +74897,7 @@ function providerCredentialNote(p) {
74796
74897
  return;
74797
74898
  const origin = peekVertexProjectOrigin();
74798
74899
  if (!origin) {
74799
- return hasVertexAdcCredentials() ? `ADC present, no project \u2014 ${VERTEX_SET_PROJECT_REMEDY}` : `No credential \u2014 run \`gcloud auth application-default login\`, then ${VERTEX_SET_PROJECT_REMEDY}`;
74900
+ return hasVertexAdcCredentials() ? `ADC present, no project \u2014 ${VERTEX_SET_PROJECT_REMEDY}` : `No credential \u2014 run \`gcloud auth application-default login\` (press l), then ${VERTEX_SET_PROJECT_REMEDY}`;
74800
74901
  }
74801
74902
  return `Project ${origin.projectId} from ${describeVertexProjectSource(origin)}`;
74802
74903
  }
@@ -76778,6 +76879,32 @@ var init_constants3 = __esm(() => {
76778
76879
 
76779
76880
  // src/tui/components/Footer.tsx
76780
76881
  import { jsx as jsx14, jsxs as jsxs10 } from "@opentui/react/jsx-runtime";
76882
+ function providerFooterKeys(providerCaps) {
76883
+ const showKey = providerCaps ? providerCaps.apiKey : true;
76884
+ const showEndpoint = providerCaps ? providerCaps.endpoint || providerCaps.local : true;
76885
+ const showLogin = providerCaps ? providerCaps.oauth : true;
76886
+ const showRemove = providerCaps ? !providerCaps.local && (providerCaps.apiKey || providerCaps.endpoint) : true;
76887
+ const showUrl = providerCaps ? providerCaps.endpoint : true;
76888
+ const keys = [[C.blue, "\u2191\u2193", "navigate"]];
76889
+ if (showKey)
76890
+ keys.push([C.green, "s", providerCaps?.setLabel === "project" ? "set project" : "set key"]);
76891
+ if (showEndpoint)
76892
+ keys.push([
76893
+ C.green,
76894
+ "e",
76895
+ providerCaps?.local ? providerCaps.localEnabled ? "disable" : "enable" : "endpoint"
76896
+ ]);
76897
+ if (showUrl)
76898
+ keys.push([C.green, "u", "url"]);
76899
+ if (showLogin)
76900
+ keys.push([C.green, "l", "login"]);
76901
+ keys.push([C.cyan, "t", "test"]);
76902
+ keys.push([C.cyan, "T", "test all"]);
76903
+ if (showRemove)
76904
+ keys.push([C.red, "x", "remove"]);
76905
+ keys.push([C.dim, "q", "quit"]);
76906
+ return keys;
76907
+ }
76781
76908
  function Footer({ activeTab, mode, probeMode, providerCaps }) {
76782
76909
  const isProfileEditMode = mode === "new_profile" || mode === "pick_profile_scope" || mode === "pick_provider_prefix" || mode === "edit_profile_opus" || mode === "edit_profile_sonnet" || mode === "edit_profile_haiku" || mode === "edit_profile_subagent";
76783
76910
  let keys;
@@ -76799,29 +76926,7 @@ function Footer({ activeTab, mode, probeMode, providerCaps }) {
76799
76926
  [C.dim, "q", "quit"]
76800
76927
  ];
76801
76928
  } else if (activeTab === "providers") {
76802
- const showKey = providerCaps ? providerCaps.apiKey : true;
76803
- const showEndpoint = providerCaps ? providerCaps.endpoint || providerCaps.local : true;
76804
- const showLogin = providerCaps ? providerCaps.oauth : true;
76805
- const showRemove = providerCaps ? !providerCaps.local && (providerCaps.apiKey || providerCaps.endpoint) : true;
76806
- const showUrl = providerCaps ? providerCaps.endpoint : true;
76807
- keys = [[C.blue, "\u2191\u2193", "navigate"]];
76808
- if (showKey)
76809
- keys.push([C.green, "s", "set key"]);
76810
- if (showEndpoint)
76811
- keys.push([
76812
- C.green,
76813
- "e",
76814
- providerCaps?.local ? providerCaps.localEnabled ? "disable" : "enable" : "endpoint"
76815
- ]);
76816
- if (showUrl)
76817
- keys.push([C.green, "u", "url"]);
76818
- if (showLogin)
76819
- keys.push([C.green, "l", "login"]);
76820
- keys.push([C.cyan, "t", "test"]);
76821
- keys.push([C.cyan, "T", "test all"]);
76822
- if (showRemove)
76823
- keys.push([C.red, "x", "remove"]);
76824
- keys.push([C.dim, "q", "quit"]);
76929
+ keys = providerFooterKeys(providerCaps);
76825
76930
  } else if (activeTab === "profiles" && isProfileEditMode) {
76826
76931
  keys = [[C.dim, "wizard", "follow the panel above"]];
76827
76932
  } else if (activeTab === "profiles") {
@@ -78949,6 +79054,9 @@ function wrapToLines(text, maxWidth, maxLines) {
78949
79054
  }
78950
79055
  return lines;
78951
79056
  }
79057
+ function credentialNoteLines(note, width, hasFailure) {
79058
+ return wrapToLines(note, width - 4 - "Auth: ".length, hasFailure ? 1 : 2);
79059
+ }
78952
79060
  function resolveProviderDetailKeyDisplay(input) {
78953
79061
  if (input.isLocal)
78954
79062
  return input.isReady ? "enabled" : "disabled";
@@ -78960,6 +79068,11 @@ function resolveProviderDetailKeyDisplay(input) {
78960
79068
  return input.cfgKeyMask;
78961
79069
  return "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500";
78962
79070
  }
79071
+ function validTestNote(input) {
79072
+ if (input.isLocal)
79073
+ return " Local provider responded through the shared probe path.";
79074
+ return input.credential === "login" ? " Login is valid and endpoint is reachable." : " API key is valid and endpoint is reachable.";
79075
+ }
78963
79076
  function ProviderDetail({
78964
79077
  selectedProvider,
78965
79078
  mode,
@@ -78997,7 +79110,7 @@ function ProviderDetail({
78997
79110
  border: true,
78998
79111
  borderStyle: "single",
78999
79112
  borderColor: C.focusBorder,
79000
- title: mode === "input_key" ? ` Set API Key \u2014 ${selectedProvider.displayName} \u2192 ${keySaveTarget} ` : ` Set Endpoint \u2014 ${selectedProvider.displayName} `,
79113
+ title: mode === "input_key" ? ` Set ${providerSetLabel(selectedProvider) === "project" ? "Project" : "API Key"} \u2014 ${selectedProvider.displayName} \u2192 ${keySaveTarget} ` : ` Set Endpoint \u2014 ${selectedProvider.displayName} `,
79001
79114
  backgroundColor: C.bg,
79002
79115
  flexDirection: "column",
79003
79116
  paddingX: 1,
@@ -79059,6 +79172,7 @@ function ProviderDetail({
79059
79172
  }
79060
79173
  const tr = testResults[selectedProvider.name];
79061
79174
  const failureText = tr && (tr.status === "failed" || tr.status === "unavailable") ? tr.providerMessage ?? tr.error : undefined;
79175
+ const noteLines = credentialNote ? credentialNoteLines(credentialNote, width, !!failureText) : [];
79062
79176
  return /* @__PURE__ */ jsxs18("box", {
79063
79177
  height: DETAIL_H,
79064
79178
  border: true,
@@ -79221,19 +79335,19 @@ function ProviderDetail({
79221
79335
  })
79222
79336
  ]
79223
79337
  }),
79224
- credentialNote && /* @__PURE__ */ jsxs18("text", {
79338
+ noteLines.map((line, i) => /* @__PURE__ */ jsxs18("text", {
79225
79339
  children: [
79226
79340
  /* @__PURE__ */ jsx22("span", {
79227
79341
  fg: C.blue,
79228
79342
  attributes: A.bold,
79229
- children: "Auth: "
79343
+ children: i === 0 ? "Auth: " : " "
79230
79344
  }),
79231
79345
  /* @__PURE__ */ jsx22("span", {
79232
79346
  fg: hasKey ? C.green : C.yellow,
79233
- children: credentialNote
79347
+ children: line
79234
79348
  })
79235
79349
  ]
79236
- }),
79350
+ }, i)),
79237
79351
  selectedProvider.endpointEnvVar && /* @__PURE__ */ jsxs18("text", {
79238
79352
  children: [
79239
79353
  /* @__PURE__ */ jsxs18("span", {
@@ -79250,7 +79364,7 @@ function ProviderDetail({
79250
79364
  })
79251
79365
  ]
79252
79366
  }),
79253
- !failureText && /* @__PURE__ */ jsxs18("text", {
79367
+ !failureText && noteLines.length < 2 && /* @__PURE__ */ jsxs18("text", {
79254
79368
  children: [
79255
79369
  /* @__PURE__ */ jsxs18("span", {
79256
79370
  fg: C.blue,
@@ -79304,7 +79418,10 @@ function ProviderDetail({
79304
79418
  }),
79305
79419
  /* @__PURE__ */ jsx22("span", {
79306
79420
  fg: C.fgMuted,
79307
- children: selectedProvider.isLocal ? " Local provider responded through the shared probe path." : " API key is valid and endpoint is reachable."
79421
+ children: validTestNote({
79422
+ isLocal: !!selectedProvider.isLocal,
79423
+ credential: isOAuth || selectedProvider.catalogName === "vertex" ? "login" : "key"
79424
+ })
79308
79425
  })
79309
79426
  ]
79310
79427
  }),
@@ -79331,6 +79448,7 @@ function ProviderDetail({
79331
79448
  }
79332
79449
  var init_ProviderDetail = __esm(() => {
79333
79450
  init_constants3();
79451
+ init_providers();
79334
79452
  init_theme2();
79335
79453
  });
79336
79454
 
@@ -81497,6 +81615,9 @@ var init_onepassword_fields = __esm(() => {
81497
81615
  import { useKeyboard as useKeyboard3, useRenderer, useTerminalDimensions as useTerminalDimensions3 } from "@opentui/react";
81498
81616
  import { useCallback as useCallback4, useEffect as useEffect11, useMemo as useMemo5, useRef as useRef8, useState as useState11 } from "react";
81499
81617
  import { jsx as jsx27, jsxs as jsxs23, Fragment as Fragment15 } from "@opentui/react/jsx-runtime";
81618
+ function nextStatusAfterProbeReady(current) {
81619
+ return current === "Starting probe proxy\u2026" ? null : current;
81620
+ }
81500
81621
  async function resolveOpEntrySecrets(entries, auth) {
81501
81622
  const secrets = {};
81502
81623
  for (const entry of entries) {
@@ -82086,6 +82207,7 @@ function App({ requestLogin } = {}) {
82086
82207
  if (prov.catalogName === "meta-muse-code")
82087
82208
  await prepareMuseLoginForTuiAction();
82088
82209
  const proxyUrl = await ensureProbeProxy();
82210
+ setStatusMsg(nextStatusAfterProbeReady);
82089
82211
  const catalogModel = getProbeModel(prov.catalogName);
82090
82212
  const tried = new Set;
82091
82213
  const MAX_ATTEMPTS = 3;
@@ -82798,15 +82920,17 @@ function App({ requestLogin } = {}) {
82798
82920
  }
82799
82921
  setStatusMsg(failureMsg ?? (changed ? removedFrom.length > 0 ? `Removed ${selectedProvider.displayName} key from ${removedFrom.join(" + ")}.` : `Stored config removed for ${selectedProvider.displayName}.` : "No stored config to remove."));
82800
82922
  } else if (key.name === "l") {
82801
- const slug = selectedProvider.oauthSlug;
82802
- if (!slug) {
82803
- setStatusMsg(`${selectedProvider.displayName} doesn't support OAuth login. Press s to set an API key.`);
82923
+ const action = providerLoginAction(selectedProvider);
82924
+ const setLabel = providerSetLabel(selectedProvider) === "project" ? "a project" : "an API key";
82925
+ const command = action?.kind === "gcloud-adc" ? "gcloud auth application-default login" : action ? `claudish login ${action.slug}` : "";
82926
+ if (!action) {
82927
+ setStatusMsg(`${selectedProvider.displayName} doesn't support OAuth login. Press s to set ${setLabel}.`);
82804
82928
  } else if (!requestLogin) {
82805
- setStatusMsg(`Run: claudish login ${slug}`);
82929
+ setStatusMsg(`Run: ${command}`);
82806
82930
  } else {
82807
- setStatusMsg(`Launching: claudish login ${slug}\u2026`);
82931
+ setStatusMsg(`Launching: ${command}\u2026`);
82808
82932
  setTimeout(() => {
82809
- requestLogin(slug);
82933
+ requestLogin(action);
82810
82934
  renderer.destroy();
82811
82935
  }, 50);
82812
82936
  }
@@ -82827,17 +82951,18 @@ function App({ requestLogin } = {}) {
82827
82951
  }
82828
82952
  } else if (key.name === "t") {
82829
82953
  const caps = providerAuthCapabilities(selectedProvider, config);
82954
+ const setLabel = providerSetLabel(selectedProvider);
82830
82955
  const localRunning = selectedProviderIsLocal && localLiveness[selectedProvider.catalogName] === "running";
82831
82956
  const ready = providerIsReady(selectedProvider, config) || localRunning;
82832
82957
  if (!ready) {
82833
82958
  if (selectedProviderIsLocal) {
82834
82959
  setStatusMsg(`${selectedProvider.displayName}: not running / disabled. Start the server, or press e to enable.`);
82835
82960
  } else if (caps.apiKey.supported && caps.oauth.supported) {
82836
- setStatusMsg(`${selectedProvider.displayName}: no credentials. Press s to set a key or l to login.`);
82961
+ setStatusMsg(`${selectedProvider.displayName}: no credentials. Press s to set a ${setLabel} or l to login.`);
82837
82962
  } else if (caps.oauth.supported) {
82838
82963
  setStatusMsg(`${selectedProvider.displayName}: no credentials. Press l to login.`);
82839
82964
  } else if (caps.apiKey.supported) {
82840
- setStatusMsg(`${selectedProvider.displayName}: no key set. Press s to set an API key.`);
82965
+ setStatusMsg(`${selectedProvider.displayName}: no ${setLabel} set. Press s to set ${setLabel === "project" ? "a project" : "an API key"}.`);
82841
82966
  } else {
82842
82967
  setStatusMsg(`${selectedProvider.displayName} doesn't support auth from the TUI.`);
82843
82968
  }
@@ -83266,7 +83391,8 @@ function App({ requestLogin } = {}) {
83266
83391
  probeMode,
83267
83392
  providerCaps: activeTab === "providers" && selectedProvider ? {
83268
83393
  apiKey: !!selectedProvider.apiKeyEnvVar,
83269
- oauth: !!selectedProvider.oauthSlug,
83394
+ oauth: Boolean(providerLoginAction(selectedProvider)),
83395
+ setLabel: providerSetLabel(selectedProvider),
83270
83396
  endpoint: !!selectedProvider.endpointEnvVar,
83271
83397
  local: selectedProviderIsLocal,
83272
83398
  localEnabled: selectedLocalEnabled
@@ -83340,21 +83466,25 @@ var init_App = __esm(() => {
83340
83466
  // src/tui/index.tsx
83341
83467
  var exports_tui = {};
83342
83468
  __export(exports_tui, {
83469
+ gcloudCommand: () => gcloudCommand,
83343
83470
  startConfigTui: () => startConfigTui
83344
83471
  });
83345
83472
  import { spawnSync as spawnSync3 } from "child_process";
83346
83473
  import { createCliRenderer as createCliRenderer3 } from "@opentui/core";
83347
83474
  import { createRoot as createRoot3 } from "@opentui/react";
83348
83475
  import { jsx as jsx28 } from "@opentui/react/jsx-runtime";
83476
+ function gcloudCommand(platform) {
83477
+ return platform === "win32" ? "gcloud.cmd" : "gcloud";
83478
+ }
83349
83479
  async function startConfigTui() {
83350
83480
  setCredentialPromptRole(decideTuiRole());
83351
83481
  ensureEndpointsRegistered();
83352
83482
  setStderrQuiet(true);
83353
83483
  const loginRequest = {
83354
- slug: null
83484
+ action: null
83355
83485
  };
83356
- const requestLogin = (slug) => {
83357
- loginRequest.slug = slug;
83486
+ const requestLogin = (action) => {
83487
+ loginRequest.action = action;
83358
83488
  };
83359
83489
  const renderer = await createCliRenderer3({
83360
83490
  exitOnCtrlC: false
@@ -83368,23 +83498,37 @@ async function startConfigTui() {
83368
83498
  });
83369
83499
  await shutdownProbeProxy();
83370
83500
  setStderrQuiet(false);
83371
- if (loginRequest.slug !== null) {
83372
- const slug = loginRequest.slug;
83501
+ if (loginRequest.action !== null) {
83502
+ const action = loginRequest.action;
83503
+ const command = action.kind === "gcloud-adc" ? "gcloud auth application-default login" : `claudish login ${action.slug}`;
83373
83504
  console.log(`
83374
- Launching: claudish login ${slug}
83505
+ Launching: ${command}
83375
83506
  `);
83376
- const result = spawnSync3(process.argv[0], [process.argv[1], "login", slug], {
83377
- stdio: "inherit"
83378
- });
83507
+ const result = action.kind === "gcloud-adc" ? spawnSync3(gcloudCommand(process.platform), ["auth", "application-default", "login"], {
83508
+ stdio: "inherit",
83509
+ shell: process.platform === "win32"
83510
+ }) : spawnSync3(process.argv[0], [process.argv[1], "login", action.slug], { stdio: "inherit" });
83379
83511
  if (result.error) {
83380
- console.error(`
83512
+ if (action.kind === "gcloud-adc" && result.error.code === "ENOENT") {
83513
+ console.error(`
83514
+ gcloud not found \u2014 install the Google Cloud CLI (https://cloud.google.com/sdk/docs/install)
83515
+ `);
83516
+ } else {
83517
+ console.error(`
83381
83518
  \u274C Failed to spawn login: ${result.error.message}
83382
83519
  `);
83520
+ }
83383
83521
  } else if (result.status !== 0) {
83384
83522
  console.error(`
83385
83523
  \u274C Login exited with status ${result.status}
83386
83524
  `);
83525
+ } else if (action.kind === "gcloud-adc") {
83526
+ resetVertexProjectDiscovery();
83527
+ credentials.invalidate("vertex");
83528
+ _clearVertexDiscoveryCache();
83529
+ invalidateProbeProxyHandlers("vertex");
83387
83530
  } else {
83531
+ const slug = action.slug;
83388
83532
  if (slug === "antigravity") {
83389
83533
  _resetAntigravityTokenState();
83390
83534
  invalidateProbeProxyHandlers("antigravity");
@@ -83414,10 +83558,12 @@ var init_tui = __esm(() => {
83414
83558
  init_authority();
83415
83559
  init_prompt_role();
83416
83560
  init_kimi_oauth();
83561
+ init_vertex_auth();
83417
83562
  init_logger();
83418
- init_renderer_theme();
83419
83563
  init_endpoint_registration();
83420
83564
  init_muse_credentials();
83565
+ init_vertex_discovery();
83566
+ init_renderer_theme();
83421
83567
  init_App();
83422
83568
  if (isDirectRun) {
83423
83569
  startConfigTui().catch((err) => {
@@ -83917,6 +84063,13 @@ function shouldHideIncidentalAnthropicKey(config, env = process.env) {
83917
84063
  return false;
83918
84064
  return !wantsAnthropicApiBilling(config, env);
83919
84065
  }
84066
+ function applyProxyPlaceholderAuth(env, paneChild = isPaneChild()) {
84067
+ env.ANTHROPIC_AUTH_TOKEN = CLAUDISH_PLACEHOLDER_AUTH_TOKEN;
84068
+ if (paneChild)
84069
+ delete env.ANTHROPIC_API_KEY;
84070
+ else
84071
+ env.ANTHROPIC_API_KEY = CLAUDISH_PLACEHOLDER_API_KEY;
84072
+ }
83920
84073
  function scrubInheritedClaudishPlaceholders(env) {
83921
84074
  const removed = [];
83922
84075
  for (const name of ["ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_API_KEY"]) {
@@ -84560,8 +84713,7 @@ async function runClaudeWithProxy(config, proxyUrl, onCleanup) {
84560
84713
  if (classifierPassthroughEnabled(config)) {
84561
84714
  console.error("[claudish] classifier passthrough enabled but no Anthropic credentials detected \u2014 " + "classifier requests will fail to authenticate against api.anthropic.com. " + "Map a role to a native Claude model (e.g. --model-sonnet claude-sonnet-5) or set ANTHROPIC_API_KEY.");
84562
84715
  }
84563
- env.ANTHROPIC_API_KEY = CLAUDISH_PLACEHOLDER_API_KEY;
84564
- env.ANTHROPIC_AUTH_TOKEN = CLAUDISH_PLACEHOLDER_AUTH_TOKEN;
84716
+ applyProxyPlaceholderAuth(env);
84565
84717
  const realWindow = await computeMainThreadContextWindow(config);
84566
84718
  const contextEnv = resolveContextWindowEnv(realWindow, process.env);
84567
84719
  Object.assign(env, contextEnv.vars);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "12.3.1",
3
+ "version": "12.3.2",
4
4
  "description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,10 +60,10 @@
60
60
  "ai"
61
61
  ],
62
62
  "optionalDependencies": {
63
- "@claudish/magmux-darwin-arm64": "12.3.1",
64
- "@claudish/magmux-darwin-x64": "12.3.1",
65
- "@claudish/magmux-linux-arm64": "12.3.1",
66
- "@claudish/magmux-linux-x64": "12.3.1"
63
+ "@claudish/magmux-darwin-arm64": "12.3.2",
64
+ "@claudish/magmux-darwin-x64": "12.3.2",
65
+ "@claudish/magmux-linux-arm64": "12.3.2",
66
+ "@claudish/magmux-linux-x64": "12.3.2"
67
67
  },
68
68
  "author": "Jack Rudenko <i@madappgang.com>",
69
69
  "license": "MIT",