@kenkaiiii/gg-ai 5.81.0 → 5.83.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.cjs CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  EventStream: () => EventStream,
34
+ FAST_MODE_SUFFIX: () => FAST_MODE_SUFFIX,
34
35
  GGAIError: () => GGAIError,
35
36
  ProviderError: () => ProviderError,
36
37
  REDACTION_MARKER: () => REDACTED,
@@ -39,6 +40,7 @@ __export(index_exports, {
39
40
  clampProviderContextImages: () => clampProviderContextImages,
40
41
  classifyProviderError: () => classifyProviderError,
41
42
  continuesTurn: () => continuesTurn,
43
+ describeFastModeRejection: () => describeFastModeRejection,
42
44
  dropInvalidToolCalls: () => dropInvalidToolCalls,
43
45
  embed: () => embed,
44
46
  environmentSecrets: () => environmentSecrets,
@@ -57,12 +59,14 @@ __export(index_exports, {
57
59
  palsuText: () => palsuText,
58
60
  palsuThinking: () => palsuThinking,
59
61
  palsuToolCall: () => palsuToolCall,
62
+ parseFastModeRejection: () => parseFastModeRejection,
60
63
  prewarmAnthropicCache: () => prewarmAnthropicCache,
61
64
  providerRegistry: () => providerRegistry,
62
65
  redactText: () => redactText,
63
66
  redactValue: () => redactValue,
64
67
  registerPalsuProvider: () => registerPalsuProvider,
65
68
  rerank: () => rerank,
69
+ resolveFastModeModel: () => resolveFastModeModel,
66
70
  resolveToolSchema: () => resolveToolSchema,
67
71
  sanitizeMessagesForWire: () => sanitizeMessagesForWire,
68
72
  setProviderDiagnostic: () => setProviderDiagnostic,
@@ -77,6 +81,96 @@ __export(index_exports, {
77
81
  });
78
82
  module.exports = __toCommonJS(index_exports);
79
83
 
84
+ // src/fast-mode.ts
85
+ var FAST_MODE_SUFFIX = "-fast";
86
+ var FAST_MODE_BASE_MODELS = {
87
+ anthropic: ["claude-opus-5-5"],
88
+ openai: ["gpt-6-astra", "gpt-6.1-sol", "gpt-6-luna"]
89
+ };
90
+ function resolveFastModeModel(provider, model) {
91
+ if (!model.endsWith(FAST_MODE_SUFFIX)) return { model, fast: false };
92
+ const base = model.slice(0, -FAST_MODE_SUFFIX.length);
93
+ return FAST_MODE_BASE_MODELS[provider]?.includes(base) ? { model: base, fast: true } : { model, fast: false };
94
+ }
95
+ var FAST_MODE_REJECTION_HEADER = "anthropic-ratelimit-unified-overage-disabled-reason";
96
+ var FAST_MODE_REJECTION_PREFIX = "Fast mode unavailable";
97
+ var USAGE_PAGE = "claude.ai/settings/usage";
98
+ var STANDARD_SPEED_FALLBACK = "or switch to Claude Opus 5.5 (standard speed), which uses your plan";
99
+ function describeFastModeRejection(reason) {
100
+ const code = reason?.trim() || "unknown";
101
+ const of = (headline, guidance, kind) => ({ reason: code, headline, guidance, kind });
102
+ switch (code) {
103
+ case "overage_not_provisioned":
104
+ case "no_limits_configured":
105
+ return of(
106
+ "Claude usage credits are turned off",
107
+ `Fast mode bills your Claude usage credits, never your plan. Turn usage credits on at ${USAGE_PAGE}, ${STANDARD_SPEED_FALLBACK}.`,
108
+ "access"
109
+ );
110
+ case "out_of_credits":
111
+ return of(
112
+ "Your Claude usage credits have run out",
113
+ `Fast mode bills your Claude usage credits, never your plan, and the balance is empty. Add funds or turn on auto-reload at ${USAGE_PAGE}, ${STANDARD_SPEED_FALLBACK}.`,
114
+ "billing"
115
+ );
116
+ case "org_level_disabled_until":
117
+ case "org_spend_cap_reached":
118
+ return of(
119
+ "Claude usage credit limit reached",
120
+ `Fast mode bills your Claude usage credits and this period's spend limit is used up. Raise the limit at ${USAGE_PAGE}, ${STANDARD_SPEED_FALLBACK}.`,
121
+ "billing"
122
+ );
123
+ case "org_level_disabled":
124
+ case "org_service_level_disabled":
125
+ return of(
126
+ "Your organization turned Claude usage credits off",
127
+ `Fast mode needs usage credits. Ask an admin to turn them on, ${STANDARD_SPEED_FALLBACK}.`,
128
+ "access"
129
+ );
130
+ case "member_level_disabled":
131
+ return of(
132
+ "Claude usage credits are off for your account",
133
+ `Fast mode needs usage credits. Ask your organization's admin to turn them on for you, ${STANDARD_SPEED_FALLBACK}.`,
134
+ "access"
135
+ );
136
+ case "seat_tier_level_disabled":
137
+ case "seat_tier_zero_credit_limit":
138
+ case "member_zero_credit_limit":
139
+ case "group_zero_credit_limit":
140
+ return of(
141
+ "Claude usage credits aren't available on your plan",
142
+ `Fast mode needs usage credits, which your seat doesn't include. Ask your admin about access, ${STANDARD_SPEED_FALLBACK}.`,
143
+ "access"
144
+ );
145
+ case "fast_mode_org_disabled":
146
+ return of(
147
+ "Your organization turned fast mode off",
148
+ `An Owner can enable fast mode for the organization, ${STANDARD_SPEED_FALLBACK}.`,
149
+ "access"
150
+ );
151
+ default:
152
+ return of(
153
+ "Fast mode needs Claude usage credits",
154
+ `Fast mode bills your Claude usage credits, never your plan, and Anthropic couldn't charge them. Check usage credits at ${USAGE_PAGE}, ${STANDARD_SPEED_FALLBACK}.`,
155
+ "billing"
156
+ );
157
+ }
158
+ }
159
+ function fastModeRejectionMessage(rejection) {
160
+ return `${FAST_MODE_REJECTION_PREFIX} (${rejection.reason}): ${rejection.headline}.`;
161
+ }
162
+ function parseFastModeRejection(message) {
163
+ const canonical = /fast mode unavailable \(([a-z_]+)\)/i.exec(message);
164
+ if (canonical) return describeFastModeRejection(canonical[1]);
165
+ if (/usage credits are required for fast mode/i.test(message)) {
166
+ return describeFastModeRejection(void 0);
167
+ }
168
+ if (/fast mode (?:has been |is )?disabled by your organization/i.test(message)) {
169
+ return describeFastModeRejection("fast_mode_org_disabled");
170
+ }
171
+ return void 0;
172
+ }
173
+
80
174
  // src/errors.ts
81
175
  function readHeader(headers, ...names) {
82
176
  if (!headers) return void 0;
@@ -156,7 +250,8 @@ function isUsageLimitError(err) {
156
250
  }
157
251
  function isHardBillingMessage(message) {
158
252
  const lower = message.toLowerCase();
159
- return lower.includes("insufficient balance") || lower.includes("insufficient credits") || lower.includes("more credits") || lower.includes("insufficient_quota") || lower.includes("exceeded your current quota") || lower.includes("quota exceeded") || lower.includes("no resource package") || lower.includes("recharge") || lower.includes("balance is too low") || lower.includes("out of credits") || lower.includes("arrears") || lower.includes("arrearage") || lower.includes("token quota") || lower.includes("exceeded_current_quota_error") || lower.includes("check your account balance") || lower.includes("does not yet include access") || lower.includes("subscription plan") || lower.includes("billing");
253
+ return lower.includes("insufficient balance") || lower.includes("insufficient credits") || lower.includes("more credits") || lower.includes("insufficient_quota") || lower.includes("exceeded your current quota") || lower.includes("quota exceeded") || lower.includes("no resource package") || lower.includes("recharge") || lower.includes("balance is too low") || lower.includes("out of credits") || // Anthropic fast mode when usage credits can't pay (see fast-mode.ts).
254
+ lower.includes("usage credits are required") || lower.includes("fast mode unavailable") || lower.includes("arrears") || lower.includes("arrearage") || lower.includes("token quota") || lower.includes("exceeded_current_quota_error") || lower.includes("check your account balance") || lower.includes("does not yet include access") || lower.includes("subscription plan") || lower.includes("billing");
160
255
  }
161
256
  function formatResetTime(resetsAt) {
162
257
  const when = new Date(resetsAt * 1e3);
@@ -209,6 +304,18 @@ function formatError(err) {
209
304
  guidance: "Request access via your Anthropic account team (see platform.claude.com/docs/en/about-claude/models/overview), or switch to Claude Fable 5.1 via the model selector \u2014 same underlying model, generally available."
210
305
  };
211
306
  }
307
+ const fastRejection = err.provider === "anthropic" ? parseFastModeRejection(err.message) : void 0;
308
+ if (fastRejection) {
309
+ return {
310
+ headline: `${fastRejection.headline}.`,
311
+ source: "provider",
312
+ message: cleanMessage,
313
+ provider: err.provider,
314
+ statusCode: err.statusCode,
315
+ ...err.requestId ? { requestId: err.requestId } : {},
316
+ guidance: fastRejection.guidance
317
+ };
318
+ }
212
319
  if (isUsageLimitError(err)) {
213
320
  const resetClause = err.resetsAt ? ` It resets at ${formatResetTime(err.resetsAt)}.` : "";
214
321
  return {
@@ -1385,7 +1492,7 @@ function isAdaptiveThinkingModel(model) {
1385
1492
  function toAnthropicThinking(level, maxTokens, model) {
1386
1493
  if (isAdaptiveThinkingModel(model)) {
1387
1494
  let effort = level;
1388
- if (effort === "xhigh" && !/opus-5|opus-4-8|opus-4-7|sonnet-5[-.]5|haiku-5[-.]5/.test(model)) {
1495
+ if (effort === "xhigh" && !/fable-5|mythos-5|opus-5|opus-4-8|opus-4-7|sonnet-5[-.]5|haiku-5[-.]5/.test(model)) {
1389
1496
  effort = "high";
1390
1497
  }
1391
1498
  return {
@@ -1653,6 +1760,7 @@ function fineGrainedToolStreamingEnabled() {
1653
1760
  return v === "1" || v === "true" || v === "yes" || v === "on";
1654
1761
  }
1655
1762
  var SERVER_FALLBACK_BETA = "server-side-fallback-2026-07-01";
1763
+ var FAST_MODE_BETA = "fast-mode-2026-02-01";
1656
1764
  var anthropicServerFallback = {
1657
1765
  disabled: /* @__PURE__ */ new Set(),
1658
1766
  reset() {
@@ -1795,6 +1903,7 @@ async function* runStream(options) {
1795
1903
  const { system: rawSystem, messages } = toAnthropicMessages(downgradedMessages, cacheControl, {
1796
1904
  fallbackBlocks: useServerFallback
1797
1905
  });
1906
+ const useFastMode = options.speed === "fast" && options.provider === "anthropic" && isDirectAnthropicApi(options.baseUrl);
1798
1907
  const system = isOAuth ? [
1799
1908
  {
1800
1909
  type: "text",
@@ -1865,6 +1974,7 @@ async function* runStream(options) {
1865
1974
  return contextEdits.length ? { context_management: { edits: contextEdits } } : {};
1866
1975
  })(),
1867
1976
  ...useServerFallback ? { fallbacks: "default" } : {},
1977
+ ...useFastMode ? { speed: "fast" } : {},
1868
1978
  stream: useStreaming
1869
1979
  };
1870
1980
  const params = mergeProviderOptions(baseParams, options.providerOptions);
@@ -1883,7 +1993,8 @@ async function* runStream(options) {
1883
1993
  // so a pre-warmed cache expires before the user's first turn. cacheControl.ttl
1884
1994
  // is only "1h" on the first-party endpoint (see toAnthropicCacheControl).
1885
1995
  ...cacheControl?.ttl === "1h" ? ["extended-cache-ttl-2025-04-11"] : [],
1886
- ...useServerFallback ? [SERVER_FALLBACK_BETA] : []
1996
+ ...useServerFallback ? [SERVER_FALLBACK_BETA] : [],
1997
+ ...useFastMode ? [FAST_MODE_BETA] : []
1887
1998
  ];
1888
1999
  const toRequestOptions = (betas) => ({
1889
2000
  signal: options.signal ?? void 0,
@@ -1921,7 +2032,7 @@ async function* runStream(options) {
1921
2032
  yield* synthesizeEventsFromMessage(message);
1922
2033
  return messageToResponse(message);
1923
2034
  } catch (err) {
1924
- throw toError(err);
2035
+ throw toError(err, { fastMode: useFastMode });
1925
2036
  }
1926
2037
  }
1927
2038
  const contentParts = [];
@@ -2138,7 +2249,7 @@ async function* runStream(options) {
2138
2249
  }
2139
2250
  }
2140
2251
  } catch (err) {
2141
- throw toError(err);
2252
+ throw toError(err, { fastMode: useFastMode });
2142
2253
  }
2143
2254
  if (!receivedAnyEvent) {
2144
2255
  throw new ProviderError("anthropic", "Stream ended without producing any events.", {
@@ -2268,6 +2379,13 @@ function messageToResponse(message) {
2268
2379
  }
2269
2380
  };
2270
2381
  }
2382
+ function readFastModeRejection(err, message, fastMode) {
2383
+ const reason = readHeader(err.headers, FAST_MODE_REJECTION_HEADER);
2384
+ if (fastMode && err.status === 429 && reason) return describeFastModeRejection(reason);
2385
+ const fromBody = parseFastModeRejection(message);
2386
+ if (!fromBody) return void 0;
2387
+ return reason ? describeFastModeRejection(reason) : fromBody;
2388
+ }
2271
2389
  function readUnifiedRateLimit(headers) {
2272
2390
  const status = readHeader(headers, "anthropic-ratelimit-unified-status");
2273
2391
  const resetRaw = readHeader(
@@ -2280,7 +2398,7 @@ function readUnifiedRateLimit(headers) {
2280
2398
  const resetsAt = Number.isFinite(resetNum) && resetNum > 0 ? resetNum : void 0;
2281
2399
  return { rejected: status === "rejected", ...resetsAt ? { resetsAt } : {} };
2282
2400
  }
2283
- function toError(err) {
2401
+ function toError(err, context) {
2284
2402
  if (err instanceof ProviderError) return err;
2285
2403
  if (err instanceof import_sdk.default.APIError) {
2286
2404
  const errorBody = err.error;
@@ -2291,6 +2409,15 @@ function toError(err) {
2291
2409
  const fallbackMessage = isRawJsonErrorEcho(err.message) ? emptyProviderErrorMessage(err.status) : err.message;
2292
2410
  const messageCandidate = bodyMessage ?? err.message;
2293
2411
  const message = isRawHtmlErrorEcho(messageCandidate) ? providerHtmlErrorMessage(err.status) : bodyType && bodyMessage ? `${bodyType}: ${bodyMessage}` : bodyMessage ?? fallbackMessage;
2412
+ const fastRejection = readFastModeRejection(err, message, context?.fastMode === true);
2413
+ if (fastRejection) {
2414
+ return new ProviderError("anthropic", fastModeRejectionMessage(fastRejection), {
2415
+ statusCode: err.status,
2416
+ ...requestId ? { requestId } : {},
2417
+ hint: fastRejection.guidance,
2418
+ cause: err
2419
+ });
2420
+ }
2294
2421
  if (err.status === 429) {
2295
2422
  const limit = readUnifiedRateLimit(err.headers);
2296
2423
  const farOff = limit.resetsAt != null && limit.resetsAt * 1e3 - Date.now() > 6e4;
@@ -2546,8 +2673,9 @@ async function* runStream2(options) {
2546
2673
  if (options.provider === "sakana" && options.model === "fugu-ultra" && (options.thinking === "max" || options.thinking === "ultra")) {
2547
2674
  params.reasoning_effort = "max";
2548
2675
  }
2549
- if (options.provider === "openai" && options.serviceTier) {
2550
- params.service_tier = options.serviceTier;
2676
+ const serviceTier = options.serviceTier ?? (options.speed === "fast" ? "priority" : void 0);
2677
+ if (options.provider === "openai" && serviceTier) {
2678
+ params.service_tier = serviceTier;
2551
2679
  }
2552
2680
  if (isKimiK3) {
2553
2681
  const paramsAny = params;
@@ -2585,10 +2713,16 @@ async function* runStream2(options) {
2585
2713
  `
2586
2714
  );
2587
2715
  }
2716
+ const requestHeaders = options.provider === "xai" ? {
2717
+ headers: {
2718
+ "x-grok-conv-id": normalizePromptCacheKey(options.promptCacheKey ?? "ggcoder")
2719
+ }
2720
+ } : {};
2588
2721
  if (!useStreaming) {
2589
2722
  try {
2590
2723
  const completion = await client.chat.completions.create(requestParams, {
2591
- signal: options.signal ?? void 0
2724
+ signal: options.signal ?? void 0,
2725
+ ...requestHeaders
2592
2726
  });
2593
2727
  yield* synthesizeEventsFromCompletion(completion, !!options.thinking, endpointKey);
2594
2728
  return completionToResponse(completion, endpointKey);
@@ -2599,7 +2733,8 @@ async function* runStream2(options) {
2599
2733
  let stream2;
2600
2734
  try {
2601
2735
  stream2 = await client.chat.completions.create(requestParams, {
2602
- signal: options.signal ?? void 0
2736
+ signal: options.signal ?? void 0,
2737
+ ...requestHeaders
2603
2738
  });
2604
2739
  } catch (err) {
2605
2740
  throw toError2(err, providerName);
@@ -3057,6 +3192,9 @@ async function* runStream3(options, retriedWithoutReasoning = false) {
3057
3192
  if (options.temperature != null && !options.thinking) {
3058
3193
  body.temperature = options.temperature;
3059
3194
  }
3195
+ if (options.speed === "fast") {
3196
+ body.service_tier = "priority";
3197
+ }
3060
3198
  body.reasoning = {
3061
3199
  // GPT-5.6/6 require at least low; older models still support thinking off.
3062
3200
  // Apply the floor here for every caller, including one-off prompt rewrites.
@@ -3639,6 +3777,9 @@ var CODE_ASSIST_SUPPORTED_MODELS = /* @__PURE__ */ new Set([
3639
3777
  "gemma-4-31b-it",
3640
3778
  "gemma-4-26b-a4b-it"
3641
3779
  ]);
3780
+ function isGeminiApiKeyRoute(options) {
3781
+ return options.baseUrl?.includes("generativelanguage.googleapis.com") === true;
3782
+ }
3642
3783
  function getGoogleProject(options) {
3643
3784
  const env = getEnvironment();
3644
3785
  return options.projectId ?? env?.GOOGLE_CLOUD_PROJECT ?? env?.GOOGLE_CLOUD_PROJECT_ID;
@@ -3671,8 +3812,28 @@ function accountGatedHint(model) {
3671
3812
  if (model === "gemini-3.8-flash" || model === "gemini-3.5-flash-lite") {
3672
3813
  return "Use /model to select Gemini 3.1 Flash Lite, or retry once Google enables this model through Code Assist for your account.";
3673
3814
  }
3674
- return `Newer Gemini models (3.7 Flash, 3.5 Flash, 3.1 Pro Preview) are available only to Code Assist Standard/Enterprise accounts with preview/GA access enabled by a cloud admin \u2014 free/personal accounts usually can't call them. Switch to Gemini 3.1 Flash Lite (it works on this account) with /model, or sign in with a Code Assist Standard/Enterprise account that has preview access.`;
3815
+ return `Newer Gemini models (3.5 Flash, 3.1 Pro Preview) are available only to Code Assist Standard/Enterprise accounts with preview/GA access enabled by a cloud admin. Try Gemini 3.1 Flash Lite with /model, or sign in with a Code Assist Standard/Enterprise account that has preview access.`;
3675
3816
  }
3817
+ function isCodeAssistLicenseRequired(status, body) {
3818
+ if (status !== 403) return false;
3819
+ try {
3820
+ const parsed = JSON.parse(body);
3821
+ const details = typeof parsed === "object" && parsed !== null && "error" in parsed ? parsed.error?.details : void 0;
3822
+ return Array.isArray(details) && details.some(
3823
+ (detail) => typeof detail === "object" && detail !== null && detail.reason === "SUBSCRIPTION_REQUIRED"
3824
+ );
3825
+ } catch {
3826
+ return false;
3827
+ }
3828
+ }
3829
+ function isInvalidGeminiApiKey(status, body) {
3830
+ if (status !== 400 && status !== 401 && status !== 403) return false;
3831
+ return /"reason"\s*:\s*"API_KEY_INVALID"/.test(body) || /API key not valid/i.test(body);
3832
+ }
3833
+ var INVALID_API_KEY_MESSAGE = "Google rejected the Gemini API key: it is not valid.";
3834
+ var INVALID_API_KEY_HINT = "Create a key at aistudio.google.com/apikey and add it again under Gemini in Providers (or `ggcoder login`).";
3835
+ var LICENSE_REQUIRED_MESSAGE = "This Google account has no Gemini Code Assist licence. Google stopped serving Gemini through Code Assist to personal accounts (Google AI Pro/Ultra and the free individual tier) on June 18, 2026, so every Gemini model is refused, not just this one.";
3836
+ var LICENSE_REQUIRED_HINT = "Sign in to Gemini with a Google account that has a Gemini Code Assist Standard or Enterprise licence, or pick a model from another provider with /model.";
3676
3837
  function formatErrorMessage(status, body, model) {
3677
3838
  if (status === 404 && !CODE_ASSIST_SUPPORTED_MODELS.has(model)) {
3678
3839
  return `Gemini API error (404): ${body}
@@ -3896,7 +4057,29 @@ function buildCodeAssistRequest(options, request, projectId) {
3896
4057
  request
3897
4058
  };
3898
4059
  }
4060
+ var API_KEY_MODEL_IDS = {
4061
+ "gemini-3-flash": "gemini-3.5-flash"
4062
+ };
4063
+ function buildApiKeyRequestPlan(options, method) {
4064
+ const { session_id: _sessionId, ...request } = mergeProviderOptions(
4065
+ buildGenerateRequest(options),
4066
+ options.providerOptions
4067
+ );
4068
+ const base = (options.baseUrl ?? "").replace(/\/+$/, "");
4069
+ return {
4070
+ url: new URL(
4071
+ `${base}/models/${encodeURIComponent(API_KEY_MODEL_IDS[options.model] ?? options.model)}:${method}`
4072
+ ),
4073
+ headers: {
4074
+ "Content-Type": "application/json",
4075
+ "x-goog-api-key": options.apiKey ?? ""
4076
+ },
4077
+ body: request,
4078
+ route: "api-key"
4079
+ };
4080
+ }
3899
4081
  function buildRequestPlan(options, method) {
4082
+ if (isGeminiApiKeyRoute(options)) return buildApiKeyRequestPlan(options, method);
3900
4083
  if (!CODE_ASSIST_SUPPORTED_MODELS.has(options.model)) {
3901
4084
  throw new ProviderError("gemini", formatUnsupportedModelMessage(options.model));
3902
4085
  }
@@ -3910,7 +4093,8 @@ function buildRequestPlan(options, method) {
3910
4093
  "User-Agent": GEMINI_CLI_USER_AGENT,
3911
4094
  "X-Goog-Api-Client": GEMINI_CLI_API_CLIENT
3912
4095
  },
3913
- body: buildCodeAssistRequest(options, request, projectId)
4096
+ body: buildCodeAssistRequest(options, request, projectId),
4097
+ route: "code-assist"
3914
4098
  };
3915
4099
  }
3916
4100
  function normalizeGeminiStopReason(reason) {
@@ -3996,8 +4180,11 @@ async function fetchCodeAssist(plan, options) {
3996
4180
  if (!response.ok) {
3997
4181
  const text = await response.text().catch(() => "");
3998
4182
  const quota = parseGeminiQuota(response.status, text);
3999
- const accountGated = response.status === 404 && ACCOUNT_GATED_MODELS.has(options.model);
4000
- let message = accountGated ? accountGatedMessage(options.model) : formatErrorMessage(response.status, text, options.model);
4183
+ const codeAssist = plan.route === "code-assist";
4184
+ const accountGated = codeAssist && response.status === 404 && ACCOUNT_GATED_MODELS.has(options.model);
4185
+ const licenseRequired = codeAssist && isCodeAssistLicenseRequired(response.status, text);
4186
+ const invalidKey = !codeAssist && isInvalidGeminiApiKey(response.status, text);
4187
+ let message = invalidKey ? INVALID_API_KEY_MESSAGE : licenseRequired ? LICENSE_REQUIRED_MESSAGE : accountGated ? accountGatedMessage(options.model) : formatErrorMessage(response.status, text, options.model);
4001
4188
  let resetsAt;
4002
4189
  if (quota?.exhausted) {
4003
4190
  message = `Gemini quota exhausted \u2014 usage limit reached. ${message}`;
@@ -4007,7 +4194,7 @@ async function fetchCodeAssist(plan, options) {
4007
4194
  throw new ProviderError("gemini", message, {
4008
4195
  statusCode: response.status,
4009
4196
  ...resetsAt !== void 0 ? { resetsAt } : {},
4010
- ...accountGated ? { hint: accountGatedHint(options.model) } : {}
4197
+ ...invalidKey ? { hint: INVALID_API_KEY_HINT, source: "auth" } : licenseRequired ? { hint: LICENSE_REQUIRED_HINT, source: "auth" } : accountGated ? { hint: accountGatedHint(options.model) } : {}
4011
4198
  });
4012
4199
  }
4013
4200
  return response;
@@ -4894,7 +5081,7 @@ providerRegistry.register("sakana", {
4894
5081
  providerRegistry.register("xai", {
4895
5082
  // xAI's public API (console.x.ai key) is OpenAI-compatible — ride the Chat
4896
5083
  // Completions transport like Moonshot/DeepSeek. Grok reasoning models take
4897
- // top-level `reasoning_effort` (low/medium/high), which the shared thinking
5084
+ // top-level `reasoning_effort` (low/medium/high/xhigh), which the shared thinking
4898
5085
  // path already sends.
4899
5086
  //
4900
5087
  // Subscription OAuth (SuperGrok / X Premium) routes to the Grok CLI chat proxy
@@ -4966,7 +5153,9 @@ function requireLocalBaseUrl(baseUrl) {
4966
5153
  }
4967
5154
  return baseUrl;
4968
5155
  }
4969
- function stream(options) {
5156
+ function stream(requested) {
5157
+ const fastMode = resolveFastModeModel(requested.provider, requested.model);
5158
+ const options = fastMode.fast ? { ...requested, model: fastMode.model, speed: "fast" } : requested;
4970
5159
  const entry = providerRegistry.get(options.provider);
4971
5160
  if (!entry) {
4972
5161
  throw new GGAIError(
@@ -5181,6 +5370,14 @@ function formatChatError(error) {
5181
5370
  "Update the app, or choose another model."
5182
5371
  );
5183
5372
  }
5373
+ const fastRejection = base.provider === "anthropic" ? parseFastModeRejection(raw) : void 0;
5374
+ if (fastRejection) {
5375
+ return present(
5376
+ fastRejection.kind === "billing" ? "billing" : "model_access",
5377
+ fastRejection.headline,
5378
+ fastRejection.guidance
5379
+ );
5380
+ }
5184
5381
  if (/insufficient.*(?:balance|credits?)|(?:balance|credits?).*(?:insufficient|exhausted|depleted)|credit balance is too low|payment_required/.test(
5185
5382
  text
5186
5383
  )) {
@@ -5598,6 +5795,7 @@ function palsuRerankScore(query, document) {
5598
5795
  // Annotate the CommonJS export names for ESM import in node:
5599
5796
  0 && (module.exports = {
5600
5797
  EventStream,
5798
+ FAST_MODE_SUFFIX,
5601
5799
  GGAIError,
5602
5800
  ProviderError,
5603
5801
  REDACTION_MARKER,
@@ -5606,6 +5804,7 @@ function palsuRerankScore(query, document) {
5606
5804
  clampProviderContextImages,
5607
5805
  classifyProviderError,
5608
5806
  continuesTurn,
5807
+ describeFastModeRejection,
5609
5808
  dropInvalidToolCalls,
5610
5809
  embed,
5611
5810
  environmentSecrets,
@@ -5624,12 +5823,14 @@ function palsuRerankScore(query, document) {
5624
5823
  palsuText,
5625
5824
  palsuThinking,
5626
5825
  palsuToolCall,
5826
+ parseFastModeRejection,
5627
5827
  prewarmAnthropicCache,
5628
5828
  providerRegistry,
5629
5829
  redactText,
5630
5830
  redactValue,
5631
5831
  registerPalsuProvider,
5632
5832
  rerank,
5833
+ resolveFastModeModel,
5633
5834
  resolveToolSchema,
5634
5835
  sanitizeMessagesForWire,
5635
5836
  setProviderDiagnostic,