@prestyj/ai 4.3.164 → 4.3.201
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 +445 -93
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +80 -3
- package/dist/index.d.ts +80 -3
- package/dist/index.js +442 -93
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -34,33 +34,180 @@ __export(index_exports, {
|
|
|
34
34
|
EventStream: () => EventStream,
|
|
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,
|
|
40
42
|
palsuToolCall: () => palsuToolCall,
|
|
41
43
|
providerRegistry: () => providerRegistry,
|
|
42
44
|
registerPalsuProvider: () => registerPalsuProvider,
|
|
45
|
+
setProviderDiagnostic: () => setProviderDiagnostic,
|
|
43
46
|
stream: () => stream
|
|
44
47
|
});
|
|
45
48
|
module.exports = __toCommonJS(index_exports);
|
|
46
49
|
|
|
47
50
|
// src/errors.ts
|
|
48
51
|
var EZCoderAIError = class extends Error {
|
|
52
|
+
source;
|
|
53
|
+
requestId;
|
|
54
|
+
hint;
|
|
49
55
|
constructor(message, options) {
|
|
50
|
-
super(message, options);
|
|
56
|
+
super(message, { cause: options?.cause });
|
|
51
57
|
this.name = "EZCoderAIError";
|
|
58
|
+
this.source = options?.source ?? "ezcoder";
|
|
59
|
+
this.requestId = options?.requestId;
|
|
60
|
+
this.hint = options?.hint;
|
|
52
61
|
}
|
|
53
62
|
};
|
|
54
63
|
var ProviderError = class extends EZCoderAIError {
|
|
55
64
|
provider;
|
|
56
65
|
statusCode;
|
|
57
66
|
constructor(provider, message, options) {
|
|
58
|
-
super(
|
|
67
|
+
super(message, {
|
|
68
|
+
source: "provider",
|
|
69
|
+
requestId: options?.requestId,
|
|
70
|
+
hint: options?.hint,
|
|
71
|
+
cause: options?.cause
|
|
72
|
+
});
|
|
59
73
|
this.name = "ProviderError";
|
|
60
74
|
this.provider = provider;
|
|
61
75
|
this.statusCode = options?.statusCode;
|
|
62
76
|
}
|
|
63
77
|
};
|
|
78
|
+
var PROVIDER_DISPLAY = {
|
|
79
|
+
openai: "OpenAI",
|
|
80
|
+
anthropic: "Anthropic",
|
|
81
|
+
glm: "Z.AI (GLM)",
|
|
82
|
+
moonshot: "Moonshot",
|
|
83
|
+
deepseek: "DeepSeek",
|
|
84
|
+
openrouter: "OpenRouter",
|
|
85
|
+
xiaomi: "Xiaomi (MiMo)",
|
|
86
|
+
minimax: "MiniMax"
|
|
87
|
+
};
|
|
88
|
+
var PROVIDER_STATUS_URL = {
|
|
89
|
+
openai: "status.openai.com",
|
|
90
|
+
anthropic: "status.anthropic.com"
|
|
91
|
+
};
|
|
92
|
+
function providerDisplayName(provider) {
|
|
93
|
+
return PROVIDER_DISPLAY[provider] ?? provider;
|
|
94
|
+
}
|
|
95
|
+
function formatError(err) {
|
|
96
|
+
if (err instanceof ProviderError) {
|
|
97
|
+
const name = providerDisplayName(err.provider);
|
|
98
|
+
const cleanMessage = cleanProviderMessage(err.message);
|
|
99
|
+
return {
|
|
100
|
+
headline: `${name} returned an error.`,
|
|
101
|
+
source: "provider",
|
|
102
|
+
message: cleanMessage,
|
|
103
|
+
provider: err.provider,
|
|
104
|
+
statusCode: err.statusCode,
|
|
105
|
+
requestId: err.requestId,
|
|
106
|
+
guidance: err.hint ?? providerGuidance(err.provider, cleanMessage, err.statusCode)
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (err instanceof EZCoderAIError) {
|
|
110
|
+
return finaliseBySource(err.source, err.message, err.requestId, err.hint);
|
|
111
|
+
}
|
|
112
|
+
if (err instanceof Error) {
|
|
113
|
+
const source = inferSource(err);
|
|
114
|
+
return finaliseBySource(source, err.message, void 0, void 0);
|
|
115
|
+
}
|
|
116
|
+
return finaliseBySource("ezcoder", String(err), void 0, void 0);
|
|
117
|
+
}
|
|
118
|
+
function finaliseBySource(source, message, requestId, hint) {
|
|
119
|
+
switch (source) {
|
|
120
|
+
case "network":
|
|
121
|
+
return {
|
|
122
|
+
headline: "Network error \u2014 couldn't reach the provider.",
|
|
123
|
+
source,
|
|
124
|
+
message,
|
|
125
|
+
guidance: hint ?? "Check your internet connection. Not a ezcoder issue \u2014 retry shortly.",
|
|
126
|
+
...requestId ? { requestId } : {}
|
|
127
|
+
};
|
|
128
|
+
case "auth":
|
|
129
|
+
return {
|
|
130
|
+
headline: "Authentication issue.",
|
|
131
|
+
source,
|
|
132
|
+
message,
|
|
133
|
+
guidance: hint ?? "Run `ezcoder login` to refresh your credentials.",
|
|
134
|
+
...requestId ? { requestId } : {}
|
|
135
|
+
};
|
|
136
|
+
case "provider":
|
|
137
|
+
return {
|
|
138
|
+
headline: "Provider returned an error.",
|
|
139
|
+
source,
|
|
140
|
+
message,
|
|
141
|
+
guidance: hint ?? providerGuidance(void 0, message, void 0),
|
|
142
|
+
...requestId ? { requestId } : {}
|
|
143
|
+
};
|
|
144
|
+
case "ezcoder":
|
|
145
|
+
return {
|
|
146
|
+
headline: "ezcoder hit an unexpected error.",
|
|
147
|
+
source,
|
|
148
|
+
message,
|
|
149
|
+
guidance: hint ?? "This looks like a ezcoder bug \u2014 please report it to the developer (see /help).",
|
|
150
|
+
...requestId ? { requestId } : {}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function formatErrorForDisplay(err) {
|
|
155
|
+
const f = formatError(err);
|
|
156
|
+
const lines = [f.headline];
|
|
157
|
+
if (f.message && f.message !== f.headline) lines.push(` ${f.message}`);
|
|
158
|
+
lines.push(` \u2192 ${f.guidance}`);
|
|
159
|
+
return lines.join("\n");
|
|
160
|
+
}
|
|
161
|
+
function cleanProviderMessage(message) {
|
|
162
|
+
return message.replace(/^\[[^\]]+\]\s*/, "").trim();
|
|
163
|
+
}
|
|
164
|
+
function inferSource(err) {
|
|
165
|
+
const msg = err.message.toLowerCase();
|
|
166
|
+
const code = err.code ?? "";
|
|
167
|
+
if (code === "ECONNREFUSED" || code === "ETIMEDOUT" || code === "ENOTFOUND" || code === "ECONNRESET" || msg.includes("fetch failed") || msg.includes("network request failed")) {
|
|
168
|
+
return "network";
|
|
169
|
+
}
|
|
170
|
+
if (msg.includes("not logged in") || msg.includes("token exchange failed") || msg.includes("token refresh failed") || msg.includes("invalid_grant")) {
|
|
171
|
+
return "auth";
|
|
172
|
+
}
|
|
173
|
+
return "ezcoder";
|
|
174
|
+
}
|
|
175
|
+
function providerGuidance(provider, message, statusCode) {
|
|
176
|
+
const name = provider ? providerDisplayName(provider) : "the provider";
|
|
177
|
+
const status = provider ? PROVIDER_STATUS_URL[provider] : void 0;
|
|
178
|
+
const lower = message.toLowerCase();
|
|
179
|
+
if (statusCode === 401 || lower.includes("unauthorized") || lower.includes("invalid api key")) {
|
|
180
|
+
return `Authentication failed with ${name}. Run \`ezcoder login\` to refresh your credentials.`;
|
|
181
|
+
}
|
|
182
|
+
if (lower.includes("overloaded") || lower.includes("engine_overloaded")) {
|
|
183
|
+
return `${name}'s servers are overloaded right now. Retry in a moment \u2014 not a ezcoder issue.`;
|
|
184
|
+
}
|
|
185
|
+
if (lower.includes("insufficient balance") || lower.includes("quota exceeded") || lower.includes("recharge") || lower.includes("no resource package")) {
|
|
186
|
+
return `Your ${name} account has a billing or quota issue \u2014 check your balance. Not a ezcoder issue.`;
|
|
187
|
+
}
|
|
188
|
+
if (statusCode === 429 || lower.includes("rate limit") || lower.includes("too many requests")) {
|
|
189
|
+
return `${name} rate limit hit. Wait a moment then retry \u2014 not a ezcoder issue.`;
|
|
190
|
+
}
|
|
191
|
+
if (statusCode === 502 || lower.includes("bad gateway")) {
|
|
192
|
+
return `${name} returned a bad gateway. Retry \u2014 this is on their side, not ezcoder.`;
|
|
193
|
+
}
|
|
194
|
+
if (statusCode === 503 || lower.includes("service unavailable")) {
|
|
195
|
+
return `${name} is temporarily unavailable. Retry shortly \u2014 not a ezcoder issue.`;
|
|
196
|
+
}
|
|
197
|
+
if (statusCode === 500 || lower.includes("server_error") || lower.includes("500") && lower.includes("internal server error")) {
|
|
198
|
+
return status ? `This is an error from ${name}, not ezcoder. Retry \u2014 if it keeps happening, check ${status}.` : `This is an error from ${name}, not ezcoder. Retry \u2014 if it keeps happening, try a different model with /model.`;
|
|
199
|
+
}
|
|
200
|
+
if (lower.includes("timeout") || lower.includes("timed out")) {
|
|
201
|
+
return `Request to ${name} timed out. Their servers may be slow \u2014 retry. Not a ezcoder issue.`;
|
|
202
|
+
}
|
|
203
|
+
if (lower.includes("does not recognize the requested model") || lower.includes("model") && (lower.includes("not exist") || lower.includes("not found") || lower.includes("no access"))) {
|
|
204
|
+
return `${name} doesn't recognise this model on your account. Use /model to switch, or check your subscription tier.`;
|
|
205
|
+
}
|
|
206
|
+
if (lower.includes("context_length_exceeded") || lower.includes("prompt is too long")) {
|
|
207
|
+
return `Context window for this ${name} model is full. Run /compact to shrink history, or start a new session.`;
|
|
208
|
+
}
|
|
209
|
+
return status ? `This is an error from ${name}, not ezcoder. Retry \u2014 if it persists, check ${status}.` : `This is an error from ${name}, not ezcoder. Retry \u2014 if it persists, try a different model with /model.`;
|
|
210
|
+
}
|
|
64
211
|
|
|
65
212
|
// src/providers/anthropic.ts
|
|
66
213
|
var import_sdk = __toESM(require("@anthropic-ai/sdk"), 1);
|
|
@@ -292,9 +439,18 @@ function toAnthropicToolResultContent(content) {
|
|
|
292
439
|
};
|
|
293
440
|
});
|
|
294
441
|
}
|
|
442
|
+
function remapAnthropicToolCallId(id, idMap) {
|
|
443
|
+
if (/^[a-zA-Z0-9_-]+$/.test(id)) return id;
|
|
444
|
+
const existing = idMap.get(id);
|
|
445
|
+
if (existing) return existing;
|
|
446
|
+
const mapped = id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
447
|
+
idMap.set(id, mapped);
|
|
448
|
+
return mapped;
|
|
449
|
+
}
|
|
295
450
|
function toAnthropicMessages(messages, cacheControl) {
|
|
296
451
|
let systemText;
|
|
297
452
|
const out = [];
|
|
453
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
298
454
|
for (const msg of messages) {
|
|
299
455
|
if (msg.role === "system") {
|
|
300
456
|
systemText = msg.content;
|
|
@@ -329,7 +485,7 @@ function toAnthropicMessages(messages, cacheControl) {
|
|
|
329
485
|
if (part.type === "tool_call")
|
|
330
486
|
return {
|
|
331
487
|
type: "tool_use",
|
|
332
|
-
id: part.id,
|
|
488
|
+
id: remapAnthropicToolCallId(part.id, idMap),
|
|
333
489
|
name: part.name,
|
|
334
490
|
input: part.args
|
|
335
491
|
};
|
|
@@ -354,7 +510,7 @@ function toAnthropicMessages(messages, cacheControl) {
|
|
|
354
510
|
role: "user",
|
|
355
511
|
content: msg.content.map((result) => ({
|
|
356
512
|
type: "tool_result",
|
|
357
|
-
tool_use_id: result.toolCallId,
|
|
513
|
+
tool_use_id: remapAnthropicToolCallId(result.toolCallId, idMap),
|
|
358
514
|
content: toAnthropicToolResultContent(result.content),
|
|
359
515
|
is_error: result.isError
|
|
360
516
|
}))
|
|
@@ -410,12 +566,19 @@ function toAnthropicMessages(messages, cacheControl) {
|
|
|
410
566
|
}
|
|
411
567
|
return { system, messages: out };
|
|
412
568
|
}
|
|
413
|
-
function toAnthropicTools(tools) {
|
|
414
|
-
return tools.map((tool) =>
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
569
|
+
function toAnthropicTools(tools, options) {
|
|
570
|
+
return tools.map((tool, index) => {
|
|
571
|
+
const anthropicTool = {
|
|
572
|
+
name: tool.name,
|
|
573
|
+
description: tool.description,
|
|
574
|
+
input_schema: tool.rawInputSchema ?? zodToJsonSchema(tool.parameters),
|
|
575
|
+
...options?.enableFineGrainedToolStreaming ? { eager_input_streaming: true } : {}
|
|
576
|
+
};
|
|
577
|
+
if (options?.cacheControl && index === tools.length - 1) {
|
|
578
|
+
anthropicTool.cache_control = options.cacheControl;
|
|
579
|
+
}
|
|
580
|
+
return anthropicTool;
|
|
581
|
+
});
|
|
419
582
|
}
|
|
420
583
|
function toAnthropicToolChoice(choice) {
|
|
421
584
|
if (choice === "auto") return { type: "auto" };
|
|
@@ -428,8 +591,8 @@ function supportsAdaptiveThinking(model) {
|
|
|
428
591
|
}
|
|
429
592
|
function toAnthropicThinking(level, maxTokens, model) {
|
|
430
593
|
if (supportsAdaptiveThinking(model)) {
|
|
431
|
-
let effort = level;
|
|
432
|
-
if (
|
|
594
|
+
let effort = level === "xhigh" ? "max" : level;
|
|
595
|
+
if (effort === "max" && !model.includes("opus")) {
|
|
433
596
|
effort = "high";
|
|
434
597
|
}
|
|
435
598
|
return {
|
|
@@ -438,7 +601,7 @@ function toAnthropicThinking(level, maxTokens, model) {
|
|
|
438
601
|
outputConfig: { effort }
|
|
439
602
|
};
|
|
440
603
|
}
|
|
441
|
-
const effectiveLevel = level === "
|
|
604
|
+
const effectiveLevel = level === "xhigh" ? "high" : level;
|
|
442
605
|
const budgetMap = {
|
|
443
606
|
low: Math.max(1024, Math.floor(maxTokens * 0.25)),
|
|
444
607
|
medium: Math.max(2048, Math.floor(maxTokens * 0.5)),
|
|
@@ -571,8 +734,8 @@ function toOpenAIToolChoice(choice) {
|
|
|
571
734
|
if (choice === "required") return "required";
|
|
572
735
|
return { type: "function", function: { name: choice.name } };
|
|
573
736
|
}
|
|
574
|
-
function toOpenAIReasoningEffort(level) {
|
|
575
|
-
return level
|
|
737
|
+
function toOpenAIReasoningEffort(level, _model) {
|
|
738
|
+
return level;
|
|
576
739
|
}
|
|
577
740
|
function normalizeAnthropicStopReason(reason) {
|
|
578
741
|
switch (reason) {
|
|
@@ -604,6 +767,23 @@ function normalizeOpenAIStopReason(reason) {
|
|
|
604
767
|
}
|
|
605
768
|
|
|
606
769
|
// src/providers/anthropic.ts
|
|
770
|
+
function isJsonObject(value) {
|
|
771
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
772
|
+
}
|
|
773
|
+
function uniqueToolsByName(tools) {
|
|
774
|
+
const seen = /* @__PURE__ */ new Set();
|
|
775
|
+
const unique = [];
|
|
776
|
+
for (const tool of tools) {
|
|
777
|
+
if (!tool.name) {
|
|
778
|
+
unique.push(tool);
|
|
779
|
+
continue;
|
|
780
|
+
}
|
|
781
|
+
if (seen.has(tool.name)) continue;
|
|
782
|
+
seen.add(tool.name);
|
|
783
|
+
unique.push(tool);
|
|
784
|
+
}
|
|
785
|
+
return unique;
|
|
786
|
+
}
|
|
607
787
|
function createClient(options) {
|
|
608
788
|
const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
|
|
609
789
|
return new import_sdk.default({
|
|
@@ -616,7 +796,10 @@ function createClient(options) {
|
|
|
616
796
|
maxRetries: 2,
|
|
617
797
|
...isOAuth ? {
|
|
618
798
|
defaultHeaders: {
|
|
619
|
-
|
|
799
|
+
// Anthropic's OAuth edge validates the claude-cli version. Callers
|
|
800
|
+
// (ezcoder) resolve the live version at runtime; the literal here
|
|
801
|
+
// is the offline fallback for direct gg-ai consumers.
|
|
802
|
+
"user-agent": options.userAgent ?? "claude-cli/2.1.75 (external, cli)",
|
|
620
803
|
"x-app": "cli"
|
|
621
804
|
}
|
|
622
805
|
} : {}
|
|
@@ -630,6 +813,7 @@ async function* runStream(options) {
|
|
|
630
813
|
const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
|
|
631
814
|
const useStreaming = options.streaming !== false;
|
|
632
815
|
const cacheControl = toAnthropicCacheControl(options.cacheRetention, options.baseUrl);
|
|
816
|
+
const supportsFirstPartyToolExtras = !options.baseUrl || options.baseUrl.includes("api.anthropic.com");
|
|
633
817
|
const downgradedMessages = downgradeUnsupportedImages(options.messages, options.supportsImages);
|
|
634
818
|
const { system: rawSystem, messages } = toAnthropicMessages(downgradedMessages, cacheControl);
|
|
635
819
|
const system = isOAuth ? [
|
|
@@ -660,13 +844,28 @@ async function* runStream(options) {
|
|
|
660
844
|
...options.temperature != null && !thinking ? { temperature: options.temperature } : {},
|
|
661
845
|
...options.topP != null ? { top_p: options.topP } : {},
|
|
662
846
|
...options.stop ? { stop_sequences: options.stop } : {},
|
|
663
|
-
...options.tools?.length || options.serverTools?.length || options.webSearch ? {
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
847
|
+
...options.tools?.length || options.serverTools?.length || options.webSearch ? (() => {
|
|
848
|
+
const reservedServerNames = /* @__PURE__ */ new Set();
|
|
849
|
+
if (options.webSearch) reservedServerNames.add("web_search");
|
|
850
|
+
for (const t of options.serverTools ?? []) {
|
|
851
|
+
const name = t.name;
|
|
852
|
+
if (name) reservedServerNames.add(name);
|
|
853
|
+
}
|
|
854
|
+
const clientTools = options.tools?.length ? toAnthropicTools(
|
|
855
|
+
uniqueToolsByName(options.tools.filter((t) => !reservedServerNames.has(t.name))),
|
|
856
|
+
{
|
|
857
|
+
...supportsFirstPartyToolExtras && cacheControl ? { cacheControl } : {},
|
|
858
|
+
...supportsFirstPartyToolExtras ? { enableFineGrainedToolStreaming: true } : {}
|
|
859
|
+
}
|
|
860
|
+
) : [];
|
|
861
|
+
return {
|
|
862
|
+
tools: uniqueToolsByName([
|
|
863
|
+
...clientTools,
|
|
864
|
+
...options.serverTools ?? [],
|
|
865
|
+
...options.webSearch ? [{ type: "web_search_20250305", name: "web_search" }] : []
|
|
866
|
+
])
|
|
867
|
+
};
|
|
868
|
+
})() : {},
|
|
670
869
|
...options.toolChoice && options.tools?.length ? { tool_choice: toAnthropicToolChoice(options.toolChoice) } : {},
|
|
671
870
|
...(() => {
|
|
672
871
|
const contextEdits = [
|
|
@@ -743,6 +942,7 @@ async function* runStream(options) {
|
|
|
743
942
|
if (block.type === "tool_use") {
|
|
744
943
|
accum.toolId = block.id;
|
|
745
944
|
accum.toolName = block.name;
|
|
945
|
+
accum.input = block.input;
|
|
746
946
|
} else if (block.type === "server_tool_use") {
|
|
747
947
|
accum.toolId = block.id;
|
|
748
948
|
accum.toolName = block.name;
|
|
@@ -751,7 +951,11 @@ async function* runStream(options) {
|
|
|
751
951
|
accum.raw = block;
|
|
752
952
|
}
|
|
753
953
|
blocks.set(idx, accum);
|
|
754
|
-
|
|
954
|
+
if (block.type === "thinking") {
|
|
955
|
+
yield { type: "thinking_delta", text: "" };
|
|
956
|
+
} else {
|
|
957
|
+
yield keepalive;
|
|
958
|
+
}
|
|
755
959
|
break;
|
|
756
960
|
}
|
|
757
961
|
case "content_block_delta": {
|
|
@@ -794,10 +998,13 @@ async function* runStream(options) {
|
|
|
794
998
|
});
|
|
795
999
|
yield keepalive;
|
|
796
1000
|
} else if (accum.type === "tool_use") {
|
|
797
|
-
let args = {};
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
1001
|
+
let args = isJsonObject(accum.input) ? accum.input : {};
|
|
1002
|
+
if (accum.argsJson) {
|
|
1003
|
+
try {
|
|
1004
|
+
const parsed = JSON.parse(accum.argsJson);
|
|
1005
|
+
args = isJsonObject(parsed) ? parsed : {};
|
|
1006
|
+
} catch {
|
|
1007
|
+
}
|
|
801
1008
|
}
|
|
802
1009
|
const tc = {
|
|
803
1010
|
type: "tool_call",
|
|
@@ -995,8 +1202,15 @@ function messageToResponse(message) {
|
|
|
995
1202
|
}
|
|
996
1203
|
function toError(err) {
|
|
997
1204
|
if (err instanceof import_sdk.default.APIError) {
|
|
998
|
-
|
|
1205
|
+
const errorBody = err.error;
|
|
1206
|
+
const nestedError = errorBody?.error;
|
|
1207
|
+
const requestId = err.requestID ?? err.request_id ?? (typeof errorBody?.request_id === "string" ? errorBody.request_id : void 0) ?? (typeof nestedError?.request_id === "string" ? nestedError.request_id : void 0) ?? void 0;
|
|
1208
|
+
const bodyMessage = typeof nestedError?.message === "string" ? nestedError.message : typeof errorBody?.message === "string" ? errorBody.message : void 0;
|
|
1209
|
+
const bodyType = typeof nestedError?.type === "string" ? nestedError.type : typeof errorBody?.type === "string" ? errorBody.type : typeof err.type === "string" ? err.type : void 0;
|
|
1210
|
+
const message = bodyType && bodyMessage ? `${bodyType}: ${bodyMessage}` : bodyMessage ?? err.message;
|
|
1211
|
+
return new ProviderError("anthropic", message, {
|
|
999
1212
|
statusCode: err.status,
|
|
1213
|
+
...requestId ? { requestId } : {},
|
|
1000
1214
|
cause: err
|
|
1001
1215
|
});
|
|
1002
1216
|
}
|
|
@@ -1008,6 +1222,38 @@ function toError(err) {
|
|
|
1008
1222
|
|
|
1009
1223
|
// src/providers/openai.ts
|
|
1010
1224
|
var import_openai = __toESM(require("openai"), 1);
|
|
1225
|
+
|
|
1226
|
+
// src/providers/prompt-cache-key.ts
|
|
1227
|
+
var MAX_PROMPT_CACHE_KEY_LENGTH = 64;
|
|
1228
|
+
function normalizePromptCacheKey(key) {
|
|
1229
|
+
if (key.length <= MAX_PROMPT_CACHE_KEY_LENGTH) return key;
|
|
1230
|
+
const hash = fnv1aHash(key);
|
|
1231
|
+
const prefixLength = MAX_PROMPT_CACHE_KEY_LENGTH - hash.length - 1;
|
|
1232
|
+
return `${key.slice(0, prefixLength)}:${hash}`;
|
|
1233
|
+
}
|
|
1234
|
+
function fnv1aHash(value) {
|
|
1235
|
+
let hash = 2166136261;
|
|
1236
|
+
for (let index = 0; index < value.length; index++) {
|
|
1237
|
+
hash ^= value.charCodeAt(index);
|
|
1238
|
+
hash = Math.imul(hash, 16777619);
|
|
1239
|
+
}
|
|
1240
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
// src/providers/openai.ts
|
|
1244
|
+
function isJsonObject2(value) {
|
|
1245
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
1246
|
+
}
|
|
1247
|
+
function parseToolArguments(argsJson) {
|
|
1248
|
+
if (!argsJson) return {};
|
|
1249
|
+
try {
|
|
1250
|
+
const parsed = JSON.parse(argsJson);
|
|
1251
|
+
const unwrapped = typeof parsed === "string" ? JSON.parse(parsed) : parsed;
|
|
1252
|
+
return isJsonObject2(unwrapped) ? unwrapped : {};
|
|
1253
|
+
} catch {
|
|
1254
|
+
return {};
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1011
1257
|
function createClient2(options) {
|
|
1012
1258
|
return new import_openai.default({
|
|
1013
1259
|
apiKey: options.apiKey,
|
|
@@ -1039,19 +1285,22 @@ async function* runStream2(options) {
|
|
|
1039
1285
|
...effectiveTemp != null && !options.thinking ? { temperature: effectiveTemp } : {},
|
|
1040
1286
|
...options.topP != null ? { top_p: options.topP } : {},
|
|
1041
1287
|
...options.stop ? { stop: options.stop } : {},
|
|
1042
|
-
...options.thinking && !usesThinkingParam ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking) } : {},
|
|
1288
|
+
...options.thinking && !usesThinkingParam ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
|
|
1043
1289
|
...options.tools?.length ? { tools: toOpenAITools(options.tools) } : {},
|
|
1044
1290
|
...options.toolChoice && options.tools?.length ? { tool_choice: toOpenAIToolChoice(options.toolChoice) } : {},
|
|
1045
1291
|
...useStreaming ? { stream_options: { include_usage: true } } : {}
|
|
1046
1292
|
};
|
|
1047
1293
|
if (options.provider === "openai" || options.provider === "moonshot") {
|
|
1048
1294
|
const paramsAny = params;
|
|
1049
|
-
paramsAny.prompt_cache_key = "ezcoder";
|
|
1295
|
+
paramsAny.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ezcoder");
|
|
1050
1296
|
const retention = options.cacheRetention ?? "short";
|
|
1051
1297
|
if (retention === "long") {
|
|
1052
1298
|
paramsAny.prompt_cache_retention = "24h";
|
|
1053
1299
|
}
|
|
1054
1300
|
}
|
|
1301
|
+
if (options.provider === "openai" && options.serviceTier) {
|
|
1302
|
+
params.service_tier = options.serviceTier;
|
|
1303
|
+
}
|
|
1055
1304
|
if (usesThinkingParam) {
|
|
1056
1305
|
if (options.thinking) {
|
|
1057
1306
|
params.thinking = { type: "enabled" };
|
|
@@ -1109,6 +1358,9 @@ async function* runStream2(options) {
|
|
|
1109
1358
|
if (!cacheRead && typeof usageAny.cached_tokens === "number" && usageAny.cached_tokens > 0) {
|
|
1110
1359
|
cacheRead = usageAny.cached_tokens;
|
|
1111
1360
|
}
|
|
1361
|
+
if (!cacheRead && typeof usageAny.prompt_cache_hit_tokens === "number" && usageAny.prompt_cache_hit_tokens > 0) {
|
|
1362
|
+
cacheRead = usageAny.prompt_cache_hit_tokens;
|
|
1363
|
+
}
|
|
1112
1364
|
inputTokens = chunk.usage.prompt_tokens - cacheRead;
|
|
1113
1365
|
}
|
|
1114
1366
|
if (!choice) continue;
|
|
@@ -1159,11 +1411,7 @@ async function* runStream2(options) {
|
|
|
1159
1411
|
contentParts.push({ type: "text", text: textAccum });
|
|
1160
1412
|
}
|
|
1161
1413
|
for (const [, tc] of toolCallAccum) {
|
|
1162
|
-
|
|
1163
|
-
try {
|
|
1164
|
-
args = JSON.parse(tc.argsJson);
|
|
1165
|
-
} catch {
|
|
1166
|
-
}
|
|
1414
|
+
const args = parseToolArguments(tc.argsJson);
|
|
1167
1415
|
const toolCall = {
|
|
1168
1416
|
type: "tool_call",
|
|
1169
1417
|
id: tc.id,
|
|
@@ -1216,11 +1464,7 @@ function* synthesizeEventsFromCompletion(completion, thinkingEnabled) {
|
|
|
1216
1464
|
argsJson
|
|
1217
1465
|
};
|
|
1218
1466
|
}
|
|
1219
|
-
|
|
1220
|
-
try {
|
|
1221
|
-
args = JSON.parse(argsJson);
|
|
1222
|
-
} catch {
|
|
1223
|
-
}
|
|
1467
|
+
const args = parseToolArguments(argsJson);
|
|
1224
1468
|
yield {
|
|
1225
1469
|
type: "toolcall_done",
|
|
1226
1470
|
id: tc.id,
|
|
@@ -1248,11 +1492,7 @@ function completionToResponse(completion) {
|
|
|
1248
1492
|
const toolCalls = msg.tool_calls;
|
|
1249
1493
|
if (toolCalls) {
|
|
1250
1494
|
for (const tc of toolCalls) {
|
|
1251
|
-
|
|
1252
|
-
try {
|
|
1253
|
-
args = JSON.parse(tc.function?.arguments ?? "{}");
|
|
1254
|
-
} catch {
|
|
1255
|
-
}
|
|
1495
|
+
const args = parseToolArguments(tc.function?.arguments ?? "");
|
|
1256
1496
|
const toolCall = {
|
|
1257
1497
|
type: "tool_call",
|
|
1258
1498
|
id: tc.id,
|
|
@@ -1274,6 +1514,9 @@ function completionToResponse(completion) {
|
|
|
1274
1514
|
if (!cacheRead && typeof usageAny.cached_tokens === "number" && usageAny.cached_tokens > 0) {
|
|
1275
1515
|
cacheRead = usageAny.cached_tokens;
|
|
1276
1516
|
}
|
|
1517
|
+
if (!cacheRead && typeof usageAny.prompt_cache_hit_tokens === "number" && usageAny.prompt_cache_hit_tokens > 0) {
|
|
1518
|
+
cacheRead = usageAny.prompt_cache_hit_tokens;
|
|
1519
|
+
}
|
|
1277
1520
|
inputTokens = completion.usage.prompt_tokens - cacheRead;
|
|
1278
1521
|
}
|
|
1279
1522
|
const stopReason = normalizeOpenAIStopReason(choice?.finish_reason ?? null);
|
|
@@ -1288,19 +1531,19 @@ function completionToResponse(completion) {
|
|
|
1288
1531
|
}
|
|
1289
1532
|
function toError2(err, provider = "openai") {
|
|
1290
1533
|
if (err instanceof import_openai.default.APIError) {
|
|
1291
|
-
let msg = err.message;
|
|
1292
1534
|
const body = err.error;
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
return new ProviderError(provider, msg, {
|
|
1535
|
+
const bodyMessage = typeof body?.message === "string" && body.message.trim() ? body.message.trim() : void 0;
|
|
1536
|
+
const modelName = typeof body?.model === "string" ? body.model : "";
|
|
1537
|
+
const cleanMessage = bodyMessage ?? err.message;
|
|
1538
|
+
let hint;
|
|
1539
|
+
if (modelName === "codex-mini-latest" || cleanMessage.includes("codex-mini-latest")) {
|
|
1540
|
+
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.";
|
|
1541
|
+
}
|
|
1542
|
+
const requestId = err.request_id ?? (typeof body?.request_id === "string" ? body.request_id : void 0);
|
|
1543
|
+
return new ProviderError(provider, cleanMessage, {
|
|
1303
1544
|
statusCode: err.status,
|
|
1545
|
+
...requestId ? { requestId } : {},
|
|
1546
|
+
...hint ? { hint } : {},
|
|
1304
1547
|
cause: err
|
|
1305
1548
|
});
|
|
1306
1549
|
}
|
|
@@ -1312,7 +1555,34 @@ function toError2(err, provider = "openai") {
|
|
|
1312
1555
|
|
|
1313
1556
|
// src/providers/openai-codex.ts
|
|
1314
1557
|
var import_node_os = __toESM(require("os"), 1);
|
|
1558
|
+
|
|
1559
|
+
// src/utils/diag.ts
|
|
1560
|
+
var _diagFn = null;
|
|
1561
|
+
function setProviderDiagnostic(fn) {
|
|
1562
|
+
_diagFn = fn;
|
|
1563
|
+
}
|
|
1564
|
+
function providerDiag(phase, data) {
|
|
1565
|
+
_diagFn?.(phase, data);
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
// src/providers/openai-codex.ts
|
|
1315
1569
|
var DEFAULT_BASE_URL = "https://chatgpt.com/backend-api";
|
|
1570
|
+
function isJsonObject3(value) {
|
|
1571
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
1572
|
+
}
|
|
1573
|
+
function parseToolArguments2(argsJson) {
|
|
1574
|
+
if (!argsJson) return {};
|
|
1575
|
+
try {
|
|
1576
|
+
const parsed = JSON.parse(argsJson);
|
|
1577
|
+
const unwrapped = typeof parsed === "string" ? JSON.parse(parsed) : parsed;
|
|
1578
|
+
return isJsonObject3(unwrapped) ? unwrapped : {};
|
|
1579
|
+
} catch {
|
|
1580
|
+
return {};
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
function outputTextKey(itemId, contentIndex) {
|
|
1584
|
+
return `${itemId ?? ""}:${contentIndex ?? 0}`;
|
|
1585
|
+
}
|
|
1316
1586
|
function streamOpenAICodex(options) {
|
|
1317
1587
|
return new StreamResult(runStream3(options));
|
|
1318
1588
|
}
|
|
@@ -1334,15 +1604,17 @@ async function* runStream3(options) {
|
|
|
1334
1604
|
if (options.tools?.length) {
|
|
1335
1605
|
body.tools = toCodexTools(options.tools);
|
|
1336
1606
|
}
|
|
1607
|
+
body.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ezcoder");
|
|
1608
|
+
if (options.cacheRetention === "long") {
|
|
1609
|
+
body.prompt_cache_retention = "24h";
|
|
1610
|
+
}
|
|
1337
1611
|
if (options.temperature != null && !options.thinking) {
|
|
1338
1612
|
body.temperature = options.temperature;
|
|
1339
1613
|
}
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
};
|
|
1345
|
-
}
|
|
1614
|
+
body.reasoning = {
|
|
1615
|
+
effort: options.thinking ?? "none",
|
|
1616
|
+
summary: "auto"
|
|
1617
|
+
};
|
|
1346
1618
|
const headers = {
|
|
1347
1619
|
"Content-Type": "application/json",
|
|
1348
1620
|
Accept: "text/event-stream",
|
|
@@ -1354,6 +1626,11 @@ async function* runStream3(options) {
|
|
|
1354
1626
|
if (options.accountId) {
|
|
1355
1627
|
headers["chatgpt-account-id"] = options.accountId;
|
|
1356
1628
|
}
|
|
1629
|
+
const cacheScopeId = body.prompt_cache_key;
|
|
1630
|
+
if (cacheScopeId) {
|
|
1631
|
+
headers["session_id"] = cacheScopeId;
|
|
1632
|
+
headers["x-client-request-id"] = cacheScopeId;
|
|
1633
|
+
}
|
|
1357
1634
|
const response = await fetch(url, {
|
|
1358
1635
|
method: "POST",
|
|
1359
1636
|
headers,
|
|
@@ -1362,19 +1639,23 @@ async function* runStream3(options) {
|
|
|
1362
1639
|
});
|
|
1363
1640
|
if (!response.ok) {
|
|
1364
1641
|
const text = await response.text().catch(() => "");
|
|
1365
|
-
|
|
1642
|
+
const parsed = parseCodexErrorBody(text);
|
|
1643
|
+
const message = parsed.message ?? `Codex API returned HTTP ${response.status}.`;
|
|
1644
|
+
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;
|
|
1645
|
+
let hint;
|
|
1366
1646
|
if (response.status === 400 && text.includes("not supported")) {
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
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.`;
|
|
1647
|
+
if (options.model === "gpt-5.5-pro") {
|
|
1648
|
+
hint = "Use gpt-5.5 instead. OpenAI's Codex model catalog does not list gpt-5.5-pro.";
|
|
1649
|
+
} else {
|
|
1650
|
+
hint = "This model is not available through Codex for the authenticated account. Run /model and choose a model listed for OpenAI Codex, or check your Codex model picker/usage limits.";
|
|
1651
|
+
}
|
|
1652
|
+
} else if (response.status === 404 && text.includes("does not exist")) {
|
|
1653
|
+
hint = "This model is not in the current OpenAI Codex catalog for this account. Try gpt-5.5, gpt-5.4, gpt-5.4-mini, or gpt-5.3-codex.";
|
|
1375
1654
|
}
|
|
1376
1655
|
throw new ProviderError("openai", message, {
|
|
1377
|
-
statusCode: response.status
|
|
1656
|
+
statusCode: response.status,
|
|
1657
|
+
...requestId ? { requestId } : {},
|
|
1658
|
+
...hint ? { hint } : {}
|
|
1378
1659
|
});
|
|
1379
1660
|
}
|
|
1380
1661
|
if (!response.body) {
|
|
@@ -1383,27 +1664,84 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1383
1664
|
const contentParts = [];
|
|
1384
1665
|
let textAccum = "";
|
|
1385
1666
|
const toolCalls = /* @__PURE__ */ new Map();
|
|
1667
|
+
const outputItemTypes = /* @__PURE__ */ new Map();
|
|
1668
|
+
const outputTextByPart = /* @__PURE__ */ new Map();
|
|
1386
1669
|
let inputTokens = 0;
|
|
1387
1670
|
let outputTokens = 0;
|
|
1671
|
+
let cacheRead = 0;
|
|
1672
|
+
const diagStart = Date.now();
|
|
1673
|
+
const diagSeen = /* @__PURE__ */ new Set();
|
|
1388
1674
|
for await (const event of parseSSE(response.body)) {
|
|
1389
1675
|
const type = event.type;
|
|
1390
1676
|
if (!type) continue;
|
|
1677
|
+
if (!diagSeen.has(type)) {
|
|
1678
|
+
diagSeen.add(type);
|
|
1679
|
+
providerDiag("codex_event_first", { type, sinceStartMs: Date.now() - diagStart });
|
|
1680
|
+
}
|
|
1391
1681
|
if (type === "error") {
|
|
1392
|
-
const
|
|
1393
|
-
|
|
1682
|
+
const nested = event.error ?? void 0;
|
|
1683
|
+
const message = nested?.message ?? event.message ?? "Codex stream emitted an error chunk without a message.";
|
|
1684
|
+
const code = nested?.code ?? nested?.type ?? event.code ?? "server_error";
|
|
1685
|
+
const requestId = extractCodexRequestId(message) ?? event.request_id;
|
|
1686
|
+
throw new ProviderError("openai", message, {
|
|
1687
|
+
...requestId != null ? { requestId } : {},
|
|
1688
|
+
...code === "server_error" ? { statusCode: 500 } : {}
|
|
1689
|
+
});
|
|
1394
1690
|
}
|
|
1395
1691
|
if (type === "response.failed") {
|
|
1396
|
-
const
|
|
1397
|
-
|
|
1692
|
+
const nested = event.error;
|
|
1693
|
+
const message = nested?.message ?? "Codex response failed.";
|
|
1694
|
+
const requestId = extractCodexRequestId(message) ?? event.request_id;
|
|
1695
|
+
throw new ProviderError("openai", message, {
|
|
1696
|
+
...requestId != null ? { requestId } : {}
|
|
1697
|
+
});
|
|
1398
1698
|
}
|
|
1399
1699
|
if (type === "response.output_text.delta") {
|
|
1400
1700
|
const delta = event.delta;
|
|
1401
|
-
|
|
1402
|
-
|
|
1701
|
+
const itemId = event.item_id;
|
|
1702
|
+
const contentIndex = event.content_index;
|
|
1703
|
+
const key = outputTextKey(itemId, contentIndex);
|
|
1704
|
+
outputTextByPart.set(key, `${outputTextByPart.get(key) ?? ""}${delta}`);
|
|
1705
|
+
if (itemId && outputItemTypes.get(itemId) === "reasoning") {
|
|
1706
|
+
if (options.thinking) yield { type: "thinking_delta", text: delta };
|
|
1707
|
+
} else {
|
|
1708
|
+
textAccum += delta;
|
|
1709
|
+
yield { type: "text_delta", text: delta };
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
if (type === "response.output_text.done") {
|
|
1713
|
+
const fullText = event.text;
|
|
1714
|
+
if (fullText) {
|
|
1715
|
+
const itemId = event.item_id;
|
|
1716
|
+
const contentIndex = event.content_index;
|
|
1717
|
+
const key = outputTextKey(itemId, contentIndex);
|
|
1718
|
+
const streamedText = outputTextByPart.get(key) ?? "";
|
|
1719
|
+
const missingText = streamedText ? fullText.slice(streamedText.length) : fullText;
|
|
1720
|
+
outputTextByPart.set(key, fullText);
|
|
1721
|
+
if (missingText && fullText.startsWith(streamedText)) {
|
|
1722
|
+
if (itemId && outputItemTypes.get(itemId) === "reasoning") {
|
|
1723
|
+
if (options.thinking) yield { type: "thinking_delta", text: missingText };
|
|
1724
|
+
} else {
|
|
1725
|
+
textAccum += missingText;
|
|
1726
|
+
yield { type: "text_delta", text: missingText };
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1403
1730
|
}
|
|
1404
|
-
if (type === "response.reasoning_summary_text.delta") {
|
|
1731
|
+
if (type === "response.reasoning_summary_text.delta" || type === "response.reasoning_summary.delta" || type === "response.reasoning_text.delta" || type === "response.reasoning.delta") {
|
|
1405
1732
|
const delta = event.delta;
|
|
1406
|
-
yield { type: "thinking_delta", text: delta };
|
|
1733
|
+
if (options.thinking) yield { type: "thinking_delta", text: delta };
|
|
1734
|
+
}
|
|
1735
|
+
if (type === "response.output_item.added") {
|
|
1736
|
+
const item = event.item;
|
|
1737
|
+
const itemId = item?.id;
|
|
1738
|
+
const itemType = item?.type;
|
|
1739
|
+
if (itemId && itemType) {
|
|
1740
|
+
outputItemTypes.set(itemId, itemType);
|
|
1741
|
+
}
|
|
1742
|
+
if (itemType === "reasoning" && options.thinking) {
|
|
1743
|
+
yield { type: "thinking_delta", text: "" };
|
|
1744
|
+
}
|
|
1407
1745
|
}
|
|
1408
1746
|
if (type === "response.output_item.added") {
|
|
1409
1747
|
const item = event.item;
|
|
@@ -1449,11 +1787,7 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1449
1787
|
const id = `${callId}|${itemId}`;
|
|
1450
1788
|
const tc = toolCalls.get(id);
|
|
1451
1789
|
if (tc) {
|
|
1452
|
-
|
|
1453
|
-
try {
|
|
1454
|
-
args = JSON.parse(tc.argsJson);
|
|
1455
|
-
} catch {
|
|
1456
|
-
}
|
|
1790
|
+
const args = parseToolArguments2(tc.argsJson);
|
|
1457
1791
|
yield {
|
|
1458
1792
|
type: "toolcall_done",
|
|
1459
1793
|
id: tc.id,
|
|
@@ -1467,7 +1801,8 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1467
1801
|
const resp = event.response;
|
|
1468
1802
|
const usage = resp?.usage;
|
|
1469
1803
|
if (usage) {
|
|
1470
|
-
|
|
1804
|
+
cacheRead = usage.input_tokens_details?.cached_tokens ?? 0;
|
|
1805
|
+
inputTokens = (usage.input_tokens ?? 0) - cacheRead;
|
|
1471
1806
|
outputTokens = usage.output_tokens ?? 0;
|
|
1472
1807
|
}
|
|
1473
1808
|
}
|
|
@@ -1476,11 +1811,7 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1476
1811
|
contentParts.push({ type: "text", text: textAccum });
|
|
1477
1812
|
}
|
|
1478
1813
|
for (const [, tc] of toolCalls) {
|
|
1479
|
-
|
|
1480
|
-
try {
|
|
1481
|
-
args = JSON.parse(tc.argsJson);
|
|
1482
|
-
} catch {
|
|
1483
|
-
}
|
|
1814
|
+
const args = parseToolArguments2(tc.argsJson);
|
|
1484
1815
|
const toolCall = {
|
|
1485
1816
|
type: "tool_call",
|
|
1486
1817
|
id: tc.id,
|
|
@@ -1497,7 +1828,7 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1497
1828
|
content: contentParts.length > 0 ? contentParts : textAccum || ""
|
|
1498
1829
|
},
|
|
1499
1830
|
stopReason,
|
|
1500
|
-
usage: { inputTokens, outputTokens }
|
|
1831
|
+
usage: { inputTokens, outputTokens, ...cacheRead > 0 && { cacheRead } }
|
|
1501
1832
|
};
|
|
1502
1833
|
yield { type: "done", stopReason };
|
|
1503
1834
|
return streamResponse;
|
|
@@ -1639,6 +1970,24 @@ function toCodexTools(tools) {
|
|
|
1639
1970
|
strict: null
|
|
1640
1971
|
}));
|
|
1641
1972
|
}
|
|
1973
|
+
function extractCodexRequestId(message) {
|
|
1974
|
+
const match = message.match(/request ID ([a-z0-9-]{8,})/i);
|
|
1975
|
+
return match?.[1];
|
|
1976
|
+
}
|
|
1977
|
+
function parseCodexErrorBody(text) {
|
|
1978
|
+
if (!text) return {};
|
|
1979
|
+
try {
|
|
1980
|
+
const parsed = JSON.parse(text);
|
|
1981
|
+
const error = parsed.error;
|
|
1982
|
+
const detail = parsed.detail;
|
|
1983
|
+
const message = error?.message ?? parsed.message ?? (typeof detail === "string" ? detail : void 0);
|
|
1984
|
+
const requestId = parsed.request_id ?? error?.request_id ?? (message ? extractCodexRequestId(message) : void 0);
|
|
1985
|
+
return { ...message ? { message } : {}, ...requestId ? { requestId } : {} };
|
|
1986
|
+
} catch {
|
|
1987
|
+
const trimmed = text.trim().slice(0, 240);
|
|
1988
|
+
return trimmed ? { message: trimmed } : {};
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1642
1991
|
|
|
1643
1992
|
// src/provider-registry.ts
|
|
1644
1993
|
var ProviderRegistryImpl = class {
|
|
@@ -1899,12 +2248,15 @@ function registerPalsuProvider(config) {
|
|
|
1899
2248
|
EventStream,
|
|
1900
2249
|
ProviderError,
|
|
1901
2250
|
StreamResult,
|
|
2251
|
+
formatError,
|
|
2252
|
+
formatErrorForDisplay,
|
|
1902
2253
|
palsuAssistantMessage,
|
|
1903
2254
|
palsuText,
|
|
1904
2255
|
palsuThinking,
|
|
1905
2256
|
palsuToolCall,
|
|
1906
2257
|
providerRegistry,
|
|
1907
2258
|
registerPalsuProvider,
|
|
2259
|
+
setProviderDiagnostic,
|
|
1908
2260
|
stream
|
|
1909
2261
|
});
|
|
1910
2262
|
//# sourceMappingURL=index.cjs.map
|