@kenkaiiii/gg-ai 4.3.165 → 4.3.167
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 +244 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +63 -2
- package/dist/index.d.ts +63 -2
- package/dist/index.js +242 -39
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -34,6 +34,8 @@ __export(index_exports, {
|
|
|
34
34
|
GGAIError: () => GGAIError,
|
|
35
35
|
ProviderError: () => ProviderError,
|
|
36
36
|
StreamResult: () => StreamResult,
|
|
37
|
+
formatError: () => formatError,
|
|
38
|
+
formatErrorForDisplay: () => formatErrorForDisplay,
|
|
37
39
|
palsuAssistantMessage: () => palsuAssistantMessage,
|
|
38
40
|
palsuText: () => palsuText,
|
|
39
41
|
palsuThinking: () => palsuThinking,
|
|
@@ -46,21 +48,165 @@ module.exports = __toCommonJS(index_exports);
|
|
|
46
48
|
|
|
47
49
|
// src/errors.ts
|
|
48
50
|
var GGAIError = class extends Error {
|
|
51
|
+
source;
|
|
52
|
+
requestId;
|
|
53
|
+
hint;
|
|
49
54
|
constructor(message, options) {
|
|
50
|
-
super(message, options);
|
|
55
|
+
super(message, { cause: options?.cause });
|
|
51
56
|
this.name = "GGAIError";
|
|
57
|
+
this.source = options?.source ?? "ggcoder";
|
|
58
|
+
this.requestId = options?.requestId;
|
|
59
|
+
this.hint = options?.hint;
|
|
52
60
|
}
|
|
53
61
|
};
|
|
54
62
|
var ProviderError = class extends GGAIError {
|
|
55
63
|
provider;
|
|
56
64
|
statusCode;
|
|
57
65
|
constructor(provider, message, options) {
|
|
58
|
-
super(
|
|
66
|
+
super(message, {
|
|
67
|
+
source: "provider",
|
|
68
|
+
requestId: options?.requestId,
|
|
69
|
+
hint: options?.hint,
|
|
70
|
+
cause: options?.cause
|
|
71
|
+
});
|
|
59
72
|
this.name = "ProviderError";
|
|
60
73
|
this.provider = provider;
|
|
61
74
|
this.statusCode = options?.statusCode;
|
|
62
75
|
}
|
|
63
76
|
};
|
|
77
|
+
var PROVIDER_DISPLAY = {
|
|
78
|
+
openai: "OpenAI",
|
|
79
|
+
anthropic: "Anthropic",
|
|
80
|
+
glm: "Z.AI (GLM)",
|
|
81
|
+
moonshot: "Moonshot",
|
|
82
|
+
deepseek: "DeepSeek",
|
|
83
|
+
openrouter: "OpenRouter",
|
|
84
|
+
xiaomi: "Xiaomi (MiMo)",
|
|
85
|
+
minimax: "MiniMax"
|
|
86
|
+
};
|
|
87
|
+
var PROVIDER_STATUS_URL = {
|
|
88
|
+
openai: "status.openai.com",
|
|
89
|
+
anthropic: "status.anthropic.com"
|
|
90
|
+
};
|
|
91
|
+
function providerDisplayName(provider) {
|
|
92
|
+
return PROVIDER_DISPLAY[provider] ?? provider;
|
|
93
|
+
}
|
|
94
|
+
function formatError(err) {
|
|
95
|
+
if (err instanceof ProviderError) {
|
|
96
|
+
const name = providerDisplayName(err.provider);
|
|
97
|
+
const cleanMessage = cleanProviderMessage(err.message);
|
|
98
|
+
return {
|
|
99
|
+
headline: `${name} returned an error.`,
|
|
100
|
+
source: "provider",
|
|
101
|
+
message: cleanMessage,
|
|
102
|
+
provider: err.provider,
|
|
103
|
+
statusCode: err.statusCode,
|
|
104
|
+
requestId: err.requestId,
|
|
105
|
+
guidance: err.hint ?? providerGuidance(err.provider, cleanMessage, err.statusCode)
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (err instanceof GGAIError) {
|
|
109
|
+
return finaliseBySource(err.source, err.message, err.requestId, err.hint);
|
|
110
|
+
}
|
|
111
|
+
if (err instanceof Error) {
|
|
112
|
+
const source = inferSource(err);
|
|
113
|
+
return finaliseBySource(source, err.message, void 0, void 0);
|
|
114
|
+
}
|
|
115
|
+
return finaliseBySource("ggcoder", String(err), void 0, void 0);
|
|
116
|
+
}
|
|
117
|
+
function finaliseBySource(source, message, requestId, hint) {
|
|
118
|
+
switch (source) {
|
|
119
|
+
case "network":
|
|
120
|
+
return {
|
|
121
|
+
headline: "Network error \u2014 couldn't reach the provider.",
|
|
122
|
+
source,
|
|
123
|
+
message,
|
|
124
|
+
guidance: hint ?? "Check your internet connection. Not a ggcoder issue \u2014 retry shortly.",
|
|
125
|
+
...requestId ? { requestId } : {}
|
|
126
|
+
};
|
|
127
|
+
case "auth":
|
|
128
|
+
return {
|
|
129
|
+
headline: "Authentication issue.",
|
|
130
|
+
source,
|
|
131
|
+
message,
|
|
132
|
+
guidance: hint ?? "Run `ggcoder login` to refresh your credentials.",
|
|
133
|
+
...requestId ? { requestId } : {}
|
|
134
|
+
};
|
|
135
|
+
case "provider":
|
|
136
|
+
return {
|
|
137
|
+
headline: "Provider returned an error.",
|
|
138
|
+
source,
|
|
139
|
+
message,
|
|
140
|
+
guidance: hint ?? providerGuidance(void 0, message, void 0),
|
|
141
|
+
...requestId ? { requestId } : {}
|
|
142
|
+
};
|
|
143
|
+
case "ggcoder":
|
|
144
|
+
return {
|
|
145
|
+
headline: "ggcoder hit an unexpected error.",
|
|
146
|
+
source,
|
|
147
|
+
message,
|
|
148
|
+
guidance: hint ?? "This looks like a ggcoder bug \u2014 please report it to the developer (see /help).",
|
|
149
|
+
...requestId ? { requestId } : {}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function formatErrorForDisplay(err) {
|
|
154
|
+
const f = formatError(err);
|
|
155
|
+
const lines = [f.headline];
|
|
156
|
+
if (f.message && f.message !== f.headline) lines.push(` ${f.message}`);
|
|
157
|
+
lines.push(` \u2192 ${f.guidance}`);
|
|
158
|
+
return lines.join("\n");
|
|
159
|
+
}
|
|
160
|
+
function cleanProviderMessage(message) {
|
|
161
|
+
return message.replace(/^\[[^\]]+\]\s*/, "").trim();
|
|
162
|
+
}
|
|
163
|
+
function inferSource(err) {
|
|
164
|
+
const msg = err.message.toLowerCase();
|
|
165
|
+
const code = err.code ?? "";
|
|
166
|
+
if (code === "ECONNREFUSED" || code === "ETIMEDOUT" || code === "ENOTFOUND" || code === "ECONNRESET" || msg.includes("fetch failed") || msg.includes("network request failed")) {
|
|
167
|
+
return "network";
|
|
168
|
+
}
|
|
169
|
+
if (msg.includes("not logged in") || msg.includes("token exchange failed") || msg.includes("token refresh failed") || msg.includes("invalid_grant")) {
|
|
170
|
+
return "auth";
|
|
171
|
+
}
|
|
172
|
+
return "ggcoder";
|
|
173
|
+
}
|
|
174
|
+
function providerGuidance(provider, message, statusCode) {
|
|
175
|
+
const name = provider ? providerDisplayName(provider) : "the provider";
|
|
176
|
+
const status = provider ? PROVIDER_STATUS_URL[provider] : void 0;
|
|
177
|
+
const lower = message.toLowerCase();
|
|
178
|
+
if (statusCode === 401 || lower.includes("unauthorized") || lower.includes("invalid api key")) {
|
|
179
|
+
return `Authentication failed with ${name}. Run \`ggcoder login\` to refresh your credentials.`;
|
|
180
|
+
}
|
|
181
|
+
if (lower.includes("overloaded") || lower.includes("engine_overloaded")) {
|
|
182
|
+
return `${name}'s servers are overloaded right now. Retry in a moment \u2014 not a ggcoder issue.`;
|
|
183
|
+
}
|
|
184
|
+
if (lower.includes("insufficient balance") || lower.includes("quota exceeded") || lower.includes("recharge") || lower.includes("no resource package")) {
|
|
185
|
+
return `Your ${name} account has a billing or quota issue \u2014 check your balance. Not a ggcoder issue.`;
|
|
186
|
+
}
|
|
187
|
+
if (statusCode === 429 || lower.includes("rate limit") || lower.includes("too many requests")) {
|
|
188
|
+
return `${name} rate limit hit. Wait a moment then retry \u2014 not a ggcoder issue.`;
|
|
189
|
+
}
|
|
190
|
+
if (statusCode === 502 || lower.includes("bad gateway")) {
|
|
191
|
+
return `${name} returned a bad gateway. Retry \u2014 this is on their side, not ggcoder.`;
|
|
192
|
+
}
|
|
193
|
+
if (statusCode === 503 || lower.includes("service unavailable")) {
|
|
194
|
+
return `${name} is temporarily unavailable. Retry shortly \u2014 not a ggcoder issue.`;
|
|
195
|
+
}
|
|
196
|
+
if (statusCode === 500 || lower.includes("server_error") || lower.includes("500") && lower.includes("internal server error")) {
|
|
197
|
+
return status ? `This is an error from ${name}, not ggcoder. Retry \u2014 if it keeps happening, check ${status}.` : `This is an error from ${name}, not ggcoder. Retry \u2014 if it keeps happening, try a different model with /model.`;
|
|
198
|
+
}
|
|
199
|
+
if (lower.includes("timeout") || lower.includes("timed out")) {
|
|
200
|
+
return `Request to ${name} timed out. Their servers may be slow \u2014 retry. Not a ggcoder issue.`;
|
|
201
|
+
}
|
|
202
|
+
if (lower.includes("does not recognize the requested model") || lower.includes("model") && (lower.includes("not exist") || lower.includes("not found") || lower.includes("no access"))) {
|
|
203
|
+
return `${name} doesn't recognise this model on your account. Use /model to switch, or check your subscription tier.`;
|
|
204
|
+
}
|
|
205
|
+
if (lower.includes("context_length_exceeded") || lower.includes("prompt is too long")) {
|
|
206
|
+
return `Context window for this ${name} model is full. Run /compact to shrink history, or start a new session.`;
|
|
207
|
+
}
|
|
208
|
+
return status ? `This is an error from ${name}, not ggcoder. Retry \u2014 if it persists, check ${status}.` : `This is an error from ${name}, not ggcoder. Retry \u2014 if it persists, try a different model with /model.`;
|
|
209
|
+
}
|
|
64
210
|
|
|
65
211
|
// src/providers/anthropic.ts
|
|
66
212
|
var import_sdk = __toESM(require("@anthropic-ai/sdk"), 1);
|
|
@@ -292,9 +438,18 @@ function toAnthropicToolResultContent(content) {
|
|
|
292
438
|
};
|
|
293
439
|
});
|
|
294
440
|
}
|
|
441
|
+
function remapAnthropicToolCallId(id, idMap) {
|
|
442
|
+
if (/^[a-zA-Z0-9_-]+$/.test(id)) return id;
|
|
443
|
+
const existing = idMap.get(id);
|
|
444
|
+
if (existing) return existing;
|
|
445
|
+
const mapped = id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
446
|
+
idMap.set(id, mapped);
|
|
447
|
+
return mapped;
|
|
448
|
+
}
|
|
295
449
|
function toAnthropicMessages(messages, cacheControl) {
|
|
296
450
|
let systemText;
|
|
297
451
|
const out = [];
|
|
452
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
298
453
|
for (const msg of messages) {
|
|
299
454
|
if (msg.role === "system") {
|
|
300
455
|
systemText = msg.content;
|
|
@@ -329,7 +484,7 @@ function toAnthropicMessages(messages, cacheControl) {
|
|
|
329
484
|
if (part.type === "tool_call")
|
|
330
485
|
return {
|
|
331
486
|
type: "tool_use",
|
|
332
|
-
id: part.id,
|
|
487
|
+
id: remapAnthropicToolCallId(part.id, idMap),
|
|
333
488
|
name: part.name,
|
|
334
489
|
input: part.args
|
|
335
490
|
};
|
|
@@ -354,7 +509,7 @@ function toAnthropicMessages(messages, cacheControl) {
|
|
|
354
509
|
role: "user",
|
|
355
510
|
content: msg.content.map((result) => ({
|
|
356
511
|
type: "tool_result",
|
|
357
|
-
tool_use_id: result.toolCallId,
|
|
512
|
+
tool_use_id: remapAnthropicToolCallId(result.toolCallId, idMap),
|
|
358
513
|
content: toAnthropicToolResultContent(result.content),
|
|
359
514
|
is_error: result.isError
|
|
360
515
|
}))
|
|
@@ -410,12 +565,19 @@ function toAnthropicMessages(messages, cacheControl) {
|
|
|
410
565
|
}
|
|
411
566
|
return { system, messages: out };
|
|
412
567
|
}
|
|
413
|
-
function toAnthropicTools(tools) {
|
|
414
|
-
return tools.map((tool) =>
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
568
|
+
function toAnthropicTools(tools, options) {
|
|
569
|
+
return tools.map((tool, index) => {
|
|
570
|
+
const anthropicTool = {
|
|
571
|
+
name: tool.name,
|
|
572
|
+
description: tool.description,
|
|
573
|
+
input_schema: tool.rawInputSchema ?? zodToJsonSchema(tool.parameters),
|
|
574
|
+
...options?.enableFineGrainedToolStreaming ? { eager_input_streaming: true } : {}
|
|
575
|
+
};
|
|
576
|
+
if (options?.cacheControl && index === tools.length - 1) {
|
|
577
|
+
anthropicTool.cache_control = options.cacheControl;
|
|
578
|
+
}
|
|
579
|
+
return anthropicTool;
|
|
580
|
+
});
|
|
419
581
|
}
|
|
420
582
|
function toAnthropicToolChoice(choice) {
|
|
421
583
|
if (choice === "auto") return { type: "auto" };
|
|
@@ -634,6 +796,7 @@ async function* runStream(options) {
|
|
|
634
796
|
const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
|
|
635
797
|
const useStreaming = options.streaming !== false;
|
|
636
798
|
const cacheControl = toAnthropicCacheControl(options.cacheRetention, options.baseUrl);
|
|
799
|
+
const supportsFirstPartyToolExtras = !options.baseUrl || options.baseUrl.includes("api.anthropic.com");
|
|
637
800
|
const downgradedMessages = downgradeUnsupportedImages(options.messages, options.supportsImages);
|
|
638
801
|
const { system: rawSystem, messages } = toAnthropicMessages(downgradedMessages, cacheControl);
|
|
639
802
|
const system = isOAuth ? [
|
|
@@ -666,7 +829,10 @@ async function* runStream(options) {
|
|
|
666
829
|
...options.stop ? { stop_sequences: options.stop } : {},
|
|
667
830
|
...options.tools?.length || options.serverTools?.length || options.webSearch ? {
|
|
668
831
|
tools: [
|
|
669
|
-
...options.tools?.length ? toAnthropicTools(options.tools
|
|
832
|
+
...options.tools?.length ? toAnthropicTools(options.tools, {
|
|
833
|
+
...supportsFirstPartyToolExtras && cacheControl ? { cacheControl } : {},
|
|
834
|
+
...supportsFirstPartyToolExtras ? { enableFineGrainedToolStreaming: true } : {}
|
|
835
|
+
}) : [],
|
|
670
836
|
...options.serverTools ?? [],
|
|
671
837
|
...options.webSearch ? [{ type: "web_search_20250305", name: "web_search" }] : []
|
|
672
838
|
]
|
|
@@ -999,8 +1165,10 @@ function messageToResponse(message) {
|
|
|
999
1165
|
}
|
|
1000
1166
|
function toError(err) {
|
|
1001
1167
|
if (err instanceof import_sdk.default.APIError) {
|
|
1168
|
+
const requestId = err.request_id ?? err.error?.request_id;
|
|
1002
1169
|
return new ProviderError("anthropic", err.message, {
|
|
1003
1170
|
statusCode: err.status,
|
|
1171
|
+
...requestId ? { requestId } : {},
|
|
1004
1172
|
cause: err
|
|
1005
1173
|
});
|
|
1006
1174
|
}
|
|
@@ -1050,12 +1218,15 @@ async function* runStream2(options) {
|
|
|
1050
1218
|
};
|
|
1051
1219
|
if (options.provider === "openai" || options.provider === "moonshot") {
|
|
1052
1220
|
const paramsAny = params;
|
|
1053
|
-
paramsAny.prompt_cache_key = "ggcoder";
|
|
1221
|
+
paramsAny.prompt_cache_key = options.promptCacheKey ?? "ggcoder";
|
|
1054
1222
|
const retention = options.cacheRetention ?? "short";
|
|
1055
1223
|
if (retention === "long") {
|
|
1056
1224
|
paramsAny.prompt_cache_retention = "24h";
|
|
1057
1225
|
}
|
|
1058
1226
|
}
|
|
1227
|
+
if (options.provider === "openai" && options.serviceTier) {
|
|
1228
|
+
params.service_tier = options.serviceTier;
|
|
1229
|
+
}
|
|
1059
1230
|
if (usesThinkingParam) {
|
|
1060
1231
|
if (options.thinking) {
|
|
1061
1232
|
params.thinking = { type: "enabled" };
|
|
@@ -1292,19 +1463,19 @@ function completionToResponse(completion) {
|
|
|
1292
1463
|
}
|
|
1293
1464
|
function toError2(err, provider = "openai") {
|
|
1294
1465
|
if (err instanceof import_openai.default.APIError) {
|
|
1295
|
-
let msg = err.message;
|
|
1296
1466
|
const body = err.error;
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
return new ProviderError(provider, msg, {
|
|
1467
|
+
const bodyMessage = typeof body?.message === "string" && body.message.trim() ? body.message.trim() : void 0;
|
|
1468
|
+
const modelName = typeof body?.model === "string" ? body.model : "";
|
|
1469
|
+
const cleanMessage = bodyMessage ?? err.message;
|
|
1470
|
+
let hint;
|
|
1471
|
+
if (modelName === "codex-mini-latest" || cleanMessage.includes("codex-mini-latest")) {
|
|
1472
|
+
hint = "codex-mini-latest requires an OpenAI Pro or Max subscription. Your account currently has access to GPT-5.4 and GPT-5.4 Mini.";
|
|
1473
|
+
}
|
|
1474
|
+
const requestId = err.request_id ?? (typeof body?.request_id === "string" ? body.request_id : void 0);
|
|
1475
|
+
return new ProviderError(provider, cleanMessage, {
|
|
1307
1476
|
statusCode: err.status,
|
|
1477
|
+
...requestId ? { requestId } : {},
|
|
1478
|
+
...hint ? { hint } : {},
|
|
1308
1479
|
cause: err
|
|
1309
1480
|
});
|
|
1310
1481
|
}
|
|
@@ -1338,6 +1509,9 @@ async function* runStream3(options) {
|
|
|
1338
1509
|
if (options.tools?.length) {
|
|
1339
1510
|
body.tools = toCodexTools(options.tools);
|
|
1340
1511
|
}
|
|
1512
|
+
if (options.promptCacheKey) {
|
|
1513
|
+
body.prompt_cache_key = options.promptCacheKey;
|
|
1514
|
+
}
|
|
1341
1515
|
if (options.temperature != null && !options.thinking) {
|
|
1342
1516
|
body.temperature = options.temperature;
|
|
1343
1517
|
}
|
|
@@ -1366,19 +1540,19 @@ async function* runStream3(options) {
|
|
|
1366
1540
|
});
|
|
1367
1541
|
if (!response.ok) {
|
|
1368
1542
|
const text = await response.text().catch(() => "");
|
|
1369
|
-
|
|
1543
|
+
const parsed = parseCodexErrorBody(text);
|
|
1544
|
+
const message = parsed.message ?? `Codex API returned HTTP ${response.status}.`;
|
|
1545
|
+
const requestId = parsed.requestId ?? response.headers.get("x-request-id") ?? response.headers.get("openai-request-id") ?? void 0;
|
|
1546
|
+
let hint;
|
|
1370
1547
|
if (response.status === 400 && text.includes("not supported")) {
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
}
|
|
1375
|
-
if (response.status === 404 && text.includes("does not exist")) {
|
|
1376
|
-
message += `
|
|
1377
|
-
|
|
1378
|
-
Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GPT-5.4 and GPT-5.4 Mini work with any active ChatGPT plan.`;
|
|
1548
|
+
hint = 'Codex models require a ChatGPT Plus ($20/mo) or Pro ($200/mo) subscription. The "codex-spark" variants require ChatGPT Pro. Check your subscription at https://chatgpt.com/settings.';
|
|
1549
|
+
} else if (response.status === 404 && text.includes("does not exist")) {
|
|
1550
|
+
hint = "codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GPT-5.4 and GPT-5.4 Mini work with any active ChatGPT plan.";
|
|
1379
1551
|
}
|
|
1380
1552
|
throw new ProviderError("openai", message, {
|
|
1381
|
-
statusCode: response.status
|
|
1553
|
+
statusCode: response.status,
|
|
1554
|
+
...requestId ? { requestId } : {},
|
|
1555
|
+
...hint ? { hint } : {}
|
|
1382
1556
|
});
|
|
1383
1557
|
}
|
|
1384
1558
|
if (!response.body) {
|
|
@@ -1389,16 +1563,27 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1389
1563
|
const toolCalls = /* @__PURE__ */ new Map();
|
|
1390
1564
|
let inputTokens = 0;
|
|
1391
1565
|
let outputTokens = 0;
|
|
1566
|
+
let cacheRead = 0;
|
|
1392
1567
|
for await (const event of parseSSE(response.body)) {
|
|
1393
1568
|
const type = event.type;
|
|
1394
1569
|
if (!type) continue;
|
|
1395
1570
|
if (type === "error") {
|
|
1396
|
-
const
|
|
1397
|
-
|
|
1571
|
+
const nested = event.error ?? void 0;
|
|
1572
|
+
const message = nested?.message ?? event.message ?? "Codex stream emitted an error chunk without a message.";
|
|
1573
|
+
const code = nested?.code ?? nested?.type ?? event.code ?? "server_error";
|
|
1574
|
+
const requestId = extractCodexRequestId(message) ?? event.request_id;
|
|
1575
|
+
throw new ProviderError("openai", message, {
|
|
1576
|
+
...requestId != null ? { requestId } : {},
|
|
1577
|
+
...code === "server_error" ? { statusCode: 500 } : {}
|
|
1578
|
+
});
|
|
1398
1579
|
}
|
|
1399
1580
|
if (type === "response.failed") {
|
|
1400
|
-
const
|
|
1401
|
-
|
|
1581
|
+
const nested = event.error;
|
|
1582
|
+
const message = nested?.message ?? "Codex response failed.";
|
|
1583
|
+
const requestId = extractCodexRequestId(message) ?? event.request_id;
|
|
1584
|
+
throw new ProviderError("openai", message, {
|
|
1585
|
+
...requestId != null ? { requestId } : {}
|
|
1586
|
+
});
|
|
1402
1587
|
}
|
|
1403
1588
|
if (type === "response.output_text.delta") {
|
|
1404
1589
|
const delta = event.delta;
|
|
@@ -1471,7 +1656,8 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1471
1656
|
const resp = event.response;
|
|
1472
1657
|
const usage = resp?.usage;
|
|
1473
1658
|
if (usage) {
|
|
1474
|
-
|
|
1659
|
+
cacheRead = usage.input_tokens_details?.cached_tokens ?? 0;
|
|
1660
|
+
inputTokens = (usage.input_tokens ?? 0) - cacheRead;
|
|
1475
1661
|
outputTokens = usage.output_tokens ?? 0;
|
|
1476
1662
|
}
|
|
1477
1663
|
}
|
|
@@ -1501,7 +1687,7 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1501
1687
|
content: contentParts.length > 0 ? contentParts : textAccum || ""
|
|
1502
1688
|
},
|
|
1503
1689
|
stopReason,
|
|
1504
|
-
usage: { inputTokens, outputTokens }
|
|
1690
|
+
usage: { inputTokens, outputTokens, ...cacheRead > 0 && { cacheRead } }
|
|
1505
1691
|
};
|
|
1506
1692
|
yield { type: "done", stopReason };
|
|
1507
1693
|
return streamResponse;
|
|
@@ -1643,6 +1829,23 @@ function toCodexTools(tools) {
|
|
|
1643
1829
|
strict: null
|
|
1644
1830
|
}));
|
|
1645
1831
|
}
|
|
1832
|
+
function extractCodexRequestId(message) {
|
|
1833
|
+
const match = message.match(/request ID ([a-z0-9-]{8,})/i);
|
|
1834
|
+
return match?.[1];
|
|
1835
|
+
}
|
|
1836
|
+
function parseCodexErrorBody(text) {
|
|
1837
|
+
if (!text) return {};
|
|
1838
|
+
try {
|
|
1839
|
+
const parsed = JSON.parse(text);
|
|
1840
|
+
const error = parsed.error;
|
|
1841
|
+
const message = error?.message ?? parsed.message;
|
|
1842
|
+
const requestId = parsed.request_id ?? error?.request_id ?? (message ? extractCodexRequestId(message) : void 0);
|
|
1843
|
+
return { ...message ? { message } : {}, ...requestId ? { requestId } : {} };
|
|
1844
|
+
} catch {
|
|
1845
|
+
const trimmed = text.trim().slice(0, 240);
|
|
1846
|
+
return trimmed ? { message: trimmed } : {};
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1646
1849
|
|
|
1647
1850
|
// src/provider-registry.ts
|
|
1648
1851
|
var ProviderRegistryImpl = class {
|
|
@@ -1903,6 +2106,8 @@ function registerPalsuProvider(config) {
|
|
|
1903
2106
|
GGAIError,
|
|
1904
2107
|
ProviderError,
|
|
1905
2108
|
StreamResult,
|
|
2109
|
+
formatError,
|
|
2110
|
+
formatErrorForDisplay,
|
|
1906
2111
|
palsuAssistantMessage,
|
|
1907
2112
|
palsuText,
|
|
1908
2113
|
palsuThinking,
|