@kenkaiiii/gg-ai 4.3.227 → 4.3.228
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 +110 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +109 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -335,6 +335,8 @@ interface FormattedError {
|
|
|
335
335
|
statusCode?: number;
|
|
336
336
|
/** Provider request ID, kept for telemetry / debug — not shown by default. */
|
|
337
337
|
requestId?: string;
|
|
338
|
+
/** Unix seconds when a usage/rate limit resets, when the provider reports it. */
|
|
339
|
+
resetsAt?: number;
|
|
338
340
|
}
|
|
339
341
|
declare class GGAIError extends Error {
|
|
340
342
|
readonly source: ErrorSource;
|
|
@@ -350,11 +352,14 @@ declare class GGAIError extends Error {
|
|
|
350
352
|
declare class ProviderError extends GGAIError {
|
|
351
353
|
readonly provider: string;
|
|
352
354
|
readonly statusCode?: number;
|
|
355
|
+
/** Unix seconds when a usage/rate limit resets, when the provider reports it. */
|
|
356
|
+
readonly resetsAt?: number;
|
|
353
357
|
constructor(provider: string, message: string, options?: {
|
|
354
358
|
statusCode?: number;
|
|
355
359
|
requestId?: string;
|
|
356
360
|
hint?: string;
|
|
357
361
|
cause?: unknown;
|
|
362
|
+
resetsAt?: number;
|
|
358
363
|
});
|
|
359
364
|
}
|
|
360
365
|
/**
|
|
@@ -362,6 +367,14 @@ declare class ProviderError extends GGAIError {
|
|
|
362
367
|
* a non-empty `headline` and `guidance` so the UI never has to second-guess
|
|
363
368
|
* what to show the user.
|
|
364
369
|
*/
|
|
370
|
+
/**
|
|
371
|
+
* Is this a subscription/plan usage-window exhaustion error (as opposed to a
|
|
372
|
+
* transient per-minute throttle)? These don't clear with a quick retry — the
|
|
373
|
+
* user has to wait for the window to reset — so callers must surface them as a
|
|
374
|
+
* hard stop, not silently retry for minutes. Detected from the canonical
|
|
375
|
+
* "usage limit reached" message gg-ai stamps onto the ProviderError.
|
|
376
|
+
*/
|
|
377
|
+
declare function isUsageLimitError(err: unknown): boolean;
|
|
365
378
|
declare function formatError(err: unknown): FormattedError;
|
|
366
379
|
/**
|
|
367
380
|
* Render a FormattedError as a multi-line string for terminal display.
|
|
@@ -452,4 +465,4 @@ interface PalsuProviderConfig {
|
|
|
452
465
|
*/
|
|
453
466
|
declare function registerPalsuProvider(config?: PalsuProviderConfig): PalsuProviderHandle;
|
|
454
467
|
|
|
455
|
-
export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, type ErrorEvent, type ErrorSource, EventStream, type FormattedError, GGAIError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderDiagnosticFn, type ProviderEntry, ProviderError, type ProviderStreamFn, type RawContent, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, formatError, formatErrorForDisplay, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, providerRegistry, registerPalsuProvider, setProviderDiagnostic, stream };
|
|
468
|
+
export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, type ErrorEvent, type ErrorSource, EventStream, type FormattedError, GGAIError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderDiagnosticFn, type ProviderEntry, ProviderError, type ProviderStreamFn, type RawContent, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, formatError, formatErrorForDisplay, isUsageLimitError, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, providerRegistry, registerPalsuProvider, setProviderDiagnostic, stream };
|
package/dist/index.d.ts
CHANGED
|
@@ -335,6 +335,8 @@ interface FormattedError {
|
|
|
335
335
|
statusCode?: number;
|
|
336
336
|
/** Provider request ID, kept for telemetry / debug — not shown by default. */
|
|
337
337
|
requestId?: string;
|
|
338
|
+
/** Unix seconds when a usage/rate limit resets, when the provider reports it. */
|
|
339
|
+
resetsAt?: number;
|
|
338
340
|
}
|
|
339
341
|
declare class GGAIError extends Error {
|
|
340
342
|
readonly source: ErrorSource;
|
|
@@ -350,11 +352,14 @@ declare class GGAIError extends Error {
|
|
|
350
352
|
declare class ProviderError extends GGAIError {
|
|
351
353
|
readonly provider: string;
|
|
352
354
|
readonly statusCode?: number;
|
|
355
|
+
/** Unix seconds when a usage/rate limit resets, when the provider reports it. */
|
|
356
|
+
readonly resetsAt?: number;
|
|
353
357
|
constructor(provider: string, message: string, options?: {
|
|
354
358
|
statusCode?: number;
|
|
355
359
|
requestId?: string;
|
|
356
360
|
hint?: string;
|
|
357
361
|
cause?: unknown;
|
|
362
|
+
resetsAt?: number;
|
|
358
363
|
});
|
|
359
364
|
}
|
|
360
365
|
/**
|
|
@@ -362,6 +367,14 @@ declare class ProviderError extends GGAIError {
|
|
|
362
367
|
* a non-empty `headline` and `guidance` so the UI never has to second-guess
|
|
363
368
|
* what to show the user.
|
|
364
369
|
*/
|
|
370
|
+
/**
|
|
371
|
+
* Is this a subscription/plan usage-window exhaustion error (as opposed to a
|
|
372
|
+
* transient per-minute throttle)? These don't clear with a quick retry — the
|
|
373
|
+
* user has to wait for the window to reset — so callers must surface them as a
|
|
374
|
+
* hard stop, not silently retry for minutes. Detected from the canonical
|
|
375
|
+
* "usage limit reached" message gg-ai stamps onto the ProviderError.
|
|
376
|
+
*/
|
|
377
|
+
declare function isUsageLimitError(err: unknown): boolean;
|
|
365
378
|
declare function formatError(err: unknown): FormattedError;
|
|
366
379
|
/**
|
|
367
380
|
* Render a FormattedError as a multi-line string for terminal display.
|
|
@@ -452,4 +465,4 @@ interface PalsuProviderConfig {
|
|
|
452
465
|
*/
|
|
453
466
|
declare function registerPalsuProvider(config?: PalsuProviderConfig): PalsuProviderHandle;
|
|
454
467
|
|
|
455
|
-
export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, type ErrorEvent, type ErrorSource, EventStream, type FormattedError, GGAIError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderDiagnosticFn, type ProviderEntry, ProviderError, type ProviderStreamFn, type RawContent, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, formatError, formatErrorForDisplay, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, providerRegistry, registerPalsuProvider, setProviderDiagnostic, stream };
|
|
468
|
+
export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, type ErrorEvent, type ErrorSource, EventStream, type FormattedError, GGAIError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderDiagnosticFn, type ProviderEntry, ProviderError, type ProviderStreamFn, type RawContent, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, formatError, formatErrorForDisplay, isUsageLimitError, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, providerRegistry, registerPalsuProvider, setProviderDiagnostic, stream };
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,8 @@ var GGAIError = class extends Error {
|
|
|
14
14
|
var ProviderError = class extends GGAIError {
|
|
15
15
|
provider;
|
|
16
16
|
statusCode;
|
|
17
|
+
/** Unix seconds when a usage/rate limit resets, when the provider reports it. */
|
|
18
|
+
resetsAt;
|
|
17
19
|
constructor(provider, message, options) {
|
|
18
20
|
super(message, {
|
|
19
21
|
source: "provider",
|
|
@@ -24,6 +26,7 @@ var ProviderError = class extends GGAIError {
|
|
|
24
26
|
this.name = "ProviderError";
|
|
25
27
|
this.provider = provider;
|
|
26
28
|
this.statusCode = options?.statusCode;
|
|
29
|
+
this.resetsAt = options?.resetsAt;
|
|
27
30
|
}
|
|
28
31
|
};
|
|
29
32
|
var PROVIDER_DISPLAY = {
|
|
@@ -44,10 +47,36 @@ var PROVIDER_STATUS_URL = {
|
|
|
44
47
|
function providerDisplayName(provider) {
|
|
45
48
|
return PROVIDER_DISPLAY[provider] ?? provider;
|
|
46
49
|
}
|
|
50
|
+
function isUsageLimitError(err) {
|
|
51
|
+
if (!(err instanceof Error)) return false;
|
|
52
|
+
return /usage limit reached/i.test(err.message);
|
|
53
|
+
}
|
|
54
|
+
function formatResetTime(resetsAt) {
|
|
55
|
+
const when = new Date(resetsAt * 1e3);
|
|
56
|
+
const sameDay = when.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
|
|
57
|
+
return sameDay ? when.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" }) : when.toLocaleString(void 0, {
|
|
58
|
+
weekday: "short",
|
|
59
|
+
hour: "numeric",
|
|
60
|
+
minute: "2-digit"
|
|
61
|
+
});
|
|
62
|
+
}
|
|
47
63
|
function formatError(err) {
|
|
48
64
|
if (err instanceof ProviderError) {
|
|
49
65
|
const name = providerDisplayName(err.provider);
|
|
50
66
|
const cleanMessage = cleanProviderMessage(err.message);
|
|
67
|
+
if (isUsageLimitError(err)) {
|
|
68
|
+
const resetClause = err.resetsAt ? ` It resets at ${formatResetTime(err.resetsAt)}.` : "";
|
|
69
|
+
return {
|
|
70
|
+
headline: `${name} usage limit reached.`,
|
|
71
|
+
source: "provider",
|
|
72
|
+
message: `Your ${name} usage is finished.${resetClause}`,
|
|
73
|
+
provider: err.provider,
|
|
74
|
+
statusCode: err.statusCode,
|
|
75
|
+
...err.requestId ? { requestId: err.requestId } : {},
|
|
76
|
+
...err.resetsAt ? { resetsAt: err.resetsAt } : {},
|
|
77
|
+
guidance: "Try again once it's back. Your conversation is preserved."
|
|
78
|
+
};
|
|
79
|
+
}
|
|
51
80
|
return {
|
|
52
81
|
headline: `${name} returned an error.`,
|
|
53
82
|
source: "provider",
|
|
@@ -327,6 +356,14 @@ function normalizeRootForAnthropic(schema) {
|
|
|
327
356
|
}
|
|
328
357
|
|
|
329
358
|
// src/providers/transform.ts
|
|
359
|
+
function isPositionSensitiveThinking(part) {
|
|
360
|
+
if (part.type === "thinking") return !!part.signature;
|
|
361
|
+
if (part.type === "raw") {
|
|
362
|
+
const t = part.data.type;
|
|
363
|
+
return t === "thinking" || t === "redacted_thinking";
|
|
364
|
+
}
|
|
365
|
+
return false;
|
|
366
|
+
}
|
|
330
367
|
var NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
|
|
331
368
|
var NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
|
|
332
369
|
function stripImages(content, placeholder) {
|
|
@@ -426,14 +463,19 @@ function toAnthropicMessages(messages, cacheControl) {
|
|
|
426
463
|
continue;
|
|
427
464
|
}
|
|
428
465
|
if (msg.role === "assistant") {
|
|
429
|
-
const
|
|
430
|
-
|
|
431
|
-
|
|
466
|
+
const lastThinkingIdx = typeof msg.content === "string" ? -1 : msg.content.reduce(
|
|
467
|
+
(last, part, idx) => isPositionSensitiveThinking(part) ? idx : last,
|
|
468
|
+
-1
|
|
469
|
+
);
|
|
470
|
+
const content = typeof msg.content === "string" ? msg.content : msg.content.filter((part, idx) => {
|
|
471
|
+
if (part.type === "thinking" && !part.signature && !part.text) return false;
|
|
472
|
+
if (part.type === "text" && !part.text && idx > lastThinkingIdx) return false;
|
|
432
473
|
return true;
|
|
433
474
|
}).map((part) => {
|
|
434
475
|
if (part.type === "text") return { type: "text", text: part.text };
|
|
435
|
-
if (part.type === "thinking")
|
|
436
|
-
return { type: "thinking", thinking: part.text, signature: part.signature };
|
|
476
|
+
if (part.type === "thinking") {
|
|
477
|
+
return part.signature ? { type: "thinking", thinking: part.text, signature: part.signature } : { type: "text", text: part.text };
|
|
478
|
+
}
|
|
437
479
|
if (part.type === "tool_call")
|
|
438
480
|
return {
|
|
439
481
|
type: "tool_use",
|
|
@@ -1138,6 +1180,24 @@ function messageToResponse(message) {
|
|
|
1138
1180
|
}
|
|
1139
1181
|
};
|
|
1140
1182
|
}
|
|
1183
|
+
function readUnifiedRateLimit(headers) {
|
|
1184
|
+
const get = (name) => {
|
|
1185
|
+
if (headers && typeof headers.get === "function") {
|
|
1186
|
+
return headers.get(name);
|
|
1187
|
+
}
|
|
1188
|
+
if (headers && typeof headers === "object") {
|
|
1189
|
+
const rec = headers;
|
|
1190
|
+
const value = rec[name] ?? rec[name.toLowerCase()];
|
|
1191
|
+
return typeof value === "string" ? value : null;
|
|
1192
|
+
}
|
|
1193
|
+
return null;
|
|
1194
|
+
};
|
|
1195
|
+
const status = get("anthropic-ratelimit-unified-status");
|
|
1196
|
+
const resetRaw = get("anthropic-ratelimit-unified-reset") ?? get("anthropic-ratelimit-unified-5h-reset") ?? get("anthropic-ratelimit-unified-7d-reset");
|
|
1197
|
+
const resetNum = resetRaw != null ? Number(resetRaw) : Number.NaN;
|
|
1198
|
+
const resetsAt = Number.isFinite(resetNum) && resetNum > 0 ? resetNum : void 0;
|
|
1199
|
+
return { rejected: status === "rejected", ...resetsAt ? { resetsAt } : {} };
|
|
1200
|
+
}
|
|
1141
1201
|
function toError(err) {
|
|
1142
1202
|
if (err instanceof Anthropic.APIError) {
|
|
1143
1203
|
const errorBody = err.error;
|
|
@@ -1146,6 +1206,18 @@ function toError(err) {
|
|
|
1146
1206
|
const bodyMessage = typeof nestedError?.message === "string" ? nestedError.message : typeof errorBody?.message === "string" ? errorBody.message : void 0;
|
|
1147
1207
|
const bodyType = typeof nestedError?.type === "string" ? nestedError.type : typeof errorBody?.type === "string" ? errorBody.type : typeof err.type === "string" ? err.type : void 0;
|
|
1148
1208
|
const message = bodyType && bodyMessage ? `${bodyType}: ${bodyMessage}` : bodyMessage ?? err.message;
|
|
1209
|
+
if (err.status === 429) {
|
|
1210
|
+
const limit = readUnifiedRateLimit(err.headers);
|
|
1211
|
+
const farOff = limit.resetsAt != null && limit.resetsAt * 1e3 - Date.now() > 6e4;
|
|
1212
|
+
if (limit.rejected || farOff) {
|
|
1213
|
+
return new ProviderError("anthropic", "Claude usage limit reached", {
|
|
1214
|
+
statusCode: 429,
|
|
1215
|
+
...requestId ? { requestId } : {},
|
|
1216
|
+
...limit.resetsAt ? { resetsAt: limit.resetsAt } : {},
|
|
1217
|
+
cause: err
|
|
1218
|
+
});
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1149
1221
|
return new ProviderError("anthropic", message, {
|
|
1150
1222
|
statusCode: err.status,
|
|
1151
1223
|
...requestId ? { requestId } : {},
|
|
@@ -1583,6 +1655,8 @@ async function* runStream3(options) {
|
|
|
1583
1655
|
const parsed = parseCodexErrorBody(text);
|
|
1584
1656
|
const message = parsed.message ?? `Codex API returned HTTP ${response.status}.`;
|
|
1585
1657
|
const requestId = parsed.requestId ?? response.headers.get("x-request-id") ?? response.headers.get("openai-request-id") ?? response.headers.get("x-oai-request-id") ?? void 0;
|
|
1658
|
+
const usageLimit = codexUsageLimitError(parsed.errorObj, response.status, requestId);
|
|
1659
|
+
if (usageLimit) throw usageLimit;
|
|
1586
1660
|
let hint;
|
|
1587
1661
|
if (response.status === 400 && text.includes("not supported")) {
|
|
1588
1662
|
if (options.model === "gpt-5.5-pro") {
|
|
@@ -1625,6 +1699,12 @@ async function* runStream3(options) {
|
|
|
1625
1699
|
const message = nested?.message ?? event.message ?? "Codex stream emitted an error chunk without a message.";
|
|
1626
1700
|
const code = nested?.code ?? nested?.type ?? event.code ?? "server_error";
|
|
1627
1701
|
const requestId = extractCodexRequestId(message) ?? event.request_id;
|
|
1702
|
+
const usageLimit = codexUsageLimitError(
|
|
1703
|
+
nested ?? event,
|
|
1704
|
+
void 0,
|
|
1705
|
+
requestId
|
|
1706
|
+
);
|
|
1707
|
+
if (usageLimit) throw usageLimit;
|
|
1628
1708
|
throw new ProviderError("openai", message, {
|
|
1629
1709
|
...requestId != null ? { requestId } : {},
|
|
1630
1710
|
...code === "server_error" ? { statusCode: 500 } : {}
|
|
@@ -1947,12 +2027,34 @@ function parseCodexErrorBody(text) {
|
|
|
1947
2027
|
const detail = parsed.detail;
|
|
1948
2028
|
const message = error?.message ?? parsed.message ?? (typeof detail === "string" ? detail : void 0);
|
|
1949
2029
|
const requestId = parsed.request_id ?? error?.request_id ?? (message ? extractCodexRequestId(message) : void 0);
|
|
1950
|
-
|
|
2030
|
+
const errorObj = error ?? parsed;
|
|
2031
|
+
return {
|
|
2032
|
+
...message ? { message } : {},
|
|
2033
|
+
...requestId ? { requestId } : {},
|
|
2034
|
+
...errorObj ? { errorObj } : {}
|
|
2035
|
+
};
|
|
1951
2036
|
} catch {
|
|
1952
2037
|
const trimmed = text.trim().slice(0, 240);
|
|
1953
2038
|
return trimmed ? { message: trimmed } : {};
|
|
1954
2039
|
}
|
|
1955
2040
|
}
|
|
2041
|
+
var CODEX_USAGE_LIMIT_CODE = /usage_limit_reached|usage_not_included/i;
|
|
2042
|
+
var CODEX_RATE_LIMIT_CODE = /rate_limit_exceeded/i;
|
|
2043
|
+
function codexUsageLimitError(errorObj, statusCode, requestId) {
|
|
2044
|
+
const code = String(errorObj?.code ?? errorObj?.type ?? "");
|
|
2045
|
+
const rateLimits = errorObj?.rate_limits;
|
|
2046
|
+
const resetsAtRaw = (typeof errorObj?.resets_at === "number" ? errorObj.resets_at : void 0) ?? rateLimits?.primary?.resets_at ?? rateLimits?.secondary?.resets_at;
|
|
2047
|
+
const resetsInSeconds = typeof errorObj?.resets_in_seconds === "number" ? errorObj.resets_in_seconds : void 0;
|
|
2048
|
+
const resetsAt = typeof resetsAtRaw === "number" && resetsAtRaw > 0 ? resetsAtRaw : resetsInSeconds != null && resetsInSeconds > 0 ? Math.floor(Date.now() / 1e3) + resetsInSeconds : void 0;
|
|
2049
|
+
const isHardUsage = CODEX_USAGE_LIMIT_CODE.test(code);
|
|
2050
|
+
const isRateOr429 = CODEX_RATE_LIMIT_CODE.test(code) || statusCode === 429;
|
|
2051
|
+
if (!isHardUsage && !(isRateOr429 && resetsAt != null)) return null;
|
|
2052
|
+
return new ProviderError("openai", "ChatGPT usage limit reached", {
|
|
2053
|
+
statusCode: statusCode ?? 429,
|
|
2054
|
+
...requestId ? { requestId } : {},
|
|
2055
|
+
...resetsAt ? { resetsAt } : {}
|
|
2056
|
+
});
|
|
2057
|
+
}
|
|
1956
2058
|
|
|
1957
2059
|
// src/providers/gemini.ts
|
|
1958
2060
|
var DEFAULT_CODE_ASSIST_BASE_URL = "https://cloudcode-pa.googleapis.com";
|
|
@@ -2715,6 +2817,7 @@ export {
|
|
|
2715
2817
|
StreamResult,
|
|
2716
2818
|
formatError,
|
|
2717
2819
|
formatErrorForDisplay,
|
|
2820
|
+
isUsageLimitError,
|
|
2718
2821
|
palsuAssistantMessage,
|
|
2719
2822
|
palsuText,
|
|
2720
2823
|
palsuThinking,
|