@kenkaiiii/gg-ai 4.3.226 → 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.cjs
CHANGED
|
@@ -36,6 +36,7 @@ __export(index_exports, {
|
|
|
36
36
|
StreamResult: () => StreamResult,
|
|
37
37
|
formatError: () => formatError,
|
|
38
38
|
formatErrorForDisplay: () => formatErrorForDisplay,
|
|
39
|
+
isUsageLimitError: () => isUsageLimitError,
|
|
39
40
|
palsuAssistantMessage: () => palsuAssistantMessage,
|
|
40
41
|
palsuText: () => palsuText,
|
|
41
42
|
palsuThinking: () => palsuThinking,
|
|
@@ -63,6 +64,8 @@ var GGAIError = class extends Error {
|
|
|
63
64
|
var ProviderError = class extends GGAIError {
|
|
64
65
|
provider;
|
|
65
66
|
statusCode;
|
|
67
|
+
/** Unix seconds when a usage/rate limit resets, when the provider reports it. */
|
|
68
|
+
resetsAt;
|
|
66
69
|
constructor(provider, message, options) {
|
|
67
70
|
super(message, {
|
|
68
71
|
source: "provider",
|
|
@@ -73,6 +76,7 @@ var ProviderError = class extends GGAIError {
|
|
|
73
76
|
this.name = "ProviderError";
|
|
74
77
|
this.provider = provider;
|
|
75
78
|
this.statusCode = options?.statusCode;
|
|
79
|
+
this.resetsAt = options?.resetsAt;
|
|
76
80
|
}
|
|
77
81
|
};
|
|
78
82
|
var PROVIDER_DISPLAY = {
|
|
@@ -93,10 +97,36 @@ var PROVIDER_STATUS_URL = {
|
|
|
93
97
|
function providerDisplayName(provider) {
|
|
94
98
|
return PROVIDER_DISPLAY[provider] ?? provider;
|
|
95
99
|
}
|
|
100
|
+
function isUsageLimitError(err) {
|
|
101
|
+
if (!(err instanceof Error)) return false;
|
|
102
|
+
return /usage limit reached/i.test(err.message);
|
|
103
|
+
}
|
|
104
|
+
function formatResetTime(resetsAt) {
|
|
105
|
+
const when = new Date(resetsAt * 1e3);
|
|
106
|
+
const sameDay = when.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
|
|
107
|
+
return sameDay ? when.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" }) : when.toLocaleString(void 0, {
|
|
108
|
+
weekday: "short",
|
|
109
|
+
hour: "numeric",
|
|
110
|
+
minute: "2-digit"
|
|
111
|
+
});
|
|
112
|
+
}
|
|
96
113
|
function formatError(err) {
|
|
97
114
|
if (err instanceof ProviderError) {
|
|
98
115
|
const name = providerDisplayName(err.provider);
|
|
99
116
|
const cleanMessage = cleanProviderMessage(err.message);
|
|
117
|
+
if (isUsageLimitError(err)) {
|
|
118
|
+
const resetClause = err.resetsAt ? ` It resets at ${formatResetTime(err.resetsAt)}.` : "";
|
|
119
|
+
return {
|
|
120
|
+
headline: `${name} usage limit reached.`,
|
|
121
|
+
source: "provider",
|
|
122
|
+
message: `Your ${name} usage is finished.${resetClause}`,
|
|
123
|
+
provider: err.provider,
|
|
124
|
+
statusCode: err.statusCode,
|
|
125
|
+
...err.requestId ? { requestId: err.requestId } : {},
|
|
126
|
+
...err.resetsAt ? { resetsAt: err.resetsAt } : {},
|
|
127
|
+
guidance: "Try again once it's back. Your conversation is preserved."
|
|
128
|
+
};
|
|
129
|
+
}
|
|
100
130
|
return {
|
|
101
131
|
headline: `${name} returned an error.`,
|
|
102
132
|
source: "provider",
|
|
@@ -376,6 +406,14 @@ function normalizeRootForAnthropic(schema) {
|
|
|
376
406
|
}
|
|
377
407
|
|
|
378
408
|
// src/providers/transform.ts
|
|
409
|
+
function isPositionSensitiveThinking(part) {
|
|
410
|
+
if (part.type === "thinking") return !!part.signature;
|
|
411
|
+
if (part.type === "raw") {
|
|
412
|
+
const t = part.data.type;
|
|
413
|
+
return t === "thinking" || t === "redacted_thinking";
|
|
414
|
+
}
|
|
415
|
+
return false;
|
|
416
|
+
}
|
|
379
417
|
var NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
|
|
380
418
|
var NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
|
|
381
419
|
function stripImages(content, placeholder) {
|
|
@@ -475,14 +513,19 @@ function toAnthropicMessages(messages, cacheControl) {
|
|
|
475
513
|
continue;
|
|
476
514
|
}
|
|
477
515
|
if (msg.role === "assistant") {
|
|
478
|
-
const
|
|
479
|
-
|
|
480
|
-
|
|
516
|
+
const lastThinkingIdx = typeof msg.content === "string" ? -1 : msg.content.reduce(
|
|
517
|
+
(last, part, idx) => isPositionSensitiveThinking(part) ? idx : last,
|
|
518
|
+
-1
|
|
519
|
+
);
|
|
520
|
+
const content = typeof msg.content === "string" ? msg.content : msg.content.filter((part, idx) => {
|
|
521
|
+
if (part.type === "thinking" && !part.signature && !part.text) return false;
|
|
522
|
+
if (part.type === "text" && !part.text && idx > lastThinkingIdx) return false;
|
|
481
523
|
return true;
|
|
482
524
|
}).map((part) => {
|
|
483
525
|
if (part.type === "text") return { type: "text", text: part.text };
|
|
484
|
-
if (part.type === "thinking")
|
|
485
|
-
return { type: "thinking", thinking: part.text, signature: part.signature };
|
|
526
|
+
if (part.type === "thinking") {
|
|
527
|
+
return part.signature ? { type: "thinking", thinking: part.text, signature: part.signature } : { type: "text", text: part.text };
|
|
528
|
+
}
|
|
486
529
|
if (part.type === "tool_call")
|
|
487
530
|
return {
|
|
488
531
|
type: "tool_use",
|
|
@@ -1187,6 +1230,24 @@ function messageToResponse(message) {
|
|
|
1187
1230
|
}
|
|
1188
1231
|
};
|
|
1189
1232
|
}
|
|
1233
|
+
function readUnifiedRateLimit(headers) {
|
|
1234
|
+
const get = (name) => {
|
|
1235
|
+
if (headers && typeof headers.get === "function") {
|
|
1236
|
+
return headers.get(name);
|
|
1237
|
+
}
|
|
1238
|
+
if (headers && typeof headers === "object") {
|
|
1239
|
+
const rec = headers;
|
|
1240
|
+
const value = rec[name] ?? rec[name.toLowerCase()];
|
|
1241
|
+
return typeof value === "string" ? value : null;
|
|
1242
|
+
}
|
|
1243
|
+
return null;
|
|
1244
|
+
};
|
|
1245
|
+
const status = get("anthropic-ratelimit-unified-status");
|
|
1246
|
+
const resetRaw = get("anthropic-ratelimit-unified-reset") ?? get("anthropic-ratelimit-unified-5h-reset") ?? get("anthropic-ratelimit-unified-7d-reset");
|
|
1247
|
+
const resetNum = resetRaw != null ? Number(resetRaw) : Number.NaN;
|
|
1248
|
+
const resetsAt = Number.isFinite(resetNum) && resetNum > 0 ? resetNum : void 0;
|
|
1249
|
+
return { rejected: status === "rejected", ...resetsAt ? { resetsAt } : {} };
|
|
1250
|
+
}
|
|
1190
1251
|
function toError(err) {
|
|
1191
1252
|
if (err instanceof import_sdk.default.APIError) {
|
|
1192
1253
|
const errorBody = err.error;
|
|
@@ -1195,6 +1256,18 @@ function toError(err) {
|
|
|
1195
1256
|
const bodyMessage = typeof nestedError?.message === "string" ? nestedError.message : typeof errorBody?.message === "string" ? errorBody.message : void 0;
|
|
1196
1257
|
const bodyType = typeof nestedError?.type === "string" ? nestedError.type : typeof errorBody?.type === "string" ? errorBody.type : typeof err.type === "string" ? err.type : void 0;
|
|
1197
1258
|
const message = bodyType && bodyMessage ? `${bodyType}: ${bodyMessage}` : bodyMessage ?? err.message;
|
|
1259
|
+
if (err.status === 429) {
|
|
1260
|
+
const limit = readUnifiedRateLimit(err.headers);
|
|
1261
|
+
const farOff = limit.resetsAt != null && limit.resetsAt * 1e3 - Date.now() > 6e4;
|
|
1262
|
+
if (limit.rejected || farOff) {
|
|
1263
|
+
return new ProviderError("anthropic", "Claude usage limit reached", {
|
|
1264
|
+
statusCode: 429,
|
|
1265
|
+
...requestId ? { requestId } : {},
|
|
1266
|
+
...limit.resetsAt ? { resetsAt: limit.resetsAt } : {},
|
|
1267
|
+
cause: err
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1198
1271
|
return new ProviderError("anthropic", message, {
|
|
1199
1272
|
statusCode: err.status,
|
|
1200
1273
|
...requestId ? { requestId } : {},
|
|
@@ -1632,6 +1705,8 @@ async function* runStream3(options) {
|
|
|
1632
1705
|
const parsed = parseCodexErrorBody(text);
|
|
1633
1706
|
const message = parsed.message ?? `Codex API returned HTTP ${response.status}.`;
|
|
1634
1707
|
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;
|
|
1708
|
+
const usageLimit = codexUsageLimitError(parsed.errorObj, response.status, requestId);
|
|
1709
|
+
if (usageLimit) throw usageLimit;
|
|
1635
1710
|
let hint;
|
|
1636
1711
|
if (response.status === 400 && text.includes("not supported")) {
|
|
1637
1712
|
if (options.model === "gpt-5.5-pro") {
|
|
@@ -1674,6 +1749,12 @@ async function* runStream3(options) {
|
|
|
1674
1749
|
const message = nested?.message ?? event.message ?? "Codex stream emitted an error chunk without a message.";
|
|
1675
1750
|
const code = nested?.code ?? nested?.type ?? event.code ?? "server_error";
|
|
1676
1751
|
const requestId = extractCodexRequestId(message) ?? event.request_id;
|
|
1752
|
+
const usageLimit = codexUsageLimitError(
|
|
1753
|
+
nested ?? event,
|
|
1754
|
+
void 0,
|
|
1755
|
+
requestId
|
|
1756
|
+
);
|
|
1757
|
+
if (usageLimit) throw usageLimit;
|
|
1677
1758
|
throw new ProviderError("openai", message, {
|
|
1678
1759
|
...requestId != null ? { requestId } : {},
|
|
1679
1760
|
...code === "server_error" ? { statusCode: 500 } : {}
|
|
@@ -1996,12 +2077,34 @@ function parseCodexErrorBody(text) {
|
|
|
1996
2077
|
const detail = parsed.detail;
|
|
1997
2078
|
const message = error?.message ?? parsed.message ?? (typeof detail === "string" ? detail : void 0);
|
|
1998
2079
|
const requestId = parsed.request_id ?? error?.request_id ?? (message ? extractCodexRequestId(message) : void 0);
|
|
1999
|
-
|
|
2080
|
+
const errorObj = error ?? parsed;
|
|
2081
|
+
return {
|
|
2082
|
+
...message ? { message } : {},
|
|
2083
|
+
...requestId ? { requestId } : {},
|
|
2084
|
+
...errorObj ? { errorObj } : {}
|
|
2085
|
+
};
|
|
2000
2086
|
} catch {
|
|
2001
2087
|
const trimmed = text.trim().slice(0, 240);
|
|
2002
2088
|
return trimmed ? { message: trimmed } : {};
|
|
2003
2089
|
}
|
|
2004
2090
|
}
|
|
2091
|
+
var CODEX_USAGE_LIMIT_CODE = /usage_limit_reached|usage_not_included/i;
|
|
2092
|
+
var CODEX_RATE_LIMIT_CODE = /rate_limit_exceeded/i;
|
|
2093
|
+
function codexUsageLimitError(errorObj, statusCode, requestId) {
|
|
2094
|
+
const code = String(errorObj?.code ?? errorObj?.type ?? "");
|
|
2095
|
+
const rateLimits = errorObj?.rate_limits;
|
|
2096
|
+
const resetsAtRaw = (typeof errorObj?.resets_at === "number" ? errorObj.resets_at : void 0) ?? rateLimits?.primary?.resets_at ?? rateLimits?.secondary?.resets_at;
|
|
2097
|
+
const resetsInSeconds = typeof errorObj?.resets_in_seconds === "number" ? errorObj.resets_in_seconds : void 0;
|
|
2098
|
+
const resetsAt = typeof resetsAtRaw === "number" && resetsAtRaw > 0 ? resetsAtRaw : resetsInSeconds != null && resetsInSeconds > 0 ? Math.floor(Date.now() / 1e3) + resetsInSeconds : void 0;
|
|
2099
|
+
const isHardUsage = CODEX_USAGE_LIMIT_CODE.test(code);
|
|
2100
|
+
const isRateOr429 = CODEX_RATE_LIMIT_CODE.test(code) || statusCode === 429;
|
|
2101
|
+
if (!isHardUsage && !(isRateOr429 && resetsAt != null)) return null;
|
|
2102
|
+
return new ProviderError("openai", "ChatGPT usage limit reached", {
|
|
2103
|
+
statusCode: statusCode ?? 429,
|
|
2104
|
+
...requestId ? { requestId } : {},
|
|
2105
|
+
...resetsAt ? { resetsAt } : {}
|
|
2106
|
+
});
|
|
2107
|
+
}
|
|
2005
2108
|
|
|
2006
2109
|
// src/providers/gemini.ts
|
|
2007
2110
|
var DEFAULT_CODE_ASSIST_BASE_URL = "https://cloudcode-pa.googleapis.com";
|
|
@@ -2765,6 +2868,7 @@ function registerPalsuProvider(config) {
|
|
|
2765
2868
|
StreamResult,
|
|
2766
2869
|
formatError,
|
|
2767
2870
|
formatErrorForDisplay,
|
|
2871
|
+
isUsageLimitError,
|
|
2768
2872
|
palsuAssistantMessage,
|
|
2769
2873
|
palsuText,
|
|
2770
2874
|
palsuThinking,
|