@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 +218 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -2
- package/dist/index.d.ts +42 -2
- package/dist/index.js +214 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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") ||
|
|
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
|
-
|
|
2550
|
-
|
|
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.
|
|
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
|
|
4000
|
-
|
|
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(
|
|
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,
|