claudish 7.29.0 → 7.30.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.
- package/dist/index.js +1783 -956
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -651,7 +651,7 @@ var init_onepassword_config = __esm(() => {
|
|
|
651
651
|
});
|
|
652
652
|
|
|
653
653
|
// src/version.ts
|
|
654
|
-
var VERSION = "7.
|
|
654
|
+
var VERSION = "7.30.0";
|
|
655
655
|
|
|
656
656
|
// src/logger.ts
|
|
657
657
|
var exports_logger = {};
|
|
@@ -27704,6 +27704,26 @@ var init_provider_definitions = __esm(() => {
|
|
|
27704
27704
|
isDirectApi: true,
|
|
27705
27705
|
description: "Direct Gemini API (g@, google@)"
|
|
27706
27706
|
},
|
|
27707
|
+
{
|
|
27708
|
+
name: "antigravity",
|
|
27709
|
+
displayName: "Antigravity",
|
|
27710
|
+
transport: "antigravity",
|
|
27711
|
+
baseUrl: "https://cloudcode-pa.googleapis.com",
|
|
27712
|
+
apiPath: "/v1internal:streamGenerateContent?alt=sse",
|
|
27713
|
+
apiKeyEnvVar: "",
|
|
27714
|
+
apiKeyDescription: "Antigravity (shared OAuth token)",
|
|
27715
|
+
apiKeyUrl: "https://antigravity.google/",
|
|
27716
|
+
oauthLoginSlug: "gemini",
|
|
27717
|
+
shortcuts: ["ag", "antigravity", "go"],
|
|
27718
|
+
shortestPrefix: "ag",
|
|
27719
|
+
legacyPrefixes: [
|
|
27720
|
+
{ prefix: "ag/", stripPrefix: true },
|
|
27721
|
+
{ prefix: "antigravity/", stripPrefix: true },
|
|
27722
|
+
{ prefix: "go/", stripPrefix: true }
|
|
27723
|
+
],
|
|
27724
|
+
isDirectApi: true,
|
|
27725
|
+
description: "Antigravity subscription (ag@; go@ deprecated)"
|
|
27726
|
+
},
|
|
27707
27727
|
{
|
|
27708
27728
|
name: "gemini-codeassist",
|
|
27709
27729
|
displayName: "Gemini Code Assist",
|
|
@@ -27714,11 +27734,11 @@ var init_provider_definitions = __esm(() => {
|
|
|
27714
27734
|
apiKeyDescription: "Gemini Code Assist (OAuth)",
|
|
27715
27735
|
apiKeyUrl: "https://cloud.google.com/code-assist",
|
|
27716
27736
|
oauthLoginSlug: "gemini",
|
|
27717
|
-
shortcuts: [
|
|
27718
|
-
shortestPrefix: "
|
|
27719
|
-
legacyPrefixes: [
|
|
27737
|
+
shortcuts: [],
|
|
27738
|
+
shortestPrefix: "gemini-codeassist",
|
|
27739
|
+
legacyPrefixes: [],
|
|
27720
27740
|
isDirectApi: true,
|
|
27721
|
-
description: "Gemini Code Assist OAuth (
|
|
27741
|
+
description: "Gemini Code Assist OAuth (routing fallback for gemini-*)"
|
|
27722
27742
|
},
|
|
27723
27743
|
{
|
|
27724
27744
|
name: "openai",
|
|
@@ -28231,125 +28251,191 @@ var init_provider_definitions = __esm(() => {
|
|
|
28231
28251
|
];
|
|
28232
28252
|
});
|
|
28233
28253
|
|
|
28234
|
-
// src/auth/
|
|
28254
|
+
// src/auth/antigravity-token.ts
|
|
28255
|
+
import { execFileSync } from "child_process";
|
|
28235
28256
|
import { existsSync as existsSync6 } from "fs";
|
|
28236
28257
|
import { homedir as homedir8 } from "os";
|
|
28237
28258
|
import { join as join8 } from "path";
|
|
28238
|
-
function
|
|
28239
|
-
if (
|
|
28240
|
-
|
|
28241
|
-
|
|
28259
|
+
function defaultReadStore() {
|
|
28260
|
+
if (process.platform !== "darwin") {
|
|
28261
|
+
logStderr("[Antigravity] Shared token store is macOS-only for now (other keyring backends are a follow-up).");
|
|
28262
|
+
return null;
|
|
28263
|
+
}
|
|
28264
|
+
try {
|
|
28265
|
+
const out = execFileSync("security", ["find-generic-password", "-s", KC_SERVICE, "-a", KC_ACCOUNT, "-w"], { encoding: "utf8" });
|
|
28266
|
+
const trimmed = out.trim();
|
|
28267
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
28268
|
+
} catch {
|
|
28269
|
+
return null;
|
|
28270
|
+
}
|
|
28242
28271
|
}
|
|
28243
|
-
|
|
28244
|
-
|
|
28245
|
-
|
|
28246
|
-
envVar;
|
|
28247
|
-
aliases;
|
|
28248
|
-
authScheme;
|
|
28249
|
-
staticHeaders;
|
|
28250
|
-
publicKeyFallback;
|
|
28251
|
-
oauthFallback;
|
|
28252
|
-
declaredKey;
|
|
28253
|
-
cachedKey;
|
|
28254
|
-
resolving;
|
|
28255
|
-
constructor(descriptor) {
|
|
28256
|
-
this.catalogName = descriptor.catalogName;
|
|
28257
|
-
this.envVar = descriptor.envVar;
|
|
28258
|
-
this.aliases = descriptor.aliases ?? [];
|
|
28259
|
-
this.authScheme = descriptor.authScheme ?? "bearer";
|
|
28260
|
-
this.staticHeaders = descriptor.staticHeaders ?? {};
|
|
28261
|
-
this.publicKeyFallback = descriptor.publicKeyFallback;
|
|
28262
|
-
this.oauthFallback = descriptor.oauthFallback;
|
|
28263
|
-
this.declaredKey = descriptor.declaredKey;
|
|
28272
|
+
function defaultWriteStore(rawValue) {
|
|
28273
|
+
if (process.platform !== "darwin") {
|
|
28274
|
+
throw new Error("[Antigravity] Cannot write the shared token store on a non-macOS platform.");
|
|
28264
28275
|
}
|
|
28265
|
-
|
|
28266
|
-
|
|
28276
|
+
execFileSync("security", ["add-generic-password", "-U", "-s", KC_SERVICE, "-a", KC_ACCOUNT, "-w", rawValue], { stdio: ["ignore", "ignore", "ignore"] });
|
|
28277
|
+
}
|
|
28278
|
+
function locateAgyBinary() {
|
|
28279
|
+
try {
|
|
28280
|
+
const p = execFileSync("which", ["agy"], { encoding: "utf8" }).trim();
|
|
28281
|
+
if (p.length > 0)
|
|
28282
|
+
return p;
|
|
28283
|
+
} catch {}
|
|
28284
|
+
const fallback = join8(homedir8(), ".local", "bin", "agy");
|
|
28285
|
+
return existsSync6(fallback) ? fallback : null;
|
|
28286
|
+
}
|
|
28287
|
+
function defaultExtractCreds() {
|
|
28288
|
+
const agy = locateAgyBinary();
|
|
28289
|
+
if (!agy) {
|
|
28290
|
+
logStderr("[Antigravity] Could not locate the `agy` binary \u2014 self-refresh is unavailable.");
|
|
28291
|
+
return [];
|
|
28267
28292
|
}
|
|
28268
|
-
|
|
28269
|
-
|
|
28270
|
-
|
|
28271
|
-
|
|
28272
|
-
|
|
28273
|
-
}
|
|
28293
|
+
let dump;
|
|
28294
|
+
try {
|
|
28295
|
+
dump = execFileSync("strings", [agy], {
|
|
28296
|
+
encoding: "utf8",
|
|
28297
|
+
maxBuffer: 128 * 1024 * 1024
|
|
28298
|
+
});
|
|
28299
|
+
} catch {
|
|
28300
|
+
logStderr("[Antigravity] `strings` failed on the agy binary \u2014 self-refresh is unavailable.");
|
|
28301
|
+
return [];
|
|
28274
28302
|
}
|
|
28275
|
-
|
|
28276
|
-
|
|
28277
|
-
|
|
28278
|
-
|
|
28279
|
-
|
|
28280
|
-
|
|
28281
|
-
return false;
|
|
28303
|
+
const clientIds = Array.from(new Set(dump.match(/[0-9]{6,}-[a-z0-9]+\.apps\.googleusercontent\.com/g) ?? []));
|
|
28304
|
+
const secrets = Array.from(new Set(dump.match(/GOCSPX-[A-Za-z0-9_-]{20,}/g) ?? []));
|
|
28305
|
+
const combos = [];
|
|
28306
|
+
for (const clientId of clientIds) {
|
|
28307
|
+
for (const clientSecret of secrets) {
|
|
28308
|
+
combos.push({ clientId, clientSecret });
|
|
28282
28309
|
}
|
|
28283
28310
|
}
|
|
28284
|
-
|
|
28285
|
-
|
|
28286
|
-
|
|
28287
|
-
|
|
28288
|
-
|
|
28289
|
-
|
|
28290
|
-
|
|
28291
|
-
|
|
28292
|
-
this.cachedKey = local;
|
|
28293
|
-
return local;
|
|
28294
|
-
}
|
|
28295
|
-
if (hasOpSources()) {
|
|
28296
|
-
const wanted = new Set([this.envVar, ...this.aliases]);
|
|
28297
|
-
const resolved = await resolveOpKeyForEnvVars(wanted, {
|
|
28298
|
-
onAuthFailure: "skip",
|
|
28299
|
-
allowPrompt: opts?.allowOpPrompt ?? false
|
|
28300
|
-
});
|
|
28301
|
-
const value = resolved[this.envVar] ?? this.aliases.map((a) => resolved[a]).find((v) => !!v);
|
|
28302
|
-
if (value) {
|
|
28303
|
-
process.env[this.envVar] = value;
|
|
28304
|
-
this.cachedKey = value;
|
|
28305
|
-
return value;
|
|
28306
|
-
}
|
|
28307
|
-
return "";
|
|
28308
|
-
}
|
|
28309
|
-
this.cachedKey = "";
|
|
28310
|
-
return "";
|
|
28311
|
-
})();
|
|
28312
|
-
try {
|
|
28313
|
-
return await this.resolving;
|
|
28314
|
-
} finally {
|
|
28315
|
-
this.resolving = undefined;
|
|
28316
|
-
}
|
|
28311
|
+
return combos;
|
|
28312
|
+
}
|
|
28313
|
+
function parseRecord(raw) {
|
|
28314
|
+
if (!raw)
|
|
28315
|
+
return null;
|
|
28316
|
+
if (!raw.startsWith(PREFIX)) {
|
|
28317
|
+
logStderr("[Antigravity] Shared token is in an unsupported keyring format (not go-keyring-base64) \u2014 skipping.");
|
|
28318
|
+
return null;
|
|
28317
28319
|
}
|
|
28318
|
-
|
|
28319
|
-
|
|
28320
|
-
|
|
28321
|
-
if (
|
|
28322
|
-
return
|
|
28323
|
-
|
|
28324
|
-
|
|
28325
|
-
|
|
28326
|
-
return
|
|
28320
|
+
try {
|
|
28321
|
+
const json2 = Buffer.from(raw.slice(PREFIX.length), "base64").toString("utf8");
|
|
28322
|
+
const rec = JSON.parse(json2);
|
|
28323
|
+
if (!rec?.token?.access_token)
|
|
28324
|
+
return null;
|
|
28325
|
+
return rec;
|
|
28326
|
+
} catch (err) {
|
|
28327
|
+
log(`[Antigravity] Failed to decode shared token: ${err}`);
|
|
28328
|
+
return null;
|
|
28327
28329
|
}
|
|
28328
|
-
|
|
28329
|
-
|
|
28330
|
-
|
|
28330
|
+
}
|
|
28331
|
+
function encodeRecord(rec) {
|
|
28332
|
+
return PREFIX + Buffer.from(JSON.stringify(rec), "utf8").toString("base64");
|
|
28333
|
+
}
|
|
28334
|
+
function readSharedAntigravityToken(deps = defaultDeps) {
|
|
28335
|
+
const rec = parseRecord(deps.readStore());
|
|
28336
|
+
return rec ? rec.token : null;
|
|
28337
|
+
}
|
|
28338
|
+
function hasSharedAntigravityToken(deps = defaultDeps) {
|
|
28339
|
+
const now = Date.now();
|
|
28340
|
+
if (cachedHasToken && now - cachedHasToken.at < HAS_TOKEN_TTL_MS)
|
|
28341
|
+
return cachedHasToken.value;
|
|
28342
|
+
let value = false;
|
|
28343
|
+
try {
|
|
28344
|
+
value = readSharedAntigravityToken(deps) != null;
|
|
28345
|
+
} catch {
|
|
28346
|
+
value = false;
|
|
28331
28347
|
}
|
|
28332
|
-
|
|
28333
|
-
|
|
28334
|
-
|
|
28335
|
-
|
|
28336
|
-
|
|
28337
|
-
|
|
28338
|
-
|
|
28339
|
-
|
|
28340
|
-
|
|
28348
|
+
cachedHasToken = { at: now, value };
|
|
28349
|
+
return value;
|
|
28350
|
+
}
|
|
28351
|
+
function writeSharedAntigravityToken(tok, deps = defaultDeps) {
|
|
28352
|
+
const existing = parseRecord(deps.readStore());
|
|
28353
|
+
const base = existing ?? { token: tok };
|
|
28354
|
+
const merged = {
|
|
28355
|
+
...base,
|
|
28356
|
+
token: { ...base.token, ...tok }
|
|
28357
|
+
};
|
|
28358
|
+
deps.writeStore(encodeRecord(merged));
|
|
28359
|
+
}
|
|
28360
|
+
function needsRefresh(tok, now) {
|
|
28361
|
+
const expMs = Date.parse(tok.expiry);
|
|
28362
|
+
if (Number.isNaN(expMs))
|
|
28363
|
+
return true;
|
|
28364
|
+
return now >= expMs - EXPIRY_SKEW_MS;
|
|
28365
|
+
}
|
|
28366
|
+
async function refreshToken(tok, deps) {
|
|
28367
|
+
const combos = cachedCred ? [cachedCred] : deps.extractCreds();
|
|
28368
|
+
if (combos.length === 0) {
|
|
28369
|
+
throw new Error("[Antigravity] Access token expired and no OAuth client credentials could be extracted " + "from the `agy` binary to refresh it. Re-run the Antigravity CLI to refresh your session, " + "or use g@<model> with GEMINI_API_KEY.");
|
|
28370
|
+
}
|
|
28371
|
+
let lastStatus = 0;
|
|
28372
|
+
let lastBody = "";
|
|
28373
|
+
for (const cred of combos) {
|
|
28374
|
+
const res = await deps.fetch(REFRESH_ENDPOINT, {
|
|
28375
|
+
method: "POST",
|
|
28376
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
28377
|
+
body: new URLSearchParams({
|
|
28378
|
+
client_id: cred.clientId,
|
|
28379
|
+
client_secret: cred.clientSecret,
|
|
28380
|
+
refresh_token: tok.refresh_token,
|
|
28381
|
+
grant_type: "refresh_token"
|
|
28382
|
+
})
|
|
28383
|
+
});
|
|
28384
|
+
if (res.ok) {
|
|
28385
|
+
cachedCred = cred;
|
|
28386
|
+
const j = await res.json();
|
|
28387
|
+
const expiry = new Date(deps.now() + j.expires_in * 1000).toISOString();
|
|
28388
|
+
return {
|
|
28389
|
+
access_token: j.access_token,
|
|
28390
|
+
token_type: tok.token_type || "Bearer",
|
|
28391
|
+
refresh_token: j.refresh_token || tok.refresh_token,
|
|
28392
|
+
expiry
|
|
28393
|
+
};
|
|
28341
28394
|
}
|
|
28342
|
-
|
|
28395
|
+
lastStatus = res.status;
|
|
28396
|
+
lastBody = await res.text().catch(() => "");
|
|
28343
28397
|
}
|
|
28398
|
+
throw new Error(`[Antigravity] Token refresh failed for all ${combos.length} client-cred combo(s) ` + `(last HTTP ${lastStatus}${lastBody ? `: ${lastBody.slice(0, 200)}` : ""}). ` + "Re-run the Antigravity CLI to refresh your session, or use g@<model> with GEMINI_API_KEY.");
|
|
28344
28399
|
}
|
|
28345
|
-
|
|
28346
|
-
|
|
28347
|
-
|
|
28348
|
-
|
|
28349
|
-
|
|
28400
|
+
async function resolveValidToken(deps) {
|
|
28401
|
+
if (process.platform !== "darwin") {
|
|
28402
|
+
throw new Error("[Antigravity] The shared Antigravity token store is macOS-only for now. " + "Use g@<model> with GEMINI_API_KEY on this platform.");
|
|
28403
|
+
}
|
|
28404
|
+
const rec = parseRecord(deps.readStore());
|
|
28405
|
+
if (!rec) {
|
|
28406
|
+
throw new Error("[Antigravity] No Antigravity session found. Install Antigravity and sign in " + "(the `agy` CLI), or use g@<model> with GEMINI_API_KEY " + "(get one at https://aistudio.google.com/app/apikey).");
|
|
28407
|
+
}
|
|
28408
|
+
const tok = rec.token;
|
|
28409
|
+
if (!needsRefresh(tok, deps.now())) {
|
|
28410
|
+
return tok.access_token;
|
|
28411
|
+
}
|
|
28412
|
+
log("[Antigravity] Access token expired/near-expiry \u2014 refreshing.");
|
|
28413
|
+
const refreshed = await refreshToken(tok, deps);
|
|
28414
|
+
writeSharedAntigravityToken(refreshed, deps);
|
|
28415
|
+
log("[Antigravity] Token refreshed and written back to the shared store.");
|
|
28416
|
+
return refreshed.access_token;
|
|
28417
|
+
}
|
|
28418
|
+
function getValidAntigravityAccessToken(deps = defaultDeps) {
|
|
28419
|
+
if (inFlight)
|
|
28420
|
+
return inFlight;
|
|
28421
|
+
inFlight = resolveValidToken(deps).finally(() => {
|
|
28422
|
+
inFlight = null;
|
|
28423
|
+
});
|
|
28424
|
+
return inFlight;
|
|
28425
|
+
}
|
|
28426
|
+
var KC_SERVICE = "gemini", KC_ACCOUNT = "antigravity", PREFIX = "go-keyring-base64:", REFRESH_ENDPOINT = "https://oauth2.googleapis.com/token", EXPIRY_SKEW_MS = 120000, defaultDeps, cachedHasToken = null, HAS_TOKEN_TTL_MS = 5000, cachedCred = null, inFlight = null;
|
|
28427
|
+
var init_antigravity_token = __esm(() => {
|
|
28428
|
+
init_logger();
|
|
28429
|
+
defaultDeps = {
|
|
28430
|
+
readStore: defaultReadStore,
|
|
28431
|
+
writeStore: defaultWriteStore,
|
|
28432
|
+
extractCreds: defaultExtractCreds,
|
|
28433
|
+
fetch: (input, init) => fetch(input, init),
|
|
28434
|
+
now: () => Date.now()
|
|
28435
|
+
};
|
|
28350
28436
|
});
|
|
28351
28437
|
|
|
28352
|
-
// src/auth/
|
|
28438
|
+
// src/auth/gemini-oauth.ts
|
|
28353
28439
|
import { exec } from "child_process";
|
|
28354
28440
|
import { createHash as createHash2, randomBytes } from "crypto";
|
|
28355
28441
|
import { closeSync as closeSync2, existsSync as existsSync7, openSync as openSync2, readFileSync as readFileSync6, unlinkSync as unlinkSync2, writeSync as writeSync2 } from "fs";
|
|
@@ -28357,18 +28443,25 @@ import { createServer } from "http";
|
|
|
28357
28443
|
import { homedir as homedir9 } from "os";
|
|
28358
28444
|
import { join as join9 } from "path";
|
|
28359
28445
|
import { promisify } from "util";
|
|
28446
|
+
function buildCodeAssistUserAgent(model) {
|
|
28447
|
+
if (USE_LEGACY_GEMINI_IDENTITY) {
|
|
28448
|
+
const modelSegment = model || "gemini-code-assist";
|
|
28449
|
+
return `GeminiCLI/0.5.6/${modelSegment} (${process.platform}; ${process.arch})`;
|
|
28450
|
+
}
|
|
28451
|
+
return `antigravity/cli/1.1.9 (aidev_client; os_type=${process.platform}; arch=${process.arch}; auth_method=consumer)`;
|
|
28452
|
+
}
|
|
28360
28453
|
|
|
28361
|
-
class
|
|
28454
|
+
class GeminiOAuth {
|
|
28362
28455
|
static instance = null;
|
|
28363
28456
|
credentials = null;
|
|
28364
28457
|
refreshPromise = null;
|
|
28365
28458
|
tokenRefreshMargin = 5 * 60 * 1000;
|
|
28366
28459
|
oauthState = null;
|
|
28367
28460
|
static getInstance() {
|
|
28368
|
-
if (!
|
|
28369
|
-
|
|
28461
|
+
if (!GeminiOAuth.instance) {
|
|
28462
|
+
GeminiOAuth.instance = new GeminiOAuth;
|
|
28370
28463
|
}
|
|
28371
|
-
return
|
|
28464
|
+
return GeminiOAuth.instance;
|
|
28372
28465
|
}
|
|
28373
28466
|
constructor() {
|
|
28374
28467
|
this.credentials = this.loadCredentials();
|
|
@@ -28382,60 +28475,55 @@ class CodexOAuth {
|
|
|
28382
28475
|
}
|
|
28383
28476
|
getCredentialsPath() {
|
|
28384
28477
|
const claudishDir = join9(homedir9(), ".claudish");
|
|
28385
|
-
return join9(claudishDir, "
|
|
28478
|
+
return join9(claudishDir, "gemini-oauth.json");
|
|
28386
28479
|
}
|
|
28387
28480
|
async login() {
|
|
28388
|
-
log("[
|
|
28481
|
+
log("[GeminiOAuth] Starting OAuth login flow");
|
|
28389
28482
|
const codeVerifier = this.generateCodeVerifier();
|
|
28390
28483
|
const codeChallenge = await this.generateCodeChallenge(codeVerifier);
|
|
28391
28484
|
this.oauthState = randomBytes(32).toString("base64url");
|
|
28392
28485
|
const { authCode, redirectUri } = await this.startCallbackServer(codeChallenge, this.oauthState);
|
|
28393
28486
|
const tokens = await this.exchangeCodeForTokens(authCode, codeVerifier, redirectUri);
|
|
28394
|
-
const accountId = tokens.id_token ? this.extractAccountId(tokens.id_token) : undefined;
|
|
28395
28487
|
const credentials = {
|
|
28396
28488
|
access_token: tokens.access_token,
|
|
28397
28489
|
refresh_token: tokens.refresh_token,
|
|
28398
|
-
expires_at: Date.now() + tokens.expires_in * 1000
|
|
28399
|
-
account_id: accountId
|
|
28490
|
+
expires_at: Date.now() + tokens.expires_in * 1000
|
|
28400
28491
|
};
|
|
28401
28492
|
this.saveCredentials(credentials);
|
|
28402
28493
|
this.credentials = credentials;
|
|
28403
28494
|
this.oauthState = null;
|
|
28404
|
-
log("[
|
|
28405
|
-
if (accountId) {
|
|
28406
|
-
log(`[CodexOAuth] Account ID: ${accountId}`);
|
|
28407
|
-
}
|
|
28495
|
+
log("[GeminiOAuth] Login successful");
|
|
28408
28496
|
}
|
|
28409
28497
|
async logout() {
|
|
28410
28498
|
const credPath = this.getCredentialsPath();
|
|
28411
28499
|
if (existsSync7(credPath)) {
|
|
28412
28500
|
unlinkSync2(credPath);
|
|
28413
|
-
log("[
|
|
28501
|
+
log("[GeminiOAuth] Credentials deleted");
|
|
28414
28502
|
}
|
|
28415
28503
|
this.credentials = null;
|
|
28416
28504
|
}
|
|
28417
28505
|
async getAccessToken() {
|
|
28418
28506
|
if (this.refreshPromise) {
|
|
28419
|
-
log("[
|
|
28507
|
+
log("[GeminiOAuth] Waiting for in-progress refresh");
|
|
28420
28508
|
return this.refreshPromise;
|
|
28421
28509
|
}
|
|
28422
28510
|
if (!this.credentials) {
|
|
28423
|
-
throw new Error("No
|
|
28511
|
+
throw new Error("No Gemini OAuth credentials found. Please run `claudish login gemini` first.");
|
|
28424
28512
|
}
|
|
28425
28513
|
if (this.isTokenValid()) {
|
|
28426
28514
|
return this.credentials.access_token;
|
|
28427
28515
|
}
|
|
28428
|
-
this.refreshPromise = this.doRefreshToken()
|
|
28516
|
+
this.refreshPromise = this.doRefreshToken();
|
|
28517
|
+
try {
|
|
28518
|
+
const token = await this.refreshPromise;
|
|
28519
|
+
return token;
|
|
28520
|
+
} finally {
|
|
28429
28521
|
this.refreshPromise = null;
|
|
28430
|
-
}
|
|
28431
|
-
return this.refreshPromise;
|
|
28432
|
-
}
|
|
28433
|
-
getAccountId() {
|
|
28434
|
-
return this.credentials?.account_id;
|
|
28522
|
+
}
|
|
28435
28523
|
}
|
|
28436
28524
|
async refreshToken() {
|
|
28437
28525
|
if (!this.credentials) {
|
|
28438
|
-
throw new Error("No
|
|
28526
|
+
throw new Error("No Gemini OAuth credentials found. Please run `claudish login gemini` first.");
|
|
28439
28527
|
}
|
|
28440
28528
|
await this.doRefreshToken();
|
|
28441
28529
|
}
|
|
@@ -28446,19 +28534,20 @@ class CodexOAuth {
|
|
|
28446
28534
|
}
|
|
28447
28535
|
async doRefreshToken() {
|
|
28448
28536
|
if (!this.credentials) {
|
|
28449
|
-
throw new Error("No
|
|
28537
|
+
throw new Error("No Gemini OAuth credentials found. Please run `claudish login gemini` first.");
|
|
28450
28538
|
}
|
|
28451
|
-
log("[
|
|
28539
|
+
log("[GeminiOAuth] Refreshing access token");
|
|
28452
28540
|
try {
|
|
28453
28541
|
const response = await fetch(OAUTH_CONFIG.tokenUrl, {
|
|
28454
28542
|
method: "POST",
|
|
28455
28543
|
headers: {
|
|
28456
|
-
"Content-Type": "application/
|
|
28544
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
28457
28545
|
},
|
|
28458
|
-
body:
|
|
28546
|
+
body: new URLSearchParams({
|
|
28459
28547
|
grant_type: "refresh_token",
|
|
28460
28548
|
refresh_token: this.credentials.refresh_token,
|
|
28461
|
-
client_id: OAUTH_CONFIG.clientId
|
|
28549
|
+
client_id: OAUTH_CONFIG.clientId,
|
|
28550
|
+
client_secret: OAUTH_CONFIG.clientSecret
|
|
28462
28551
|
})
|
|
28463
28552
|
});
|
|
28464
28553
|
if (!response.ok) {
|
|
@@ -28466,20 +28555,18 @@ class CodexOAuth {
|
|
|
28466
28555
|
throw new Error(`Token refresh failed: ${response.status} - ${errorText}`);
|
|
28467
28556
|
}
|
|
28468
28557
|
const tokens = await response.json();
|
|
28469
|
-
const accountId = tokens.id_token ? this.extractAccountId(tokens.id_token) : this.credentials.account_id;
|
|
28470
28558
|
const updatedCredentials = {
|
|
28471
28559
|
access_token: tokens.access_token,
|
|
28472
28560
|
refresh_token: tokens.refresh_token || this.credentials.refresh_token,
|
|
28473
|
-
expires_at: Date.now() + tokens.expires_in * 1000
|
|
28474
|
-
account_id: accountId
|
|
28561
|
+
expires_at: Date.now() + tokens.expires_in * 1000
|
|
28475
28562
|
};
|
|
28476
28563
|
this.saveCredentials(updatedCredentials);
|
|
28477
28564
|
this.credentials = updatedCredentials;
|
|
28478
|
-
log(`[
|
|
28565
|
+
log(`[GeminiOAuth] Token refreshed, valid until ${new Date(updatedCredentials.expires_at).toISOString()}`);
|
|
28479
28566
|
return updatedCredentials.access_token;
|
|
28480
28567
|
} catch (e) {
|
|
28481
|
-
log(`[
|
|
28482
|
-
throw new Error(`OAuth credentials invalid. Please run \`claudish login
|
|
28568
|
+
log(`[GeminiOAuth] Refresh failed: ${e.message}`);
|
|
28569
|
+
throw new Error(`OAuth credentials invalid. Please run \`claudish login gemini\` again.
|
|
28483
28570
|
|
|
28484
28571
|
Details: ${e.message}`);
|
|
28485
28572
|
}
|
|
@@ -28493,13 +28580,13 @@ Details: ${e.message}`);
|
|
|
28493
28580
|
const data = readFileSync6(credPath, "utf-8");
|
|
28494
28581
|
const credentials = JSON.parse(data);
|
|
28495
28582
|
if (!credentials.access_token || !credentials.refresh_token || !credentials.expires_at) {
|
|
28496
|
-
log("[
|
|
28583
|
+
log("[GeminiOAuth] Invalid credentials file structure");
|
|
28497
28584
|
return null;
|
|
28498
28585
|
}
|
|
28499
|
-
log("[
|
|
28586
|
+
log("[GeminiOAuth] Loaded credentials from file");
|
|
28500
28587
|
return credentials;
|
|
28501
28588
|
} catch (e) {
|
|
28502
|
-
log(`[
|
|
28589
|
+
log(`[GeminiOAuth] Failed to load credentials: ${e.message}`);
|
|
28503
28590
|
return null;
|
|
28504
28591
|
}
|
|
28505
28592
|
}
|
|
@@ -28517,7 +28604,7 @@ Details: ${e.message}`);
|
|
|
28517
28604
|
} finally {
|
|
28518
28605
|
closeSync2(fd);
|
|
28519
28606
|
}
|
|
28520
|
-
log(`[
|
|
28607
|
+
log(`[GeminiOAuth] Credentials saved to ${credPath}`);
|
|
28521
28608
|
}
|
|
28522
28609
|
generateCodeVerifier() {
|
|
28523
28610
|
return randomBytes(64).toString("base64url");
|
|
@@ -28526,46 +28613,26 @@ Details: ${e.message}`);
|
|
|
28526
28613
|
const hash2 = createHash2("sha256").update(verifier).digest("base64url");
|
|
28527
28614
|
return hash2;
|
|
28528
28615
|
}
|
|
28529
|
-
extractAccountId(idToken) {
|
|
28530
|
-
try {
|
|
28531
|
-
const parts = idToken.split(".");
|
|
28532
|
-
if (parts.length !== 3)
|
|
28533
|
-
return;
|
|
28534
|
-
const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf-8"));
|
|
28535
|
-
const authClaim = payload["https://api.openai.com/auth"];
|
|
28536
|
-
const accountId = authClaim?.chatgpt_account_id || payload.chatgpt_account_id || authClaim?.user_id;
|
|
28537
|
-
if (accountId) {
|
|
28538
|
-
log(`[CodexOAuth] Extracted account ID from id_token: ${accountId}`);
|
|
28539
|
-
return accountId;
|
|
28540
|
-
}
|
|
28541
|
-
return;
|
|
28542
|
-
} catch (e) {
|
|
28543
|
-
log(`[CodexOAuth] Failed to extract account ID from id_token: ${e.message}`);
|
|
28544
|
-
return;
|
|
28545
|
-
}
|
|
28546
|
-
}
|
|
28547
28616
|
buildAuthUrl(codeChallenge, state, redirectUri) {
|
|
28548
|
-
const
|
|
28549
|
-
|
|
28550
|
-
|
|
28551
|
-
|
|
28552
|
-
|
|
28553
|
-
|
|
28554
|
-
|
|
28555
|
-
"
|
|
28556
|
-
"
|
|
28557
|
-
|
|
28558
|
-
|
|
28559
|
-
|
|
28560
|
-
].join("&");
|
|
28561
|
-
return `${OAUTH_CONFIG.authUrl}?${params}`;
|
|
28617
|
+
const params = new URLSearchParams({
|
|
28618
|
+
client_id: OAUTH_CONFIG.clientId,
|
|
28619
|
+
redirect_uri: redirectUri,
|
|
28620
|
+
response_type: "code",
|
|
28621
|
+
scope: OAUTH_CONFIG.scopes.join(" "),
|
|
28622
|
+
code_challenge: codeChallenge,
|
|
28623
|
+
code_challenge_method: "S256",
|
|
28624
|
+
access_type: "offline",
|
|
28625
|
+
prompt: "consent",
|
|
28626
|
+
state
|
|
28627
|
+
});
|
|
28628
|
+
return `${OAUTH_CONFIG.authUrl}?${params.toString()}`;
|
|
28562
28629
|
}
|
|
28563
28630
|
async startCallbackServer(codeChallenge, state) {
|
|
28564
28631
|
return new Promise((resolve, reject) => {
|
|
28565
28632
|
let redirectUri = "";
|
|
28566
28633
|
const server = createServer((req, res) => {
|
|
28567
|
-
const url2 = new URL(req.url, redirectUri.replace("/
|
|
28568
|
-
if (url2.pathname === "/
|
|
28634
|
+
const url2 = new URL(req.url, redirectUri.replace("/callback", ""));
|
|
28635
|
+
if (url2.pathname === "/callback") {
|
|
28569
28636
|
const code = url2.searchParams.get("code");
|
|
28570
28637
|
const callbackState = url2.searchParams.get("state");
|
|
28571
28638
|
const error46 = url2.searchParams.get("error");
|
|
@@ -28630,15 +28697,15 @@ Details: ${e.message}`);
|
|
|
28630
28697
|
res.end("Not found");
|
|
28631
28698
|
}
|
|
28632
28699
|
});
|
|
28633
|
-
server.listen(
|
|
28700
|
+
server.listen(0, () => {
|
|
28634
28701
|
const address = server.address();
|
|
28635
28702
|
if (!address || typeof address === "string") {
|
|
28636
28703
|
reject(new Error("Failed to get server port"));
|
|
28637
28704
|
return;
|
|
28638
28705
|
}
|
|
28639
28706
|
const port = address.port;
|
|
28640
|
-
redirectUri = `http://localhost:${port}/
|
|
28641
|
-
log(`[
|
|
28707
|
+
redirectUri = `http://localhost:${port}/callback`;
|
|
28708
|
+
log(`[GeminiOAuth] Callback server started on http://localhost:${port}`);
|
|
28642
28709
|
const authUrl = this.buildAuthUrl(codeChallenge, state, redirectUri);
|
|
28643
28710
|
this.openBrowser(authUrl);
|
|
28644
28711
|
});
|
|
@@ -28652,7 +28719,7 @@ Details: ${e.message}`);
|
|
|
28652
28719
|
});
|
|
28653
28720
|
}
|
|
28654
28721
|
async exchangeCodeForTokens(code, verifier, redirectUri) {
|
|
28655
|
-
log("[
|
|
28722
|
+
log("[GeminiOAuth] Exchanging auth code for tokens");
|
|
28656
28723
|
try {
|
|
28657
28724
|
const response = await fetch(OAUTH_CONFIG.tokenUrl, {
|
|
28658
28725
|
method: "POST",
|
|
@@ -28664,6 +28731,7 @@ Details: ${e.message}`);
|
|
|
28664
28731
|
code,
|
|
28665
28732
|
redirect_uri: redirectUri,
|
|
28666
28733
|
client_id: OAUTH_CONFIG.clientId,
|
|
28734
|
+
client_secret: OAUTH_CONFIG.clientSecret,
|
|
28667
28735
|
code_verifier: verifier
|
|
28668
28736
|
})
|
|
28669
28737
|
});
|
|
@@ -28677,7 +28745,7 @@ Details: ${e.message}`);
|
|
|
28677
28745
|
}
|
|
28678
28746
|
return tokens;
|
|
28679
28747
|
} catch (e) {
|
|
28680
|
-
throw new Error(`Failed to authenticate with
|
|
28748
|
+
throw new Error(`Failed to authenticate with Google OAuth: ${e.message}`);
|
|
28681
28749
|
}
|
|
28682
28750
|
}
|
|
28683
28751
|
async openBrowser(url2) {
|
|
@@ -28691,7 +28759,7 @@ Details: ${e.message}`);
|
|
|
28691
28759
|
await execAsync(`xdg-open "${url2}"`);
|
|
28692
28760
|
}
|
|
28693
28761
|
console.log(`
|
|
28694
|
-
Opening browser for
|
|
28762
|
+
Opening browser for authentication...`);
|
|
28695
28763
|
console.log(`If the browser doesn't open, visit this URL:
|
|
28696
28764
|
${url2}
|
|
28697
28765
|
`);
|
|
@@ -28703,136 +28771,1006 @@ Please open this URL in your browser to authenticate:`);
|
|
|
28703
28771
|
}
|
|
28704
28772
|
}
|
|
28705
28773
|
}
|
|
28706
|
-
function
|
|
28707
|
-
|
|
28774
|
+
function reloadGeminiCredentials() {
|
|
28775
|
+
GeminiOAuth.getInstance().reloadCredentials();
|
|
28776
|
+
resetGeminiUserCache();
|
|
28708
28777
|
}
|
|
28709
|
-
|
|
28710
|
-
|
|
28778
|
+
function rankCodeAssistModel(model) {
|
|
28779
|
+
const lower = model.toLowerCase();
|
|
28780
|
+
let tier;
|
|
28781
|
+
if (lower.includes("pro"))
|
|
28782
|
+
tier = 0;
|
|
28783
|
+
else if (lower.includes("lite"))
|
|
28784
|
+
tier = 2;
|
|
28785
|
+
else if (lower.includes("flash"))
|
|
28786
|
+
tier = 1;
|
|
28787
|
+
else
|
|
28788
|
+
tier = 3;
|
|
28789
|
+
const vMatch = lower.match(/^gemini-(\d+(?:\.\d+)?)(?![\d.])/);
|
|
28790
|
+
const version2 = vMatch ? Number.parseFloat(vMatch[1]) : 0;
|
|
28791
|
+
return tier * 1000 - version2;
|
|
28792
|
+
}
|
|
28793
|
+
async function getServedCodeAssistModels(accessToken, projectId, opts) {
|
|
28794
|
+
const now = Date.now();
|
|
28795
|
+
if (!opts?.force && servedModelsCache && now - servedModelsCacheAt < SERVED_MODELS_TTL_MS) {
|
|
28796
|
+
return servedModelsCache;
|
|
28797
|
+
}
|
|
28798
|
+
try {
|
|
28799
|
+
const data = await retrieveUserQuota(accessToken, projectId);
|
|
28800
|
+
const ids = (data?.buckets ?? []).map((b) => b.modelId).filter((m) => typeof m === "string" && m.length > 0);
|
|
28801
|
+
if (ids.length > 0) {
|
|
28802
|
+
const sorted = ids.slice().sort((a, b) => rankCodeAssistModel(a) - rankCodeAssistModel(b));
|
|
28803
|
+
servedModelsCache = sorted;
|
|
28804
|
+
servedModelsCacheAt = now;
|
|
28805
|
+
return sorted;
|
|
28806
|
+
}
|
|
28807
|
+
} catch (err) {
|
|
28808
|
+
log(`[GeminiOAuth] getServedCodeAssistModels error: ${err}`);
|
|
28809
|
+
}
|
|
28810
|
+
if (servedModelsCache)
|
|
28811
|
+
return servedModelsCache;
|
|
28812
|
+
return CODE_ASSIST_FALLBACK_CHAIN.slice().sort((a, b) => rankCodeAssistModel(a) - rankCodeAssistModel(b));
|
|
28813
|
+
}
|
|
28814
|
+
async function getValidAccessToken() {
|
|
28815
|
+
const oauth = GeminiOAuth.getInstance();
|
|
28816
|
+
return oauth.getAccessToken();
|
|
28817
|
+
}
|
|
28818
|
+
function resetGeminiUserCache() {
|
|
28819
|
+
cachedProjectId = null;
|
|
28820
|
+
cachedTierId = null;
|
|
28821
|
+
cachedTierName = null;
|
|
28822
|
+
cachedSetupError = null;
|
|
28823
|
+
}
|
|
28824
|
+
function getGeminiTierDisplayName() {
|
|
28825
|
+
if (!cachedTierId)
|
|
28826
|
+
return "GeminiCA";
|
|
28827
|
+
return TIER_SHORT_NAMES[cachedTierId] || cachedTierId.replace(/-tier$/, "");
|
|
28828
|
+
}
|
|
28829
|
+
function getGeminiTierFullName() {
|
|
28830
|
+
if (cachedTierName)
|
|
28831
|
+
return cachedTierName;
|
|
28832
|
+
return getGeminiTierDisplayName();
|
|
28833
|
+
}
|
|
28834
|
+
function makeTerminalSetupError(message) {
|
|
28835
|
+
const err = new Error(message);
|
|
28836
|
+
err.terminal = true;
|
|
28837
|
+
return err;
|
|
28838
|
+
}
|
|
28839
|
+
function buildProjectRequiredError(tierId, chosenTier, loadRes) {
|
|
28840
|
+
const tierLabel = chosenTier?.name || chosenTier?.displayName || tierId;
|
|
28841
|
+
const lines = [
|
|
28842
|
+
`Gemini Code Assist requires a Google Cloud project for the "${tierLabel}" tier (${tierId}), and none is configured.`,
|
|
28843
|
+
"",
|
|
28844
|
+
"Set the project that holds your Code Assist license:",
|
|
28845
|
+
" export GOOGLE_CLOUD_PROJECT='your-project-id'"
|
|
28846
|
+
];
|
|
28847
|
+
const refused = loadRes.ineligibleTiers ?? [];
|
|
28848
|
+
if (refused.length > 0) {
|
|
28849
|
+
lines.push("", "Google refused the other tier(s) on this account:");
|
|
28850
|
+
for (const t of refused) {
|
|
28851
|
+
const name = t.tierName || t.tierId || "unknown tier";
|
|
28852
|
+
const code = t.reasonCode ? ` [${t.reasonCode}]` : "";
|
|
28853
|
+
lines.push(` \u2022 ${name}${code}`);
|
|
28854
|
+
if (t.reasonMessage)
|
|
28855
|
+
lines.push(` ${t.reasonMessage}`);
|
|
28856
|
+
}
|
|
28857
|
+
}
|
|
28858
|
+
lines.push("", "No project / no Code Assist seat? Use the direct Gemini API instead:", " export GEMINI_API_KEY='your-key' # https://aistudio.google.com/app/apikey", ' claudish --model google@gemini-2.5-pro "..."');
|
|
28859
|
+
return lines.join(`
|
|
28860
|
+
`);
|
|
28861
|
+
}
|
|
28862
|
+
async function setupGeminiUser(accessToken) {
|
|
28863
|
+
if (cachedProjectId && cachedTierId) {
|
|
28864
|
+
log(`[GeminiOAuth] Using cached project ID: ${cachedProjectId}, tier: ${cachedTierId}`);
|
|
28865
|
+
return { projectId: cachedProjectId, tierId: cachedTierId };
|
|
28866
|
+
}
|
|
28867
|
+
if (cachedSetupError) {
|
|
28868
|
+
log("[GeminiOAuth] Re-raising cached setup failure (no network retry)");
|
|
28869
|
+
throw makeTerminalSetupError(cachedSetupError);
|
|
28870
|
+
}
|
|
28871
|
+
const envProject = process.env.GOOGLE_CLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT_ID;
|
|
28872
|
+
log("[GeminiOAuth] Calling loadCodeAssist...");
|
|
28873
|
+
const loadRes = await callLoadCodeAssist(accessToken, envProject);
|
|
28874
|
+
log(`[GeminiOAuth] loadCodeAssist response: ${JSON.stringify(loadRes)}`);
|
|
28875
|
+
const resolvedTier = loadRes.paidTier?.id || (typeof loadRes.currentTier === "object" ? loadRes.currentTier?.id : loadRes.currentTier) || null;
|
|
28876
|
+
if ((loadRes.currentTier || loadRes.paidTier) && loadRes.cloudaicompanionProject) {
|
|
28877
|
+
const projectId2 = envProject || loadRes.cloudaicompanionProject;
|
|
28878
|
+
if (projectId2) {
|
|
28879
|
+
cachedProjectId = projectId2;
|
|
28880
|
+
cachedTierId = resolvedTier || "free-tier";
|
|
28881
|
+
cachedTierName = loadRes.paidTier?.name || null;
|
|
28882
|
+
log(`[GeminiOAuth] User already set up, project: ${projectId2}, tier: ${cachedTierId}`);
|
|
28883
|
+
return { projectId: projectId2, tierId: cachedTierId };
|
|
28884
|
+
}
|
|
28885
|
+
}
|
|
28886
|
+
const tierId = resolvedTier || loadRes.allowedTiers?.[0]?.id || "free-tier";
|
|
28887
|
+
const isFree = tierId === "free-tier";
|
|
28888
|
+
const onboardProject = isFree ? undefined : envProject;
|
|
28889
|
+
const chosenTier = loadRes.allowedTiers?.find((t) => t.id === tierId);
|
|
28890
|
+
if (!isFree && chosenTier?.userDefinedCloudaicompanionProject && !onboardProject) {
|
|
28891
|
+
cachedSetupError = buildProjectRequiredError(tierId, chosenTier, loadRes);
|
|
28892
|
+
throw makeTerminalSetupError(cachedSetupError);
|
|
28893
|
+
}
|
|
28894
|
+
const MAX_POLL_ATTEMPTS = 30;
|
|
28895
|
+
log(`[GeminiOAuth] Onboarding user to ${tierId}...`);
|
|
28896
|
+
let lro = await callOnboardUser(accessToken, tierId, onboardProject);
|
|
28897
|
+
log(`[GeminiOAuth] Initial onboardUser response: done=${lro.done}`);
|
|
28898
|
+
let attempts = 0;
|
|
28899
|
+
while (!lro.done && attempts < MAX_POLL_ATTEMPTS) {
|
|
28900
|
+
attempts++;
|
|
28901
|
+
log(`[GeminiOAuth] Polling onboardUser (attempt ${attempts}/${MAX_POLL_ATTEMPTS})...`);
|
|
28902
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
28903
|
+
lro = await callOnboardUser(accessToken, tierId, onboardProject);
|
|
28904
|
+
}
|
|
28905
|
+
if (!lro.done) {
|
|
28906
|
+
throw new Error(`Gemini onboarding timed out after ${MAX_POLL_ATTEMPTS * 2} seconds`);
|
|
28907
|
+
}
|
|
28908
|
+
if (lro.error) {
|
|
28909
|
+
throw new Error(`Gemini onboarding failed: ${JSON.stringify(lro.error)}`);
|
|
28910
|
+
}
|
|
28911
|
+
const projectId = lro.response?.cloudaicompanionProject?.id;
|
|
28912
|
+
if (!projectId) {
|
|
28913
|
+
if (envProject) {
|
|
28914
|
+
cachedProjectId = envProject;
|
|
28915
|
+
cachedTierId = tierId;
|
|
28916
|
+
return { projectId: envProject, tierId };
|
|
28917
|
+
}
|
|
28918
|
+
cachedSetupError = buildProjectRequiredError(tierId, chosenTier, loadRes);
|
|
28919
|
+
throw makeTerminalSetupError(cachedSetupError);
|
|
28920
|
+
}
|
|
28921
|
+
cachedProjectId = projectId;
|
|
28922
|
+
cachedTierId = tierId;
|
|
28923
|
+
log(`[GeminiOAuth] Onboarding complete, project: ${projectId}, tier: ${tierId}`);
|
|
28924
|
+
return { projectId, tierId };
|
|
28925
|
+
}
|
|
28926
|
+
async function callLoadCodeAssist(accessToken, projectId) {
|
|
28927
|
+
const metadata = GEMINI_IDENTITY_IS_ANTIGRAVITY ? { ideType: GEMINI_IDE_TYPE } : {
|
|
28928
|
+
pluginType: "GEMINI",
|
|
28929
|
+
ideType: GEMINI_IDE_TYPE,
|
|
28930
|
+
platform: "PLATFORM_UNSPECIFIED",
|
|
28931
|
+
duetProject: projectId
|
|
28932
|
+
};
|
|
28933
|
+
const res = await fetch(`${CODE_ASSIST_API_BASE}:loadCodeAssist`, {
|
|
28934
|
+
method: "POST",
|
|
28935
|
+
headers: {
|
|
28936
|
+
Authorization: `Bearer ${accessToken}`,
|
|
28937
|
+
"Content-Type": "application/json",
|
|
28938
|
+
"User-Agent": buildCodeAssistUserAgent()
|
|
28939
|
+
},
|
|
28940
|
+
body: JSON.stringify({ metadata, cloudaicompanionProject: projectId })
|
|
28941
|
+
});
|
|
28942
|
+
if (!res.ok) {
|
|
28943
|
+
throw new Error(`loadCodeAssist failed: ${res.status} ${await res.text()}`);
|
|
28944
|
+
}
|
|
28945
|
+
return await res.json();
|
|
28946
|
+
}
|
|
28947
|
+
async function callOnboardUser(accessToken, tierId, projectId) {
|
|
28948
|
+
const metadata = {
|
|
28949
|
+
pluginType: "GEMINI",
|
|
28950
|
+
ideType: GEMINI_IDE_TYPE,
|
|
28951
|
+
platform: "PLATFORM_UNSPECIFIED",
|
|
28952
|
+
duetProject: projectId
|
|
28953
|
+
};
|
|
28954
|
+
const res = await fetch(`${CODE_ASSIST_API_BASE}:onboardUser`, {
|
|
28955
|
+
method: "POST",
|
|
28956
|
+
headers: {
|
|
28957
|
+
Authorization: `Bearer ${accessToken}`,
|
|
28958
|
+
"Content-Type": "application/json",
|
|
28959
|
+
"User-Agent": buildCodeAssistUserAgent()
|
|
28960
|
+
},
|
|
28961
|
+
body: JSON.stringify({
|
|
28962
|
+
tierId,
|
|
28963
|
+
metadata,
|
|
28964
|
+
cloudaicompanionProject: projectId
|
|
28965
|
+
})
|
|
28966
|
+
});
|
|
28967
|
+
if (!res.ok) {
|
|
28968
|
+
throw new Error(`onboardUser failed: ${res.status} ${await res.text()}`);
|
|
28969
|
+
}
|
|
28970
|
+
return await res.json();
|
|
28971
|
+
}
|
|
28972
|
+
async function retrieveUserQuota(accessToken, projectId) {
|
|
28973
|
+
try {
|
|
28974
|
+
const res = await fetch(`${CODE_ASSIST_API_BASE}:retrieveUserQuota`, {
|
|
28975
|
+
method: "POST",
|
|
28976
|
+
headers: {
|
|
28977
|
+
Authorization: `Bearer ${accessToken}`,
|
|
28978
|
+
"Content-Type": "application/json",
|
|
28979
|
+
"User-Agent": `GeminiCLI/0.5.6/gemini-code-assist (${process.platform}; ${process.arch})`
|
|
28980
|
+
},
|
|
28981
|
+
body: JSON.stringify({ project: projectId })
|
|
28982
|
+
});
|
|
28983
|
+
if (!res.ok) {
|
|
28984
|
+
log(`[GeminiOAuth] retrieveUserQuota failed: ${res.status}`);
|
|
28985
|
+
return null;
|
|
28986
|
+
}
|
|
28987
|
+
return await res.json();
|
|
28988
|
+
} catch (err) {
|
|
28989
|
+
log(`[GeminiOAuth] retrieveUserQuota error: ${err}`);
|
|
28990
|
+
return null;
|
|
28991
|
+
}
|
|
28992
|
+
}
|
|
28993
|
+
function buildAntigravityUserAgent() {
|
|
28994
|
+
return `antigravity/cli/1.1.9 (aidev_client; os_type=${process.platform}; arch=${process.arch}; auth_method=consumer)`;
|
|
28995
|
+
}
|
|
28996
|
+
async function callLoadCodeAssistAntigravity(accessToken) {
|
|
28997
|
+
const res = await fetch(`${CODE_ASSIST_API_BASE}:loadCodeAssist`, {
|
|
28998
|
+
method: "POST",
|
|
28999
|
+
headers: {
|
|
29000
|
+
Authorization: `Bearer ${accessToken}`,
|
|
29001
|
+
"Content-Type": "application/json",
|
|
29002
|
+
"User-Agent": buildAntigravityUserAgent()
|
|
29003
|
+
},
|
|
29004
|
+
body: JSON.stringify({ metadata: { ideType: ANTIGRAVITY_IDE_TYPE } })
|
|
29005
|
+
});
|
|
29006
|
+
if (!res.ok) {
|
|
29007
|
+
throw new Error(`loadCodeAssist (antigravity) failed: ${res.status} ${await res.text()}`);
|
|
29008
|
+
}
|
|
29009
|
+
return await res.json();
|
|
29010
|
+
}
|
|
29011
|
+
async function setupAntigravityUser(accessToken) {
|
|
29012
|
+
if (cachedAgProjectId && cachedAgTierId) {
|
|
29013
|
+
return { projectId: cachedAgProjectId, tierId: cachedAgTierId };
|
|
29014
|
+
}
|
|
29015
|
+
const loadRes = await callLoadCodeAssistAntigravity(accessToken);
|
|
29016
|
+
log(`[Antigravity] loadCodeAssist response: ${JSON.stringify(loadRes)}`);
|
|
29017
|
+
const resolvedTier = loadRes.paidTier?.id || (typeof loadRes.currentTier === "object" ? loadRes.currentTier?.id : loadRes.currentTier) || "free-tier";
|
|
29018
|
+
const projectId = loadRes.cloudaicompanionProject;
|
|
29019
|
+
if (!projectId) {
|
|
29020
|
+
throw makeTerminalSetupError("Antigravity did not return a project for this account. Sign in to Antigravity " + "(the `agy` CLI) and try again, or use g@<model> with GEMINI_API_KEY " + "(get one at https://aistudio.google.com/app/apikey).");
|
|
29021
|
+
}
|
|
29022
|
+
cachedAgProjectId = projectId;
|
|
29023
|
+
cachedAgTierId = resolvedTier;
|
|
29024
|
+
cachedAgTierName = loadRes.paidTier?.name || null;
|
|
29025
|
+
log(`[Antigravity] User set up, project: ${projectId}, tier: ${resolvedTier}`);
|
|
29026
|
+
return { projectId, tierId: resolvedTier };
|
|
29027
|
+
}
|
|
29028
|
+
function getAntigravityTierDisplayName() {
|
|
29029
|
+
if (!cachedAgTierName && !cachedAgTierId)
|
|
29030
|
+
return "Antigravity";
|
|
29031
|
+
const id = cachedAgTierId || "";
|
|
29032
|
+
if (id.includes("ultra"))
|
|
29033
|
+
return "Antigravity Ultra";
|
|
29034
|
+
if (id.includes("pro"))
|
|
29035
|
+
return "Antigravity Pro";
|
|
29036
|
+
if (id === "free-tier")
|
|
29037
|
+
return "Antigravity Free";
|
|
29038
|
+
return cachedAgTierName || "Antigravity";
|
|
29039
|
+
}
|
|
29040
|
+
async function getServedAntigravityModels(accessToken, projectId, opts) {
|
|
29041
|
+
const now = Date.now();
|
|
29042
|
+
if (!opts?.force && agServedCache && now - agServedCacheAt < SERVED_MODELS_TTL_MS) {
|
|
29043
|
+
return agServedCache;
|
|
29044
|
+
}
|
|
29045
|
+
try {
|
|
29046
|
+
const res = await fetch(`${CODE_ASSIST_API_BASE}:fetchAvailableModels`, {
|
|
29047
|
+
method: "POST",
|
|
29048
|
+
headers: {
|
|
29049
|
+
Authorization: `Bearer ${accessToken}`,
|
|
29050
|
+
"Content-Type": "application/json",
|
|
29051
|
+
"User-Agent": buildAntigravityUserAgent()
|
|
29052
|
+
},
|
|
29053
|
+
body: JSON.stringify({ project: projectId })
|
|
29054
|
+
});
|
|
29055
|
+
if (res.ok) {
|
|
29056
|
+
const data = await res.json();
|
|
29057
|
+
const servedIds = data.models ? Object.keys(data.models) : [];
|
|
29058
|
+
const defaultId = typeof data.defaultAgentModelId === "string" ? data.defaultAgentModelId : null;
|
|
29059
|
+
if (servedIds.length > 0) {
|
|
29060
|
+
agServedCache = { servedIds, defaultId };
|
|
29061
|
+
agServedCacheAt = now;
|
|
29062
|
+
return agServedCache;
|
|
29063
|
+
}
|
|
29064
|
+
} else {
|
|
29065
|
+
log(`[Antigravity] fetchAvailableModels failed: ${res.status}`);
|
|
29066
|
+
}
|
|
29067
|
+
} catch (err) {
|
|
29068
|
+
log(`[Antigravity] fetchAvailableModels error: ${err}`);
|
|
29069
|
+
}
|
|
29070
|
+
if (agServedCache)
|
|
29071
|
+
return agServedCache;
|
|
29072
|
+
return { servedIds: [], defaultId: null };
|
|
29073
|
+
}
|
|
29074
|
+
var execAsync, getDefaultClientId = () => {
|
|
29075
|
+
const parts = [
|
|
29076
|
+
"681255809395",
|
|
29077
|
+
"oo8ft2oprdrnp9e3aqf6av3hmdib135j",
|
|
29078
|
+
"apps",
|
|
29079
|
+
"googleusercontent",
|
|
29080
|
+
"com"
|
|
29081
|
+
];
|
|
29082
|
+
return `${parts[0]}-${parts[1]}.${parts[2]}.${parts[3]}.${parts[4]}`;
|
|
29083
|
+
}, getDefaultClientSecret = () => {
|
|
29084
|
+
const p = ["GOCSPX", "4uHgMPm", "1o7Sk", "geV6Cu5clXFsxl"];
|
|
29085
|
+
return `${p[0]}-${p[1]}-${p[2]}-${p[3]}`;
|
|
29086
|
+
}, OAUTH_CONFIG, USE_ANTIGRAVITY_GEMINI_IDENTITY, USE_LEGACY_GEMINI_IDENTITY, GEMINI_IDE_TYPE, GEMINI_IDENTITY_IS_ANTIGRAVITY, CODE_ASSIST_API_BASE = "https://cloudcode-pa.googleapis.com/v1internal", CODE_ASSIST_FALLBACK_CHAIN, servedModelsCache = null, servedModelsCacheAt = 0, SERVED_MODELS_TTL_MS, cachedProjectId = null, cachedTierId = null, cachedTierName = null, cachedSetupError = null, TIER_SHORT_NAMES, ANTIGRAVITY_IDE_TYPE = "ANTIGRAVITY", cachedAgProjectId = null, cachedAgTierId = null, cachedAgTierName = null, agServedCache = null, agServedCacheAt = 0;
|
|
29087
|
+
var init_gemini_oauth = __esm(() => {
|
|
28711
29088
|
init_logger();
|
|
28712
29089
|
execAsync = promisify(exec);
|
|
28713
29090
|
OAUTH_CONFIG = {
|
|
28714
|
-
clientId:
|
|
28715
|
-
|
|
28716
|
-
|
|
28717
|
-
|
|
29091
|
+
clientId: process.env.GEMINI_CLIENT_ID || getDefaultClientId(),
|
|
29092
|
+
clientSecret: process.env.GEMINI_CLIENT_SECRET || getDefaultClientSecret(),
|
|
29093
|
+
authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
29094
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
29095
|
+
scopes: [
|
|
29096
|
+
"https://www.googleapis.com/auth/cloud-platform",
|
|
29097
|
+
"https://www.googleapis.com/auth/userinfo.email",
|
|
29098
|
+
"https://www.googleapis.com/auth/userinfo.profile"
|
|
29099
|
+
]
|
|
29100
|
+
};
|
|
29101
|
+
USE_ANTIGRAVITY_GEMINI_IDENTITY = process.env.CLAUDISH_GEMINI_ANTIGRAVITY === "1";
|
|
29102
|
+
USE_LEGACY_GEMINI_IDENTITY = !USE_ANTIGRAVITY_GEMINI_IDENTITY;
|
|
29103
|
+
GEMINI_IDE_TYPE = USE_LEGACY_GEMINI_IDENTITY ? "GEMINI_CLI" : "ANTIGRAVITY";
|
|
29104
|
+
GEMINI_IDENTITY_IS_ANTIGRAVITY = !USE_LEGACY_GEMINI_IDENTITY;
|
|
29105
|
+
CODE_ASSIST_FALLBACK_CHAIN = [
|
|
29106
|
+
"gemini-2.5-pro",
|
|
29107
|
+
"gemini-2.5-flash",
|
|
29108
|
+
"gemini-2.5-flash-lite",
|
|
29109
|
+
"gemini-3.1-flash-lite"
|
|
29110
|
+
];
|
|
29111
|
+
SERVED_MODELS_TTL_MS = 10 * 60 * 1000;
|
|
29112
|
+
TIER_SHORT_NAMES = {
|
|
29113
|
+
"free-tier": "GeminiCA Free",
|
|
29114
|
+
"standard-tier": "GeminiCA Std",
|
|
29115
|
+
"g1-pro-tier": "GeminiCA Pro",
|
|
29116
|
+
"legacy-tier": "GeminiCA Legacy"
|
|
28718
29117
|
};
|
|
28719
29118
|
});
|
|
28720
29119
|
|
|
28721
|
-
// src/
|
|
28722
|
-
class
|
|
28723
|
-
|
|
28724
|
-
|
|
28725
|
-
|
|
28726
|
-
|
|
28727
|
-
|
|
28728
|
-
|
|
28729
|
-
|
|
28730
|
-
|
|
28731
|
-
|
|
29120
|
+
// src/handlers/shared/gemini-queue.ts
|
|
29121
|
+
class GeminiRequestQueue {
|
|
29122
|
+
static instance = null;
|
|
29123
|
+
queue = [];
|
|
29124
|
+
processing = false;
|
|
29125
|
+
minDelayMs = 1000;
|
|
29126
|
+
lastRequestTime = 0;
|
|
29127
|
+
consecutiveErrors = 0;
|
|
29128
|
+
totalProcessed = 0;
|
|
29129
|
+
totalErrors = 0;
|
|
29130
|
+
baseDelayMs = 1000;
|
|
29131
|
+
maxDelayMs = 1e4;
|
|
29132
|
+
maxQueueSize = 100;
|
|
29133
|
+
constructor() {
|
|
29134
|
+
log("[GeminiQueue] Queue initialized with minDelay=1000ms, maxQueueSize=100");
|
|
28732
29135
|
}
|
|
28733
|
-
|
|
28734
|
-
|
|
29136
|
+
static getInstance() {
|
|
29137
|
+
if (!GeminiRequestQueue.instance) {
|
|
29138
|
+
GeminiRequestQueue.instance = new GeminiRequestQueue;
|
|
29139
|
+
}
|
|
29140
|
+
return GeminiRequestQueue.instance;
|
|
28735
29141
|
}
|
|
28736
|
-
|
|
28737
|
-
this.
|
|
28738
|
-
|
|
29142
|
+
async enqueue(fetchFn) {
|
|
29143
|
+
if (this.queue.length >= this.maxQueueSize) {
|
|
29144
|
+
log(`[GeminiQueue] Queue full (${this.queue.length}/${this.maxQueueSize}), rejecting request`);
|
|
29145
|
+
throw new Error("Gemini request queue full. Please retry later.");
|
|
29146
|
+
}
|
|
29147
|
+
return new Promise((resolve, reject) => {
|
|
29148
|
+
const queuedRequest = {
|
|
29149
|
+
fetchFn,
|
|
29150
|
+
resolve,
|
|
29151
|
+
reject
|
|
29152
|
+
};
|
|
29153
|
+
this.queue.push(queuedRequest);
|
|
29154
|
+
log(`[GeminiQueue] Request enqueued (queue length: ${this.queue.length})`);
|
|
29155
|
+
if (!this.processing) {
|
|
29156
|
+
this.processQueue();
|
|
29157
|
+
}
|
|
29158
|
+
});
|
|
28739
29159
|
}
|
|
28740
|
-
async
|
|
28741
|
-
if (
|
|
29160
|
+
async processQueue() {
|
|
29161
|
+
if (this.processing) {
|
|
29162
|
+
return;
|
|
29163
|
+
}
|
|
29164
|
+
this.processing = true;
|
|
29165
|
+
log("[GeminiQueue] Worker started");
|
|
29166
|
+
while (this.queue.length > 0) {
|
|
29167
|
+
const request = this.queue.shift();
|
|
29168
|
+
if (!request)
|
|
29169
|
+
break;
|
|
29170
|
+
log(`[GeminiQueue] Processing request (${this.queue.length} remaining in queue)`);
|
|
28742
29171
|
try {
|
|
28743
|
-
|
|
28744
|
-
|
|
28745
|
-
|
|
28746
|
-
if (
|
|
28747
|
-
|
|
29172
|
+
await this.waitForNextSlot();
|
|
29173
|
+
const response = await request.fetchFn();
|
|
29174
|
+
this.lastRequestTime = Date.now();
|
|
29175
|
+
if (response.status === 429) {
|
|
29176
|
+
this.totalErrors++;
|
|
29177
|
+
const errorText = await response.clone().text();
|
|
29178
|
+
this.handleRateLimitResponse(errorText);
|
|
29179
|
+
log(`[GeminiQueue] Rate limit hit (429), adjusted delay to ${this.minDelayMs}ms`);
|
|
29180
|
+
} else {
|
|
29181
|
+
this.handleSuccessResponse();
|
|
28748
29182
|
}
|
|
28749
|
-
|
|
29183
|
+
this.totalProcessed++;
|
|
29184
|
+
request.resolve(response);
|
|
29185
|
+
} catch (error46) {
|
|
29186
|
+
this.totalErrors++;
|
|
29187
|
+
log(`[GeminiQueue] Request failed with error: ${error46}`);
|
|
29188
|
+
request.reject(error46 instanceof Error ? error46 : new Error(String(error46)));
|
|
28750
29189
|
}
|
|
28751
29190
|
}
|
|
28752
|
-
|
|
29191
|
+
this.processing = false;
|
|
29192
|
+
log("[GeminiQueue] Worker stopped (queue empty)");
|
|
28753
29193
|
}
|
|
28754
|
-
async
|
|
28755
|
-
|
|
29194
|
+
async waitForNextSlot() {
|
|
29195
|
+
const now = Date.now();
|
|
29196
|
+
const timeSinceLastRequest = now - this.lastRequestTime;
|
|
29197
|
+
let delayMs = this.minDelayMs;
|
|
29198
|
+
if (this.consecutiveErrors > 0) {
|
|
29199
|
+
const backoffMultiplier = 1 + this.consecutiveErrors * 0.5;
|
|
29200
|
+
delayMs = Math.min(this.minDelayMs * backoffMultiplier, this.maxDelayMs);
|
|
29201
|
+
log(`[GeminiQueue] Applying backoff (${this.consecutiveErrors} errors): ${delayMs}ms`);
|
|
29202
|
+
}
|
|
29203
|
+
if (timeSinceLastRequest < delayMs) {
|
|
29204
|
+
const waitMs = delayMs - timeSinceLastRequest;
|
|
29205
|
+
log(`[GeminiQueue] Waiting ${waitMs}ms before next request`);
|
|
29206
|
+
await new Promise((resolve) => setTimeout(resolve, waitMs));
|
|
29207
|
+
}
|
|
28756
29208
|
}
|
|
28757
|
-
|
|
28758
|
-
|
|
29209
|
+
handleRateLimitResponse(errorText) {
|
|
29210
|
+
this.consecutiveErrors++;
|
|
29211
|
+
try {
|
|
29212
|
+
const errorData = JSON.parse(errorText);
|
|
29213
|
+
const quotaDetail = errorData?.error?.details?.find((d) => d.quotaResetDelay);
|
|
29214
|
+
if (quotaDetail?.quotaResetDelay) {
|
|
29215
|
+
const delayStr = quotaDetail.quotaResetDelay;
|
|
29216
|
+
const match = delayStr.match(/(\d+(?:\.\d+)?)/);
|
|
29217
|
+
if (match) {
|
|
29218
|
+
const delaySeconds = Number.parseFloat(match[1]);
|
|
29219
|
+
const suggestedDelayMs = Math.ceil(delaySeconds * 1000);
|
|
29220
|
+
this.minDelayMs = Math.max(suggestedDelayMs, this.minDelayMs, this.baseDelayMs);
|
|
29221
|
+
this.minDelayMs = Math.min(this.minDelayMs, this.maxDelayMs);
|
|
29222
|
+
log(`[GeminiQueue] Parsed quotaResetDelay: ${delayStr} (${suggestedDelayMs}ms), ` + `new minDelay: ${this.minDelayMs}ms`);
|
|
29223
|
+
}
|
|
29224
|
+
}
|
|
29225
|
+
} catch {
|
|
29226
|
+
log("[GeminiQueue] Failed to parse rate limit response, using backoff");
|
|
29227
|
+
}
|
|
29228
|
+
const backoffMultiplier = 1 + this.consecutiveErrors * 0.5;
|
|
29229
|
+
this.minDelayMs = Math.min(this.baseDelayMs * backoffMultiplier, this.maxDelayMs);
|
|
29230
|
+
}
|
|
29231
|
+
handleSuccessResponse() {
|
|
29232
|
+
if (this.consecutiveErrors > 0) {
|
|
29233
|
+
log(`[GeminiQueue] Success after ${this.consecutiveErrors} errors, resetting counter`);
|
|
29234
|
+
this.consecutiveErrors = 0;
|
|
29235
|
+
}
|
|
29236
|
+
if (this.minDelayMs > this.baseDelayMs) {
|
|
29237
|
+
this.minDelayMs = Math.max(this.baseDelayMs, this.minDelayMs * 0.9);
|
|
29238
|
+
log(`[GeminiQueue] Reducing delay to ${this.minDelayMs}ms`);
|
|
29239
|
+
}
|
|
29240
|
+
}
|
|
29241
|
+
getStats() {
|
|
29242
|
+
return {
|
|
29243
|
+
queueLength: this.queue.length,
|
|
29244
|
+
processing: this.processing,
|
|
29245
|
+
consecutiveErrors: this.consecutiveErrors,
|
|
29246
|
+
currentDelayMs: this.minDelayMs,
|
|
29247
|
+
totalProcessed: this.totalProcessed,
|
|
29248
|
+
totalErrors: this.totalErrors
|
|
29249
|
+
};
|
|
28759
29250
|
}
|
|
28760
29251
|
}
|
|
29252
|
+
var init_gemini_queue = __esm(() => {
|
|
29253
|
+
init_logger();
|
|
29254
|
+
});
|
|
28761
29255
|
|
|
28762
|
-
// src/
|
|
28763
|
-
|
|
28764
|
-
|
|
28765
|
-
|
|
28766
|
-
|
|
28767
|
-
|
|
28768
|
-
|
|
28769
|
-
|
|
28770
|
-
if (
|
|
28771
|
-
|
|
28772
|
-
|
|
28773
|
-
|
|
29256
|
+
// src/providers/transport/antigravity.ts
|
|
29257
|
+
import { randomUUID } from "crypto";
|
|
29258
|
+
function rankReasoningSuffix(suffix) {
|
|
29259
|
+
const rank = REASONING_TIER_RANK[suffix.toLowerCase()];
|
|
29260
|
+
return rank === undefined ? Number.MAX_SAFE_INTEGER : rank;
|
|
29261
|
+
}
|
|
29262
|
+
function resolveAntigravityModelId(requested, servedIds, defaultId) {
|
|
29263
|
+
const req = requested.trim();
|
|
29264
|
+
if (servedIds.includes(req))
|
|
29265
|
+
return req;
|
|
29266
|
+
const familyPrefix = `${req}-`;
|
|
29267
|
+
const variants = servedIds.filter((id) => id.startsWith(familyPrefix));
|
|
29268
|
+
if (variants.length > 0) {
|
|
29269
|
+
if (defaultId && variants.includes(defaultId))
|
|
29270
|
+
return defaultId;
|
|
29271
|
+
let best = variants[0];
|
|
29272
|
+
let bestRank = rankReasoningSuffix(best.slice(familyPrefix.length));
|
|
29273
|
+
for (const variant of variants.slice(1)) {
|
|
29274
|
+
const rank = rankReasoningSuffix(variant.slice(familyPrefix.length));
|
|
29275
|
+
if (rank < bestRank) {
|
|
29276
|
+
best = variant;
|
|
29277
|
+
bestRank = rank;
|
|
29278
|
+
}
|
|
29279
|
+
}
|
|
29280
|
+
return best;
|
|
29281
|
+
}
|
|
29282
|
+
return req;
|
|
29283
|
+
}
|
|
29284
|
+
function createActivityRequestId() {
|
|
29285
|
+
return Math.random().toString(36).substring(7);
|
|
29286
|
+
}
|
|
29287
|
+
function classify429(responseBody) {
|
|
29288
|
+
try {
|
|
29289
|
+
const raw = JSON.parse(responseBody);
|
|
29290
|
+
const error46 = Array.isArray(raw) ? raw[0]?.error : raw?.error;
|
|
29291
|
+
const details = Array.isArray(error46?.details) ? error46.details : [];
|
|
29292
|
+
const retryInfo = details.find((d) => d["@type"] === "type.googleapis.com/google.rpc.RetryInfo");
|
|
29293
|
+
let retryDelayMs = parseRetryDelay(retryInfo?.retryDelay);
|
|
29294
|
+
if (retryDelayMs === undefined && typeof error46?.message === "string") {
|
|
29295
|
+
const match = error46.message.match(/retry in ([\d.]+)(ms|s)/i);
|
|
29296
|
+
if (match) {
|
|
29297
|
+
const val = Number.parseFloat(match[1]);
|
|
29298
|
+
retryDelayMs = match[2] === "ms" ? Math.round(val) : Math.round(val * 1000);
|
|
29299
|
+
}
|
|
29300
|
+
}
|
|
29301
|
+
const errorInfo = details.find((d) => d["@type"] === "type.googleapis.com/google.rpc.ErrorInfo");
|
|
29302
|
+
const reason = errorInfo?.reason;
|
|
29303
|
+
if (reason === "QUOTA_EXHAUSTED") {
|
|
29304
|
+
return { terminal: true, retryDelayMs, reason };
|
|
29305
|
+
}
|
|
29306
|
+
if (reason === "RATE_LIMIT_EXCEEDED") {
|
|
29307
|
+
return { terminal: false, retryDelayMs: retryDelayMs ?? DEFAULT_RATE_LIMIT_DELAY_MS, reason };
|
|
29308
|
+
}
|
|
29309
|
+
if (reason === "MODEL_CAPACITY_EXHAUSTED") {
|
|
29310
|
+
return { terminal: true, retryDelayMs, reason };
|
|
29311
|
+
}
|
|
29312
|
+
const quotaFailure = details.find((d) => d["@type"] === "type.googleapis.com/google.rpc.QuotaFailure");
|
|
29313
|
+
if (quotaFailure?.violations?.length) {
|
|
29314
|
+
const text = quotaFailure.violations.map((v) => `${v.quotaId || ""} ${v.description || ""}`).join(" ").toLowerCase();
|
|
29315
|
+
if (text.includes("perday") || text.includes("daily") || text.includes("per day")) {
|
|
29316
|
+
return { terminal: true, retryDelayMs, reason };
|
|
29317
|
+
}
|
|
29318
|
+
if (text.includes("perminute") || text.includes("per minute")) {
|
|
29319
|
+
return { terminal: false, retryDelayMs: retryDelayMs ?? 60000, reason };
|
|
29320
|
+
}
|
|
29321
|
+
}
|
|
29322
|
+
return { terminal: false, retryDelayMs, reason };
|
|
29323
|
+
} catch {
|
|
29324
|
+
return null;
|
|
28774
29325
|
}
|
|
28775
|
-
|
|
29326
|
+
}
|
|
29327
|
+
function parseRetryDelay(value) {
|
|
29328
|
+
if (!value)
|
|
29329
|
+
return;
|
|
29330
|
+
if (typeof value === "string") {
|
|
29331
|
+
const match = value.match(/([\d.]+)s/);
|
|
29332
|
+
return match ? Math.round(Number.parseFloat(match[1]) * 1000) : undefined;
|
|
29333
|
+
}
|
|
29334
|
+
if (typeof value === "object") {
|
|
29335
|
+
const seconds = typeof value.seconds === "number" ? value.seconds : 0;
|
|
29336
|
+
const nanos = typeof value.nanos === "number" ? value.nanos : 0;
|
|
29337
|
+
const ms = Math.round(seconds * 1000 + nanos / 1e6);
|
|
29338
|
+
return ms > 0 ? ms : undefined;
|
|
29339
|
+
}
|
|
29340
|
+
return;
|
|
28776
29341
|
}
|
|
28777
29342
|
|
|
28778
|
-
class
|
|
28779
|
-
|
|
28780
|
-
|
|
28781
|
-
|
|
28782
|
-
return this.
|
|
29343
|
+
class AntigravityProviderTransport {
|
|
29344
|
+
name = "antigravity";
|
|
29345
|
+
_displayName = "Antigravity";
|
|
29346
|
+
get displayName() {
|
|
29347
|
+
return this._displayName;
|
|
28783
29348
|
}
|
|
28784
|
-
|
|
28785
|
-
|
|
28786
|
-
|
|
29349
|
+
streamFormat = "gemini-sse";
|
|
29350
|
+
modelName;
|
|
29351
|
+
servedModelName;
|
|
29352
|
+
accessToken = null;
|
|
29353
|
+
projectId = null;
|
|
29354
|
+
tierId = null;
|
|
29355
|
+
cachedAuth = null;
|
|
29356
|
+
lastEnvelope = null;
|
|
29357
|
+
_activeModelName;
|
|
29358
|
+
servedModels = [];
|
|
29359
|
+
defaultServedModel = null;
|
|
29360
|
+
constructor(modelName) {
|
|
29361
|
+
this.modelName = modelName;
|
|
29362
|
+
this.servedModelName = modelName;
|
|
29363
|
+
}
|
|
29364
|
+
getActiveModelName() {
|
|
29365
|
+
return this._activeModelName;
|
|
29366
|
+
}
|
|
29367
|
+
getEndpoint() {
|
|
29368
|
+
return CODE_ASSIST_ENDPOINT;
|
|
29369
|
+
}
|
|
29370
|
+
async getHeaders() {
|
|
29371
|
+
if (this.cachedAuth)
|
|
29372
|
+
return { ...this.cachedAuth.headers };
|
|
29373
|
+
return this.buildLocalHeaders();
|
|
29374
|
+
}
|
|
29375
|
+
buildLocalHeaders() {
|
|
28787
29376
|
return {
|
|
28788
|
-
|
|
28789
|
-
|
|
28790
|
-
|
|
28791
|
-
...p,
|
|
28792
|
-
store: false,
|
|
28793
|
-
include: ["reasoning.encrypted_content"]
|
|
28794
|
-
})
|
|
29377
|
+
Authorization: `Bearer ${this.accessToken}`,
|
|
29378
|
+
"User-Agent": buildAntigravityUserAgent(),
|
|
29379
|
+
"x-activity-request-id": createActivityRequestId()
|
|
28795
29380
|
};
|
|
28796
29381
|
}
|
|
28797
|
-
async
|
|
28798
|
-
await
|
|
29382
|
+
async refreshAuth() {
|
|
29383
|
+
this.cachedAuth = await credentials.getRequestAuth("antigravity", {
|
|
29384
|
+
model: this.modelName
|
|
29385
|
+
});
|
|
29386
|
+
this.accessToken = await getValidAntigravityAccessToken();
|
|
29387
|
+
const { projectId, tierId } = await setupAntigravityUser(this.accessToken);
|
|
29388
|
+
this.projectId = projectId;
|
|
29389
|
+
this.tierId = tierId;
|
|
29390
|
+
this._displayName = getAntigravityTierDisplayName();
|
|
29391
|
+
const served = await getServedAntigravityModels(this.accessToken, this.projectId);
|
|
29392
|
+
this.servedModels = served.servedIds;
|
|
29393
|
+
this.defaultServedModel = served.defaultId;
|
|
29394
|
+
this.servedModelName = resolveAntigravityModelId(this.modelName, this.servedModels, this.defaultServedModel);
|
|
29395
|
+
log(`[Antigravity] Auth refreshed, project: ${this.projectId}, tier: ${this._displayName}, ` + `model: ${this.modelName} -> ${this.servedModelName}, served: ${this.servedModels.join(",") || "(none)"}`);
|
|
28799
29396
|
}
|
|
28800
|
-
|
|
28801
|
-
|
|
29397
|
+
transformPayload(payload) {
|
|
29398
|
+
const envelope = this.cachedAuth?.transformPayload ? this.cachedAuth.transformPayload(payload) : this.buildEnvelope(payload, this.servedModelName);
|
|
29399
|
+
this.lastEnvelope = envelope;
|
|
29400
|
+
return envelope;
|
|
29401
|
+
}
|
|
29402
|
+
buildEnvelope(innerPayload, model) {
|
|
29403
|
+
const envelope = {
|
|
29404
|
+
model,
|
|
29405
|
+
project: this.projectId,
|
|
29406
|
+
user_prompt_id: randomUUID(),
|
|
29407
|
+
request: innerPayload
|
|
29408
|
+
};
|
|
29409
|
+
if (this.tierId && this.tierId !== "free-tier") {
|
|
29410
|
+
envelope.enabled_credit_types = ["GOOGLE_ONE_AI"];
|
|
29411
|
+
}
|
|
29412
|
+
return envelope;
|
|
29413
|
+
}
|
|
29414
|
+
async enqueueRequest(fetchFn) {
|
|
29415
|
+
const queue = GeminiRequestQueue.getInstance();
|
|
29416
|
+
let lastResponse = null;
|
|
29417
|
+
for (let attempt = 1;attempt <= MAX_RETRY_ATTEMPTS; attempt++) {
|
|
29418
|
+
const response = attempt === 1 ? await queue.enqueue(fetchFn) : await queue.enqueue(fetchFn);
|
|
29419
|
+
if (response.status !== 429) {
|
|
29420
|
+
if (response.status === 404) {
|
|
29421
|
+
return this.rewriteModelNotFound(response);
|
|
29422
|
+
}
|
|
29423
|
+
return response;
|
|
29424
|
+
}
|
|
29425
|
+
const bodyText = await response.clone().text();
|
|
29426
|
+
const classification = classify429(bodyText);
|
|
29427
|
+
lastResponse = response;
|
|
29428
|
+
if (!classification) {
|
|
29429
|
+
log("[Antigravity] 429 response could not be classified, returning to caller");
|
|
29430
|
+
return response;
|
|
29431
|
+
}
|
|
29432
|
+
log(`[Antigravity] 429 classified: reason=${classification.reason}, terminal=${classification.terminal}, delay=${classification.retryDelayMs}ms`);
|
|
29433
|
+
if (classification.reason === "MODEL_CAPACITY_EXHAUSTED") {
|
|
29434
|
+
return this.handleCapacityExhausted(response, queue);
|
|
29435
|
+
}
|
|
29436
|
+
if (classification.terminal) {
|
|
29437
|
+
logStderr(`[Antigravity] Quota exhausted (${classification.reason || "daily limit"}). Check plan limits.`);
|
|
29438
|
+
return response;
|
|
29439
|
+
}
|
|
29440
|
+
if (attempt < MAX_RETRY_ATTEMPTS) {
|
|
29441
|
+
const delay = classification.retryDelayMs ?? DEFAULT_RATE_LIMIT_DELAY_MS;
|
|
29442
|
+
logStderr(`[Antigravity] Rate limited (${classification.reason || "unknown"}), retrying in ${(delay / 1000).toFixed(1)}s (attempt ${attempt}/${MAX_RETRY_ATTEMPTS})`);
|
|
29443
|
+
if (attempt === 1) {
|
|
29444
|
+
await this.logQuotaInfo();
|
|
29445
|
+
}
|
|
29446
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
29447
|
+
}
|
|
29448
|
+
}
|
|
29449
|
+
logStderr(`[Antigravity] Rate limit persisted after ${MAX_RETRY_ATTEMPTS} retries`);
|
|
29450
|
+
return lastResponse;
|
|
29451
|
+
}
|
|
29452
|
+
async handleCapacityExhausted(originalResponse, queue) {
|
|
29453
|
+
const candidates = this.servedModels.filter((m) => m !== this.servedModelName);
|
|
29454
|
+
if (candidates.length === 0) {
|
|
29455
|
+
log(`[Antigravity] ${this.servedModelName} capacity exhausted, no fallback models available`);
|
|
29456
|
+
return originalResponse;
|
|
29457
|
+
}
|
|
29458
|
+
if (!this.lastEnvelope) {
|
|
29459
|
+
log(`[Antigravity] ${this.servedModelName} capacity exhausted but no stored envelope for retry`);
|
|
29460
|
+
return originalResponse;
|
|
29461
|
+
}
|
|
29462
|
+
log(`[Antigravity] Model ${this.servedModelName} capacity exhausted, starting fallback chain`);
|
|
29463
|
+
logStderr(`[Antigravity] ${this.servedModelName} capacity exhausted, trying fallback models...`);
|
|
29464
|
+
let lastResponse = originalResponse;
|
|
29465
|
+
const innerPayload = this.lastEnvelope.request;
|
|
29466
|
+
const endpoint = this.getEndpoint();
|
|
29467
|
+
const tried = [this.servedModelName];
|
|
29468
|
+
for (const fallbackModel of candidates) {
|
|
29469
|
+
log(`[Antigravity] Trying fallback model: ${fallbackModel}`);
|
|
29470
|
+
tried.push(fallbackModel);
|
|
29471
|
+
const fallbackEnvelope = this.buildEnvelope(innerPayload, fallbackModel);
|
|
29472
|
+
const headers = this.buildLocalHeaders();
|
|
29473
|
+
headers["Content-Type"] = "application/json";
|
|
29474
|
+
const fallbackResponse = await queue.enqueue(() => fetch(endpoint, {
|
|
29475
|
+
method: "POST",
|
|
29476
|
+
headers,
|
|
29477
|
+
body: JSON.stringify(fallbackEnvelope)
|
|
29478
|
+
}));
|
|
29479
|
+
if (fallbackResponse.status === 200) {
|
|
29480
|
+
this._activeModelName = fallbackModel;
|
|
29481
|
+
logStderr(`[Antigravity] Using fallback model: ${fallbackModel} (${this.servedModelName} had no capacity)`);
|
|
29482
|
+
return fallbackResponse;
|
|
29483
|
+
}
|
|
29484
|
+
if (fallbackResponse.status === 404) {
|
|
29485
|
+
log(`[Antigravity] ${fallbackModel} returned 404, skipping to next fallback`);
|
|
29486
|
+
lastResponse = fallbackResponse;
|
|
29487
|
+
continue;
|
|
29488
|
+
}
|
|
29489
|
+
if (fallbackResponse.status === 429) {
|
|
29490
|
+
const fallbackBodyText = await fallbackResponse.clone().text();
|
|
29491
|
+
const classification = classify429(fallbackBodyText);
|
|
29492
|
+
if (classification?.reason === "MODEL_CAPACITY_EXHAUSTED") {
|
|
29493
|
+
log(`[Antigravity] ${fallbackModel} also capacity exhausted, trying next...`);
|
|
29494
|
+
lastResponse = fallbackResponse;
|
|
29495
|
+
continue;
|
|
29496
|
+
}
|
|
29497
|
+
return fallbackResponse;
|
|
29498
|
+
}
|
|
29499
|
+
return fallbackResponse;
|
|
29500
|
+
}
|
|
29501
|
+
log("[Antigravity] All fallback models exhausted");
|
|
29502
|
+
logStderr(`[Antigravity] All models capacity exhausted (tried: ${tried.join(" -> ")})`);
|
|
29503
|
+
if (lastResponse.status === 404) {
|
|
29504
|
+
return this.rewriteModelNotFound(lastResponse, true);
|
|
29505
|
+
}
|
|
29506
|
+
return lastResponse;
|
|
29507
|
+
}
|
|
29508
|
+
rewriteModelNotFound(response, capacityFallbacksExhausted = false) {
|
|
29509
|
+
const served = this.servedModels;
|
|
29510
|
+
if (!capacityFallbacksExhausted && served.includes(this.servedModelName)) {
|
|
29511
|
+
log(`[Antigravity] 404 for ${this.servedModelName}, which IS in the served set \u2014 passing through unmodified`);
|
|
29512
|
+
return response;
|
|
29513
|
+
}
|
|
29514
|
+
response.text().catch(() => {});
|
|
29515
|
+
const servesClause = served.length > 0 ? `That tier currently serves: ${served.join(", ")}. ` : "";
|
|
29516
|
+
const tier = this._displayName || "Antigravity";
|
|
29517
|
+
const reason = capacityFallbacksExhausted ? `${this.modelName} could not be served after every Antigravity capacity fallback failed (${tier}, via ag@). ` + servesClause : `${this.modelName} is not served by your Antigravity tier (${tier}, via ag@). ` + servesClause;
|
|
29518
|
+
const message = reason + `To use ${this.modelName}, go through the direct Gemini API instead \u2014 ` + `set GEMINI_API_KEY (get one at https://aistudio.google.com/app/apikey) and run ` + `google@${this.modelName}.`;
|
|
29519
|
+
const list = served.join(", ");
|
|
29520
|
+
const body = JSON.stringify({
|
|
29521
|
+
error: { code: 404, status: "NOT_FOUND", message }
|
|
29522
|
+
});
|
|
29523
|
+
if (capacityFallbacksExhausted) {
|
|
29524
|
+
logStderr(`[Antigravity] ${this.modelName} capacity fallbacks exhausted (404). Reported models: ${list}`);
|
|
29525
|
+
} else {
|
|
29526
|
+
logStderr(`[Antigravity] ${this.modelName} not served by ${tier} (404). Serves: ${list}`);
|
|
29527
|
+
}
|
|
29528
|
+
return new Response(body, {
|
|
29529
|
+
status: 404,
|
|
29530
|
+
headers: { "Content-Type": "application/json" }
|
|
29531
|
+
});
|
|
29532
|
+
}
|
|
29533
|
+
async logQuotaInfo() {
|
|
29534
|
+
if (!this.accessToken || !this.projectId)
|
|
29535
|
+
return;
|
|
29536
|
+
try {
|
|
29537
|
+
const data = await retrieveUserQuota(this.accessToken, this.projectId);
|
|
29538
|
+
if (!data?.buckets?.length)
|
|
29539
|
+
return;
|
|
29540
|
+
const lines = [];
|
|
29541
|
+
for (const bucket of data.buckets) {
|
|
29542
|
+
if (!bucket.modelId)
|
|
29543
|
+
continue;
|
|
29544
|
+
const pct = typeof bucket.remainingFraction === "number" ? `${(bucket.remainingFraction * 100).toFixed(1)}%` : "?";
|
|
29545
|
+
const reset = bucket.resetTime ? new Date(bucket.resetTime).toLocaleTimeString([], {
|
|
29546
|
+
hour: "2-digit",
|
|
29547
|
+
minute: "2-digit"
|
|
29548
|
+
}) : "?";
|
|
29549
|
+
lines.push(` ${bucket.modelId}: ${pct} remaining (resets ${reset})`);
|
|
29550
|
+
}
|
|
29551
|
+
if (lines.length > 0) {
|
|
29552
|
+
logStderr(`[Antigravity] Quota status:
|
|
29553
|
+
${lines.join(`
|
|
29554
|
+
`)}`);
|
|
29555
|
+
}
|
|
29556
|
+
} catch {}
|
|
29557
|
+
}
|
|
29558
|
+
async getQuotaRemaining(modelName) {
|
|
29559
|
+
if (!this.accessToken || !this.projectId)
|
|
29560
|
+
return;
|
|
29561
|
+
try {
|
|
29562
|
+
const data = await retrieveUserQuota(this.accessToken, this.projectId);
|
|
29563
|
+
if (!data?.buckets?.length)
|
|
29564
|
+
return;
|
|
29565
|
+
const bucket = data.buckets.find((b) => b.modelId === modelName);
|
|
29566
|
+
return typeof bucket?.remainingFraction === "number" ? bucket.remainingFraction : undefined;
|
|
29567
|
+
} catch {
|
|
29568
|
+
return;
|
|
29569
|
+
}
|
|
28802
29570
|
}
|
|
28803
29571
|
}
|
|
28804
|
-
|
|
28805
|
-
|
|
28806
|
-
|
|
28807
|
-
|
|
28808
|
-
|
|
29572
|
+
var CODE_ASSIST_BASE = "https://cloudcode-pa.googleapis.com", CODE_ASSIST_ENDPOINT, MAX_RETRY_ATTEMPTS = 3, DEFAULT_RATE_LIMIT_DELAY_MS = 1e4, REASONING_TIER_RANK;
|
|
29573
|
+
var init_antigravity = __esm(() => {
|
|
29574
|
+
init_authority();
|
|
29575
|
+
init_antigravity_token();
|
|
29576
|
+
init_gemini_oauth();
|
|
29577
|
+
init_gemini_queue();
|
|
29578
|
+
init_logger();
|
|
29579
|
+
CODE_ASSIST_ENDPOINT = `${CODE_ASSIST_BASE}/v1internal:streamGenerateContent?alt=sse`;
|
|
29580
|
+
REASONING_TIER_RANK = {
|
|
29581
|
+
high: 0,
|
|
29582
|
+
medium: 1,
|
|
29583
|
+
low: 2,
|
|
29584
|
+
"extra-low": 3,
|
|
29585
|
+
tiered: 4
|
|
29586
|
+
};
|
|
29587
|
+
});
|
|
29588
|
+
|
|
29589
|
+
// src/auth/credentials/antigravity-credential.ts
|
|
29590
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
29591
|
+
function createActivityRequestId2() {
|
|
29592
|
+
return Math.random().toString(36).substring(7);
|
|
28809
29593
|
}
|
|
28810
|
-
|
|
28811
|
-
|
|
28812
|
-
|
|
28813
|
-
|
|
29594
|
+
|
|
29595
|
+
class AntigravityCredentialProvider {
|
|
29596
|
+
catalogName = "antigravity";
|
|
29597
|
+
async isAvailable() {
|
|
29598
|
+
try {
|
|
29599
|
+
return readSharedAntigravityToken() !== null;
|
|
29600
|
+
} catch {
|
|
29601
|
+
return false;
|
|
29602
|
+
}
|
|
29603
|
+
}
|
|
29604
|
+
async getRequestAuth(ctx) {
|
|
29605
|
+
const token = await getValidAntigravityAccessToken();
|
|
29606
|
+
const { projectId, tierId } = await setupAntigravityUser(token);
|
|
29607
|
+
const { servedIds, defaultId } = await getServedAntigravityModels(token, projectId);
|
|
29608
|
+
const servedModel = resolveAntigravityModelId(ctx.model, servedIds, defaultId);
|
|
29609
|
+
return {
|
|
29610
|
+
headers: {
|
|
29611
|
+
Authorization: `Bearer ${token}`,
|
|
29612
|
+
"User-Agent": buildAntigravityUserAgent(),
|
|
29613
|
+
"x-activity-request-id": createActivityRequestId2()
|
|
29614
|
+
},
|
|
29615
|
+
transformPayload: (inner) => {
|
|
29616
|
+
const env = {
|
|
29617
|
+
model: servedModel,
|
|
29618
|
+
project: projectId,
|
|
29619
|
+
user_prompt_id: randomUUID2(),
|
|
29620
|
+
request: inner
|
|
29621
|
+
};
|
|
29622
|
+
if (tierId && tierId !== "free-tier") {
|
|
29623
|
+
env.enabled_credit_types = ["GOOGLE_ONE_AI"];
|
|
29624
|
+
}
|
|
29625
|
+
return env;
|
|
29626
|
+
}
|
|
29627
|
+
};
|
|
29628
|
+
}
|
|
29629
|
+
}
|
|
29630
|
+
var init_antigravity_credential = __esm(() => {
|
|
29631
|
+
init_antigravity();
|
|
29632
|
+
init_antigravity_token();
|
|
29633
|
+
init_gemini_oauth();
|
|
28814
29634
|
});
|
|
28815
29635
|
|
|
28816
|
-
// src/auth/
|
|
29636
|
+
// src/auth/credentials/api-key-credential.ts
|
|
29637
|
+
import { existsSync as existsSync8 } from "fs";
|
|
29638
|
+
import { homedir as homedir10 } from "os";
|
|
29639
|
+
import { join as join10 } from "path";
|
|
29640
|
+
function realValue(v) {
|
|
29641
|
+
if (!v)
|
|
29642
|
+
return;
|
|
29643
|
+
return UNEXPANDED_PLACEHOLDER.test(v.trim()) ? undefined : v;
|
|
29644
|
+
}
|
|
29645
|
+
|
|
29646
|
+
class ApiKeyCredentialProvider {
|
|
29647
|
+
catalogName;
|
|
29648
|
+
envVar;
|
|
29649
|
+
aliases;
|
|
29650
|
+
authScheme;
|
|
29651
|
+
staticHeaders;
|
|
29652
|
+
publicKeyFallback;
|
|
29653
|
+
oauthFallback;
|
|
29654
|
+
declaredKey;
|
|
29655
|
+
cachedKey;
|
|
29656
|
+
resolving;
|
|
29657
|
+
constructor(descriptor) {
|
|
29658
|
+
this.catalogName = descriptor.catalogName;
|
|
29659
|
+
this.envVar = descriptor.envVar;
|
|
29660
|
+
this.aliases = descriptor.aliases ?? [];
|
|
29661
|
+
this.authScheme = descriptor.authScheme ?? "bearer";
|
|
29662
|
+
this.staticHeaders = descriptor.staticHeaders ?? {};
|
|
29663
|
+
this.publicKeyFallback = descriptor.publicKeyFallback;
|
|
29664
|
+
this.oauthFallback = descriptor.oauthFallback;
|
|
29665
|
+
this.declaredKey = descriptor.declaredKey;
|
|
29666
|
+
}
|
|
29667
|
+
resolveFromEnvConfig() {
|
|
29668
|
+
return realValue(process.env[this.envVar]) || this.aliases.map((a) => realValue(process.env[a])).find((v) => !!v) || realValue(getApiKey(this.envVar)) || realValue(this.resolveDeclared());
|
|
29669
|
+
}
|
|
29670
|
+
resolveDeclared() {
|
|
29671
|
+
try {
|
|
29672
|
+
return this.declaredKey?.() || undefined;
|
|
29673
|
+
} catch {
|
|
29674
|
+
return;
|
|
29675
|
+
}
|
|
29676
|
+
}
|
|
29677
|
+
hasOauthFallbackFile() {
|
|
29678
|
+
if (!this.oauthFallback)
|
|
29679
|
+
return false;
|
|
29680
|
+
try {
|
|
29681
|
+
return existsSync8(join10(homedir10(), ".claudish", this.oauthFallback));
|
|
29682
|
+
} catch {
|
|
29683
|
+
return false;
|
|
29684
|
+
}
|
|
29685
|
+
}
|
|
29686
|
+
async resolveKey(opts) {
|
|
29687
|
+
if (this.cachedKey !== undefined)
|
|
29688
|
+
return this.cachedKey;
|
|
29689
|
+
if (this.resolving)
|
|
29690
|
+
return this.resolving;
|
|
29691
|
+
this.resolving = (async () => {
|
|
29692
|
+
const local = this.resolveFromEnvConfig();
|
|
29693
|
+
if (local) {
|
|
29694
|
+
this.cachedKey = local;
|
|
29695
|
+
return local;
|
|
29696
|
+
}
|
|
29697
|
+
if (hasOpSources()) {
|
|
29698
|
+
const wanted = new Set([this.envVar, ...this.aliases]);
|
|
29699
|
+
const resolved = await resolveOpKeyForEnvVars(wanted, {
|
|
29700
|
+
onAuthFailure: "skip",
|
|
29701
|
+
allowPrompt: opts?.allowOpPrompt ?? false
|
|
29702
|
+
});
|
|
29703
|
+
const value = resolved[this.envVar] ?? this.aliases.map((a) => resolved[a]).find((v) => !!v);
|
|
29704
|
+
if (value) {
|
|
29705
|
+
process.env[this.envVar] = value;
|
|
29706
|
+
this.cachedKey = value;
|
|
29707
|
+
return value;
|
|
29708
|
+
}
|
|
29709
|
+
return "";
|
|
29710
|
+
}
|
|
29711
|
+
this.cachedKey = "";
|
|
29712
|
+
return "";
|
|
29713
|
+
})();
|
|
29714
|
+
try {
|
|
29715
|
+
return await this.resolving;
|
|
29716
|
+
} finally {
|
|
29717
|
+
this.resolving = undefined;
|
|
29718
|
+
}
|
|
29719
|
+
}
|
|
29720
|
+
async isAvailable(opts) {
|
|
29721
|
+
if (this.publicKeyFallback)
|
|
29722
|
+
return true;
|
|
29723
|
+
if (this.resolveFromEnvConfig())
|
|
29724
|
+
return true;
|
|
29725
|
+
if (this.hasOauthFallbackFile())
|
|
29726
|
+
return true;
|
|
29727
|
+
const key = await this.resolveKey(opts);
|
|
29728
|
+
return !!key;
|
|
29729
|
+
}
|
|
29730
|
+
invalidate() {
|
|
29731
|
+
this.cachedKey = undefined;
|
|
29732
|
+
this.resolving = undefined;
|
|
29733
|
+
}
|
|
29734
|
+
async getRequestAuth(ctx) {
|
|
29735
|
+
const key = await this.resolveKey({ allowOpPrompt: ctx.allowOpPrompt }) || this.publicKeyFallback || "";
|
|
29736
|
+
let headers;
|
|
29737
|
+
if (this.authScheme === "x-api-key") {
|
|
29738
|
+
headers = { "x-api-key": key, ...this.staticHeaders };
|
|
29739
|
+
} else if (key) {
|
|
29740
|
+
headers = { Authorization: `Bearer ${key}`, ...this.staticHeaders };
|
|
29741
|
+
} else {
|
|
29742
|
+
headers = { ...this.staticHeaders };
|
|
29743
|
+
}
|
|
29744
|
+
return { headers };
|
|
29745
|
+
}
|
|
29746
|
+
}
|
|
29747
|
+
var UNEXPANDED_PLACEHOLDER;
|
|
29748
|
+
var init_api_key_credential = __esm(() => {
|
|
29749
|
+
init_profile_config();
|
|
29750
|
+
init_op_source();
|
|
29751
|
+
UNEXPANDED_PLACEHOLDER = /^\$\{[^}]*\}$/;
|
|
29752
|
+
});
|
|
29753
|
+
|
|
29754
|
+
// src/auth/codex-oauth.ts
|
|
28817
29755
|
import { exec as exec2 } from "child_process";
|
|
28818
29756
|
import { createHash as createHash3, randomBytes as randomBytes2 } from "crypto";
|
|
28819
|
-
import { closeSync as closeSync3, existsSync as
|
|
29757
|
+
import { closeSync as closeSync3, existsSync as existsSync9, openSync as openSync3, readFileSync as readFileSync7, unlinkSync as unlinkSync3, writeSync as writeSync3 } from "fs";
|
|
28820
29758
|
import { createServer as createServer2 } from "http";
|
|
28821
|
-
import { homedir as
|
|
28822
|
-
import { join as
|
|
29759
|
+
import { homedir as homedir11 } from "os";
|
|
29760
|
+
import { join as join11 } from "path";
|
|
28823
29761
|
import { promisify as promisify2 } from "util";
|
|
28824
29762
|
|
|
28825
|
-
class
|
|
29763
|
+
class CodexOAuth {
|
|
28826
29764
|
static instance = null;
|
|
28827
29765
|
credentials = null;
|
|
28828
29766
|
refreshPromise = null;
|
|
28829
29767
|
tokenRefreshMargin = 5 * 60 * 1000;
|
|
28830
29768
|
oauthState = null;
|
|
28831
29769
|
static getInstance() {
|
|
28832
|
-
if (!
|
|
28833
|
-
|
|
29770
|
+
if (!CodexOAuth.instance) {
|
|
29771
|
+
CodexOAuth.instance = new CodexOAuth;
|
|
28834
29772
|
}
|
|
28835
|
-
return
|
|
29773
|
+
return CodexOAuth.instance;
|
|
28836
29774
|
}
|
|
28837
29775
|
constructor() {
|
|
28838
29776
|
this.credentials = this.loadCredentials();
|
|
@@ -28845,56 +29783,61 @@ class GeminiOAuth {
|
|
|
28845
29783
|
return this.credentials !== null && !!this.credentials.refresh_token;
|
|
28846
29784
|
}
|
|
28847
29785
|
getCredentialsPath() {
|
|
28848
|
-
const claudishDir =
|
|
28849
|
-
return
|
|
29786
|
+
const claudishDir = join11(homedir11(), ".claudish");
|
|
29787
|
+
return join11(claudishDir, "codex-oauth.json");
|
|
28850
29788
|
}
|
|
28851
29789
|
async login() {
|
|
28852
|
-
log("[
|
|
29790
|
+
log("[CodexOAuth] Starting OAuth login flow");
|
|
28853
29791
|
const codeVerifier = this.generateCodeVerifier();
|
|
28854
29792
|
const codeChallenge = await this.generateCodeChallenge(codeVerifier);
|
|
28855
29793
|
this.oauthState = randomBytes2(32).toString("base64url");
|
|
28856
29794
|
const { authCode, redirectUri } = await this.startCallbackServer(codeChallenge, this.oauthState);
|
|
28857
29795
|
const tokens = await this.exchangeCodeForTokens(authCode, codeVerifier, redirectUri);
|
|
28858
|
-
const
|
|
29796
|
+
const accountId = tokens.id_token ? this.extractAccountId(tokens.id_token) : undefined;
|
|
29797
|
+
const credentials2 = {
|
|
28859
29798
|
access_token: tokens.access_token,
|
|
28860
29799
|
refresh_token: tokens.refresh_token,
|
|
28861
|
-
expires_at: Date.now() + tokens.expires_in * 1000
|
|
29800
|
+
expires_at: Date.now() + tokens.expires_in * 1000,
|
|
29801
|
+
account_id: accountId
|
|
28862
29802
|
};
|
|
28863
|
-
this.saveCredentials(
|
|
28864
|
-
this.credentials =
|
|
29803
|
+
this.saveCredentials(credentials2);
|
|
29804
|
+
this.credentials = credentials2;
|
|
28865
29805
|
this.oauthState = null;
|
|
28866
|
-
log("[
|
|
29806
|
+
log("[CodexOAuth] Login successful");
|
|
29807
|
+
if (accountId) {
|
|
29808
|
+
log(`[CodexOAuth] Account ID: ${accountId}`);
|
|
29809
|
+
}
|
|
28867
29810
|
}
|
|
28868
29811
|
async logout() {
|
|
28869
29812
|
const credPath = this.getCredentialsPath();
|
|
28870
|
-
if (
|
|
29813
|
+
if (existsSync9(credPath)) {
|
|
28871
29814
|
unlinkSync3(credPath);
|
|
28872
|
-
log("[
|
|
29815
|
+
log("[CodexOAuth] Credentials deleted");
|
|
28873
29816
|
}
|
|
28874
29817
|
this.credentials = null;
|
|
28875
29818
|
}
|
|
28876
29819
|
async getAccessToken() {
|
|
28877
29820
|
if (this.refreshPromise) {
|
|
28878
|
-
log("[
|
|
29821
|
+
log("[CodexOAuth] Waiting for in-progress refresh");
|
|
28879
29822
|
return this.refreshPromise;
|
|
28880
29823
|
}
|
|
28881
29824
|
if (!this.credentials) {
|
|
28882
|
-
throw new Error("No
|
|
29825
|
+
throw new Error("No OpenAI Codex OAuth credentials found. Please run `claudish login codex` first.");
|
|
28883
29826
|
}
|
|
28884
29827
|
if (this.isTokenValid()) {
|
|
28885
29828
|
return this.credentials.access_token;
|
|
28886
29829
|
}
|
|
28887
|
-
this.refreshPromise = this.doRefreshToken()
|
|
28888
|
-
try {
|
|
28889
|
-
const token = await this.refreshPromise;
|
|
28890
|
-
return token;
|
|
28891
|
-
} finally {
|
|
29830
|
+
this.refreshPromise = this.doRefreshToken().finally(() => {
|
|
28892
29831
|
this.refreshPromise = null;
|
|
28893
|
-
}
|
|
29832
|
+
});
|
|
29833
|
+
return this.refreshPromise;
|
|
29834
|
+
}
|
|
29835
|
+
getAccountId() {
|
|
29836
|
+
return this.credentials?.account_id;
|
|
28894
29837
|
}
|
|
28895
29838
|
async refreshToken() {
|
|
28896
29839
|
if (!this.credentials) {
|
|
28897
|
-
throw new Error("No
|
|
29840
|
+
throw new Error("No OpenAI Codex OAuth credentials found. Please run `claudish login codex` first.");
|
|
28898
29841
|
}
|
|
28899
29842
|
await this.doRefreshToken();
|
|
28900
29843
|
}
|
|
@@ -28905,20 +29848,19 @@ class GeminiOAuth {
|
|
|
28905
29848
|
}
|
|
28906
29849
|
async doRefreshToken() {
|
|
28907
29850
|
if (!this.credentials) {
|
|
28908
|
-
throw new Error("No
|
|
29851
|
+
throw new Error("No OpenAI Codex OAuth credentials found. Please run `claudish login codex` first.");
|
|
28909
29852
|
}
|
|
28910
|
-
log("[
|
|
29853
|
+
log("[CodexOAuth] Refreshing access token");
|
|
28911
29854
|
try {
|
|
28912
29855
|
const response = await fetch(OAUTH_CONFIG2.tokenUrl, {
|
|
28913
29856
|
method: "POST",
|
|
28914
29857
|
headers: {
|
|
28915
|
-
"Content-Type": "application/
|
|
29858
|
+
"Content-Type": "application/json"
|
|
28916
29859
|
},
|
|
28917
|
-
body:
|
|
29860
|
+
body: JSON.stringify({
|
|
28918
29861
|
grant_type: "refresh_token",
|
|
28919
29862
|
refresh_token: this.credentials.refresh_token,
|
|
28920
|
-
client_id: OAUTH_CONFIG2.clientId
|
|
28921
|
-
client_secret: OAUTH_CONFIG2.clientSecret
|
|
29863
|
+
client_id: OAUTH_CONFIG2.clientId
|
|
28922
29864
|
})
|
|
28923
29865
|
});
|
|
28924
29866
|
if (!response.ok) {
|
|
@@ -28926,56 +29868,58 @@ class GeminiOAuth {
|
|
|
28926
29868
|
throw new Error(`Token refresh failed: ${response.status} - ${errorText}`);
|
|
28927
29869
|
}
|
|
28928
29870
|
const tokens = await response.json();
|
|
29871
|
+
const accountId = tokens.id_token ? this.extractAccountId(tokens.id_token) : this.credentials.account_id;
|
|
28929
29872
|
const updatedCredentials = {
|
|
28930
29873
|
access_token: tokens.access_token,
|
|
28931
29874
|
refresh_token: tokens.refresh_token || this.credentials.refresh_token,
|
|
28932
|
-
expires_at: Date.now() + tokens.expires_in * 1000
|
|
29875
|
+
expires_at: Date.now() + tokens.expires_in * 1000,
|
|
29876
|
+
account_id: accountId
|
|
28933
29877
|
};
|
|
28934
29878
|
this.saveCredentials(updatedCredentials);
|
|
28935
29879
|
this.credentials = updatedCredentials;
|
|
28936
|
-
log(`[
|
|
29880
|
+
log(`[CodexOAuth] Token refreshed, valid until ${new Date(updatedCredentials.expires_at).toISOString()}`);
|
|
28937
29881
|
return updatedCredentials.access_token;
|
|
28938
29882
|
} catch (e) {
|
|
28939
|
-
log(`[
|
|
28940
|
-
throw new Error(`OAuth credentials invalid. Please run \`claudish login
|
|
29883
|
+
log(`[CodexOAuth] Refresh failed: ${e.message}`);
|
|
29884
|
+
throw new Error(`OAuth credentials invalid. Please run \`claudish login codex\` again.
|
|
28941
29885
|
|
|
28942
29886
|
Details: ${e.message}`);
|
|
28943
29887
|
}
|
|
28944
29888
|
}
|
|
28945
29889
|
loadCredentials() {
|
|
28946
29890
|
const credPath = this.getCredentialsPath();
|
|
28947
|
-
if (!
|
|
29891
|
+
if (!existsSync9(credPath)) {
|
|
28948
29892
|
return null;
|
|
28949
29893
|
}
|
|
28950
29894
|
try {
|
|
28951
29895
|
const data = readFileSync7(credPath, "utf-8");
|
|
28952
|
-
const
|
|
28953
|
-
if (!
|
|
28954
|
-
log("[
|
|
29896
|
+
const credentials2 = JSON.parse(data);
|
|
29897
|
+
if (!credentials2.access_token || !credentials2.refresh_token || !credentials2.expires_at) {
|
|
29898
|
+
log("[CodexOAuth] Invalid credentials file structure");
|
|
28955
29899
|
return null;
|
|
28956
29900
|
}
|
|
28957
|
-
log("[
|
|
28958
|
-
return
|
|
29901
|
+
log("[CodexOAuth] Loaded credentials from file");
|
|
29902
|
+
return credentials2;
|
|
28959
29903
|
} catch (e) {
|
|
28960
|
-
log(`[
|
|
29904
|
+
log(`[CodexOAuth] Failed to load credentials: ${e.message}`);
|
|
28961
29905
|
return null;
|
|
28962
29906
|
}
|
|
28963
29907
|
}
|
|
28964
|
-
saveCredentials(
|
|
29908
|
+
saveCredentials(credentials2) {
|
|
28965
29909
|
const credPath = this.getCredentialsPath();
|
|
28966
|
-
const claudishDir =
|
|
28967
|
-
if (!
|
|
29910
|
+
const claudishDir = join11(homedir11(), ".claudish");
|
|
29911
|
+
if (!existsSync9(claudishDir)) {
|
|
28968
29912
|
const { mkdirSync: mkdirSync6 } = __require("fs");
|
|
28969
29913
|
mkdirSync6(claudishDir, { recursive: true });
|
|
28970
29914
|
}
|
|
28971
29915
|
const fd = openSync3(credPath, "w", 384);
|
|
28972
29916
|
try {
|
|
28973
|
-
const data = JSON.stringify(
|
|
29917
|
+
const data = JSON.stringify(credentials2, null, 2);
|
|
28974
29918
|
writeSync3(fd, data, 0, "utf-8");
|
|
28975
29919
|
} finally {
|
|
28976
29920
|
closeSync3(fd);
|
|
28977
29921
|
}
|
|
28978
|
-
log(`[
|
|
29922
|
+
log(`[CodexOAuth] Credentials saved to ${credPath}`);
|
|
28979
29923
|
}
|
|
28980
29924
|
generateCodeVerifier() {
|
|
28981
29925
|
return randomBytes2(64).toString("base64url");
|
|
@@ -28984,26 +29928,46 @@ Details: ${e.message}`);
|
|
|
28984
29928
|
const hash2 = createHash3("sha256").update(verifier).digest("base64url");
|
|
28985
29929
|
return hash2;
|
|
28986
29930
|
}
|
|
29931
|
+
extractAccountId(idToken) {
|
|
29932
|
+
try {
|
|
29933
|
+
const parts = idToken.split(".");
|
|
29934
|
+
if (parts.length !== 3)
|
|
29935
|
+
return;
|
|
29936
|
+
const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf-8"));
|
|
29937
|
+
const authClaim = payload["https://api.openai.com/auth"];
|
|
29938
|
+
const accountId = authClaim?.chatgpt_account_id || payload.chatgpt_account_id || authClaim?.user_id;
|
|
29939
|
+
if (accountId) {
|
|
29940
|
+
log(`[CodexOAuth] Extracted account ID from id_token: ${accountId}`);
|
|
29941
|
+
return accountId;
|
|
29942
|
+
}
|
|
29943
|
+
return;
|
|
29944
|
+
} catch (e) {
|
|
29945
|
+
log(`[CodexOAuth] Failed to extract account ID from id_token: ${e.message}`);
|
|
29946
|
+
return;
|
|
29947
|
+
}
|
|
29948
|
+
}
|
|
28987
29949
|
buildAuthUrl(codeChallenge, state, redirectUri) {
|
|
28988
|
-
const
|
|
28989
|
-
|
|
28990
|
-
|
|
28991
|
-
|
|
28992
|
-
|
|
28993
|
-
|
|
28994
|
-
|
|
28995
|
-
|
|
28996
|
-
|
|
28997
|
-
|
|
28998
|
-
|
|
28999
|
-
|
|
29950
|
+
const scope = OAUTH_CONFIG2.scopes.join("+");
|
|
29951
|
+
const params = [
|
|
29952
|
+
"response_type=code",
|
|
29953
|
+
`client_id=${encodeURIComponent(OAUTH_CONFIG2.clientId)}`,
|
|
29954
|
+
`redirect_uri=${encodeURIComponent(redirectUri)}`,
|
|
29955
|
+
`scope=${scope}`,
|
|
29956
|
+
`code_challenge=${encodeURIComponent(codeChallenge)}`,
|
|
29957
|
+
"code_challenge_method=S256",
|
|
29958
|
+
"id_token_add_organizations=true",
|
|
29959
|
+
"codex_cli_simplified_flow=true",
|
|
29960
|
+
`state=${encodeURIComponent(state)}`,
|
|
29961
|
+
"originator=opencode"
|
|
29962
|
+
].join("&");
|
|
29963
|
+
return `${OAUTH_CONFIG2.authUrl}?${params}`;
|
|
29000
29964
|
}
|
|
29001
29965
|
async startCallbackServer(codeChallenge, state) {
|
|
29002
29966
|
return new Promise((resolve, reject) => {
|
|
29003
29967
|
let redirectUri = "";
|
|
29004
29968
|
const server = createServer2((req, res) => {
|
|
29005
|
-
const url2 = new URL(req.url, redirectUri.replace("/callback", ""));
|
|
29006
|
-
if (url2.pathname === "/callback") {
|
|
29969
|
+
const url2 = new URL(req.url, redirectUri.replace("/auth/callback", ""));
|
|
29970
|
+
if (url2.pathname === "/auth/callback") {
|
|
29007
29971
|
const code = url2.searchParams.get("code");
|
|
29008
29972
|
const callbackState = url2.searchParams.get("state");
|
|
29009
29973
|
const error46 = url2.searchParams.get("error");
|
|
@@ -29068,15 +30032,15 @@ Details: ${e.message}`);
|
|
|
29068
30032
|
res.end("Not found");
|
|
29069
30033
|
}
|
|
29070
30034
|
});
|
|
29071
|
-
server.listen(
|
|
30035
|
+
server.listen(1455, () => {
|
|
29072
30036
|
const address = server.address();
|
|
29073
30037
|
if (!address || typeof address === "string") {
|
|
29074
30038
|
reject(new Error("Failed to get server port"));
|
|
29075
30039
|
return;
|
|
29076
30040
|
}
|
|
29077
30041
|
const port = address.port;
|
|
29078
|
-
redirectUri = `http://localhost:${port}/callback`;
|
|
29079
|
-
log(`[
|
|
30042
|
+
redirectUri = `http://localhost:${port}/auth/callback`;
|
|
30043
|
+
log(`[CodexOAuth] Callback server started on http://localhost:${port}`);
|
|
29080
30044
|
const authUrl = this.buildAuthUrl(codeChallenge, state, redirectUri);
|
|
29081
30045
|
this.openBrowser(authUrl);
|
|
29082
30046
|
});
|
|
@@ -29090,7 +30054,7 @@ Details: ${e.message}`);
|
|
|
29090
30054
|
});
|
|
29091
30055
|
}
|
|
29092
30056
|
async exchangeCodeForTokens(code, verifier, redirectUri) {
|
|
29093
|
-
log("[
|
|
30057
|
+
log("[CodexOAuth] Exchanging auth code for tokens");
|
|
29094
30058
|
try {
|
|
29095
30059
|
const response = await fetch(OAUTH_CONFIG2.tokenUrl, {
|
|
29096
30060
|
method: "POST",
|
|
@@ -29102,7 +30066,6 @@ Details: ${e.message}`);
|
|
|
29102
30066
|
code,
|
|
29103
30067
|
redirect_uri: redirectUri,
|
|
29104
30068
|
client_id: OAUTH_CONFIG2.clientId,
|
|
29105
|
-
client_secret: OAUTH_CONFIG2.clientSecret,
|
|
29106
30069
|
code_verifier: verifier
|
|
29107
30070
|
})
|
|
29108
30071
|
});
|
|
@@ -29116,7 +30079,7 @@ Details: ${e.message}`);
|
|
|
29116
30079
|
}
|
|
29117
30080
|
return tokens;
|
|
29118
30081
|
} catch (e) {
|
|
29119
|
-
throw new Error(`Failed to authenticate with
|
|
30082
|
+
throw new Error(`Failed to authenticate with OpenAI OAuth: ${e.message}`);
|
|
29120
30083
|
}
|
|
29121
30084
|
}
|
|
29122
30085
|
async openBrowser(url2) {
|
|
@@ -29130,7 +30093,7 @@ Details: ${e.message}`);
|
|
|
29130
30093
|
await execAsync2(`xdg-open "${url2}"`);
|
|
29131
30094
|
}
|
|
29132
30095
|
console.log(`
|
|
29133
|
-
Opening browser for authentication...`);
|
|
30096
|
+
Opening browser for OpenAI authentication...`);
|
|
29134
30097
|
console.log(`If the browser doesn't open, visit this URL:
|
|
29135
30098
|
${url2}
|
|
29136
30099
|
`);
|
|
@@ -29142,197 +30105,123 @@ Please open this URL in your browser to authenticate:`);
|
|
|
29142
30105
|
}
|
|
29143
30106
|
}
|
|
29144
30107
|
}
|
|
29145
|
-
function
|
|
29146
|
-
|
|
29147
|
-
resetGeminiUserCache();
|
|
29148
|
-
}
|
|
29149
|
-
async function getValidAccessToken() {
|
|
29150
|
-
const oauth = GeminiOAuth.getInstance();
|
|
29151
|
-
return oauth.getAccessToken();
|
|
29152
|
-
}
|
|
29153
|
-
function resetGeminiUserCache() {
|
|
29154
|
-
cachedProjectId = null;
|
|
29155
|
-
cachedTierId = null;
|
|
29156
|
-
cachedTierName = null;
|
|
29157
|
-
}
|
|
29158
|
-
function getGeminiTierDisplayName() {
|
|
29159
|
-
if (!cachedTierId)
|
|
29160
|
-
return "Gemini Free";
|
|
29161
|
-
return TIER_SHORT_NAMES[cachedTierId] || cachedTierId.replace(/-tier$/, "");
|
|
29162
|
-
}
|
|
29163
|
-
function getGeminiTierFullName() {
|
|
29164
|
-
if (cachedTierName)
|
|
29165
|
-
return cachedTierName;
|
|
29166
|
-
return getGeminiTierDisplayName();
|
|
30108
|
+
function getCodexOAuth() {
|
|
30109
|
+
return CodexOAuth.getInstance();
|
|
29167
30110
|
}
|
|
29168
|
-
|
|
29169
|
-
|
|
29170
|
-
|
|
29171
|
-
|
|
30111
|
+
var execAsync2, OAUTH_CONFIG2;
|
|
30112
|
+
var init_codex_oauth = __esm(() => {
|
|
30113
|
+
init_logger();
|
|
30114
|
+
execAsync2 = promisify2(exec2);
|
|
30115
|
+
OAUTH_CONFIG2 = {
|
|
30116
|
+
clientId: "app_EMoamEEZ73f0CkXaXp7hrann",
|
|
30117
|
+
authUrl: "https://auth.openai.com/oauth/authorize",
|
|
30118
|
+
tokenUrl: "https://auth.openai.com/oauth/token",
|
|
30119
|
+
scopes: ["openid", "profile", "email", "offline_access"]
|
|
30120
|
+
};
|
|
30121
|
+
});
|
|
30122
|
+
|
|
30123
|
+
// src/auth/credentials/composite-credential.ts
|
|
30124
|
+
class CompositeCredentialProvider {
|
|
30125
|
+
catalogName;
|
|
30126
|
+
primary;
|
|
30127
|
+
fallback;
|
|
30128
|
+
opts;
|
|
30129
|
+
constructor(catalogName, primary, fallback, opts = {}) {
|
|
30130
|
+
this.catalogName = catalogName;
|
|
30131
|
+
this.primary = primary;
|
|
30132
|
+
this.fallback = fallback;
|
|
30133
|
+
this.opts = opts;
|
|
29172
30134
|
}
|
|
29173
|
-
|
|
29174
|
-
|
|
29175
|
-
const loadRes = await callLoadCodeAssist(accessToken, envProject);
|
|
29176
|
-
log(`[GeminiOAuth] loadCodeAssist response: ${JSON.stringify(loadRes)}`);
|
|
29177
|
-
const resolvedTier = loadRes.paidTier?.id || (typeof loadRes.currentTier === "object" ? loadRes.currentTier?.id : loadRes.currentTier) || null;
|
|
29178
|
-
if ((loadRes.currentTier || loadRes.paidTier) && loadRes.cloudaicompanionProject) {
|
|
29179
|
-
const projectId2 = envProject || loadRes.cloudaicompanionProject;
|
|
29180
|
-
if (projectId2) {
|
|
29181
|
-
cachedProjectId = projectId2;
|
|
29182
|
-
cachedTierId = resolvedTier || "free-tier";
|
|
29183
|
-
cachedTierName = loadRes.paidTier?.name || null;
|
|
29184
|
-
log(`[GeminiOAuth] User already set up, project: ${projectId2}, tier: ${cachedTierId}`);
|
|
29185
|
-
return { projectId: projectId2, tierId: cachedTierId };
|
|
29186
|
-
}
|
|
30135
|
+
async isAvailable(opts) {
|
|
30136
|
+
return await this.primary.isAvailable(opts) || await this.fallback.isAvailable(opts);
|
|
29187
30137
|
}
|
|
29188
|
-
|
|
29189
|
-
|
|
29190
|
-
|
|
29191
|
-
const MAX_POLL_ATTEMPTS = 30;
|
|
29192
|
-
log(`[GeminiOAuth] Onboarding user to ${tierId}...`);
|
|
29193
|
-
let lro = await callOnboardUser(accessToken, tierId, onboardProject);
|
|
29194
|
-
log(`[GeminiOAuth] Initial onboardUser response: done=${lro.done}`);
|
|
29195
|
-
let attempts = 0;
|
|
29196
|
-
while (!lro.done && attempts < MAX_POLL_ATTEMPTS) {
|
|
29197
|
-
attempts++;
|
|
29198
|
-
log(`[GeminiOAuth] Polling onboardUser (attempt ${attempts}/${MAX_POLL_ATTEMPTS})...`);
|
|
29199
|
-
await new Promise((r) => setTimeout(r, 2000));
|
|
29200
|
-
lro = await callOnboardUser(accessToken, tierId, onboardProject);
|
|
30138
|
+
invalidate() {
|
|
30139
|
+
this.primary.invalidate?.();
|
|
30140
|
+
this.fallback.invalidate?.();
|
|
29201
30141
|
}
|
|
29202
|
-
|
|
29203
|
-
|
|
30142
|
+
async getRequestAuth(ctx) {
|
|
30143
|
+
if (await this.primary.isAvailable({ allowOpPrompt: ctx.allowOpPrompt })) {
|
|
30144
|
+
try {
|
|
30145
|
+
return await this.primary.getRequestAuth(ctx);
|
|
30146
|
+
} catch (e) {
|
|
30147
|
+
const signal = this.opts.fallbackSignal;
|
|
30148
|
+
if (signal && String(e?.message) === signal) {
|
|
30149
|
+
return this.fallback.getRequestAuth(ctx);
|
|
30150
|
+
}
|
|
30151
|
+
throw e;
|
|
30152
|
+
}
|
|
30153
|
+
}
|
|
30154
|
+
return this.fallback.getRequestAuth(ctx);
|
|
29204
30155
|
}
|
|
29205
|
-
|
|
29206
|
-
|
|
30156
|
+
async login() {
|
|
30157
|
+
await this.primary.login?.();
|
|
29207
30158
|
}
|
|
29208
|
-
|
|
29209
|
-
|
|
29210
|
-
if (envProject) {
|
|
29211
|
-
cachedProjectId = envProject;
|
|
29212
|
-
cachedTierId = tierId;
|
|
29213
|
-
return { projectId: envProject, tierId };
|
|
29214
|
-
}
|
|
29215
|
-
throw new Error("Gemini onboarding completed but no project ID returned.");
|
|
30159
|
+
async logout() {
|
|
30160
|
+
await this.primary.logout?.();
|
|
29216
30161
|
}
|
|
29217
|
-
cachedProjectId = projectId;
|
|
29218
|
-
cachedTierId = tierId;
|
|
29219
|
-
log(`[GeminiOAuth] Onboarding complete, project: ${projectId}, tier: ${tierId}`);
|
|
29220
|
-
return { projectId, tierId };
|
|
29221
30162
|
}
|
|
29222
|
-
|
|
29223
|
-
|
|
29224
|
-
|
|
29225
|
-
|
|
29226
|
-
|
|
29227
|
-
|
|
30163
|
+
|
|
30164
|
+
// src/auth/credentials/codex-credential.ts
|
|
30165
|
+
function buildOAuthHeaders(token, accountId) {
|
|
30166
|
+
const headers = {
|
|
30167
|
+
Authorization: `Bearer ${token}`,
|
|
30168
|
+
"OpenAI-Beta": "responses=experimental",
|
|
30169
|
+
originator: "codex_cli_rs",
|
|
30170
|
+
accept: "text/event-stream"
|
|
29228
30171
|
};
|
|
29229
|
-
|
|
29230
|
-
|
|
29231
|
-
headers
|
|
29232
|
-
|
|
29233
|
-
"Content-Type": "application/json"
|
|
29234
|
-
},
|
|
29235
|
-
body: JSON.stringify({ metadata, cloudaicompanionProject: projectId })
|
|
29236
|
-
});
|
|
29237
|
-
if (!res.ok) {
|
|
29238
|
-
throw new Error(`loadCodeAssist failed: ${res.status} ${await res.text()}`);
|
|
30172
|
+
if (accountId) {
|
|
30173
|
+
headers["chatgpt-account-id"] = accountId;
|
|
30174
|
+
headers["x-conversation-id"] = "claudish-session";
|
|
30175
|
+
headers["x-session-id"] = "claudish-session";
|
|
29239
30176
|
}
|
|
29240
|
-
return
|
|
30177
|
+
return headers;
|
|
29241
30178
|
}
|
|
29242
|
-
|
|
29243
|
-
|
|
29244
|
-
|
|
29245
|
-
|
|
29246
|
-
|
|
29247
|
-
|
|
29248
|
-
};
|
|
29249
|
-
const res = await fetch(`${CODE_ASSIST_API_BASE}:onboardUser`, {
|
|
29250
|
-
method: "POST",
|
|
29251
|
-
headers: {
|
|
29252
|
-
Authorization: `Bearer ${accessToken}`,
|
|
29253
|
-
"Content-Type": "application/json"
|
|
29254
|
-
},
|
|
29255
|
-
body: JSON.stringify({
|
|
29256
|
-
tierId,
|
|
29257
|
-
metadata,
|
|
29258
|
-
cloudaicompanionProject: projectId
|
|
29259
|
-
})
|
|
29260
|
-
});
|
|
29261
|
-
if (!res.ok) {
|
|
29262
|
-
throw new Error(`onboardUser failed: ${res.status} ${await res.text()}`);
|
|
30179
|
+
|
|
30180
|
+
class CodexOAuthHalf {
|
|
30181
|
+
catalogName = "openai-codex";
|
|
30182
|
+
oauth = CodexOAuth.getInstance();
|
|
30183
|
+
async isAvailable() {
|
|
30184
|
+
return this.oauth.hasCredentials();
|
|
29263
30185
|
}
|
|
29264
|
-
|
|
29265
|
-
|
|
29266
|
-
|
|
29267
|
-
|
|
29268
|
-
|
|
29269
|
-
|
|
29270
|
-
|
|
29271
|
-
|
|
29272
|
-
|
|
29273
|
-
|
|
29274
|
-
}
|
|
29275
|
-
|
|
29276
|
-
|
|
29277
|
-
|
|
29278
|
-
|
|
29279
|
-
|
|
29280
|
-
|
|
29281
|
-
|
|
29282
|
-
} catch (err) {
|
|
29283
|
-
log(`[GeminiOAuth] retrieveUserQuota error: ${err}`);
|
|
29284
|
-
return null;
|
|
30186
|
+
async getRequestAuth(_ctx) {
|
|
30187
|
+
const token = await this.oauth.getAccessToken();
|
|
30188
|
+
const accountId = this.oauth.getAccountId();
|
|
30189
|
+
return {
|
|
30190
|
+
headers: buildOAuthHeaders(token, accountId),
|
|
30191
|
+
endpoint: CODEX_RESPONSES_ENDPOINT,
|
|
30192
|
+
transformPayload: (p) => ({
|
|
30193
|
+
...p,
|
|
30194
|
+
store: false,
|
|
30195
|
+
include: ["reasoning.encrypted_content"]
|
|
30196
|
+
})
|
|
30197
|
+
};
|
|
30198
|
+
}
|
|
30199
|
+
async login() {
|
|
30200
|
+
await this.oauth.login();
|
|
30201
|
+
}
|
|
30202
|
+
async logout() {
|
|
30203
|
+
await this.oauth.logout();
|
|
29285
30204
|
}
|
|
29286
30205
|
}
|
|
29287
|
-
|
|
29288
|
-
|
|
29289
|
-
"
|
|
29290
|
-
"
|
|
29291
|
-
|
|
29292
|
-
|
|
29293
|
-
|
|
29294
|
-
|
|
29295
|
-
|
|
29296
|
-
|
|
29297
|
-
const p = ["GOCSPX", "4uHgMPm", "1o7Sk", "geV6Cu5clXFsxl"];
|
|
29298
|
-
return `${p[0]}-${p[1]}-${p[2]}-${p[3]}`;
|
|
29299
|
-
}, OAUTH_CONFIG2, CODE_ASSIST_API_BASE = "https://cloudcode-pa.googleapis.com/v1internal", CODE_ASSIST_FALLBACK_CHAIN, cachedProjectId = null, cachedTierId = null, cachedTierName = null, TIER_SHORT_NAMES;
|
|
29300
|
-
var init_gemini_oauth = __esm(() => {
|
|
29301
|
-
init_logger();
|
|
29302
|
-
execAsync2 = promisify2(exec2);
|
|
29303
|
-
OAUTH_CONFIG2 = {
|
|
29304
|
-
clientId: process.env.GEMINI_CLIENT_ID || getDefaultClientId(),
|
|
29305
|
-
clientSecret: process.env.GEMINI_CLIENT_SECRET || getDefaultClientSecret(),
|
|
29306
|
-
authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
29307
|
-
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
29308
|
-
scopes: [
|
|
29309
|
-
"https://www.googleapis.com/auth/cloud-platform",
|
|
29310
|
-
"https://www.googleapis.com/auth/userinfo.email",
|
|
29311
|
-
"https://www.googleapis.com/auth/userinfo.profile"
|
|
29312
|
-
]
|
|
29313
|
-
};
|
|
29314
|
-
CODE_ASSIST_FALLBACK_CHAIN = [
|
|
29315
|
-
"gemini-3.1-pro-preview",
|
|
29316
|
-
"gemini-3-pro-preview",
|
|
29317
|
-
"gemini-3-flash-preview",
|
|
29318
|
-
"gemini-2.5-pro",
|
|
29319
|
-
"gemini-2.5-flash"
|
|
29320
|
-
];
|
|
29321
|
-
TIER_SHORT_NAMES = {
|
|
29322
|
-
"free-tier": "GeminiCA Free",
|
|
29323
|
-
"standard-tier": "GeminiCA Std",
|
|
29324
|
-
"g1-pro-tier": "GeminiCA Pro",
|
|
29325
|
-
"legacy-tier": "GeminiCA Legacy"
|
|
29326
|
-
};
|
|
30206
|
+
function makeCodexCredential() {
|
|
30207
|
+
return new CompositeCredentialProvider("openai-codex", new CodexOAuthHalf, new ApiKeyCredentialProvider({
|
|
30208
|
+
catalogName: "openai-codex",
|
|
30209
|
+
envVar: "OPENAI_CODEX_API_KEY"
|
|
30210
|
+
}));
|
|
30211
|
+
}
|
|
30212
|
+
var CODEX_RESPONSES_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
|
|
30213
|
+
var init_codex_credential = __esm(() => {
|
|
30214
|
+
init_codex_oauth();
|
|
30215
|
+
init_api_key_credential();
|
|
29327
30216
|
});
|
|
29328
30217
|
|
|
29329
30218
|
// src/auth/oauth-registry.ts
|
|
29330
|
-
import { existsSync as
|
|
29331
|
-
import { homedir as
|
|
29332
|
-
import { join as
|
|
30219
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
|
|
30220
|
+
import { homedir as homedir12 } from "os";
|
|
30221
|
+
import { join as join12 } from "path";
|
|
29333
30222
|
function hasValidOAuthCredentials(descriptor) {
|
|
29334
|
-
const credPath =
|
|
29335
|
-
if (!
|
|
30223
|
+
const credPath = join12(homedir12(), ".claudish", descriptor.credentialFile);
|
|
30224
|
+
if (!existsSync10(credPath))
|
|
29336
30225
|
return false;
|
|
29337
30226
|
if (descriptor.validationMode === "file-exists") {
|
|
29338
30227
|
return true;
|
|
@@ -29395,13 +30284,8 @@ var init_oauth_registry = __esm(() => {
|
|
|
29395
30284
|
});
|
|
29396
30285
|
|
|
29397
30286
|
// src/auth/credentials/gemini-credential.ts
|
|
29398
|
-
import { randomUUID } from "crypto";
|
|
29399
|
-
function
|
|
29400
|
-
const version2 = "0.5.6";
|
|
29401
|
-
const modelSegment = model || "gemini-code-assist";
|
|
29402
|
-
return `GeminiCLI/${version2}/${modelSegment} (${process.platform}; ${process.arch})`;
|
|
29403
|
-
}
|
|
29404
|
-
function createActivityRequestId() {
|
|
30287
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
30288
|
+
function createActivityRequestId3() {
|
|
29405
30289
|
return Math.random().toString(36).substring(7);
|
|
29406
30290
|
}
|
|
29407
30291
|
|
|
@@ -29416,14 +30300,14 @@ class GeminiCodeAssistCredentialProvider {
|
|
|
29416
30300
|
return {
|
|
29417
30301
|
headers: {
|
|
29418
30302
|
Authorization: `Bearer ${token}`,
|
|
29419
|
-
"User-Agent":
|
|
29420
|
-
"x-activity-request-id":
|
|
30303
|
+
"User-Agent": buildCodeAssistUserAgent(ctx.model),
|
|
30304
|
+
"x-activity-request-id": createActivityRequestId3()
|
|
29421
30305
|
},
|
|
29422
30306
|
transformPayload: (inner) => {
|
|
29423
30307
|
const env = {
|
|
29424
30308
|
model: ctx.model,
|
|
29425
30309
|
project: projectId,
|
|
29426
|
-
user_prompt_id:
|
|
30310
|
+
user_prompt_id: randomUUID3(),
|
|
29427
30311
|
request: inner
|
|
29428
30312
|
};
|
|
29429
30313
|
if (tierId && tierId !== "free-tier") {
|
|
@@ -29448,9 +30332,9 @@ var init_gemini_credential = __esm(() => {
|
|
|
29448
30332
|
// src/auth/kimi-oauth.ts
|
|
29449
30333
|
import { exec as exec3 } from "child_process";
|
|
29450
30334
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
29451
|
-
import { closeSync as closeSync4, existsSync as
|
|
29452
|
-
import { homedir as
|
|
29453
|
-
import { join as
|
|
30335
|
+
import { closeSync as closeSync4, existsSync as existsSync11, openSync as openSync4, readFileSync as readFileSync9, unlinkSync as unlinkSync4, writeSync as writeSync4 } from "fs";
|
|
30336
|
+
import { homedir as homedir13, hostname as hostname3, platform, release as release2 } from "os";
|
|
30337
|
+
import { join as join13 } from "path";
|
|
29454
30338
|
import { promisify as promisify3 } from "util";
|
|
29455
30339
|
|
|
29456
30340
|
class KimiOAuth {
|
|
@@ -29478,21 +30362,21 @@ class KimiOAuth {
|
|
|
29478
30362
|
return this.credentials !== null && !!this.credentials.refresh_token;
|
|
29479
30363
|
}
|
|
29480
30364
|
getCredentialsPath() {
|
|
29481
|
-
const claudishDir =
|
|
29482
|
-
return
|
|
30365
|
+
const claudishDir = join13(homedir13(), ".claudish");
|
|
30366
|
+
return join13(claudishDir, "kimi-oauth.json");
|
|
29483
30367
|
}
|
|
29484
30368
|
getDeviceIdPath() {
|
|
29485
|
-
const claudishDir =
|
|
29486
|
-
return
|
|
30369
|
+
const claudishDir = join13(homedir13(), ".claudish");
|
|
30370
|
+
return join13(claudishDir, "kimi-device-id");
|
|
29487
30371
|
}
|
|
29488
30372
|
loadOrCreateDeviceId() {
|
|
29489
30373
|
const deviceIdPath = this.getDeviceIdPath();
|
|
29490
|
-
const claudishDir =
|
|
29491
|
-
if (!
|
|
30374
|
+
const claudishDir = join13(homedir13(), ".claudish");
|
|
30375
|
+
if (!existsSync11(claudishDir)) {
|
|
29492
30376
|
const { mkdirSync: mkdirSync6 } = __require("fs");
|
|
29493
30377
|
mkdirSync6(claudishDir, { recursive: true });
|
|
29494
30378
|
}
|
|
29495
|
-
if (
|
|
30379
|
+
if (existsSync11(deviceIdPath)) {
|
|
29496
30380
|
try {
|
|
29497
30381
|
const deviceId2 = readFileSync9(deviceIdPath, "utf-8").trim();
|
|
29498
30382
|
if (deviceId2) {
|
|
@@ -29544,15 +30428,15 @@ Please authorize this device:`);
|
|
|
29544
30428
|
Waiting for authorization...`);
|
|
29545
30429
|
await this.openBrowser(deviceAuth.verification_uri_complete);
|
|
29546
30430
|
const tokens = await this.pollForToken(deviceAuth.device_code, deviceAuth.interval, deviceAuth.expires_in);
|
|
29547
|
-
const
|
|
30431
|
+
const credentials2 = {
|
|
29548
30432
|
access_token: tokens.access_token,
|
|
29549
30433
|
refresh_token: tokens.refresh_token,
|
|
29550
30434
|
expires_at: Date.now() + tokens.expires_in * 1000,
|
|
29551
30435
|
scope: tokens.scope,
|
|
29552
30436
|
token_type: tokens.token_type
|
|
29553
30437
|
};
|
|
29554
|
-
this.saveCredentials(
|
|
29555
|
-
this.credentials =
|
|
30438
|
+
this.saveCredentials(credentials2);
|
|
30439
|
+
this.credentials = credentials2;
|
|
29556
30440
|
log("[KimiOAuth] Login successful");
|
|
29557
30441
|
}
|
|
29558
30442
|
async requestDeviceAuthorization() {
|
|
@@ -29665,7 +30549,7 @@ Waiting for authorization...`);
|
|
|
29665
30549
|
}
|
|
29666
30550
|
async logout() {
|
|
29667
30551
|
const credPath = this.getCredentialsPath();
|
|
29668
|
-
if (
|
|
30552
|
+
if (existsSync11(credPath)) {
|
|
29669
30553
|
unlinkSync4(credPath);
|
|
29670
30554
|
log("[KimiOAuth] Credentials deleted");
|
|
29671
30555
|
}
|
|
@@ -29732,7 +30616,7 @@ Waiting for authorization...`);
|
|
|
29732
30616
|
} catch (e) {
|
|
29733
30617
|
log(`[KimiOAuth] Refresh failed: ${e.message}`);
|
|
29734
30618
|
const credPath = this.getCredentialsPath();
|
|
29735
|
-
if (
|
|
30619
|
+
if (existsSync11(credPath)) {
|
|
29736
30620
|
unlinkSync4(credPath);
|
|
29737
30621
|
}
|
|
29738
30622
|
this.credentials = null;
|
|
@@ -29749,33 +30633,33 @@ Details: ${e.message}`);
|
|
|
29749
30633
|
}
|
|
29750
30634
|
loadCredentials() {
|
|
29751
30635
|
const credPath = this.getCredentialsPath();
|
|
29752
|
-
if (!
|
|
30636
|
+
if (!existsSync11(credPath)) {
|
|
29753
30637
|
return null;
|
|
29754
30638
|
}
|
|
29755
30639
|
try {
|
|
29756
30640
|
const data = readFileSync9(credPath, "utf-8");
|
|
29757
|
-
const
|
|
29758
|
-
if (!
|
|
30641
|
+
const credentials2 = JSON.parse(data);
|
|
30642
|
+
if (!credentials2.access_token || !credentials2.refresh_token || !credentials2.expires_at || !credentials2.scope || !credentials2.token_type) {
|
|
29759
30643
|
log("[KimiOAuth] Invalid credentials file structure");
|
|
29760
30644
|
return null;
|
|
29761
30645
|
}
|
|
29762
30646
|
log("[KimiOAuth] Loaded credentials from file");
|
|
29763
|
-
return
|
|
30647
|
+
return credentials2;
|
|
29764
30648
|
} catch (e) {
|
|
29765
30649
|
log(`[KimiOAuth] Failed to load credentials: ${e.message}`);
|
|
29766
30650
|
return null;
|
|
29767
30651
|
}
|
|
29768
30652
|
}
|
|
29769
|
-
saveCredentials(
|
|
30653
|
+
saveCredentials(credentials2) {
|
|
29770
30654
|
const credPath = this.getCredentialsPath();
|
|
29771
|
-
const claudishDir =
|
|
29772
|
-
if (!
|
|
30655
|
+
const claudishDir = join13(homedir13(), ".claudish");
|
|
30656
|
+
if (!existsSync11(claudishDir)) {
|
|
29773
30657
|
const { mkdirSync: mkdirSync6 } = __require("fs");
|
|
29774
30658
|
mkdirSync6(claudishDir, { recursive: true });
|
|
29775
30659
|
}
|
|
29776
30660
|
const fd = openSync4(credPath, "w", 384);
|
|
29777
30661
|
try {
|
|
29778
|
-
const data = JSON.stringify(
|
|
30662
|
+
const data = JSON.stringify(credentials2, null, 2);
|
|
29779
30663
|
writeSync4(fd, data, 0, "utf-8");
|
|
29780
30664
|
} finally {
|
|
29781
30665
|
closeSync4(fd);
|
|
@@ -29943,9 +30827,9 @@ var init_native_anthropic_credential = __esm(() => {
|
|
|
29943
30827
|
|
|
29944
30828
|
// src/auth/vertex-auth.ts
|
|
29945
30829
|
import { exec as exec4 } from "child_process";
|
|
29946
|
-
import { existsSync as
|
|
29947
|
-
import { homedir as
|
|
29948
|
-
import { join as
|
|
30830
|
+
import { existsSync as existsSync12 } from "fs";
|
|
30831
|
+
import { homedir as homedir14 } from "os";
|
|
30832
|
+
import { join as join14 } from "path";
|
|
29949
30833
|
import { promisify as promisify4 } from "util";
|
|
29950
30834
|
|
|
29951
30835
|
class VertexAuthManager {
|
|
@@ -30000,8 +30884,8 @@ class VertexAuthManager {
|
|
|
30000
30884
|
}
|
|
30001
30885
|
async tryADC() {
|
|
30002
30886
|
try {
|
|
30003
|
-
const adcPath =
|
|
30004
|
-
if (!
|
|
30887
|
+
const adcPath = join14(homedir14(), ".config/gcloud/application_default_credentials.json");
|
|
30888
|
+
if (!existsSync12(adcPath)) {
|
|
30005
30889
|
log("[VertexAuth] ADC credentials file not found");
|
|
30006
30890
|
return null;
|
|
30007
30891
|
}
|
|
@@ -30025,7 +30909,7 @@ class VertexAuthManager {
|
|
|
30025
30909
|
if (!credPath) {
|
|
30026
30910
|
return null;
|
|
30027
30911
|
}
|
|
30028
|
-
if (!
|
|
30912
|
+
if (!existsSync12(credPath)) {
|
|
30029
30913
|
throw new Error(`Service account file not found: ${credPath}
|
|
30030
30914
|
|
|
30031
30915
|
Check GOOGLE_APPLICATION_CREDENTIALS path.`);
|
|
@@ -30064,8 +30948,8 @@ function validateVertexOAuthConfig() {
|
|
|
30064
30948
|
` + ` export VERTEX_PROJECT='your-gcp-project-id'
|
|
30065
30949
|
` + " export VERTEX_LOCATION='us-central1' # optional";
|
|
30066
30950
|
}
|
|
30067
|
-
const adcPath =
|
|
30068
|
-
const hasADC =
|
|
30951
|
+
const adcPath = join14(homedir14(), ".config/gcloud/application_default_credentials.json");
|
|
30952
|
+
const hasADC = existsSync12(adcPath);
|
|
30069
30953
|
const hasServiceAccount = !!process.env.GOOGLE_APPLICATION_CREDENTIALS;
|
|
30070
30954
|
if (!hasADC && !hasServiceAccount) {
|
|
30071
30955
|
return `No Vertex AI credentials found.
|
|
@@ -30184,6 +31068,7 @@ class CredentialAuthority {
|
|
|
30184
31068
|
const authority = new CredentialAuthority;
|
|
30185
31069
|
authority.register(makeCodexCredential(), ["openai-codex"]);
|
|
30186
31070
|
authority.register(new GeminiCodeAssistCredentialProvider, ["gemini-codeassist"]);
|
|
31071
|
+
authority.register(new AntigravityCredentialProvider, ["antigravity"]);
|
|
30187
31072
|
authority.register(makeKimiCredential(), ["kimi"]);
|
|
30188
31073
|
authority.register(makeKimiCodingCredential(), ["kimi-coding"]);
|
|
30189
31074
|
authority.register(new VertexCredentialProvider, ["vertex"]);
|
|
@@ -30194,6 +31079,7 @@ class CredentialAuthority {
|
|
|
30194
31079
|
const alreadyRegistered = new Set([
|
|
30195
31080
|
"openai-codex",
|
|
30196
31081
|
"gemini-codeassist",
|
|
31082
|
+
"antigravity",
|
|
30197
31083
|
"kimi",
|
|
30198
31084
|
"kimi-coding",
|
|
30199
31085
|
"vertex",
|
|
@@ -30222,6 +31108,7 @@ class CredentialAuthority {
|
|
|
30222
31108
|
var LOCAL_PROVIDER_NAMES, RUNTIME_NAME_ALIASES, credentials;
|
|
30223
31109
|
var init_authority = __esm(() => {
|
|
30224
31110
|
init_provider_definitions();
|
|
31111
|
+
init_antigravity_credential();
|
|
30225
31112
|
init_api_key_credential();
|
|
30226
31113
|
init_codex_credential();
|
|
30227
31114
|
init_gemini_credential();
|
|
@@ -30237,6 +31124,13 @@ var init_authority = __esm(() => {
|
|
|
30237
31124
|
});
|
|
30238
31125
|
|
|
30239
31126
|
// src/providers/model-parser.ts
|
|
31127
|
+
function warnGoAliasDeprecatedOnce() {
|
|
31128
|
+
if (_goDeprecationWarned)
|
|
31129
|
+
return;
|
|
31130
|
+
_goDeprecationWarned = true;
|
|
31131
|
+
process.stderr.write(`[claudish] go@ is deprecated \u2014 use ag@<model> (Antigravity). Routing there.
|
|
31132
|
+
`);
|
|
31133
|
+
}
|
|
30240
31134
|
function parseModelSpec(modelSpec) {
|
|
30241
31135
|
const original = modelSpec;
|
|
30242
31136
|
if (modelSpec.startsWith("http://") || modelSpec.startsWith("https://")) {
|
|
@@ -30259,6 +31153,8 @@ function parseModelSpec(modelSpec) {
|
|
|
30259
31153
|
concurrency = Number.parseInt(concurrencyMatch[2], 10);
|
|
30260
31154
|
}
|
|
30261
31155
|
const provider = PROVIDER_SHORTCUTS[providerPart] || providerPart;
|
|
31156
|
+
if (providerPart === "go")
|
|
31157
|
+
warnGoAliasDeprecatedOnce();
|
|
30262
31158
|
return {
|
|
30263
31159
|
provider,
|
|
30264
31160
|
model: modelPart,
|
|
@@ -30272,6 +31168,8 @@ function parseModelSpec(modelSpec) {
|
|
|
30272
31168
|
for (const { prefix, provider, stripPrefix } of LEGACY_PREFIX_PATTERNS) {
|
|
30273
31169
|
if (lowerSpec.startsWith(prefix)) {
|
|
30274
31170
|
const model = stripPrefix ? modelSpec.slice(prefix.length) : modelSpec;
|
|
31171
|
+
if (prefix === "go/")
|
|
31172
|
+
warnGoAliasDeprecatedOnce();
|
|
30275
31173
|
let concurrency;
|
|
30276
31174
|
let modelName = model;
|
|
30277
31175
|
if (LOCAL_PROVIDERS.has(provider)) {
|
|
@@ -30332,7 +31230,7 @@ function getLegacySyntaxWarning(parsed) {
|
|
|
30332
31230
|
return `Deprecation warning: "${parsed.original}" uses legacy prefix syntax.
|
|
30333
31231
|
` + ` Consider using: ${newSyntax}`;
|
|
30334
31232
|
}
|
|
30335
|
-
var PROVIDER_SHORTCUTS, LOCAL_PROVIDERS, NATIVE_MODEL_PATTERNS, LEGACY_PREFIX_PATTERNS;
|
|
31233
|
+
var PROVIDER_SHORTCUTS, _goDeprecationWarned = false, LOCAL_PROVIDERS, NATIVE_MODEL_PATTERNS, LEGACY_PREFIX_PATTERNS;
|
|
30336
31234
|
var init_model_parser = __esm(() => {
|
|
30337
31235
|
init_provider_definitions();
|
|
30338
31236
|
PROVIDER_SHORTCUTS = getShortcuts();
|
|
@@ -30612,11 +31510,11 @@ var init_routing_hints = __esm(() => {
|
|
|
30612
31510
|
});
|
|
30613
31511
|
|
|
30614
31512
|
// src/providers/all-models-cache.ts
|
|
30615
|
-
import { existsSync as
|
|
30616
|
-
import { homedir as
|
|
30617
|
-
import { dirname as dirname5, join as
|
|
31513
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
|
|
31514
|
+
import { homedir as homedir15 } from "os";
|
|
31515
|
+
import { dirname as dirname5, join as join15 } from "path";
|
|
30618
31516
|
function readAllModelsCache(path = ALL_MODELS_CACHE_PATH) {
|
|
30619
|
-
if (!
|
|
31517
|
+
if (!existsSync13(path))
|
|
30620
31518
|
return null;
|
|
30621
31519
|
let raw;
|
|
30622
31520
|
try {
|
|
@@ -30650,7 +31548,7 @@ function writeAllModelsCache(data, path = ALL_MODELS_CACHE_PATH) {
|
|
|
30650
31548
|
}
|
|
30651
31549
|
var ALL_MODELS_CACHE_PATH;
|
|
30652
31550
|
var init_all_models_cache = __esm(() => {
|
|
30653
|
-
ALL_MODELS_CACHE_PATH =
|
|
31551
|
+
ALL_MODELS_CACHE_PATH = join15(homedir15(), ".claudish", "all-models.json");
|
|
30654
31552
|
});
|
|
30655
31553
|
|
|
30656
31554
|
// src/adapters/model-catalog.ts
|
|
@@ -31745,10 +32643,10 @@ var init_signal_watcher = __esm(() => {
|
|
|
31745
32643
|
|
|
31746
32644
|
// src/channel/session-manager.ts
|
|
31747
32645
|
import { spawn } from "child_process";
|
|
31748
|
-
import { randomUUID as
|
|
32646
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
31749
32647
|
import { createWriteStream, mkdirSync as mkdirSync7, writeFileSync as writeFileSync7 } from "fs";
|
|
31750
|
-
import { homedir as
|
|
31751
|
-
import { join as
|
|
32648
|
+
import { homedir as homedir16 } from "os";
|
|
32649
|
+
import { join as join16 } from "path";
|
|
31752
32650
|
|
|
31753
32651
|
class SessionManager {
|
|
31754
32652
|
sessions = new Map;
|
|
@@ -31765,13 +32663,13 @@ class SessionManager {
|
|
|
31765
32663
|
if (this.activeSessions >= this.maxSessions) {
|
|
31766
32664
|
throw new Error(`Max sessions (${this.maxSessions}) reached`);
|
|
31767
32665
|
}
|
|
31768
|
-
const sessionId =
|
|
32666
|
+
const sessionId = randomUUID4().slice(0, 8);
|
|
31769
32667
|
const timeout = Math.min(opts.timeoutSeconds ?? DEFAULT_TIMEOUT, MAX_TIMEOUT);
|
|
31770
32668
|
const startedAt = new Date().toISOString();
|
|
31771
|
-
const sessionDir =
|
|
32669
|
+
const sessionDir = join16(homedir16(), ".claudish", "sessions", sessionId);
|
|
31772
32670
|
mkdirSync7(sessionDir, { recursive: true });
|
|
31773
32671
|
if (opts.prompt) {
|
|
31774
|
-
writeFileSync7(
|
|
32672
|
+
writeFileSync7(join16(sessionDir, "prompt.md"), opts.prompt, "utf-8");
|
|
31775
32673
|
}
|
|
31776
32674
|
const args = ["--model", opts.model, "-y", "--stdin", "--quiet", ...opts.claudishFlags ?? []];
|
|
31777
32675
|
const proc = spawn("claudish", args, {
|
|
@@ -31798,7 +32696,7 @@ class SessionManager {
|
|
|
31798
32696
|
});
|
|
31799
32697
|
}
|
|
31800
32698
|
});
|
|
31801
|
-
const outputLogStream = createWriteStream(
|
|
32699
|
+
const outputLogStream = createWriteStream(join16(sessionDir, "output.log"));
|
|
31802
32700
|
const entry = {
|
|
31803
32701
|
info: {
|
|
31804
32702
|
sessionId,
|
|
@@ -31845,9 +32743,9 @@ class SessionManager {
|
|
|
31845
32743
|
watcher.processExited(code);
|
|
31846
32744
|
outputLogStream.end();
|
|
31847
32745
|
if (entry.stderr) {
|
|
31848
|
-
writeFileSync7(
|
|
32746
|
+
writeFileSync7(join16(sessionDir, "stderr.log"), entry.stderr, "utf-8");
|
|
31849
32747
|
}
|
|
31850
|
-
writeFileSync7(
|
|
32748
|
+
writeFileSync7(join16(sessionDir, "meta.json"), JSON.stringify(entry.info, null, 2), "utf-8");
|
|
31851
32749
|
this.cleanupSigint();
|
|
31852
32750
|
});
|
|
31853
32751
|
proc.on("error", (err) => {
|
|
@@ -32020,9 +32918,9 @@ var init_cache_ttl = __esm(() => {
|
|
|
32020
32918
|
});
|
|
32021
32919
|
|
|
32022
32920
|
// src/model-loader.ts
|
|
32023
|
-
import { existsSync as
|
|
32024
|
-
import { homedir as
|
|
32025
|
-
import { join as
|
|
32921
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "fs";
|
|
32922
|
+
import { homedir as homedir17 } from "os";
|
|
32923
|
+
import { join as join17 } from "path";
|
|
32026
32924
|
function groupRecommendedModels(entries) {
|
|
32027
32925
|
const byId = new Map;
|
|
32028
32926
|
for (const entry of entries) {
|
|
@@ -32118,7 +33016,7 @@ async function getRecommendedModels(opts = {}) {
|
|
|
32118
33016
|
if (!forceRefresh && _cachedRecommendedModels) {
|
|
32119
33017
|
return _cachedRecommendedModels;
|
|
32120
33018
|
}
|
|
32121
|
-
if (!forceRefresh &&
|
|
33019
|
+
if (!forceRefresh && existsSync14(RECOMMENDED_MODELS_CACHE_PATH)) {
|
|
32122
33020
|
try {
|
|
32123
33021
|
const cacheData = JSON.parse(readFileSync11(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
|
|
32124
33022
|
if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
|
|
@@ -32136,7 +33034,7 @@ async function getRecommendedModels(opts = {}) {
|
|
|
32136
33034
|
if (data.models && data.models.length > 0) {
|
|
32137
33035
|
_cachedRecommendedModels = data;
|
|
32138
33036
|
try {
|
|
32139
|
-
const cacheDir =
|
|
33037
|
+
const cacheDir = join17(homedir17(), ".claudish");
|
|
32140
33038
|
mkdirSync8(cacheDir, { recursive: true });
|
|
32141
33039
|
writeFileSync8(RECOMMENDED_MODELS_CACHE_PATH, JSON.stringify(data), "utf-8");
|
|
32142
33040
|
} catch {}
|
|
@@ -32149,7 +33047,7 @@ async function getRecommendedModels(opts = {}) {
|
|
|
32149
33047
|
function getRecommendedModelsSync() {
|
|
32150
33048
|
if (_cachedRecommendedModels)
|
|
32151
33049
|
return _cachedRecommendedModels;
|
|
32152
|
-
if (
|
|
33050
|
+
if (existsSync14(RECOMMENDED_MODELS_CACHE_PATH)) {
|
|
32153
33051
|
try {
|
|
32154
33052
|
const cacheData = JSON.parse(readFileSync11(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
|
|
32155
33053
|
if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
|
|
@@ -32275,7 +33173,7 @@ var _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels =
|
|
|
32275
33173
|
var init_model_loader = __esm(() => {
|
|
32276
33174
|
init_cache_ttl();
|
|
32277
33175
|
FIREBASE_RECOMMENDED_URL = `${FIREBASE_BASE_URL}?catalog=recommended`;
|
|
32278
|
-
RECOMMENDED_MODELS_CACHE_PATH =
|
|
33176
|
+
RECOMMENDED_MODELS_CACHE_PATH = join17(homedir17(), ".claudish", "recommended-models-cache.json");
|
|
32279
33177
|
FIREBASE_SLUG_TO_PROVIDER_NAME = {
|
|
32280
33178
|
openai: "openai",
|
|
32281
33179
|
google: "google",
|
|
@@ -37176,8 +38074,8 @@ var init_harness = __esm(() => {
|
|
|
37176
38074
|
|
|
37177
38075
|
// src/behavior/journal.ts
|
|
37178
38076
|
import { appendFile as appendFile2, mkdir, stat } from "fs/promises";
|
|
37179
|
-
import { homedir as
|
|
37180
|
-
import { dirname as dirname6, join as
|
|
38077
|
+
import { homedir as homedir18 } from "os";
|
|
38078
|
+
import { dirname as dirname6, join as join18 } from "path";
|
|
37181
38079
|
function classifyPath(observed, expected) {
|
|
37182
38080
|
if (!observed)
|
|
37183
38081
|
return "not_applicable";
|
|
@@ -37189,7 +38087,7 @@ function classifyPath(observed, expected) {
|
|
|
37189
38087
|
return dirOf(observed) === dirOf(expected) ? "same_dir_wrong_name" : "outside_expected_dir";
|
|
37190
38088
|
}
|
|
37191
38089
|
function journalPath() {
|
|
37192
|
-
return
|
|
38090
|
+
return join18(homedir18(), ".claudish", "behavior-journal.jsonl");
|
|
37193
38091
|
}
|
|
37194
38092
|
async function recordDecision(entry, path = journalPath()) {
|
|
37195
38093
|
try {
|
|
@@ -37406,10 +38304,10 @@ __export(exports_live_log, {
|
|
|
37406
38304
|
recordLiveDivergence: () => recordLiveDivergence
|
|
37407
38305
|
});
|
|
37408
38306
|
import { appendFile as appendFile3 } from "fs/promises";
|
|
37409
|
-
import { homedir as
|
|
37410
|
-
import { join as
|
|
38307
|
+
import { homedir as homedir19 } from "os";
|
|
38308
|
+
import { join as join19 } from "path";
|
|
37411
38309
|
function defaultPath() {
|
|
37412
|
-
return
|
|
38310
|
+
return join19(homedir19(), ".claudish", "behavior-divergences.jsonl");
|
|
37413
38311
|
}
|
|
37414
38312
|
async function recordLiveDivergence(entry, path = defaultPath()) {
|
|
37415
38313
|
try {
|
|
@@ -37830,8 +38728,8 @@ var init_hooks = __esm(() => {
|
|
|
37830
38728
|
|
|
37831
38729
|
// src/behavior/observer/corpus.ts
|
|
37832
38730
|
import { appendFileSync as appendFileSync3, readFileSync as readFileSync12, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
37833
|
-
import { homedir as
|
|
37834
|
-
import { join as
|
|
38731
|
+
import { homedir as homedir20 } from "os";
|
|
38732
|
+
import { join as join20 } from "path";
|
|
37835
38733
|
function directoryOf2(filePath) {
|
|
37836
38734
|
const slash = filePath.lastIndexOf("/");
|
|
37837
38735
|
return slash > 0 ? filePath.slice(0, slash) : undefined;
|
|
@@ -37910,26 +38808,26 @@ function listTranscripts(root) {
|
|
|
37910
38808
|
return files;
|
|
37911
38809
|
}
|
|
37912
38810
|
for (const project of projects) {
|
|
37913
|
-
const dir =
|
|
38811
|
+
const dir = join20(root, project);
|
|
37914
38812
|
try {
|
|
37915
38813
|
if (!statSync2(dir).isDirectory())
|
|
37916
38814
|
continue;
|
|
37917
38815
|
for (const f of readdirSync2(dir)) {
|
|
37918
38816
|
if (f.endsWith(".jsonl"))
|
|
37919
|
-
files.push(
|
|
38817
|
+
files.push(join20(dir, f));
|
|
37920
38818
|
}
|
|
37921
38819
|
} catch {}
|
|
37922
38820
|
}
|
|
37923
38821
|
return files;
|
|
37924
38822
|
}
|
|
37925
38823
|
function buildCorpus(options = {}) {
|
|
37926
|
-
const root = options.projectsRoot ??
|
|
38824
|
+
const root = options.projectsRoot ?? join20(homedir20(), ".claude", "projects");
|
|
37927
38825
|
const files = listTranscripts(root);
|
|
37928
38826
|
const records = [];
|
|
37929
38827
|
for (const f of files)
|
|
37930
38828
|
records.push(...replayTranscript(f));
|
|
37931
38829
|
if (options.write && records.length > 0) {
|
|
37932
|
-
const outputPath = options.outputPath ??
|
|
38830
|
+
const outputPath = options.outputPath ?? join20(homedir20(), ".claudish", "behavior-divergences.jsonl");
|
|
37933
38831
|
try {
|
|
37934
38832
|
appendFileSync3(outputPath, `${records.map((r) => JSON.stringify(r)).join(`
|
|
37935
38833
|
`)}
|
|
@@ -38540,23 +39438,23 @@ var init_vision_proxy = __esm(() => {
|
|
|
38540
39438
|
|
|
38541
39439
|
// src/stats-buffer.ts
|
|
38542
39440
|
import {
|
|
38543
|
-
existsSync as
|
|
39441
|
+
existsSync as existsSync15,
|
|
38544
39442
|
mkdirSync as mkdirSync9,
|
|
38545
39443
|
readFileSync as readFileSync13,
|
|
38546
39444
|
renameSync,
|
|
38547
39445
|
unlinkSync as unlinkSync5,
|
|
38548
39446
|
writeFileSync as writeFileSync9
|
|
38549
39447
|
} from "fs";
|
|
38550
|
-
import { homedir as
|
|
38551
|
-
import { join as
|
|
39448
|
+
import { homedir as homedir21 } from "os";
|
|
39449
|
+
import { join as join21 } from "path";
|
|
38552
39450
|
function ensureDir() {
|
|
38553
|
-
if (!
|
|
39451
|
+
if (!existsSync15(CLAUDISH_DIR)) {
|
|
38554
39452
|
mkdirSync9(CLAUDISH_DIR, { recursive: true });
|
|
38555
39453
|
}
|
|
38556
39454
|
}
|
|
38557
39455
|
function readFromDisk() {
|
|
38558
39456
|
try {
|
|
38559
|
-
if (!
|
|
39457
|
+
if (!existsSync15(BUFFER_FILE))
|
|
38560
39458
|
return [];
|
|
38561
39459
|
const raw2 = readFileSync13(BUFFER_FILE, "utf-8");
|
|
38562
39460
|
const parsed = JSON.parse(raw2);
|
|
@@ -38583,7 +39481,7 @@ function writeToDisk(events) {
|
|
|
38583
39481
|
ensureDir();
|
|
38584
39482
|
const trimmed = enforceSizeCap([...events]);
|
|
38585
39483
|
const payload = { version: 1, events: trimmed };
|
|
38586
|
-
const tmpFile =
|
|
39484
|
+
const tmpFile = join21(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
|
|
38587
39485
|
writeFileSync9(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
|
|
38588
39486
|
renameSync(tmpFile, BUFFER_FILE);
|
|
38589
39487
|
memoryCache = trimmed;
|
|
@@ -38627,7 +39525,7 @@ function clearBuffer() {
|
|
|
38627
39525
|
try {
|
|
38628
39526
|
memoryCache = [];
|
|
38629
39527
|
eventsSinceLastFlush = 0;
|
|
38630
|
-
if (
|
|
39528
|
+
if (existsSync15(BUFFER_FILE)) {
|
|
38631
39529
|
unlinkSync5(BUFFER_FILE);
|
|
38632
39530
|
}
|
|
38633
39531
|
} catch {}
|
|
@@ -38656,8 +39554,8 @@ function syncFlushOnExit() {
|
|
|
38656
39554
|
var BUFFER_MAX_BYTES, CLAUDISH_DIR, BUFFER_FILE, memoryCache = null, eventsSinceLastFlush = 0, flushScheduled = false;
|
|
38657
39555
|
var init_stats_buffer = __esm(() => {
|
|
38658
39556
|
BUFFER_MAX_BYTES = 64 * 1024;
|
|
38659
|
-
CLAUDISH_DIR =
|
|
38660
|
-
BUFFER_FILE =
|
|
39557
|
+
CLAUDISH_DIR = join21(homedir21(), ".claudish");
|
|
39558
|
+
BUFFER_FILE = join21(CLAUDISH_DIR, "stats-buffer.json");
|
|
38661
39559
|
process.on("exit", syncFlushOnExit);
|
|
38662
39560
|
process.on("SIGTERM", () => {
|
|
38663
39561
|
try {
|
|
@@ -40938,8 +41836,8 @@ var init_openai_responses_sse = __esm(() => {
|
|
|
40938
41836
|
|
|
40939
41837
|
// src/handlers/shared/token-tracker.ts
|
|
40940
41838
|
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
|
|
40941
|
-
import { homedir as
|
|
40942
|
-
import { dirname as dirname7, join as
|
|
41839
|
+
import { homedir as homedir22 } from "os";
|
|
41840
|
+
import { dirname as dirname7, join as join22 } from "path";
|
|
40943
41841
|
|
|
40944
41842
|
class TokenTracker {
|
|
40945
41843
|
port;
|
|
@@ -41083,7 +41981,7 @@ class TokenTracker {
|
|
|
41083
41981
|
data.quota_remaining = this.quotaRemaining;
|
|
41084
41982
|
}
|
|
41085
41983
|
const override = process.env.CLAUDISH_TOKEN_FILE;
|
|
41086
|
-
const outPath = override ||
|
|
41984
|
+
const outPath = override || join22(homedir22(), ".claudish", `tokens-${this.port}.json`);
|
|
41087
41985
|
mkdirSync10(dirname7(outPath), { recursive: true });
|
|
41088
41986
|
writeFileSync10(outPath, JSON.stringify(data), "utf-8");
|
|
41089
41987
|
} catch (e) {
|
|
@@ -41304,6 +42202,9 @@ class ComposedHandler {
|
|
|
41304
42202
|
isInteractive: this.isInteractive,
|
|
41305
42203
|
authType: "oauth"
|
|
41306
42204
|
});
|
|
42205
|
+
if (err?.terminal) {
|
|
42206
|
+
return c.json(wrapAnthropicError(400, err.message, "invalid_request_error"), 400);
|
|
42207
|
+
}
|
|
41307
42208
|
return c.json(wrapAnthropicError(401, err.message, "authentication_error"), 401);
|
|
41308
42209
|
}
|
|
41309
42210
|
}
|
|
@@ -41898,7 +42799,7 @@ function isRetryableError(status, errorBody) {
|
|
|
41898
42799
|
}
|
|
41899
42800
|
}
|
|
41900
42801
|
if (status === 400) {
|
|
41901
|
-
if (lower.includes("model not found") || lower.includes("not registered") || lower.includes("does not exist") || lower.includes("unknown model") || lower.includes("unsupported model") || lower.includes("no healthy deployment")) {
|
|
42802
|
+
if (lower.includes("model not found") || lower.includes("not registered") || lower.includes("does not exist") || lower.includes("unknown model") || lower.includes("unsupported model") || lower.includes("no healthy deployment") || lower.includes("requires a google cloud project") || lower.includes("unsupported_client")) {
|
|
41902
42803
|
return true;
|
|
41903
42804
|
}
|
|
41904
42805
|
}
|
|
@@ -43033,38 +43934,32 @@ function extractModelIds(body) {
|
|
|
43033
43934
|
}
|
|
43034
43935
|
return [];
|
|
43035
43936
|
}
|
|
43937
|
+
function orderByCost(models) {
|
|
43938
|
+
const sized = models.filter((m) => typeof m.size === "number");
|
|
43939
|
+
const unsized = models.filter((m) => typeof m.size !== "number");
|
|
43940
|
+
const bySize = [...sized].sort((a, b) => (a.size ?? Number.POSITIVE_INFINITY) - (b.size ?? Number.POSITIVE_INFINITY)).map((m) => m.name);
|
|
43941
|
+
return [...bySize, ...rankProbeCandidates(unsized.map((m) => m.name))];
|
|
43942
|
+
}
|
|
43036
43943
|
async function discoverViaOllama(baseUrl, cacheKey) {
|
|
43037
43944
|
const cached2 = cacheGet(cacheKey.key, cacheKey.exclude);
|
|
43038
43945
|
if (cached2 !== undefined)
|
|
43039
43946
|
return cached2;
|
|
43040
|
-
|
|
43041
|
-
|
|
43042
|
-
|
|
43043
|
-
|
|
43044
|
-
|
|
43045
|
-
|
|
43046
|
-
}
|
|
43047
|
-
|
|
43048
|
-
|
|
43049
|
-
|
|
43050
|
-
|
|
43051
|
-
}
|
|
43052
|
-
connectionError ??= classifyFetchError(e, `${baseUrl}/api/tags`);
|
|
43053
|
-
}
|
|
43054
|
-
}
|
|
43055
|
-
const candidates = allRaw.filter((m) => isChatCapable(m.name));
|
|
43056
|
-
if (candidates.length === 0) {
|
|
43057
|
-
const reason = connectionError ?? (allRaw.length === 0 ? `no models on ${baseUrl} (pull one: ollama pull llama3.2)` : `only embedding/non-chat models on ${baseUrl}`);
|
|
43947
|
+
const [psResult, tagsResult] = await Promise.allSettled([
|
|
43948
|
+
fetchOllamaModels2(`${baseUrl}/api/ps`),
|
|
43949
|
+
fetchOllamaModels2(`${baseUrl}/api/tags`)
|
|
43950
|
+
]);
|
|
43951
|
+
const loadedRaw = psResult.status === "fulfilled" ? psResult.value : [];
|
|
43952
|
+
const tagsRaw = tagsResult.status === "fulfilled" ? tagsResult.value : [];
|
|
43953
|
+
const connectionError = psResult.status === "rejected" ? classifyFetchError(psResult.reason, `${baseUrl}/api/ps`) : tagsResult.status === "rejected" ? classifyFetchError(tagsResult.reason, `${baseUrl}/api/tags`) : undefined;
|
|
43954
|
+
const loaded = loadedRaw.filter((m) => isChatCapable(m.name));
|
|
43955
|
+
const loadedNames = new Set(loaded.map((m) => m.name));
|
|
43956
|
+
const rest = tagsRaw.filter((m) => isChatCapable(m.name) && !loadedNames.has(m.name));
|
|
43957
|
+
if (loaded.length === 0 && rest.length === 0) {
|
|
43958
|
+
const reason = connectionError ?? (loadedRaw.length === 0 && tagsRaw.length === 0 ? `no models on ${baseUrl} (pull one: ollama pull llama3.2)` : `only embedding/non-chat models on ${baseUrl}`);
|
|
43058
43959
|
cacheSetFailure(cacheKey.key, reason);
|
|
43059
43960
|
return { model: null, reason };
|
|
43060
43961
|
}
|
|
43061
|
-
const
|
|
43062
|
-
let ranked;
|
|
43063
|
-
if (sized.length > 0) {
|
|
43064
|
-
ranked = [...sized].sort((a, b) => (a.size ?? Number.POSITIVE_INFINITY) - (b.size ?? Number.POSITIVE_INFINITY)).map((m) => m.name);
|
|
43065
|
-
} else {
|
|
43066
|
-
ranked = rankProbeCandidates(candidates.map((m) => m.name));
|
|
43067
|
-
}
|
|
43962
|
+
const ranked = [...orderByCost(loaded), ...orderByCost(rest)];
|
|
43068
43963
|
if (ranked.length === 0) {
|
|
43069
43964
|
const reason = "no chat-capable model on Ollama endpoint";
|
|
43070
43965
|
cacheSetFailure(cacheKey.key, reason);
|
|
@@ -43588,11 +44483,11 @@ var init_ollama_api_format = __esm(() => {
|
|
|
43588
44483
|
});
|
|
43589
44484
|
|
|
43590
44485
|
// src/providers/api-key-provenance.ts
|
|
43591
|
-
import { existsSync as
|
|
43592
|
-
import { homedir as
|
|
43593
|
-
import { join as
|
|
44486
|
+
import { existsSync as existsSync16, readFileSync as readFileSync14 } from "fs";
|
|
44487
|
+
import { homedir as homedir23 } from "os";
|
|
44488
|
+
import { join as join23, resolve as resolve2 } from "path";
|
|
43594
44489
|
function activeConfigPath() {
|
|
43595
|
-
return activeGlobalConfigFile(
|
|
44490
|
+
return activeGlobalConfigFile(join23(homedir23(), ".claudish", "config.json"));
|
|
43596
44491
|
}
|
|
43597
44492
|
function configLayerLabel() {
|
|
43598
44493
|
return getConfigFileOverride() ? activeConfigPath() : "~/.claudish/config.json";
|
|
@@ -43669,7 +44564,7 @@ function formatProvenanceLog(p) {
|
|
|
43669
44564
|
function readDotenvKey(envVars) {
|
|
43670
44565
|
try {
|
|
43671
44566
|
const dotenvPath = resolve2(".env");
|
|
43672
|
-
if (!
|
|
44567
|
+
if (!existsSync16(dotenvPath))
|
|
43673
44568
|
return null;
|
|
43674
44569
|
const parsed = import_dotenv.parse(readFileSync14(dotenvPath, "utf-8"));
|
|
43675
44570
|
for (const v of envVars) {
|
|
@@ -43684,7 +44579,7 @@ function readDotenvKey(envVars) {
|
|
|
43684
44579
|
function readConfigKey(envVar) {
|
|
43685
44580
|
try {
|
|
43686
44581
|
const configPath = activeConfigPath();
|
|
43687
|
-
if (!
|
|
44582
|
+
if (!existsSync16(configPath))
|
|
43688
44583
|
return null;
|
|
43689
44584
|
const cfg = JSON.parse(readFileSync14(configPath, "utf-8"));
|
|
43690
44585
|
return cfg.apiKeys?.[envVar] || null;
|
|
@@ -43698,142 +44593,6 @@ var init_api_key_provenance = __esm(() => {
|
|
|
43698
44593
|
import_dotenv = __toESM(require_main(), 1);
|
|
43699
44594
|
});
|
|
43700
44595
|
|
|
43701
|
-
// src/handlers/shared/gemini-queue.ts
|
|
43702
|
-
class GeminiRequestQueue {
|
|
43703
|
-
static instance = null;
|
|
43704
|
-
queue = [];
|
|
43705
|
-
processing = false;
|
|
43706
|
-
minDelayMs = 1000;
|
|
43707
|
-
lastRequestTime = 0;
|
|
43708
|
-
consecutiveErrors = 0;
|
|
43709
|
-
totalProcessed = 0;
|
|
43710
|
-
totalErrors = 0;
|
|
43711
|
-
baseDelayMs = 1000;
|
|
43712
|
-
maxDelayMs = 1e4;
|
|
43713
|
-
maxQueueSize = 100;
|
|
43714
|
-
constructor() {
|
|
43715
|
-
log("[GeminiQueue] Queue initialized with minDelay=1000ms, maxQueueSize=100");
|
|
43716
|
-
}
|
|
43717
|
-
static getInstance() {
|
|
43718
|
-
if (!GeminiRequestQueue.instance) {
|
|
43719
|
-
GeminiRequestQueue.instance = new GeminiRequestQueue;
|
|
43720
|
-
}
|
|
43721
|
-
return GeminiRequestQueue.instance;
|
|
43722
|
-
}
|
|
43723
|
-
async enqueue(fetchFn) {
|
|
43724
|
-
if (this.queue.length >= this.maxQueueSize) {
|
|
43725
|
-
log(`[GeminiQueue] Queue full (${this.queue.length}/${this.maxQueueSize}), rejecting request`);
|
|
43726
|
-
throw new Error("Gemini request queue full. Please retry later.");
|
|
43727
|
-
}
|
|
43728
|
-
return new Promise((resolve3, reject) => {
|
|
43729
|
-
const queuedRequest = {
|
|
43730
|
-
fetchFn,
|
|
43731
|
-
resolve: resolve3,
|
|
43732
|
-
reject
|
|
43733
|
-
};
|
|
43734
|
-
this.queue.push(queuedRequest);
|
|
43735
|
-
log(`[GeminiQueue] Request enqueued (queue length: ${this.queue.length})`);
|
|
43736
|
-
if (!this.processing) {
|
|
43737
|
-
this.processQueue();
|
|
43738
|
-
}
|
|
43739
|
-
});
|
|
43740
|
-
}
|
|
43741
|
-
async processQueue() {
|
|
43742
|
-
if (this.processing) {
|
|
43743
|
-
return;
|
|
43744
|
-
}
|
|
43745
|
-
this.processing = true;
|
|
43746
|
-
log("[GeminiQueue] Worker started");
|
|
43747
|
-
while (this.queue.length > 0) {
|
|
43748
|
-
const request = this.queue.shift();
|
|
43749
|
-
if (!request)
|
|
43750
|
-
break;
|
|
43751
|
-
log(`[GeminiQueue] Processing request (${this.queue.length} remaining in queue)`);
|
|
43752
|
-
try {
|
|
43753
|
-
await this.waitForNextSlot();
|
|
43754
|
-
const response = await request.fetchFn();
|
|
43755
|
-
this.lastRequestTime = Date.now();
|
|
43756
|
-
if (response.status === 429) {
|
|
43757
|
-
this.totalErrors++;
|
|
43758
|
-
const errorText = await response.clone().text();
|
|
43759
|
-
this.handleRateLimitResponse(errorText);
|
|
43760
|
-
log(`[GeminiQueue] Rate limit hit (429), adjusted delay to ${this.minDelayMs}ms`);
|
|
43761
|
-
} else {
|
|
43762
|
-
this.handleSuccessResponse();
|
|
43763
|
-
}
|
|
43764
|
-
this.totalProcessed++;
|
|
43765
|
-
request.resolve(response);
|
|
43766
|
-
} catch (error46) {
|
|
43767
|
-
this.totalErrors++;
|
|
43768
|
-
log(`[GeminiQueue] Request failed with error: ${error46}`);
|
|
43769
|
-
request.reject(error46 instanceof Error ? error46 : new Error(String(error46)));
|
|
43770
|
-
}
|
|
43771
|
-
}
|
|
43772
|
-
this.processing = false;
|
|
43773
|
-
log("[GeminiQueue] Worker stopped (queue empty)");
|
|
43774
|
-
}
|
|
43775
|
-
async waitForNextSlot() {
|
|
43776
|
-
const now = Date.now();
|
|
43777
|
-
const timeSinceLastRequest = now - this.lastRequestTime;
|
|
43778
|
-
let delayMs = this.minDelayMs;
|
|
43779
|
-
if (this.consecutiveErrors > 0) {
|
|
43780
|
-
const backoffMultiplier = 1 + this.consecutiveErrors * 0.5;
|
|
43781
|
-
delayMs = Math.min(this.minDelayMs * backoffMultiplier, this.maxDelayMs);
|
|
43782
|
-
log(`[GeminiQueue] Applying backoff (${this.consecutiveErrors} errors): ${delayMs}ms`);
|
|
43783
|
-
}
|
|
43784
|
-
if (timeSinceLastRequest < delayMs) {
|
|
43785
|
-
const waitMs = delayMs - timeSinceLastRequest;
|
|
43786
|
-
log(`[GeminiQueue] Waiting ${waitMs}ms before next request`);
|
|
43787
|
-
await new Promise((resolve3) => setTimeout(resolve3, waitMs));
|
|
43788
|
-
}
|
|
43789
|
-
}
|
|
43790
|
-
handleRateLimitResponse(errorText) {
|
|
43791
|
-
this.consecutiveErrors++;
|
|
43792
|
-
try {
|
|
43793
|
-
const errorData = JSON.parse(errorText);
|
|
43794
|
-
const quotaDetail = errorData?.error?.details?.find((d) => d.quotaResetDelay);
|
|
43795
|
-
if (quotaDetail?.quotaResetDelay) {
|
|
43796
|
-
const delayStr = quotaDetail.quotaResetDelay;
|
|
43797
|
-
const match2 = delayStr.match(/(\d+(?:\.\d+)?)/);
|
|
43798
|
-
if (match2) {
|
|
43799
|
-
const delaySeconds = Number.parseFloat(match2[1]);
|
|
43800
|
-
const suggestedDelayMs = Math.ceil(delaySeconds * 1000);
|
|
43801
|
-
this.minDelayMs = Math.max(suggestedDelayMs, this.minDelayMs, this.baseDelayMs);
|
|
43802
|
-
this.minDelayMs = Math.min(this.minDelayMs, this.maxDelayMs);
|
|
43803
|
-
log(`[GeminiQueue] Parsed quotaResetDelay: ${delayStr} (${suggestedDelayMs}ms), ` + `new minDelay: ${this.minDelayMs}ms`);
|
|
43804
|
-
}
|
|
43805
|
-
}
|
|
43806
|
-
} catch {
|
|
43807
|
-
log("[GeminiQueue] Failed to parse rate limit response, using backoff");
|
|
43808
|
-
}
|
|
43809
|
-
const backoffMultiplier = 1 + this.consecutiveErrors * 0.5;
|
|
43810
|
-
this.minDelayMs = Math.min(this.baseDelayMs * backoffMultiplier, this.maxDelayMs);
|
|
43811
|
-
}
|
|
43812
|
-
handleSuccessResponse() {
|
|
43813
|
-
if (this.consecutiveErrors > 0) {
|
|
43814
|
-
log(`[GeminiQueue] Success after ${this.consecutiveErrors} errors, resetting counter`);
|
|
43815
|
-
this.consecutiveErrors = 0;
|
|
43816
|
-
}
|
|
43817
|
-
if (this.minDelayMs > this.baseDelayMs) {
|
|
43818
|
-
this.minDelayMs = Math.max(this.baseDelayMs, this.minDelayMs * 0.9);
|
|
43819
|
-
log(`[GeminiQueue] Reducing delay to ${this.minDelayMs}ms`);
|
|
43820
|
-
}
|
|
43821
|
-
}
|
|
43822
|
-
getStats() {
|
|
43823
|
-
return {
|
|
43824
|
-
queueLength: this.queue.length,
|
|
43825
|
-
processing: this.processing,
|
|
43826
|
-
consecutiveErrors: this.consecutiveErrors,
|
|
43827
|
-
currentDelayMs: this.minDelayMs,
|
|
43828
|
-
totalProcessed: this.totalProcessed,
|
|
43829
|
-
totalErrors: this.totalErrors
|
|
43830
|
-
};
|
|
43831
|
-
}
|
|
43832
|
-
}
|
|
43833
|
-
var init_gemini_queue = __esm(() => {
|
|
43834
|
-
init_logger();
|
|
43835
|
-
});
|
|
43836
|
-
|
|
43837
44596
|
// src/providers/transport/gemini-apikey.ts
|
|
43838
44597
|
class GeminiProviderTransport {
|
|
43839
44598
|
name = "gemini";
|
|
@@ -43866,22 +44625,17 @@ var init_gemini_apikey = __esm(() => {
|
|
|
43866
44625
|
});
|
|
43867
44626
|
|
|
43868
44627
|
// src/providers/transport/gemini-codeassist.ts
|
|
43869
|
-
import { randomUUID as
|
|
43870
|
-
function
|
|
43871
|
-
const version2 = "0.5.6";
|
|
43872
|
-
const modelSegment = model || "gemini-code-assist";
|
|
43873
|
-
return `GeminiCLI/${version2}/${modelSegment} (${process.platform}; ${process.arch})`;
|
|
43874
|
-
}
|
|
43875
|
-
function createActivityRequestId2() {
|
|
44628
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
44629
|
+
function createActivityRequestId4() {
|
|
43876
44630
|
return Math.random().toString(36).substring(7);
|
|
43877
44631
|
}
|
|
43878
|
-
function
|
|
44632
|
+
function classify4292(responseBody) {
|
|
43879
44633
|
try {
|
|
43880
44634
|
const raw2 = JSON.parse(responseBody);
|
|
43881
44635
|
const error46 = Array.isArray(raw2) ? raw2[0]?.error : raw2?.error;
|
|
43882
44636
|
const details = Array.isArray(error46?.details) ? error46.details : [];
|
|
43883
44637
|
const retryInfo = details.find((d) => d["@type"] === "type.googleapis.com/google.rpc.RetryInfo");
|
|
43884
|
-
let retryDelayMs =
|
|
44638
|
+
let retryDelayMs = parseRetryDelay2(retryInfo?.retryDelay);
|
|
43885
44639
|
if (retryDelayMs === undefined && typeof error46?.message === "string") {
|
|
43886
44640
|
const match2 = error46.message.match(/retry in ([\d.]+)(ms|s)/i);
|
|
43887
44641
|
if (match2) {
|
|
@@ -43895,7 +44649,7 @@ function classify429(responseBody) {
|
|
|
43895
44649
|
return { terminal: true, retryDelayMs, reason };
|
|
43896
44650
|
}
|
|
43897
44651
|
if (reason === "RATE_LIMIT_EXCEEDED") {
|
|
43898
|
-
return { terminal: false, retryDelayMs: retryDelayMs ??
|
|
44652
|
+
return { terminal: false, retryDelayMs: retryDelayMs ?? DEFAULT_RATE_LIMIT_DELAY_MS2, reason };
|
|
43899
44653
|
}
|
|
43900
44654
|
if (reason === "MODEL_CAPACITY_EXHAUSTED") {
|
|
43901
44655
|
return { terminal: true, retryDelayMs, reason };
|
|
@@ -43915,7 +44669,7 @@ function classify429(responseBody) {
|
|
|
43915
44669
|
return null;
|
|
43916
44670
|
}
|
|
43917
44671
|
}
|
|
43918
|
-
function
|
|
44672
|
+
function parseRetryDelay2(value) {
|
|
43919
44673
|
if (!value)
|
|
43920
44674
|
return;
|
|
43921
44675
|
if (typeof value === "string") {
|
|
@@ -43933,7 +44687,7 @@ function parseRetryDelay(value) {
|
|
|
43933
44687
|
|
|
43934
44688
|
class GeminiCodeAssistProviderTransport {
|
|
43935
44689
|
name = "gemini-codeassist";
|
|
43936
|
-
_displayName = "
|
|
44690
|
+
_displayName = "GeminiCA";
|
|
43937
44691
|
get displayName() {
|
|
43938
44692
|
return this._displayName;
|
|
43939
44693
|
}
|
|
@@ -43943,19 +44697,17 @@ class GeminiCodeAssistProviderTransport {
|
|
|
43943
44697
|
projectId = null;
|
|
43944
44698
|
tierId = null;
|
|
43945
44699
|
cachedAuth = null;
|
|
43946
|
-
fallbackStartIndex;
|
|
43947
44700
|
lastEnvelope = null;
|
|
43948
44701
|
_activeModelName;
|
|
44702
|
+
servedModels = [];
|
|
43949
44703
|
constructor(modelName) {
|
|
43950
44704
|
this.modelName = modelName;
|
|
43951
|
-
const idx = CODE_ASSIST_FALLBACK_CHAIN.indexOf(modelName);
|
|
43952
|
-
this.fallbackStartIndex = idx >= 0 ? idx : CODE_ASSIST_FALLBACK_CHAIN.length;
|
|
43953
44705
|
}
|
|
43954
44706
|
getActiveModelName() {
|
|
43955
44707
|
return this._activeModelName;
|
|
43956
44708
|
}
|
|
43957
44709
|
getEndpoint() {
|
|
43958
|
-
return
|
|
44710
|
+
return CODE_ASSIST_ENDPOINT2;
|
|
43959
44711
|
}
|
|
43960
44712
|
async getHeaders() {
|
|
43961
44713
|
if (this.cachedAuth)
|
|
@@ -43965,8 +44717,8 @@ class GeminiCodeAssistProviderTransport {
|
|
|
43965
44717
|
buildLocalHeaders() {
|
|
43966
44718
|
return {
|
|
43967
44719
|
Authorization: `Bearer ${this.accessToken}`,
|
|
43968
|
-
"User-Agent":
|
|
43969
|
-
"x-activity-request-id":
|
|
44720
|
+
"User-Agent": buildCodeAssistUserAgent(this.modelName),
|
|
44721
|
+
"x-activity-request-id": createActivityRequestId4()
|
|
43970
44722
|
};
|
|
43971
44723
|
}
|
|
43972
44724
|
async refreshAuth() {
|
|
@@ -43978,7 +44730,8 @@ class GeminiCodeAssistProviderTransport {
|
|
|
43978
44730
|
this.projectId = projectId;
|
|
43979
44731
|
this.tierId = tierId;
|
|
43980
44732
|
this._displayName = getGeminiTierDisplayName();
|
|
43981
|
-
|
|
44733
|
+
this.servedModels = await getServedCodeAssistModels(this.accessToken, this.projectId);
|
|
44734
|
+
log(`[GeminiCodeAssist] Auth refreshed, project: ${this.projectId}, tier: ${this._displayName}, served: ${this.servedModels.join(",") || "(none)"}`);
|
|
43982
44735
|
}
|
|
43983
44736
|
transformPayload(payload) {
|
|
43984
44737
|
const envelope = this.cachedAuth?.transformPayload ? this.cachedAuth.transformPayload(payload) : this.buildEnvelope(payload, this.modelName);
|
|
@@ -43989,7 +44742,7 @@ class GeminiCodeAssistProviderTransport {
|
|
|
43989
44742
|
const envelope = {
|
|
43990
44743
|
model,
|
|
43991
44744
|
project: this.projectId,
|
|
43992
|
-
user_prompt_id:
|
|
44745
|
+
user_prompt_id: randomUUID5(),
|
|
43993
44746
|
request: innerPayload
|
|
43994
44747
|
};
|
|
43995
44748
|
if (this.tierId && this.tierId !== "free-tier") {
|
|
@@ -44000,13 +44753,16 @@ class GeminiCodeAssistProviderTransport {
|
|
|
44000
44753
|
async enqueueRequest(fetchFn) {
|
|
44001
44754
|
const queue = GeminiRequestQueue.getInstance();
|
|
44002
44755
|
let lastResponse = null;
|
|
44003
|
-
for (let attempt = 1;attempt <=
|
|
44756
|
+
for (let attempt = 1;attempt <= MAX_RETRY_ATTEMPTS2; attempt++) {
|
|
44004
44757
|
const response = attempt === 1 ? await queue.enqueue(fetchFn) : await queue.enqueue(fetchFn);
|
|
44005
44758
|
if (response.status !== 429) {
|
|
44759
|
+
if (response.status === 404) {
|
|
44760
|
+
return this.rewriteModelNotFound(response);
|
|
44761
|
+
}
|
|
44006
44762
|
return response;
|
|
44007
44763
|
}
|
|
44008
44764
|
const bodyText = await response.clone().text();
|
|
44009
|
-
const classification =
|
|
44765
|
+
const classification = classify4292(bodyText);
|
|
44010
44766
|
lastResponse = response;
|
|
44011
44767
|
if (!classification) {
|
|
44012
44768
|
log("[GeminiCodeAssist] 429 response could not be classified, returning to caller");
|
|
@@ -44020,20 +44776,21 @@ class GeminiCodeAssistProviderTransport {
|
|
|
44020
44776
|
logStderr(`[GeminiCodeAssist] Quota exhausted (${classification.reason || "daily limit"}). Check plan limits.`);
|
|
44021
44777
|
return response;
|
|
44022
44778
|
}
|
|
44023
|
-
if (attempt <
|
|
44024
|
-
const delay = classification.retryDelayMs ??
|
|
44025
|
-
logStderr(`[GeminiCodeAssist] Rate limited (${classification.reason || "unknown"}), retrying in ${(delay / 1000).toFixed(1)}s (attempt ${attempt}/${
|
|
44779
|
+
if (attempt < MAX_RETRY_ATTEMPTS2) {
|
|
44780
|
+
const delay = classification.retryDelayMs ?? DEFAULT_RATE_LIMIT_DELAY_MS2;
|
|
44781
|
+
logStderr(`[GeminiCodeAssist] Rate limited (${classification.reason || "unknown"}), retrying in ${(delay / 1000).toFixed(1)}s (attempt ${attempt}/${MAX_RETRY_ATTEMPTS2})`);
|
|
44026
44782
|
if (attempt === 1) {
|
|
44027
44783
|
await this.logQuotaInfo();
|
|
44028
44784
|
}
|
|
44029
44785
|
await new Promise((r) => setTimeout(r, delay));
|
|
44030
44786
|
}
|
|
44031
44787
|
}
|
|
44032
|
-
logStderr(`[GeminiCodeAssist] Rate limit persisted after ${
|
|
44788
|
+
logStderr(`[GeminiCodeAssist] Rate limit persisted after ${MAX_RETRY_ATTEMPTS2} retries`);
|
|
44033
44789
|
return lastResponse;
|
|
44034
44790
|
}
|
|
44035
44791
|
async handleCapacityExhausted(originalResponse, queue) {
|
|
44036
|
-
|
|
44792
|
+
const candidates = this.servedModels.filter((m) => m !== this.modelName);
|
|
44793
|
+
if (candidates.length === 0) {
|
|
44037
44794
|
log(`[GeminiCodeAssist] ${this.modelName} capacity exhausted, no fallback models available`);
|
|
44038
44795
|
return originalResponse;
|
|
44039
44796
|
}
|
|
@@ -44045,11 +44802,12 @@ class GeminiCodeAssistProviderTransport {
|
|
|
44045
44802
|
logStderr(`[GeminiCodeAssist] ${this.modelName} capacity exhausted, trying fallback models...`);
|
|
44046
44803
|
let lastResponse = originalResponse;
|
|
44047
44804
|
const innerPayload = this.lastEnvelope.request;
|
|
44048
|
-
|
|
44049
|
-
|
|
44805
|
+
const endpoint = this.getEndpoint();
|
|
44806
|
+
const tried = [this.modelName];
|
|
44807
|
+
for (const fallbackModel of candidates) {
|
|
44050
44808
|
log(`[GeminiCodeAssist] Trying fallback model: ${fallbackModel}`);
|
|
44809
|
+
tried.push(fallbackModel);
|
|
44051
44810
|
const fallbackEnvelope = this.buildEnvelope(innerPayload, fallbackModel);
|
|
44052
|
-
const endpoint = this.getEndpoint();
|
|
44053
44811
|
const headers = this.buildLocalHeaders();
|
|
44054
44812
|
headers["Content-Type"] = "application/json";
|
|
44055
44813
|
const fallbackResponse = await queue.enqueue(() => fetch(endpoint, {
|
|
@@ -44057,23 +44815,59 @@ class GeminiCodeAssistProviderTransport {
|
|
|
44057
44815
|
headers,
|
|
44058
44816
|
body: JSON.stringify(fallbackEnvelope)
|
|
44059
44817
|
}));
|
|
44060
|
-
if (fallbackResponse.status
|
|
44818
|
+
if (fallbackResponse.status === 200) {
|
|
44061
44819
|
this._activeModelName = fallbackModel;
|
|
44062
44820
|
logStderr(`[GeminiCodeAssist] Using fallback model: ${fallbackModel} (${this.modelName} had no capacity)`);
|
|
44063
44821
|
return fallbackResponse;
|
|
44064
44822
|
}
|
|
44065
|
-
|
|
44066
|
-
|
|
44067
|
-
|
|
44823
|
+
if (fallbackResponse.status === 404) {
|
|
44824
|
+
log(`[GeminiCodeAssist] ${fallbackModel} returned 404, skipping to next fallback`);
|
|
44825
|
+
lastResponse = fallbackResponse;
|
|
44826
|
+
continue;
|
|
44827
|
+
}
|
|
44828
|
+
if (fallbackResponse.status === 429) {
|
|
44829
|
+
const fallbackBodyText = await fallbackResponse.clone().text();
|
|
44830
|
+
const classification = classify4292(fallbackBodyText);
|
|
44831
|
+
if (classification?.reason === "MODEL_CAPACITY_EXHAUSTED") {
|
|
44832
|
+
log(`[GeminiCodeAssist] ${fallbackModel} also capacity exhausted, trying next...`);
|
|
44833
|
+
lastResponse = fallbackResponse;
|
|
44834
|
+
continue;
|
|
44835
|
+
}
|
|
44068
44836
|
return fallbackResponse;
|
|
44069
44837
|
}
|
|
44070
|
-
|
|
44071
|
-
lastResponse = fallbackResponse;
|
|
44838
|
+
return fallbackResponse;
|
|
44072
44839
|
}
|
|
44073
44840
|
log("[GeminiCodeAssist] All fallback models exhausted");
|
|
44074
|
-
logStderr(`[GeminiCodeAssist] All models capacity exhausted (tried: ${
|
|
44841
|
+
logStderr(`[GeminiCodeAssist] All models capacity exhausted (tried: ${tried.join(" -> ")})`);
|
|
44842
|
+
if (lastResponse.status === 404) {
|
|
44843
|
+
return this.rewriteModelNotFound(lastResponse, true);
|
|
44844
|
+
}
|
|
44075
44845
|
return lastResponse;
|
|
44076
44846
|
}
|
|
44847
|
+
rewriteModelNotFound(response, capacityFallbacksExhausted = false) {
|
|
44848
|
+
const served = this.servedModels.length > 0 ? this.servedModels : CODE_ASSIST_FALLBACK_CHAIN.slice();
|
|
44849
|
+
if (!capacityFallbacksExhausted && served.includes(this.modelName)) {
|
|
44850
|
+
log(`[GeminiCodeAssist] 404 for ${this.modelName}, which IS in the served set \u2014 passing through unmodified`);
|
|
44851
|
+
return response;
|
|
44852
|
+
}
|
|
44853
|
+
response.text().catch(() => {});
|
|
44854
|
+
const list = served.join(", ");
|
|
44855
|
+
const tier = this._displayName || "Gemini Code Assist";
|
|
44856
|
+
const reason = capacityFallbacksExhausted ? `${this.modelName} could not be served after every Gemini Code Assist capacity fallback failed (${tier}, via go@). ` + `That tier currently reports: ${list}. ` : `${this.modelName} is not served by your Gemini Code Assist tier (${tier}, via go@). ` + `That tier currently serves: ${list}. `;
|
|
44857
|
+
const message = reason + `To use ${this.modelName}, go through the direct Gemini API instead \u2014 ` + `set GEMINI_API_KEY (get one at https://aistudio.google.com/app/apikey) and run ` + `google@${this.modelName}.`;
|
|
44858
|
+
const body = JSON.stringify({
|
|
44859
|
+
error: { code: 404, status: "NOT_FOUND", message }
|
|
44860
|
+
});
|
|
44861
|
+
if (capacityFallbacksExhausted) {
|
|
44862
|
+
logStderr(`[GeminiCodeAssist] ${this.modelName} capacity fallbacks exhausted (404). Reported models: ${list}`);
|
|
44863
|
+
} else {
|
|
44864
|
+
logStderr(`[GeminiCodeAssist] ${this.modelName} not served by ${tier} (404). Serves: ${list}`);
|
|
44865
|
+
}
|
|
44866
|
+
return new Response(body, {
|
|
44867
|
+
status: 404,
|
|
44868
|
+
headers: { "Content-Type": "application/json" }
|
|
44869
|
+
});
|
|
44870
|
+
}
|
|
44077
44871
|
async logQuotaInfo() {
|
|
44078
44872
|
if (!this.accessToken || !this.projectId)
|
|
44079
44873
|
return;
|
|
@@ -44113,13 +44907,13 @@ ${lines.join(`
|
|
|
44113
44907
|
}
|
|
44114
44908
|
}
|
|
44115
44909
|
}
|
|
44116
|
-
var
|
|
44910
|
+
var CODE_ASSIST_BASE2 = "https://cloudcode-pa.googleapis.com", CODE_ASSIST_ENDPOINT2, MAX_RETRY_ATTEMPTS2 = 3, DEFAULT_RATE_LIMIT_DELAY_MS2 = 1e4;
|
|
44117
44911
|
var init_gemini_codeassist = __esm(() => {
|
|
44118
44912
|
init_authority();
|
|
44119
44913
|
init_gemini_oauth();
|
|
44120
44914
|
init_gemini_queue();
|
|
44121
44915
|
init_logger();
|
|
44122
|
-
|
|
44916
|
+
CODE_ASSIST_ENDPOINT2 = `${CODE_ASSIST_BASE2}/v1internal:streamGenerateContent?alt=sse`;
|
|
44123
44917
|
});
|
|
44124
44918
|
|
|
44125
44919
|
// src/providers/transport/ollamacloud.ts
|
|
@@ -44281,7 +45075,7 @@ function createHandlerForProvider(ctx) {
|
|
|
44281
45075
|
log(`[Proxy] Handler: provider=${ctx.provider.name}, model=${ctx.modelName}`);
|
|
44282
45076
|
return profile.createHandler(ctx);
|
|
44283
45077
|
}
|
|
44284
|
-
var geminiProfile, geminiCodeAssistProfile, openaiProfile, openaiCodexProfile, anthropicCompatProfile, glmProfile, openCodeZenProfile, ollamaCloudProfile, litellmProfile, vertexProfile, PROVIDER_PROFILES;
|
|
45078
|
+
var geminiProfile, geminiCodeAssistProfile, antigravityProfile, openaiProfile, openaiCodexProfile, anthropicCompatProfile, glmProfile, openCodeZenProfile, ollamaCloudProfile, litellmProfile, vertexProfile, PROVIDER_PROFILES;
|
|
44285
45079
|
var init_provider_profiles = __esm(() => {
|
|
44286
45080
|
init_anthropic_api_format();
|
|
44287
45081
|
init_base_api_format();
|
|
@@ -44297,6 +45091,7 @@ var init_provider_profiles = __esm(() => {
|
|
|
44297
45091
|
init_remote_provider_registry();
|
|
44298
45092
|
init_runtime_providers();
|
|
44299
45093
|
init_anthropic_compat();
|
|
45094
|
+
init_antigravity();
|
|
44300
45095
|
init_gemini_apikey();
|
|
44301
45096
|
init_gemini_codeassist();
|
|
44302
45097
|
init_litellm();
|
|
@@ -44329,6 +45124,19 @@ var init_provider_profiles = __esm(() => {
|
|
|
44329
45124
|
return handler;
|
|
44330
45125
|
}
|
|
44331
45126
|
};
|
|
45127
|
+
antigravityProfile = {
|
|
45128
|
+
createHandler(ctx) {
|
|
45129
|
+
const transport = new AntigravityProviderTransport(ctx.modelName);
|
|
45130
|
+
const adapter = new GeminiAPIFormat(ctx.modelName);
|
|
45131
|
+
const handler = new ComposedHandler(transport, ctx.targetModel, ctx.modelName, ctx.port, {
|
|
45132
|
+
adapter,
|
|
45133
|
+
unwrapGeminiResponse: true,
|
|
45134
|
+
...ctx.sharedOpts
|
|
45135
|
+
});
|
|
45136
|
+
log(`[Proxy] Created Antigravity handler (composed): ${ctx.modelName}`);
|
|
45137
|
+
return handler;
|
|
45138
|
+
}
|
|
45139
|
+
};
|
|
44332
45140
|
openaiProfile = {
|
|
44333
45141
|
createHandler(ctx) {
|
|
44334
45142
|
if (requiresResponsesApi(ctx.modelName)) {
|
|
@@ -44507,6 +45315,7 @@ var init_provider_profiles = __esm(() => {
|
|
|
44507
45315
|
PROVIDER_PROFILES = {
|
|
44508
45316
|
gemini: geminiProfile,
|
|
44509
45317
|
"gemini-codeassist": geminiCodeAssistProfile,
|
|
45318
|
+
antigravity: antigravityProfile,
|
|
44510
45319
|
openai: openaiProfile,
|
|
44511
45320
|
"openai-codex": openaiCodexProfile,
|
|
44512
45321
|
"x-ai": openaiProfile,
|
|
@@ -45244,9 +46053,9 @@ var init_poe = __esm(() => {
|
|
|
45244
46053
|
});
|
|
45245
46054
|
|
|
45246
46055
|
// src/services/pricing-cache.ts
|
|
45247
|
-
import { existsSync as
|
|
45248
|
-
import { homedir as
|
|
45249
|
-
import { join as
|
|
46056
|
+
import { existsSync as existsSync17, readFileSync as readFileSync15, statSync as statSync4 } from "fs";
|
|
46057
|
+
import { homedir as homedir24 } from "os";
|
|
46058
|
+
import { join as join24 } from "path";
|
|
45250
46059
|
function prefixMatch(modelName) {
|
|
45251
46060
|
for (const [key, pricing] of pricingMap) {
|
|
45252
46061
|
if (modelName.startsWith(key))
|
|
@@ -45284,7 +46093,7 @@ async function warmPricingCache() {
|
|
|
45284
46093
|
}
|
|
45285
46094
|
function loadDiskCache() {
|
|
45286
46095
|
try {
|
|
45287
|
-
if (!
|
|
46096
|
+
if (!existsSync17(CACHE_FILE))
|
|
45288
46097
|
return false;
|
|
45289
46098
|
const stat2 = statSync4(CACHE_FILE);
|
|
45290
46099
|
const age = Date.now() - stat2.mtimeMs;
|
|
@@ -45305,8 +46114,8 @@ var init_pricing_cache = __esm(() => {
|
|
|
45305
46114
|
init_logger();
|
|
45306
46115
|
init_catalog_query();
|
|
45307
46116
|
pricingMap = new Map;
|
|
45308
|
-
CACHE_DIR =
|
|
45309
|
-
CACHE_FILE =
|
|
46117
|
+
CACHE_DIR = join24(homedir24(), ".claudish");
|
|
46118
|
+
CACHE_FILE = join24(CACHE_DIR, "pricing-cache.json");
|
|
45310
46119
|
CACHE_TTL_MS2 = 24 * 60 * 60 * 1000;
|
|
45311
46120
|
});
|
|
45312
46121
|
|
|
@@ -45763,17 +46572,17 @@ var init_proxy_server = __esm(() => {
|
|
|
45763
46572
|
});
|
|
45764
46573
|
|
|
45765
46574
|
// src/team-stats.ts
|
|
45766
|
-
import { existsSync as
|
|
45767
|
-
import { join as
|
|
46575
|
+
import { existsSync as existsSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "fs";
|
|
46576
|
+
import { join as join25 } from "path";
|
|
45768
46577
|
function statsDir(sessionPath) {
|
|
45769
|
-
return
|
|
46578
|
+
return join25(sessionPath, "stats");
|
|
45770
46579
|
}
|
|
45771
46580
|
function tokenFileFor(sessionPath, anonId) {
|
|
45772
|
-
return
|
|
46581
|
+
return join25(statsDir(sessionPath), `${anonId}.json`);
|
|
45773
46582
|
}
|
|
45774
46583
|
function readTokenStats(sessionPath, anonId) {
|
|
45775
46584
|
const path = tokenFileFor(sessionPath, anonId);
|
|
45776
|
-
if (!
|
|
46585
|
+
if (!existsSync18(path))
|
|
45777
46586
|
return null;
|
|
45778
46587
|
try {
|
|
45779
46588
|
return JSON.parse(readFileSync16(path, "utf-8"));
|
|
@@ -45924,7 +46733,7 @@ ${segs.join(" \xB7 ")}`;
|
|
|
45924
46733
|
}
|
|
45925
46734
|
function writeStatusFile(sessionPath, manifest, status, opts) {
|
|
45926
46735
|
try {
|
|
45927
|
-
writeFileSync11(
|
|
46736
|
+
writeFileSync11(join25(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
|
|
45928
46737
|
`, "utf-8");
|
|
45929
46738
|
} catch {}
|
|
45930
46739
|
}
|
|
@@ -45950,13 +46759,13 @@ __export(exports_team_orchestrator, {
|
|
|
45950
46759
|
import { spawn as spawn2 } from "child_process";
|
|
45951
46760
|
import {
|
|
45952
46761
|
createWriteStream as createWriteStream2,
|
|
45953
|
-
existsSync as
|
|
46762
|
+
existsSync as existsSync19,
|
|
45954
46763
|
mkdirSync as mkdirSync11,
|
|
45955
46764
|
readFileSync as readFileSync17,
|
|
45956
46765
|
readdirSync as readdirSync3,
|
|
45957
46766
|
writeFileSync as writeFileSync12
|
|
45958
46767
|
} from "fs";
|
|
45959
|
-
import { join as
|
|
46768
|
+
import { join as join26, resolve as resolve3 } from "path";
|
|
45960
46769
|
function classifyRunOutput(opts) {
|
|
45961
46770
|
const { outputSize, stdoutTail, stderr, minOutputBytes } = opts;
|
|
45962
46771
|
const apiError = API_ERROR_RE.exec(stdoutTail);
|
|
@@ -46017,18 +46826,18 @@ function setupSession(sessionPath, models, input) {
|
|
|
46017
46826
|
if (models.length === 0) {
|
|
46018
46827
|
throw new Error("At least one model is required");
|
|
46019
46828
|
}
|
|
46020
|
-
if (
|
|
46829
|
+
if (existsSync19(join26(sessionPath, "manifest.json"))) {
|
|
46021
46830
|
throw new Error(`Session already exists at ${sessionPath}. Use a new directory path or delete the existing session first.`);
|
|
46022
46831
|
}
|
|
46023
46832
|
const sentinels = models.filter(isSentinelModel);
|
|
46024
46833
|
if (sentinels.length > 0) {
|
|
46025
46834
|
throw new Error(`Invalid model(s) for team run: ${sentinels.join(", ")}. These are Claude Code agent selectors, not external model IDs. Use real external models (e.g., "gemini-2.0-flash", "gpt-4o", "or@deepseek/deepseek-r1"). For Claude models, use a Task agent instead of the team tool.`);
|
|
46026
46835
|
}
|
|
46027
|
-
mkdirSync11(
|
|
46028
|
-
mkdirSync11(
|
|
46836
|
+
mkdirSync11(join26(sessionPath, "work"), { recursive: true });
|
|
46837
|
+
mkdirSync11(join26(sessionPath, "errors"), { recursive: true });
|
|
46029
46838
|
if (input !== undefined) {
|
|
46030
|
-
writeFileSync12(
|
|
46031
|
-
} else if (!
|
|
46839
|
+
writeFileSync12(join26(sessionPath, "input.md"), input, "utf-8");
|
|
46840
|
+
} else if (!existsSync19(join26(sessionPath, "input.md"))) {
|
|
46032
46841
|
throw new Error(`No input.md found at ${sessionPath} and no input provided`);
|
|
46033
46842
|
}
|
|
46034
46843
|
const ids = models.map((_, i) => String(i + 1).padStart(2, "0"));
|
|
@@ -46045,9 +46854,9 @@ function setupSession(sessionPath, models, input) {
|
|
|
46045
46854
|
model: models[i],
|
|
46046
46855
|
assignedAt: now
|
|
46047
46856
|
};
|
|
46048
|
-
mkdirSync11(
|
|
46857
|
+
mkdirSync11(join26(sessionPath, "work", anonId), { recursive: true });
|
|
46049
46858
|
}
|
|
46050
|
-
writeFileSync12(
|
|
46859
|
+
writeFileSync12(join26(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
|
|
46051
46860
|
const status = {
|
|
46052
46861
|
startedAt: now,
|
|
46053
46862
|
models: Object.fromEntries(Object.keys(manifest.models).map((id) => [
|
|
@@ -46061,14 +46870,14 @@ function setupSession(sessionPath, models, input) {
|
|
|
46061
46870
|
}
|
|
46062
46871
|
]))
|
|
46063
46872
|
};
|
|
46064
|
-
writeFileSync12(
|
|
46873
|
+
writeFileSync12(join26(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
|
|
46065
46874
|
return manifest;
|
|
46066
46875
|
}
|
|
46067
46876
|
async function runModels(sessionPath, opts = {}) {
|
|
46068
46877
|
const timeoutMs = (opts.timeout ?? 300) * 1000;
|
|
46069
|
-
const manifest = JSON.parse(readFileSync17(
|
|
46070
|
-
const statusPath =
|
|
46071
|
-
const inputPath =
|
|
46878
|
+
const manifest = JSON.parse(readFileSync17(join26(sessionPath, "manifest.json"), "utf-8"));
|
|
46879
|
+
const statusPath = join26(sessionPath, "status.json");
|
|
46880
|
+
const inputPath = join26(sessionPath, "input.md");
|
|
46072
46881
|
const inputContent = readFileSync17(inputPath, "utf-8");
|
|
46073
46882
|
await prehydrateCredentialsForSpawn(Object.values(manifest.models).map((m) => m.model));
|
|
46074
46883
|
const statusCache = JSON.parse(readFileSync17(statusPath, "utf-8"));
|
|
@@ -46090,8 +46899,8 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
46090
46899
|
process.on("SIGINT", sigintHandler);
|
|
46091
46900
|
const completionPromises = [];
|
|
46092
46901
|
for (const [anonId, entry] of Object.entries(manifest.models)) {
|
|
46093
|
-
const outputPath =
|
|
46094
|
-
const errorLogPath =
|
|
46902
|
+
const outputPath = join26(sessionPath, `response-${anonId}.md`);
|
|
46903
|
+
const errorLogPath = join26(sessionPath, "errors", `${anonId}.log`);
|
|
46095
46904
|
const args = ["--model", entry.model, "-y", "--stdin", "--quiet", ...opts.claudeFlags ?? []];
|
|
46096
46905
|
updateModelStatus(anonId, {
|
|
46097
46906
|
state: "RUNNING",
|
|
@@ -46280,23 +47089,23 @@ async function judgeResponses(sessionPath, opts = {}) {
|
|
|
46280
47089
|
const responses = {};
|
|
46281
47090
|
for (const file2 of responseFiles) {
|
|
46282
47091
|
const id = file2.replace(/^response-/, "").replace(/\.md$/, "");
|
|
46283
|
-
responses[id] = readFileSync17(
|
|
47092
|
+
responses[id] = readFileSync17(join26(sessionPath, file2), "utf-8");
|
|
46284
47093
|
}
|
|
46285
|
-
const input = readFileSync17(
|
|
47094
|
+
const input = readFileSync17(join26(sessionPath, "input.md"), "utf-8");
|
|
46286
47095
|
const judgePrompt = buildJudgePrompt(input, responses);
|
|
46287
|
-
writeFileSync12(
|
|
47096
|
+
writeFileSync12(join26(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
|
|
46288
47097
|
const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
|
|
46289
|
-
const judgePath =
|
|
47098
|
+
const judgePath = join26(sessionPath, "judging");
|
|
46290
47099
|
mkdirSync11(judgePath, { recursive: true });
|
|
46291
47100
|
setupSession(judgePath, judgeModels, judgePrompt);
|
|
46292
47101
|
await runModels(judgePath, { claudeFlags: opts.claudeFlags });
|
|
46293
47102
|
const votes = parseJudgeVotes(judgePath, Object.keys(responses));
|
|
46294
47103
|
const verdict = aggregateVerdict(votes, Object.keys(responses));
|
|
46295
|
-
writeFileSync12(
|
|
47104
|
+
writeFileSync12(join26(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
|
|
46296
47105
|
return verdict;
|
|
46297
47106
|
}
|
|
46298
47107
|
function getStatus(sessionPath) {
|
|
46299
|
-
return JSON.parse(readFileSync17(
|
|
47108
|
+
return JSON.parse(readFileSync17(join26(sessionPath, "status.json"), "utf-8"));
|
|
46300
47109
|
}
|
|
46301
47110
|
function fisherYatesShuffle(arr) {
|
|
46302
47111
|
for (let i = arr.length - 1;i > 0; i--) {
|
|
@@ -46306,7 +47115,7 @@ function fisherYatesShuffle(arr) {
|
|
|
46306
47115
|
return arr;
|
|
46307
47116
|
}
|
|
46308
47117
|
function getDefaultJudgeModels(sessionPath) {
|
|
46309
|
-
const manifest = JSON.parse(readFileSync17(
|
|
47118
|
+
const manifest = JSON.parse(readFileSync17(join26(sessionPath, "manifest.json"), "utf-8"));
|
|
46310
47119
|
return Object.values(manifest.models).map((e) => e.model);
|
|
46311
47120
|
}
|
|
46312
47121
|
function buildJudgePrompt(input, responses) {
|
|
@@ -46369,7 +47178,7 @@ function parseJudgeVotes(judgePath, responseIds) {
|
|
|
46369
47178
|
const judgeId = file2.replace(/^response-/, "").replace(/\.md$/, "");
|
|
46370
47179
|
let content;
|
|
46371
47180
|
try {
|
|
46372
|
-
content = readFileSync17(
|
|
47181
|
+
content = readFileSync17(join26(judgePath, file2), "utf-8");
|
|
46373
47182
|
} catch {
|
|
46374
47183
|
continue;
|
|
46375
47184
|
}
|
|
@@ -46421,7 +47230,7 @@ function aggregateVerdict(votes, responseIds) {
|
|
|
46421
47230
|
function formatVerdict(verdict, sessionPath) {
|
|
46422
47231
|
let manifest = null;
|
|
46423
47232
|
try {
|
|
46424
|
-
manifest = JSON.parse(readFileSync17(
|
|
47233
|
+
manifest = JSON.parse(readFileSync17(join26(sessionPath, "manifest.json"), "utf-8"));
|
|
46425
47234
|
} catch {}
|
|
46426
47235
|
let output = `# Team Verdict
|
|
46427
47236
|
|
|
@@ -46476,12 +47285,12 @@ __export(exports_mcp_server, {
|
|
|
46476
47285
|
parseAnthropicSse: () => parseAnthropicSse,
|
|
46477
47286
|
formatTeamResult: () => formatTeamResult
|
|
46478
47287
|
});
|
|
46479
|
-
import { existsSync as
|
|
46480
|
-
import { homedir as
|
|
46481
|
-
import { dirname as dirname8, join as
|
|
47288
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync12, readFileSync as readFileSync18, readdirSync as readdirSync4, writeFileSync as writeFileSync13 } from "fs";
|
|
47289
|
+
import { homedir as homedir25 } from "os";
|
|
47290
|
+
import { dirname as dirname8, join as join27 } from "path";
|
|
46482
47291
|
import { fileURLToPath } from "url";
|
|
46483
47292
|
async function loadAllModels(forceRefresh = false) {
|
|
46484
|
-
if (!forceRefresh &&
|
|
47293
|
+
if (!forceRefresh && existsSync20(ALL_MODELS_CACHE_PATH2)) {
|
|
46485
47294
|
try {
|
|
46486
47295
|
const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH2, "utf-8"));
|
|
46487
47296
|
const lastUpdated = new Date(cacheData.lastUpdated);
|
|
@@ -46501,7 +47310,7 @@ async function loadAllModels(forceRefresh = false) {
|
|
|
46501
47310
|
writeFileSync13(ALL_MODELS_CACHE_PATH2, JSON.stringify({ lastUpdated: new Date().toISOString(), models }), "utf-8");
|
|
46502
47311
|
return models;
|
|
46503
47312
|
} catch {
|
|
46504
|
-
if (
|
|
47313
|
+
if (existsSync20(ALL_MODELS_CACHE_PATH2)) {
|
|
46505
47314
|
const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH2, "utf-8"));
|
|
46506
47315
|
return cacheData.models || [];
|
|
46507
47316
|
}
|
|
@@ -47077,16 +47886,16 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
|
|
|
47077
47886
|
const sp = session_path;
|
|
47078
47887
|
for (const file2 of ["status.json", "manifest.json", "input.md"]) {
|
|
47079
47888
|
try {
|
|
47080
|
-
sessionData[file2] = readFileSync18(
|
|
47889
|
+
sessionData[file2] = readFileSync18(join27(sp, file2), "utf-8");
|
|
47081
47890
|
} catch {}
|
|
47082
47891
|
}
|
|
47083
47892
|
try {
|
|
47084
|
-
const errorDir =
|
|
47085
|
-
if (
|
|
47893
|
+
const errorDir = join27(sp, "errors");
|
|
47894
|
+
if (existsSync20(errorDir)) {
|
|
47086
47895
|
for (const f of readdirSync4(errorDir)) {
|
|
47087
47896
|
if (f.endsWith(".log")) {
|
|
47088
47897
|
try {
|
|
47089
|
-
sessionData[`errors/${f}`] = readFileSync18(
|
|
47898
|
+
sessionData[`errors/${f}`] = readFileSync18(join27(errorDir, f), "utf-8");
|
|
47090
47899
|
} catch {}
|
|
47091
47900
|
}
|
|
47092
47901
|
}
|
|
@@ -47096,7 +47905,7 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
|
|
|
47096
47905
|
for (const f of readdirSync4(sp)) {
|
|
47097
47906
|
if (f.startsWith("response-") && f.endsWith(".md")) {
|
|
47098
47907
|
try {
|
|
47099
|
-
const content = readFileSync18(
|
|
47908
|
+
const content = readFileSync18(join27(sp, f), "utf-8");
|
|
47100
47909
|
sessionData[f] = content.slice(0, 200) + (content.length > 200 ? "... (truncated)" : "");
|
|
47101
47910
|
} catch {}
|
|
47102
47911
|
}
|
|
@@ -47105,8 +47914,8 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
|
|
|
47105
47914
|
}
|
|
47106
47915
|
let version2 = "unknown";
|
|
47107
47916
|
try {
|
|
47108
|
-
const pkgPath =
|
|
47109
|
-
if (
|
|
47917
|
+
const pkgPath = join27(__dirname2, "../package.json");
|
|
47918
|
+
if (existsSync20(pkgPath)) {
|
|
47110
47919
|
version2 = JSON.parse(readFileSync18(pkgPath, "utf-8")).version;
|
|
47111
47920
|
}
|
|
47112
47921
|
} catch {}
|
|
@@ -47505,8 +48314,8 @@ var init_mcp_server = __esm(() => {
|
|
|
47505
48314
|
import_dotenv2.config({ quiet: true });
|
|
47506
48315
|
__filename2 = fileURLToPath(import.meta.url);
|
|
47507
48316
|
__dirname2 = dirname8(__filename2);
|
|
47508
|
-
CLAUDISH_CACHE_DIR =
|
|
47509
|
-
ALL_MODELS_CACHE_PATH2 =
|
|
48317
|
+
CLAUDISH_CACHE_DIR = join27(homedir25(), ".claudish");
|
|
48318
|
+
ALL_MODELS_CACHE_PATH2 = join27(CLAUDISH_CACHE_DIR, "all-models.json");
|
|
47510
48319
|
NEXT_STEP = {
|
|
47511
48320
|
nonzero_exit: "read the evidence log, then retry or drop the model",
|
|
47512
48321
|
timeout: "raise `timeout`, or pick a faster model",
|
|
@@ -47531,7 +48340,7 @@ var exports_serve_command = {};
|
|
|
47531
48340
|
__export(exports_serve_command, {
|
|
47532
48341
|
serveCommand: () => serveCommand
|
|
47533
48342
|
});
|
|
47534
|
-
import { existsSync as
|
|
48343
|
+
import { existsSync as existsSync21, readFileSync as readFileSync19 } from "fs";
|
|
47535
48344
|
function parseServeArgs(args) {
|
|
47536
48345
|
const out = {};
|
|
47537
48346
|
for (let i = 0;i < args.length; i++) {
|
|
@@ -47550,7 +48359,7 @@ function parseServeArgs(args) {
|
|
|
47550
48359
|
return out;
|
|
47551
48360
|
}
|
|
47552
48361
|
function loadModelMap(path) {
|
|
47553
|
-
if (!
|
|
48362
|
+
if (!existsSync21(path)) {
|
|
47554
48363
|
throw new Error(`--models file not found: ${path}`);
|
|
47555
48364
|
}
|
|
47556
48365
|
let raw2;
|
|
@@ -47754,6 +48563,8 @@ function describeSourceSync(p, config3) {
|
|
|
47754
48563
|
return isLocalProviderEnabled(p.catalogName, config3) ? "local" : null;
|
|
47755
48564
|
if (p.oauthSlug && hasOAuthCredentials(p.catalogName))
|
|
47756
48565
|
return "oauth";
|
|
48566
|
+
if (p.catalogName === "antigravity" && hasSharedAntigravityToken())
|
|
48567
|
+
return "oauth";
|
|
47757
48568
|
const hasCfg = !!p.apiKeyEnvVar && !!realValue(config3.apiKeys?.[p.apiKeyEnvVar]);
|
|
47758
48569
|
const hasEnv = !!p.apiKeyEnvVar && !!realValue(process.env[p.apiKeyEnvVar]);
|
|
47759
48570
|
if (hasEnv && hasCfg)
|
|
@@ -47774,6 +48585,7 @@ async function describeSource(p, config3) {
|
|
|
47774
48585
|
}
|
|
47775
48586
|
var init_source = __esm(() => {
|
|
47776
48587
|
init_profile_config();
|
|
48588
|
+
init_antigravity_token();
|
|
47777
48589
|
init_oauth_registry();
|
|
47778
48590
|
init_api_key_credential();
|
|
47779
48591
|
init_authority();
|
|
@@ -47821,7 +48633,7 @@ function providerAuthCapabilities(p, config3) {
|
|
|
47821
48633
|
const apiKeySupported = !!p.apiKeyEnvVar;
|
|
47822
48634
|
const apiKeySet = apiKeySupported && (!!process.env[p.apiKeyEnvVar] || !!config3.apiKeys?.[p.apiKeyEnvVar]);
|
|
47823
48635
|
const oauthSupported = !!p.oauthSlug;
|
|
47824
|
-
const oauthSet = oauthSupported && hasOAuthCredentials(p.catalogName);
|
|
48636
|
+
const oauthSet = oauthSupported && (hasOAuthCredentials(p.catalogName) || p.catalogName === "antigravity" && hasSharedAntigravityToken());
|
|
47825
48637
|
return {
|
|
47826
48638
|
apiKey: { supported: apiKeySupported, set: apiKeySet },
|
|
47827
48639
|
oauth: { supported: oauthSupported, set: oauthSet }
|
|
@@ -47837,6 +48649,7 @@ function maskKey2(key) {
|
|
|
47837
48649
|
var SKIP, PROVIDERS;
|
|
47838
48650
|
var init_providers = __esm(() => {
|
|
47839
48651
|
init_source();
|
|
48652
|
+
init_antigravity_token();
|
|
47840
48653
|
init_oauth_registry();
|
|
47841
48654
|
init_provider_definitions();
|
|
47842
48655
|
SKIP = new Set(["qwen", "native-anthropic"]);
|
|
@@ -59151,7 +59964,7 @@ import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
|
|
|
59151
59964
|
import { readFileSync as readFileSync20, unlinkSync as unlinkSync6, writeFileSync as writeFileSync14 } from "fs";
|
|
59152
59965
|
import path from "path";
|
|
59153
59966
|
import os from "os";
|
|
59154
|
-
import { randomUUID as
|
|
59967
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
59155
59968
|
function editAsync(text = "", callback, fileOptions) {
|
|
59156
59969
|
const editor = new ExternalEditor(text, fileOptions);
|
|
59157
59970
|
editor.runAsync((err, result) => {
|
|
@@ -59243,7 +60056,7 @@ class ExternalEditor {
|
|
|
59243
60056
|
createTemporaryFile() {
|
|
59244
60057
|
try {
|
|
59245
60058
|
const baseDir = this.fileOptions.dir ?? os.tmpdir();
|
|
59246
|
-
const id =
|
|
60059
|
+
const id = randomUUID6();
|
|
59247
60060
|
const prefix = sanitizeAffix(this.fileOptions.prefix);
|
|
59248
60061
|
const postfix = sanitizeAffix(this.fileOptions.postfix);
|
|
59249
60062
|
const filename = `${prefix}${id}${postfix}`;
|
|
@@ -60419,13 +61232,14 @@ async function geminiQuotaHandler() {
|
|
|
60419
61232
|
}
|
|
60420
61233
|
console.log("");
|
|
60421
61234
|
}
|
|
61235
|
+
const fallbackChain = quota.buckets.map((b) => b.modelId).filter((m) => typeof m === "string" && m.length > 0).sort((a, b) => rankCodeAssistModel(a) - rankCodeAssistModel(b));
|
|
60422
61236
|
console.log(` ${B}${CYN}Fallback Chain${R} ${D}(on capacity exhaustion)${R}`);
|
|
60423
|
-
for (let i = 0;i <
|
|
60424
|
-
const model =
|
|
61237
|
+
for (let i = 0;i < fallbackChain.length; i++) {
|
|
61238
|
+
const model = fallbackChain[i];
|
|
60425
61239
|
const rem = remainingByModel.get(model);
|
|
60426
61240
|
const pct = rem !== undefined ? `${((1 - rem) * 100).toFixed(0)}%` : "?";
|
|
60427
61241
|
const color = rem === undefined ? GRY : rem > 0.5 ? GRN : rem > 0.2 ? YEL : RED;
|
|
60428
|
-
const arrow = i <
|
|
61242
|
+
const arrow = i < fallbackChain.length - 1 ? ` ${GRY}\u2192${R}` : "";
|
|
60429
61243
|
const marker = i === 0 ? `${CYN}\u25B8${R} ` : " ";
|
|
60430
61244
|
console.log(` ${marker}${WHT}${model}${R} ${color}${pct}${R}${arrow}`);
|
|
60431
61245
|
}
|
|
@@ -60459,11 +61273,11 @@ async function geminiQuotaHandler() {
|
|
|
60459
61273
|
}
|
|
60460
61274
|
}
|
|
60461
61275
|
async function codexQuotaHandler() {
|
|
60462
|
-
const { readFileSync: readFileSync21, existsSync:
|
|
60463
|
-
const { join:
|
|
60464
|
-
const { homedir:
|
|
60465
|
-
const credPath =
|
|
60466
|
-
if (!
|
|
61276
|
+
const { readFileSync: readFileSync21, existsSync: existsSync22 } = await import("fs");
|
|
61277
|
+
const { join: join28 } = await import("path");
|
|
61278
|
+
const { homedir: homedir26 } = await import("os");
|
|
61279
|
+
const credPath = join28(homedir26(), ".claudish", "codex-oauth.json");
|
|
61280
|
+
if (!existsSync22(credPath)) {
|
|
60467
61281
|
console.error(`${RED}No Codex credentials found.${R} Run: ${B}claudish login codex${R}`);
|
|
60468
61282
|
process.exit(1);
|
|
60469
61283
|
}
|
|
@@ -60519,8 +61333,8 @@ async function codexQuotaHandler() {
|
|
|
60519
61333
|
}
|
|
60520
61334
|
let modelSlugs = [];
|
|
60521
61335
|
try {
|
|
60522
|
-
const modelsPath =
|
|
60523
|
-
if (
|
|
61336
|
+
const modelsPath = join28(homedir26(), ".codex", "models_cache.json");
|
|
61337
|
+
if (existsSync22(modelsPath)) {
|
|
60524
61338
|
const cache2 = JSON.parse(readFileSync21(modelsPath, "utf-8"));
|
|
60525
61339
|
modelSlugs = (cache2.models || []).map((m) => m.slug || m.id).filter(Boolean);
|
|
60526
61340
|
}
|
|
@@ -61892,6 +62706,8 @@ function annotateOAuthHint(result, provider, isOAuth) {
|
|
|
61892
62706
|
const loginCommand2 = provider === "gemini-codeassist" ? "claudish login gemini" : provider === "vertex" ? "gcloud auth application-default login" : undefined;
|
|
61893
62707
|
if (!loginCommand2)
|
|
61894
62708
|
return result;
|
|
62709
|
+
if (result.httpStatus === 403)
|
|
62710
|
+
return result;
|
|
61895
62711
|
const looksLikeAuthFailure = result.state === "auth-failed" || /auth|token|login|credential|unauthor/i.test(result.errorMessage || "");
|
|
61896
62712
|
if (!looksLikeAuthFailure)
|
|
61897
62713
|
return result;
|
|
@@ -62174,29 +62990,34 @@ function isContentEvent(parsed, eventType) {
|
|
|
62174
62990
|
return true;
|
|
62175
62991
|
return false;
|
|
62176
62992
|
}
|
|
62993
|
+
function withDetail(base, message) {
|
|
62994
|
+
return message ? `${base} \u2014 ${message}` : base;
|
|
62995
|
+
}
|
|
62177
62996
|
function describeProbeState(result) {
|
|
62997
|
+
const status = result.httpStatus ?? "";
|
|
62998
|
+
const latency = result.latencyMs ? ` \xB7 ${result.latencyMs}ms` : "";
|
|
62178
62999
|
switch (result.state) {
|
|
62179
63000
|
case "live":
|
|
62180
63001
|
return `live \xB7 ${result.latencyMs}ms`;
|
|
62181
63002
|
case "key-missing":
|
|
62182
63003
|
return result.errorMessage ? `missing (${result.errorMessage})` : "missing";
|
|
62183
63004
|
case "auth-failed":
|
|
62184
|
-
return `auth failed \xB7 ${
|
|
63005
|
+
return withDetail(`auth failed \xB7 ${status}${latency}`.trim(), result.errorMessage);
|
|
62185
63006
|
case "model-not-found":
|
|
62186
|
-
return `model not found \xB7 ${
|
|
63007
|
+
return withDetail(`model not found \xB7 ${status}${latency}`.trim(), result.errorMessage);
|
|
62187
63008
|
case "rate-limited":
|
|
62188
|
-
return `rate limited \xB7 ${result.latencyMs}ms
|
|
63009
|
+
return withDetail(`rate limited \xB7 ${result.latencyMs}ms`, result.errorMessage);
|
|
62189
63010
|
case "out-of-credit":
|
|
62190
|
-
return `out of credit \xB7 ${
|
|
63011
|
+
return withDetail(`out of credit \xB7 ${status}${latency}`.trim(), result.errorMessage);
|
|
62191
63012
|
case "server-error":
|
|
62192
|
-
return `server error \xB7 ${
|
|
63013
|
+
return withDetail(`server error \xB7 ${status} \xB7 ${result.latencyMs}ms`, result.errorMessage);
|
|
62193
63014
|
case "timeout":
|
|
62194
|
-
return `timeout \xB7 ${result.latencyMs}ms
|
|
63015
|
+
return withDetail(`timeout \xB7 ${result.latencyMs}ms`, result.errorMessage);
|
|
62195
63016
|
case "network-error":
|
|
62196
|
-
return `network error \xB7 ${result.latencyMs}ms
|
|
63017
|
+
return withDetail(`network error \xB7 ${result.latencyMs}ms`, result.errorMessage);
|
|
62197
63018
|
case "error": {
|
|
62198
|
-
const base = `error${result.httpStatus ? ` \xB7 ${result.httpStatus}` : ""}${
|
|
62199
|
-
return
|
|
63019
|
+
const base = `error${result.httpStatus ? ` \xB7 ${result.httpStatus}` : ""}${latency}`;
|
|
63020
|
+
return withDetail(base, result.errorMessage);
|
|
62200
63021
|
}
|
|
62201
63022
|
}
|
|
62202
63023
|
}
|
|
@@ -64484,22 +65305,22 @@ __export(exports_cli, {
|
|
|
64484
65305
|
});
|
|
64485
65306
|
import {
|
|
64486
65307
|
copyFileSync as copyFileSync2,
|
|
64487
|
-
existsSync as
|
|
65308
|
+
existsSync as existsSync22,
|
|
64488
65309
|
mkdirSync as mkdirSync13,
|
|
64489
65310
|
readFileSync as readFileSync21,
|
|
64490
65311
|
readdirSync as readdirSync5,
|
|
64491
65312
|
unlinkSync as unlinkSync7,
|
|
64492
65313
|
writeFileSync as writeFileSync15
|
|
64493
65314
|
} from "fs";
|
|
64494
|
-
import { homedir as
|
|
64495
|
-
import { dirname as dirname9, join as
|
|
65315
|
+
import { homedir as homedir26 } from "os";
|
|
65316
|
+
import { dirname as dirname9, join as join28 } from "path";
|
|
64496
65317
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
64497
65318
|
function getVersion3() {
|
|
64498
65319
|
return VERSION;
|
|
64499
65320
|
}
|
|
64500
65321
|
function clearAllModelCaches() {
|
|
64501
|
-
const cacheDir =
|
|
64502
|
-
if (!
|
|
65322
|
+
const cacheDir = join28(homedir26(), ".claudish");
|
|
65323
|
+
if (!existsSync22(cacheDir))
|
|
64503
65324
|
return;
|
|
64504
65325
|
const cachePatterns = ["pricing-cache.json", "recommended-models-cache.json"];
|
|
64505
65326
|
let cleared = 0;
|
|
@@ -64507,7 +65328,7 @@ function clearAllModelCaches() {
|
|
|
64507
65328
|
const files = readdirSync5(cacheDir);
|
|
64508
65329
|
for (const file2 of files) {
|
|
64509
65330
|
if (cachePatterns.includes(file2)) {
|
|
64510
|
-
unlinkSync7(
|
|
65331
|
+
unlinkSync7(join28(cacheDir, file2));
|
|
64511
65332
|
cleared++;
|
|
64512
65333
|
}
|
|
64513
65334
|
}
|
|
@@ -64917,8 +65738,8 @@ Usage: claudish --models --provider <slug>`);
|
|
|
64917
65738
|
});
|
|
64918
65739
|
config3.resolvedDefaultProvider = resolved;
|
|
64919
65740
|
if (resolved.legacyAutoPromoted && !config3.quiet) {
|
|
64920
|
-
const markerFile =
|
|
64921
|
-
if (!
|
|
65741
|
+
const markerFile = join28(homedir26(), ".claudish", ".legacy-litellm-hint-shown");
|
|
65742
|
+
if (!existsSync22(markerFile)) {
|
|
64922
65743
|
const hint = buildLegacyHint(resolved);
|
|
64923
65744
|
if (hint) {
|
|
64924
65745
|
console.error(hint);
|
|
@@ -65985,7 +66806,7 @@ ${h("MORE INFO")}
|
|
|
65985
66806
|
}
|
|
65986
66807
|
function printAIAgentGuide() {
|
|
65987
66808
|
try {
|
|
65988
|
-
const guidePath =
|
|
66809
|
+
const guidePath = join28(__dirname3, "../AI_AGENT_GUIDE.md");
|
|
65989
66810
|
const guideContent = readFileSync21(guidePath, "utf-8");
|
|
65990
66811
|
console.log(guideContent);
|
|
65991
66812
|
} catch (error46) {
|
|
@@ -66002,19 +66823,19 @@ async function initializeClaudishSkill() {
|
|
|
66002
66823
|
console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
|
|
66003
66824
|
`);
|
|
66004
66825
|
const cwd = process.cwd();
|
|
66005
|
-
const claudeDir =
|
|
66006
|
-
const skillsDir =
|
|
66007
|
-
const claudishSkillDir =
|
|
66008
|
-
const skillFile =
|
|
66009
|
-
if (
|
|
66826
|
+
const claudeDir = join28(cwd, ".claude");
|
|
66827
|
+
const skillsDir = join28(claudeDir, "skills");
|
|
66828
|
+
const claudishSkillDir = join28(skillsDir, "claudish-usage");
|
|
66829
|
+
const skillFile = join28(claudishSkillDir, "SKILL.md");
|
|
66830
|
+
if (existsSync22(skillFile)) {
|
|
66010
66831
|
console.log("\u2705 Claudish skill already installed at:");
|
|
66011
66832
|
console.log(` ${skillFile}
|
|
66012
66833
|
`);
|
|
66013
66834
|
console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
|
|
66014
66835
|
return;
|
|
66015
66836
|
}
|
|
66016
|
-
const sourceSkillPath =
|
|
66017
|
-
if (!
|
|
66837
|
+
const sourceSkillPath = join28(__dirname3, "../skills/claudish-usage/SKILL.md");
|
|
66838
|
+
if (!existsSync22(sourceSkillPath)) {
|
|
66018
66839
|
console.error("\u274C Error: Claudish skill file not found in installation.");
|
|
66019
66840
|
console.error(` Expected at: ${sourceSkillPath}`);
|
|
66020
66841
|
console.error(`
|
|
@@ -66023,15 +66844,15 @@ async function initializeClaudishSkill() {
|
|
|
66023
66844
|
process.exit(1);
|
|
66024
66845
|
}
|
|
66025
66846
|
try {
|
|
66026
|
-
if (!
|
|
66847
|
+
if (!existsSync22(claudeDir)) {
|
|
66027
66848
|
mkdirSync13(claudeDir, { recursive: true });
|
|
66028
66849
|
console.log("\uD83D\uDCC1 Created .claude/ directory");
|
|
66029
66850
|
}
|
|
66030
|
-
if (!
|
|
66851
|
+
if (!existsSync22(skillsDir)) {
|
|
66031
66852
|
mkdirSync13(skillsDir, { recursive: true });
|
|
66032
66853
|
console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
|
|
66033
66854
|
}
|
|
66034
|
-
if (!
|
|
66855
|
+
if (!existsSync22(claudishSkillDir)) {
|
|
66035
66856
|
mkdirSync13(claudishSkillDir, { recursive: true });
|
|
66036
66857
|
console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
|
|
66037
66858
|
}
|
|
@@ -66116,30 +66937,30 @@ __export(exports_update_checker, {
|
|
|
66116
66937
|
clearCache: () => clearCache,
|
|
66117
66938
|
checkForUpdates: () => checkForUpdates
|
|
66118
66939
|
});
|
|
66119
|
-
import { existsSync as
|
|
66120
|
-
import { homedir as
|
|
66121
|
-
import { join as
|
|
66940
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync14, readFileSync as readFileSync22, unlinkSync as unlinkSync8, writeFileSync as writeFileSync16 } from "fs";
|
|
66941
|
+
import { homedir as homedir27, platform as platform2, tmpdir } from "os";
|
|
66942
|
+
import { join as join29 } from "path";
|
|
66122
66943
|
function getCacheFilePath() {
|
|
66123
66944
|
let cacheDir;
|
|
66124
66945
|
if (isWindows) {
|
|
66125
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
66126
|
-
cacheDir =
|
|
66946
|
+
const localAppData = process.env.LOCALAPPDATA || join29(homedir27(), "AppData", "Local");
|
|
66947
|
+
cacheDir = join29(localAppData, "claudish");
|
|
66127
66948
|
} else {
|
|
66128
|
-
cacheDir =
|
|
66949
|
+
cacheDir = join29(homedir27(), ".cache", "claudish");
|
|
66129
66950
|
}
|
|
66130
66951
|
try {
|
|
66131
|
-
if (!
|
|
66952
|
+
if (!existsSync23(cacheDir)) {
|
|
66132
66953
|
mkdirSync14(cacheDir, { recursive: true });
|
|
66133
66954
|
}
|
|
66134
|
-
return
|
|
66955
|
+
return join29(cacheDir, "update-check.json");
|
|
66135
66956
|
} catch {
|
|
66136
|
-
return
|
|
66957
|
+
return join29(tmpdir(), "claudish-update-check.json");
|
|
66137
66958
|
}
|
|
66138
66959
|
}
|
|
66139
66960
|
function readCache() {
|
|
66140
66961
|
try {
|
|
66141
66962
|
const cachePath = getCacheFilePath();
|
|
66142
|
-
if (!
|
|
66963
|
+
if (!existsSync23(cachePath)) {
|
|
66143
66964
|
return null;
|
|
66144
66965
|
}
|
|
66145
66966
|
const data = JSON.parse(readFileSync22(cachePath, "utf-8"));
|
|
@@ -66165,7 +66986,7 @@ function isCacheValid(cache2) {
|
|
|
66165
66986
|
function clearCache() {
|
|
66166
66987
|
try {
|
|
66167
66988
|
const cachePath = getCacheFilePath();
|
|
66168
|
-
if (
|
|
66989
|
+
if (existsSync23(cachePath)) {
|
|
66169
66990
|
unlinkSync8(cachePath);
|
|
66170
66991
|
}
|
|
66171
66992
|
} catch {}
|
|
@@ -67013,16 +67834,22 @@ function localBaseUrl(catalogName) {
|
|
|
67013
67834
|
}
|
|
67014
67835
|
return (def.baseUrl || "").replace(/\/+$/, "") || null;
|
|
67015
67836
|
}
|
|
67837
|
+
function isHtmlResponse(res) {
|
|
67838
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
67839
|
+
return /\btext\/html\b|\bapplication\/xhtml\+xml\b/i.test(contentType);
|
|
67840
|
+
}
|
|
67016
67841
|
async function pingLocalProvider(catalogName, timeoutMs = PING_TIMEOUT_MS) {
|
|
67017
67842
|
const base = localBaseUrl(catalogName);
|
|
67018
67843
|
const path2 = HEALTH_PATH[catalogName];
|
|
67019
67844
|
if (!base || !path2)
|
|
67020
67845
|
return "unknown";
|
|
67021
67846
|
try {
|
|
67022
|
-
await fetch(`${base}${path2}`, {
|
|
67847
|
+
const res = await fetch(`${base}${path2}`, {
|
|
67023
67848
|
method: "GET",
|
|
67024
67849
|
signal: AbortSignal.timeout(timeoutMs)
|
|
67025
67850
|
});
|
|
67851
|
+
if (res.ok && isHtmlResponse(res))
|
|
67852
|
+
return "down";
|
|
67026
67853
|
return "running";
|
|
67027
67854
|
} catch {
|
|
67028
67855
|
return "down";
|
|
@@ -67044,11 +67871,11 @@ var init_local_liveness = __esm(() => {
|
|
|
67044
67871
|
});
|
|
67045
67872
|
|
|
67046
67873
|
// src/providers/probe-catalog.ts
|
|
67047
|
-
import { existsSync as
|
|
67048
|
-
import { homedir as
|
|
67049
|
-
import { dirname as dirname10, join as
|
|
67874
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync15, readFileSync as readFileSync23, writeFileSync as writeFileSync17 } from "fs";
|
|
67875
|
+
import { homedir as homedir28 } from "os";
|
|
67876
|
+
import { dirname as dirname10, join as join30 } from "path";
|
|
67050
67877
|
function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
|
|
67051
|
-
if (!
|
|
67878
|
+
if (!existsSync24(path2))
|
|
67052
67879
|
return null;
|
|
67053
67880
|
let raw2;
|
|
67054
67881
|
try {
|
|
@@ -67181,7 +68008,7 @@ function isValidResponse(raw2) {
|
|
|
67181
68008
|
var PROBE_MODELS_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/probeModels", CACHE_TTL_MS4, FETCH_TIMEOUT_MS3 = 15000, PROBE_MODELS_CACHE_PATH, _inFlight = null;
|
|
67182
68009
|
var init_probe_catalog = __esm(() => {
|
|
67183
68010
|
CACHE_TTL_MS4 = 60 * 60 * 1000;
|
|
67184
|
-
PROBE_MODELS_CACHE_PATH =
|
|
68011
|
+
PROBE_MODELS_CACHE_PATH = join30(homedir28(), ".claudish", "probe-models.json");
|
|
67185
68012
|
});
|
|
67186
68013
|
|
|
67187
68014
|
// src/tui/constants.ts
|
|
@@ -73518,15 +74345,15 @@ __export(exports_claude_runner, {
|
|
|
73518
74345
|
import { spawn as spawn4 } from "child_process";
|
|
73519
74346
|
import {
|
|
73520
74347
|
closeSync as closeSync5,
|
|
73521
|
-
existsSync as
|
|
74348
|
+
existsSync as existsSync25,
|
|
73522
74349
|
mkdirSync as mkdirSync16,
|
|
73523
74350
|
openSync as openSync5,
|
|
73524
74351
|
readFileSync as readFileSync24,
|
|
73525
74352
|
unlinkSync as unlinkSync9,
|
|
73526
74353
|
writeFileSync as writeFileSync18
|
|
73527
74354
|
} from "fs";
|
|
73528
|
-
import { homedir as
|
|
73529
|
-
import { join as
|
|
74355
|
+
import { homedir as homedir29, tmpdir as tmpdir2 } from "os";
|
|
74356
|
+
import { join as join31 } from "path";
|
|
73530
74357
|
import { isatty } from "tty";
|
|
73531
74358
|
function releaseTerminalIsolation() {
|
|
73532
74359
|
if (!restoreTerminal)
|
|
@@ -73561,7 +74388,7 @@ function isProxyAuthMode(config3) {
|
|
|
73561
74388
|
}
|
|
73562
74389
|
function managedSettingsPath() {
|
|
73563
74390
|
if (isWindows2()) {
|
|
73564
|
-
return
|
|
74391
|
+
return join31(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
|
|
73565
74392
|
}
|
|
73566
74393
|
if (process.platform === "darwin") {
|
|
73567
74394
|
return "/Library/Application Support/ClaudeCode/managed-settings.json";
|
|
@@ -73582,9 +74409,9 @@ function isWindows2() {
|
|
|
73582
74409
|
}
|
|
73583
74410
|
function createStatusLineScript(tokenFilePath) {
|
|
73584
74411
|
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
|
|
73585
|
-
const claudishDir =
|
|
74412
|
+
const claudishDir = join31(homeDir, ".claudish");
|
|
73586
74413
|
const timestamp = Date.now();
|
|
73587
|
-
const scriptPath =
|
|
74414
|
+
const scriptPath = join31(claudishDir, `status-${timestamp}.js`);
|
|
73588
74415
|
const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
|
|
73589
74416
|
const script = `
|
|
73590
74417
|
const fs = require('fs');
|
|
@@ -73707,13 +74534,13 @@ process.stdin.on('end', () => {
|
|
|
73707
74534
|
}
|
|
73708
74535
|
function createTempSettingsFile(_modelDisplay, port, proxyAuthMode) {
|
|
73709
74536
|
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
|
|
73710
|
-
const claudishDir =
|
|
74537
|
+
const claudishDir = join31(homeDir, ".claudish");
|
|
73711
74538
|
try {
|
|
73712
74539
|
mkdirSync16(claudishDir, { recursive: true });
|
|
73713
74540
|
} catch {}
|
|
73714
74541
|
const timestamp = Date.now();
|
|
73715
|
-
const tempPath =
|
|
73716
|
-
const tokenFilePath =
|
|
74542
|
+
const tempPath = join31(claudishDir, `settings-${timestamp}.json`);
|
|
74543
|
+
const tokenFilePath = join31(claudishDir, `tokens-${port}.json`);
|
|
73717
74544
|
let statusCommand;
|
|
73718
74545
|
if (isWindows2()) {
|
|
73719
74546
|
const scriptPath = createStatusLineScript(tokenFilePath);
|
|
@@ -73928,8 +74755,8 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
|
|
|
73928
74755
|
console.error("Install it from: https://claude.com/claude-code");
|
|
73929
74756
|
console.error(`
|
|
73930
74757
|
Or set CLAUDE_PATH to your custom installation:`);
|
|
73931
|
-
const home =
|
|
73932
|
-
const localPath = isWindows2() ?
|
|
74758
|
+
const home = homedir29();
|
|
74759
|
+
const localPath = isWindows2() ? join31(home, ".claude", "local", "claude.exe") : join31(home, ".claude", "local", "claude");
|
|
73933
74760
|
console.error(` export CLAUDE_PATH=${localPath}`);
|
|
73934
74761
|
process.exit(1);
|
|
73935
74762
|
}
|
|
@@ -74009,23 +74836,23 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
|
|
|
74009
74836
|
async function findClaudeBinary() {
|
|
74010
74837
|
const isWindows3 = process.platform === "win32";
|
|
74011
74838
|
if (process.env.CLAUDE_PATH) {
|
|
74012
|
-
if (
|
|
74839
|
+
if (existsSync25(process.env.CLAUDE_PATH)) {
|
|
74013
74840
|
return process.env.CLAUDE_PATH;
|
|
74014
74841
|
}
|
|
74015
74842
|
}
|
|
74016
|
-
const home =
|
|
74017
|
-
const localPath = isWindows3 ?
|
|
74018
|
-
if (
|
|
74843
|
+
const home = homedir29();
|
|
74844
|
+
const localPath = isWindows3 ? join31(home, ".claude", "local", "claude.exe") : join31(home, ".claude", "local", "claude");
|
|
74845
|
+
if (existsSync25(localPath)) {
|
|
74019
74846
|
return localPath;
|
|
74020
74847
|
}
|
|
74021
74848
|
if (isWindows3) {
|
|
74022
74849
|
const windowsPaths = [
|
|
74023
|
-
|
|
74024
|
-
|
|
74025
|
-
|
|
74850
|
+
join31(home, "AppData", "Roaming", "npm", "claude.cmd"),
|
|
74851
|
+
join31(home, ".npm-global", "claude.cmd"),
|
|
74852
|
+
join31(home, "node_modules", ".bin", "claude.cmd")
|
|
74026
74853
|
];
|
|
74027
74854
|
for (const path2 of windowsPaths) {
|
|
74028
|
-
if (
|
|
74855
|
+
if (existsSync25(path2)) {
|
|
74029
74856
|
return path2;
|
|
74030
74857
|
}
|
|
74031
74858
|
}
|
|
@@ -74033,14 +74860,14 @@ async function findClaudeBinary() {
|
|
|
74033
74860
|
const commonPaths = [
|
|
74034
74861
|
"/usr/local/bin/claude",
|
|
74035
74862
|
"/opt/homebrew/bin/claude",
|
|
74036
|
-
|
|
74037
|
-
|
|
74038
|
-
|
|
74863
|
+
join31(home, ".npm-global/bin/claude"),
|
|
74864
|
+
join31(home, ".local/bin/claude"),
|
|
74865
|
+
join31(home, "node_modules/.bin/claude"),
|
|
74039
74866
|
"/data/data/com.termux/files/usr/bin/claude",
|
|
74040
|
-
|
|
74867
|
+
join31(home, "../usr/bin/claude")
|
|
74041
74868
|
];
|
|
74042
74869
|
for (const path2 of commonPaths) {
|
|
74043
|
-
if (
|
|
74870
|
+
if (existsSync25(path2)) {
|
|
74044
74871
|
return path2;
|
|
74045
74872
|
}
|
|
74046
74873
|
}
|
|
@@ -74098,17 +74925,17 @@ __export(exports_diag_output, {
|
|
|
74098
74925
|
LogFileDiagOutput: () => LogFileDiagOutput
|
|
74099
74926
|
});
|
|
74100
74927
|
import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync17, unlinkSync as unlinkSync10, writeFileSync as writeFileSync19 } from "fs";
|
|
74101
|
-
import { homedir as
|
|
74102
|
-
import { join as
|
|
74928
|
+
import { homedir as homedir30 } from "os";
|
|
74929
|
+
import { join as join32 } from "path";
|
|
74103
74930
|
function getClaudishDir() {
|
|
74104
|
-
const dir =
|
|
74931
|
+
const dir = join32(homedir30(), ".claudish");
|
|
74105
74932
|
try {
|
|
74106
74933
|
mkdirSync17(dir, { recursive: true });
|
|
74107
74934
|
} catch {}
|
|
74108
74935
|
return dir;
|
|
74109
74936
|
}
|
|
74110
74937
|
function getDiagLogPath() {
|
|
74111
|
-
return
|
|
74938
|
+
return join32(getClaudishDir(), `diag-${process.pid}.log`);
|
|
74112
74939
|
}
|
|
74113
74940
|
|
|
74114
74941
|
class LogFileDiagOutput {
|
|
@@ -74319,9 +75146,9 @@ __export(exports_team_grid, {
|
|
|
74319
75146
|
});
|
|
74320
75147
|
import { spawn as spawn5 } from "child_process";
|
|
74321
75148
|
import { execSync as execSync2 } from "child_process";
|
|
74322
|
-
import { existsSync as
|
|
75149
|
+
import { existsSync as existsSync26, readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "fs";
|
|
74323
75150
|
import { connect as netConnect } from "net";
|
|
74324
|
-
import { dirname as dirname11, join as
|
|
75151
|
+
import { dirname as dirname11, join as join33 } from "path";
|
|
74325
75152
|
import { setTimeout as wait } from "timers/promises";
|
|
74326
75153
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
74327
75154
|
function resolveRouteInfo(modelId) {
|
|
@@ -74415,18 +75242,18 @@ function buildPaneHeader(model, prompt, bg) {
|
|
|
74415
75242
|
function findMagmuxBinary() {
|
|
74416
75243
|
const thisFile = fileURLToPath3(import.meta.url);
|
|
74417
75244
|
const thisDir = dirname11(thisFile);
|
|
74418
|
-
const pkgRoot =
|
|
75245
|
+
const pkgRoot = join33(thisDir, "..");
|
|
74419
75246
|
const platform3 = process.platform;
|
|
74420
75247
|
const arch = process.arch;
|
|
74421
|
-
const bundledMagmux =
|
|
74422
|
-
if (
|
|
75248
|
+
const bundledMagmux = join33(pkgRoot, "native", `magmux-${platform3}-${arch}`);
|
|
75249
|
+
if (existsSync26(bundledMagmux))
|
|
74423
75250
|
return bundledMagmux;
|
|
74424
75251
|
try {
|
|
74425
75252
|
const pkgName = `@claudish/magmux-${platform3}-${arch}`;
|
|
74426
75253
|
let searchDir = pkgRoot;
|
|
74427
75254
|
for (let i = 0;i < 5; i++) {
|
|
74428
|
-
const candidate =
|
|
74429
|
-
if (
|
|
75255
|
+
const candidate = join33(searchDir, "node_modules", pkgName, "bin", "magmux");
|
|
75256
|
+
if (existsSync26(candidate))
|
|
74430
75257
|
return candidate;
|
|
74431
75258
|
const parent = dirname11(searchDir);
|
|
74432
75259
|
if (parent === searchDir)
|
|
@@ -74445,7 +75272,7 @@ function findMagmuxBinary() {
|
|
|
74445
75272
|
async function subscribeToMagmux(sockPath, onEvent) {
|
|
74446
75273
|
let client = null;
|
|
74447
75274
|
for (let attempt = 0;attempt < 40; attempt++) {
|
|
74448
|
-
if (
|
|
75275
|
+
if (existsSync26(sockPath)) {
|
|
74449
75276
|
try {
|
|
74450
75277
|
client = await new Promise((resolve4, reject) => {
|
|
74451
75278
|
const s = netConnect(sockPath);
|
|
@@ -74532,9 +75359,9 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
74532
75359
|
const keep = opts?.keep ?? false;
|
|
74533
75360
|
const manifest = setupSession(sessionPath, models, input);
|
|
74534
75361
|
const startedAt = new Date().toISOString();
|
|
74535
|
-
const gridfilePath =
|
|
74536
|
-
const prompt = readFileSync25(
|
|
74537
|
-
const rawPrompt = readFileSync25(
|
|
75362
|
+
const gridfilePath = join33(sessionPath, "gridfile.txt");
|
|
75363
|
+
const prompt = readFileSync25(join33(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
|
|
75364
|
+
const rawPrompt = readFileSync25(join33(sessionPath, "input.md"), "utf-8");
|
|
74538
75365
|
const usedBannerColors = new Set;
|
|
74539
75366
|
const gridLines = Object.entries(manifest.models).map(([anonId]) => {
|
|
74540
75367
|
const model = manifest.models[anonId].model;
|
|
@@ -74565,7 +75392,7 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
74565
75392
|
});
|
|
74566
75393
|
const [{ results }] = await Promise.all([subscription, procExit]);
|
|
74567
75394
|
const status = buildTeamStatus(manifest, startedAt, results?.panes ?? null);
|
|
74568
|
-
const statusPath =
|
|
75395
|
+
const statusPath = join33(sessionPath, "status.json");
|
|
74569
75396
|
writeFileSync20(statusPath, JSON.stringify(status, null, 2), "utf-8");
|
|
74570
75397
|
return status;
|
|
74571
75398
|
}
|
|
@@ -74589,8 +75416,8 @@ var init_team_grid = __esm(() => {
|
|
|
74589
75416
|
init_op_source();
|
|
74590
75417
|
init_startup_trace();
|
|
74591
75418
|
var import_dotenv3 = __toESM(require_main(), 1);
|
|
74592
|
-
import { existsSync as
|
|
74593
|
-
import { join as
|
|
75419
|
+
import { existsSync as existsSync27, readFileSync as readFileSync26 } from "fs";
|
|
75420
|
+
import { join as join34, resolve as resolve4 } from "path";
|
|
74594
75421
|
import_dotenv3.config({ quiet: true });
|
|
74595
75422
|
function classifyStartupKind() {
|
|
74596
75423
|
const argv = process.argv.slice(2);
|
|
@@ -74689,7 +75516,7 @@ async function applyConfigOverride() {
|
|
|
74689
75516
|
const { planConfigOverride: planConfigOverride2, setConfigFileOverride: setConfigFileOverride2 } = await Promise.resolve().then(() => exports_config_override);
|
|
74690
75517
|
const plan = planConfigOverride2(process.argv.slice(2), process.env, {
|
|
74691
75518
|
resolve: resolve4,
|
|
74692
|
-
exists:
|
|
75519
|
+
exists: existsSync27
|
|
74693
75520
|
});
|
|
74694
75521
|
if (plan.kind === "none")
|
|
74695
75522
|
return;
|
|
@@ -74838,7 +75665,7 @@ async function runCli() {
|
|
|
74838
75665
|
process.exit(1);
|
|
74839
75666
|
}
|
|
74840
75667
|
const mode = cliConfig.teamMode ?? "default";
|
|
74841
|
-
const sessionPath =
|
|
75668
|
+
const sessionPath = join34(process.cwd(), `.claudish-team-${Date.now()}`);
|
|
74842
75669
|
if (mode === "json") {
|
|
74843
75670
|
const { setupSession: setupSession2, runModels: runModels2 } = await Promise.resolve().then(() => (init_team_orchestrator(), exports_team_orchestrator));
|
|
74844
75671
|
setupSession2(sessionPath, cliConfig.team, prompt);
|
|
@@ -74848,7 +75675,7 @@ async function runCli() {
|
|
|
74848
75675
|
});
|
|
74849
75676
|
const result = { ...status2, responses: {} };
|
|
74850
75677
|
for (const anonId of Object.keys(status2.models)) {
|
|
74851
|
-
const responsePath =
|
|
75678
|
+
const responsePath = join34(sessionPath, `response-${anonId}.md`);
|
|
74852
75679
|
try {
|
|
74853
75680
|
const raw2 = readFileSync26(responsePath, "utf-8").trim();
|
|
74854
75681
|
try {
|