@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.js
CHANGED
|
@@ -1,20 +1,164 @@
|
|
|
1
1
|
// src/errors.ts
|
|
2
2
|
var EZCoderAIError = class extends Error {
|
|
3
|
+
source;
|
|
4
|
+
requestId;
|
|
5
|
+
hint;
|
|
3
6
|
constructor(message, options) {
|
|
4
|
-
super(message, options);
|
|
7
|
+
super(message, { cause: options?.cause });
|
|
5
8
|
this.name = "EZCoderAIError";
|
|
9
|
+
this.source = options?.source ?? "ezcoder";
|
|
10
|
+
this.requestId = options?.requestId;
|
|
11
|
+
this.hint = options?.hint;
|
|
6
12
|
}
|
|
7
13
|
};
|
|
8
14
|
var ProviderError = class extends EZCoderAIError {
|
|
9
15
|
provider;
|
|
10
16
|
statusCode;
|
|
11
17
|
constructor(provider, message, options) {
|
|
12
|
-
super(
|
|
18
|
+
super(message, {
|
|
19
|
+
source: "provider",
|
|
20
|
+
requestId: options?.requestId,
|
|
21
|
+
hint: options?.hint,
|
|
22
|
+
cause: options?.cause
|
|
23
|
+
});
|
|
13
24
|
this.name = "ProviderError";
|
|
14
25
|
this.provider = provider;
|
|
15
26
|
this.statusCode = options?.statusCode;
|
|
16
27
|
}
|
|
17
28
|
};
|
|
29
|
+
var PROVIDER_DISPLAY = {
|
|
30
|
+
openai: "OpenAI",
|
|
31
|
+
anthropic: "Anthropic",
|
|
32
|
+
glm: "Z.AI (GLM)",
|
|
33
|
+
moonshot: "Moonshot",
|
|
34
|
+
deepseek: "DeepSeek",
|
|
35
|
+
openrouter: "OpenRouter",
|
|
36
|
+
xiaomi: "Xiaomi (MiMo)",
|
|
37
|
+
minimax: "MiniMax"
|
|
38
|
+
};
|
|
39
|
+
var PROVIDER_STATUS_URL = {
|
|
40
|
+
openai: "status.openai.com",
|
|
41
|
+
anthropic: "status.anthropic.com"
|
|
42
|
+
};
|
|
43
|
+
function providerDisplayName(provider) {
|
|
44
|
+
return PROVIDER_DISPLAY[provider] ?? provider;
|
|
45
|
+
}
|
|
46
|
+
function formatError(err) {
|
|
47
|
+
if (err instanceof ProviderError) {
|
|
48
|
+
const name = providerDisplayName(err.provider);
|
|
49
|
+
const cleanMessage = cleanProviderMessage(err.message);
|
|
50
|
+
return {
|
|
51
|
+
headline: `${name} returned an error.`,
|
|
52
|
+
source: "provider",
|
|
53
|
+
message: cleanMessage,
|
|
54
|
+
provider: err.provider,
|
|
55
|
+
statusCode: err.statusCode,
|
|
56
|
+
requestId: err.requestId,
|
|
57
|
+
guidance: err.hint ?? providerGuidance(err.provider, cleanMessage, err.statusCode)
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (err instanceof EZCoderAIError) {
|
|
61
|
+
return finaliseBySource(err.source, err.message, err.requestId, err.hint);
|
|
62
|
+
}
|
|
63
|
+
if (err instanceof Error) {
|
|
64
|
+
const source = inferSource(err);
|
|
65
|
+
return finaliseBySource(source, err.message, void 0, void 0);
|
|
66
|
+
}
|
|
67
|
+
return finaliseBySource("ezcoder", String(err), void 0, void 0);
|
|
68
|
+
}
|
|
69
|
+
function finaliseBySource(source, message, requestId, hint) {
|
|
70
|
+
switch (source) {
|
|
71
|
+
case "network":
|
|
72
|
+
return {
|
|
73
|
+
headline: "Network error \u2014 couldn't reach the provider.",
|
|
74
|
+
source,
|
|
75
|
+
message,
|
|
76
|
+
guidance: hint ?? "Check your internet connection. Not a ezcoder issue \u2014 retry shortly.",
|
|
77
|
+
...requestId ? { requestId } : {}
|
|
78
|
+
};
|
|
79
|
+
case "auth":
|
|
80
|
+
return {
|
|
81
|
+
headline: "Authentication issue.",
|
|
82
|
+
source,
|
|
83
|
+
message,
|
|
84
|
+
guidance: hint ?? "Run `ezcoder login` to refresh your credentials.",
|
|
85
|
+
...requestId ? { requestId } : {}
|
|
86
|
+
};
|
|
87
|
+
case "provider":
|
|
88
|
+
return {
|
|
89
|
+
headline: "Provider returned an error.",
|
|
90
|
+
source,
|
|
91
|
+
message,
|
|
92
|
+
guidance: hint ?? providerGuidance(void 0, message, void 0),
|
|
93
|
+
...requestId ? { requestId } : {}
|
|
94
|
+
};
|
|
95
|
+
case "ezcoder":
|
|
96
|
+
return {
|
|
97
|
+
headline: "ezcoder hit an unexpected error.",
|
|
98
|
+
source,
|
|
99
|
+
message,
|
|
100
|
+
guidance: hint ?? "This looks like a ezcoder bug \u2014 please report it to the developer (see /help).",
|
|
101
|
+
...requestId ? { requestId } : {}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function formatErrorForDisplay(err) {
|
|
106
|
+
const f = formatError(err);
|
|
107
|
+
const lines = [f.headline];
|
|
108
|
+
if (f.message && f.message !== f.headline) lines.push(` ${f.message}`);
|
|
109
|
+
lines.push(` \u2192 ${f.guidance}`);
|
|
110
|
+
return lines.join("\n");
|
|
111
|
+
}
|
|
112
|
+
function cleanProviderMessage(message) {
|
|
113
|
+
return message.replace(/^\[[^\]]+\]\s*/, "").trim();
|
|
114
|
+
}
|
|
115
|
+
function inferSource(err) {
|
|
116
|
+
const msg = err.message.toLowerCase();
|
|
117
|
+
const code = err.code ?? "";
|
|
118
|
+
if (code === "ECONNREFUSED" || code === "ETIMEDOUT" || code === "ENOTFOUND" || code === "ECONNRESET" || msg.includes("fetch failed") || msg.includes("network request failed")) {
|
|
119
|
+
return "network";
|
|
120
|
+
}
|
|
121
|
+
if (msg.includes("not logged in") || msg.includes("token exchange failed") || msg.includes("token refresh failed") || msg.includes("invalid_grant")) {
|
|
122
|
+
return "auth";
|
|
123
|
+
}
|
|
124
|
+
return "ezcoder";
|
|
125
|
+
}
|
|
126
|
+
function providerGuidance(provider, message, statusCode) {
|
|
127
|
+
const name = provider ? providerDisplayName(provider) : "the provider";
|
|
128
|
+
const status = provider ? PROVIDER_STATUS_URL[provider] : void 0;
|
|
129
|
+
const lower = message.toLowerCase();
|
|
130
|
+
if (statusCode === 401 || lower.includes("unauthorized") || lower.includes("invalid api key")) {
|
|
131
|
+
return `Authentication failed with ${name}. Run \`ezcoder login\` to refresh your credentials.`;
|
|
132
|
+
}
|
|
133
|
+
if (lower.includes("overloaded") || lower.includes("engine_overloaded")) {
|
|
134
|
+
return `${name}'s servers are overloaded right now. Retry in a moment \u2014 not a ezcoder issue.`;
|
|
135
|
+
}
|
|
136
|
+
if (lower.includes("insufficient balance") || lower.includes("quota exceeded") || lower.includes("recharge") || lower.includes("no resource package")) {
|
|
137
|
+
return `Your ${name} account has a billing or quota issue \u2014 check your balance. Not a ezcoder issue.`;
|
|
138
|
+
}
|
|
139
|
+
if (statusCode === 429 || lower.includes("rate limit") || lower.includes("too many requests")) {
|
|
140
|
+
return `${name} rate limit hit. Wait a moment then retry \u2014 not a ezcoder issue.`;
|
|
141
|
+
}
|
|
142
|
+
if (statusCode === 502 || lower.includes("bad gateway")) {
|
|
143
|
+
return `${name} returned a bad gateway. Retry \u2014 this is on their side, not ezcoder.`;
|
|
144
|
+
}
|
|
145
|
+
if (statusCode === 503 || lower.includes("service unavailable")) {
|
|
146
|
+
return `${name} is temporarily unavailable. Retry shortly \u2014 not a ezcoder issue.`;
|
|
147
|
+
}
|
|
148
|
+
if (statusCode === 500 || lower.includes("server_error") || lower.includes("500") && lower.includes("internal server error")) {
|
|
149
|
+
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.`;
|
|
150
|
+
}
|
|
151
|
+
if (lower.includes("timeout") || lower.includes("timed out")) {
|
|
152
|
+
return `Request to ${name} timed out. Their servers may be slow \u2014 retry. Not a ezcoder issue.`;
|
|
153
|
+
}
|
|
154
|
+
if (lower.includes("does not recognize the requested model") || lower.includes("model") && (lower.includes("not exist") || lower.includes("not found") || lower.includes("no access"))) {
|
|
155
|
+
return `${name} doesn't recognise this model on your account. Use /model to switch, or check your subscription tier.`;
|
|
156
|
+
}
|
|
157
|
+
if (lower.includes("context_length_exceeded") || lower.includes("prompt is too long")) {
|
|
158
|
+
return `Context window for this ${name} model is full. Run /compact to shrink history, or start a new session.`;
|
|
159
|
+
}
|
|
160
|
+
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.`;
|
|
161
|
+
}
|
|
18
162
|
|
|
19
163
|
// src/providers/anthropic.ts
|
|
20
164
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -246,9 +390,18 @@ function toAnthropicToolResultContent(content) {
|
|
|
246
390
|
};
|
|
247
391
|
});
|
|
248
392
|
}
|
|
393
|
+
function remapAnthropicToolCallId(id, idMap) {
|
|
394
|
+
if (/^[a-zA-Z0-9_-]+$/.test(id)) return id;
|
|
395
|
+
const existing = idMap.get(id);
|
|
396
|
+
if (existing) return existing;
|
|
397
|
+
const mapped = id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
398
|
+
idMap.set(id, mapped);
|
|
399
|
+
return mapped;
|
|
400
|
+
}
|
|
249
401
|
function toAnthropicMessages(messages, cacheControl) {
|
|
250
402
|
let systemText;
|
|
251
403
|
const out = [];
|
|
404
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
252
405
|
for (const msg of messages) {
|
|
253
406
|
if (msg.role === "system") {
|
|
254
407
|
systemText = msg.content;
|
|
@@ -283,7 +436,7 @@ function toAnthropicMessages(messages, cacheControl) {
|
|
|
283
436
|
if (part.type === "tool_call")
|
|
284
437
|
return {
|
|
285
438
|
type: "tool_use",
|
|
286
|
-
id: part.id,
|
|
439
|
+
id: remapAnthropicToolCallId(part.id, idMap),
|
|
287
440
|
name: part.name,
|
|
288
441
|
input: part.args
|
|
289
442
|
};
|
|
@@ -308,7 +461,7 @@ function toAnthropicMessages(messages, cacheControl) {
|
|
|
308
461
|
role: "user",
|
|
309
462
|
content: msg.content.map((result) => ({
|
|
310
463
|
type: "tool_result",
|
|
311
|
-
tool_use_id: result.toolCallId,
|
|
464
|
+
tool_use_id: remapAnthropicToolCallId(result.toolCallId, idMap),
|
|
312
465
|
content: toAnthropicToolResultContent(result.content),
|
|
313
466
|
is_error: result.isError
|
|
314
467
|
}))
|
|
@@ -364,12 +517,19 @@ function toAnthropicMessages(messages, cacheControl) {
|
|
|
364
517
|
}
|
|
365
518
|
return { system, messages: out };
|
|
366
519
|
}
|
|
367
|
-
function toAnthropicTools(tools) {
|
|
368
|
-
return tools.map((tool) =>
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
520
|
+
function toAnthropicTools(tools, options) {
|
|
521
|
+
return tools.map((tool, index) => {
|
|
522
|
+
const anthropicTool = {
|
|
523
|
+
name: tool.name,
|
|
524
|
+
description: tool.description,
|
|
525
|
+
input_schema: tool.rawInputSchema ?? zodToJsonSchema(tool.parameters),
|
|
526
|
+
...options?.enableFineGrainedToolStreaming ? { eager_input_streaming: true } : {}
|
|
527
|
+
};
|
|
528
|
+
if (options?.cacheControl && index === tools.length - 1) {
|
|
529
|
+
anthropicTool.cache_control = options.cacheControl;
|
|
530
|
+
}
|
|
531
|
+
return anthropicTool;
|
|
532
|
+
});
|
|
373
533
|
}
|
|
374
534
|
function toAnthropicToolChoice(choice) {
|
|
375
535
|
if (choice === "auto") return { type: "auto" };
|
|
@@ -382,8 +542,8 @@ function supportsAdaptiveThinking(model) {
|
|
|
382
542
|
}
|
|
383
543
|
function toAnthropicThinking(level, maxTokens, model) {
|
|
384
544
|
if (supportsAdaptiveThinking(model)) {
|
|
385
|
-
let effort = level;
|
|
386
|
-
if (
|
|
545
|
+
let effort = level === "xhigh" ? "max" : level;
|
|
546
|
+
if (effort === "max" && !model.includes("opus")) {
|
|
387
547
|
effort = "high";
|
|
388
548
|
}
|
|
389
549
|
return {
|
|
@@ -392,7 +552,7 @@ function toAnthropicThinking(level, maxTokens, model) {
|
|
|
392
552
|
outputConfig: { effort }
|
|
393
553
|
};
|
|
394
554
|
}
|
|
395
|
-
const effectiveLevel = level === "
|
|
555
|
+
const effectiveLevel = level === "xhigh" ? "high" : level;
|
|
396
556
|
const budgetMap = {
|
|
397
557
|
low: Math.max(1024, Math.floor(maxTokens * 0.25)),
|
|
398
558
|
medium: Math.max(2048, Math.floor(maxTokens * 0.5)),
|
|
@@ -525,8 +685,8 @@ function toOpenAIToolChoice(choice) {
|
|
|
525
685
|
if (choice === "required") return "required";
|
|
526
686
|
return { type: "function", function: { name: choice.name } };
|
|
527
687
|
}
|
|
528
|
-
function toOpenAIReasoningEffort(level) {
|
|
529
|
-
return level
|
|
688
|
+
function toOpenAIReasoningEffort(level, _model) {
|
|
689
|
+
return level;
|
|
530
690
|
}
|
|
531
691
|
function normalizeAnthropicStopReason(reason) {
|
|
532
692
|
switch (reason) {
|
|
@@ -558,6 +718,23 @@ function normalizeOpenAIStopReason(reason) {
|
|
|
558
718
|
}
|
|
559
719
|
|
|
560
720
|
// src/providers/anthropic.ts
|
|
721
|
+
function isJsonObject(value) {
|
|
722
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
723
|
+
}
|
|
724
|
+
function uniqueToolsByName(tools) {
|
|
725
|
+
const seen = /* @__PURE__ */ new Set();
|
|
726
|
+
const unique = [];
|
|
727
|
+
for (const tool of tools) {
|
|
728
|
+
if (!tool.name) {
|
|
729
|
+
unique.push(tool);
|
|
730
|
+
continue;
|
|
731
|
+
}
|
|
732
|
+
if (seen.has(tool.name)) continue;
|
|
733
|
+
seen.add(tool.name);
|
|
734
|
+
unique.push(tool);
|
|
735
|
+
}
|
|
736
|
+
return unique;
|
|
737
|
+
}
|
|
561
738
|
function createClient(options) {
|
|
562
739
|
const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
|
|
563
740
|
return new Anthropic({
|
|
@@ -570,7 +747,10 @@ function createClient(options) {
|
|
|
570
747
|
maxRetries: 2,
|
|
571
748
|
...isOAuth ? {
|
|
572
749
|
defaultHeaders: {
|
|
573
|
-
|
|
750
|
+
// Anthropic's OAuth edge validates the claude-cli version. Callers
|
|
751
|
+
// (ezcoder) resolve the live version at runtime; the literal here
|
|
752
|
+
// is the offline fallback for direct gg-ai consumers.
|
|
753
|
+
"user-agent": options.userAgent ?? "claude-cli/2.1.75 (external, cli)",
|
|
574
754
|
"x-app": "cli"
|
|
575
755
|
}
|
|
576
756
|
} : {}
|
|
@@ -584,6 +764,7 @@ async function* runStream(options) {
|
|
|
584
764
|
const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
|
|
585
765
|
const useStreaming = options.streaming !== false;
|
|
586
766
|
const cacheControl = toAnthropicCacheControl(options.cacheRetention, options.baseUrl);
|
|
767
|
+
const supportsFirstPartyToolExtras = !options.baseUrl || options.baseUrl.includes("api.anthropic.com");
|
|
587
768
|
const downgradedMessages = downgradeUnsupportedImages(options.messages, options.supportsImages);
|
|
588
769
|
const { system: rawSystem, messages } = toAnthropicMessages(downgradedMessages, cacheControl);
|
|
589
770
|
const system = isOAuth ? [
|
|
@@ -614,13 +795,28 @@ async function* runStream(options) {
|
|
|
614
795
|
...options.temperature != null && !thinking ? { temperature: options.temperature } : {},
|
|
615
796
|
...options.topP != null ? { top_p: options.topP } : {},
|
|
616
797
|
...options.stop ? { stop_sequences: options.stop } : {},
|
|
617
|
-
...options.tools?.length || options.serverTools?.length || options.webSearch ? {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
798
|
+
...options.tools?.length || options.serverTools?.length || options.webSearch ? (() => {
|
|
799
|
+
const reservedServerNames = /* @__PURE__ */ new Set();
|
|
800
|
+
if (options.webSearch) reservedServerNames.add("web_search");
|
|
801
|
+
for (const t of options.serverTools ?? []) {
|
|
802
|
+
const name = t.name;
|
|
803
|
+
if (name) reservedServerNames.add(name);
|
|
804
|
+
}
|
|
805
|
+
const clientTools = options.tools?.length ? toAnthropicTools(
|
|
806
|
+
uniqueToolsByName(options.tools.filter((t) => !reservedServerNames.has(t.name))),
|
|
807
|
+
{
|
|
808
|
+
...supportsFirstPartyToolExtras && cacheControl ? { cacheControl } : {},
|
|
809
|
+
...supportsFirstPartyToolExtras ? { enableFineGrainedToolStreaming: true } : {}
|
|
810
|
+
}
|
|
811
|
+
) : [];
|
|
812
|
+
return {
|
|
813
|
+
tools: uniqueToolsByName([
|
|
814
|
+
...clientTools,
|
|
815
|
+
...options.serverTools ?? [],
|
|
816
|
+
...options.webSearch ? [{ type: "web_search_20250305", name: "web_search" }] : []
|
|
817
|
+
])
|
|
818
|
+
};
|
|
819
|
+
})() : {},
|
|
624
820
|
...options.toolChoice && options.tools?.length ? { tool_choice: toAnthropicToolChoice(options.toolChoice) } : {},
|
|
625
821
|
...(() => {
|
|
626
822
|
const contextEdits = [
|
|
@@ -697,6 +893,7 @@ async function* runStream(options) {
|
|
|
697
893
|
if (block.type === "tool_use") {
|
|
698
894
|
accum.toolId = block.id;
|
|
699
895
|
accum.toolName = block.name;
|
|
896
|
+
accum.input = block.input;
|
|
700
897
|
} else if (block.type === "server_tool_use") {
|
|
701
898
|
accum.toolId = block.id;
|
|
702
899
|
accum.toolName = block.name;
|
|
@@ -705,7 +902,11 @@ async function* runStream(options) {
|
|
|
705
902
|
accum.raw = block;
|
|
706
903
|
}
|
|
707
904
|
blocks.set(idx, accum);
|
|
708
|
-
|
|
905
|
+
if (block.type === "thinking") {
|
|
906
|
+
yield { type: "thinking_delta", text: "" };
|
|
907
|
+
} else {
|
|
908
|
+
yield keepalive;
|
|
909
|
+
}
|
|
709
910
|
break;
|
|
710
911
|
}
|
|
711
912
|
case "content_block_delta": {
|
|
@@ -748,10 +949,13 @@ async function* runStream(options) {
|
|
|
748
949
|
});
|
|
749
950
|
yield keepalive;
|
|
750
951
|
} else if (accum.type === "tool_use") {
|
|
751
|
-
let args = {};
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
952
|
+
let args = isJsonObject(accum.input) ? accum.input : {};
|
|
953
|
+
if (accum.argsJson) {
|
|
954
|
+
try {
|
|
955
|
+
const parsed = JSON.parse(accum.argsJson);
|
|
956
|
+
args = isJsonObject(parsed) ? parsed : {};
|
|
957
|
+
} catch {
|
|
958
|
+
}
|
|
755
959
|
}
|
|
756
960
|
const tc = {
|
|
757
961
|
type: "tool_call",
|
|
@@ -949,8 +1153,15 @@ function messageToResponse(message) {
|
|
|
949
1153
|
}
|
|
950
1154
|
function toError(err) {
|
|
951
1155
|
if (err instanceof Anthropic.APIError) {
|
|
952
|
-
|
|
1156
|
+
const errorBody = err.error;
|
|
1157
|
+
const nestedError = errorBody?.error;
|
|
1158
|
+
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;
|
|
1159
|
+
const bodyMessage = typeof nestedError?.message === "string" ? nestedError.message : typeof errorBody?.message === "string" ? errorBody.message : void 0;
|
|
1160
|
+
const bodyType = typeof nestedError?.type === "string" ? nestedError.type : typeof errorBody?.type === "string" ? errorBody.type : typeof err.type === "string" ? err.type : void 0;
|
|
1161
|
+
const message = bodyType && bodyMessage ? `${bodyType}: ${bodyMessage}` : bodyMessage ?? err.message;
|
|
1162
|
+
return new ProviderError("anthropic", message, {
|
|
953
1163
|
statusCode: err.status,
|
|
1164
|
+
...requestId ? { requestId } : {},
|
|
954
1165
|
cause: err
|
|
955
1166
|
});
|
|
956
1167
|
}
|
|
@@ -962,6 +1173,38 @@ function toError(err) {
|
|
|
962
1173
|
|
|
963
1174
|
// src/providers/openai.ts
|
|
964
1175
|
import OpenAI from "openai";
|
|
1176
|
+
|
|
1177
|
+
// src/providers/prompt-cache-key.ts
|
|
1178
|
+
var MAX_PROMPT_CACHE_KEY_LENGTH = 64;
|
|
1179
|
+
function normalizePromptCacheKey(key) {
|
|
1180
|
+
if (key.length <= MAX_PROMPT_CACHE_KEY_LENGTH) return key;
|
|
1181
|
+
const hash = fnv1aHash(key);
|
|
1182
|
+
const prefixLength = MAX_PROMPT_CACHE_KEY_LENGTH - hash.length - 1;
|
|
1183
|
+
return `${key.slice(0, prefixLength)}:${hash}`;
|
|
1184
|
+
}
|
|
1185
|
+
function fnv1aHash(value) {
|
|
1186
|
+
let hash = 2166136261;
|
|
1187
|
+
for (let index = 0; index < value.length; index++) {
|
|
1188
|
+
hash ^= value.charCodeAt(index);
|
|
1189
|
+
hash = Math.imul(hash, 16777619);
|
|
1190
|
+
}
|
|
1191
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
// src/providers/openai.ts
|
|
1195
|
+
function isJsonObject2(value) {
|
|
1196
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
1197
|
+
}
|
|
1198
|
+
function parseToolArguments(argsJson) {
|
|
1199
|
+
if (!argsJson) return {};
|
|
1200
|
+
try {
|
|
1201
|
+
const parsed = JSON.parse(argsJson);
|
|
1202
|
+
const unwrapped = typeof parsed === "string" ? JSON.parse(parsed) : parsed;
|
|
1203
|
+
return isJsonObject2(unwrapped) ? unwrapped : {};
|
|
1204
|
+
} catch {
|
|
1205
|
+
return {};
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
965
1208
|
function createClient2(options) {
|
|
966
1209
|
return new OpenAI({
|
|
967
1210
|
apiKey: options.apiKey,
|
|
@@ -993,19 +1236,22 @@ async function* runStream2(options) {
|
|
|
993
1236
|
...effectiveTemp != null && !options.thinking ? { temperature: effectiveTemp } : {},
|
|
994
1237
|
...options.topP != null ? { top_p: options.topP } : {},
|
|
995
1238
|
...options.stop ? { stop: options.stop } : {},
|
|
996
|
-
...options.thinking && !usesThinkingParam ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking) } : {},
|
|
1239
|
+
...options.thinking && !usesThinkingParam ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
|
|
997
1240
|
...options.tools?.length ? { tools: toOpenAITools(options.tools) } : {},
|
|
998
1241
|
...options.toolChoice && options.tools?.length ? { tool_choice: toOpenAIToolChoice(options.toolChoice) } : {},
|
|
999
1242
|
...useStreaming ? { stream_options: { include_usage: true } } : {}
|
|
1000
1243
|
};
|
|
1001
1244
|
if (options.provider === "openai" || options.provider === "moonshot") {
|
|
1002
1245
|
const paramsAny = params;
|
|
1003
|
-
paramsAny.prompt_cache_key = "ezcoder";
|
|
1246
|
+
paramsAny.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ezcoder");
|
|
1004
1247
|
const retention = options.cacheRetention ?? "short";
|
|
1005
1248
|
if (retention === "long") {
|
|
1006
1249
|
paramsAny.prompt_cache_retention = "24h";
|
|
1007
1250
|
}
|
|
1008
1251
|
}
|
|
1252
|
+
if (options.provider === "openai" && options.serviceTier) {
|
|
1253
|
+
params.service_tier = options.serviceTier;
|
|
1254
|
+
}
|
|
1009
1255
|
if (usesThinkingParam) {
|
|
1010
1256
|
if (options.thinking) {
|
|
1011
1257
|
params.thinking = { type: "enabled" };
|
|
@@ -1063,6 +1309,9 @@ async function* runStream2(options) {
|
|
|
1063
1309
|
if (!cacheRead && typeof usageAny.cached_tokens === "number" && usageAny.cached_tokens > 0) {
|
|
1064
1310
|
cacheRead = usageAny.cached_tokens;
|
|
1065
1311
|
}
|
|
1312
|
+
if (!cacheRead && typeof usageAny.prompt_cache_hit_tokens === "number" && usageAny.prompt_cache_hit_tokens > 0) {
|
|
1313
|
+
cacheRead = usageAny.prompt_cache_hit_tokens;
|
|
1314
|
+
}
|
|
1066
1315
|
inputTokens = chunk.usage.prompt_tokens - cacheRead;
|
|
1067
1316
|
}
|
|
1068
1317
|
if (!choice) continue;
|
|
@@ -1113,11 +1362,7 @@ async function* runStream2(options) {
|
|
|
1113
1362
|
contentParts.push({ type: "text", text: textAccum });
|
|
1114
1363
|
}
|
|
1115
1364
|
for (const [, tc] of toolCallAccum) {
|
|
1116
|
-
|
|
1117
|
-
try {
|
|
1118
|
-
args = JSON.parse(tc.argsJson);
|
|
1119
|
-
} catch {
|
|
1120
|
-
}
|
|
1365
|
+
const args = parseToolArguments(tc.argsJson);
|
|
1121
1366
|
const toolCall = {
|
|
1122
1367
|
type: "tool_call",
|
|
1123
1368
|
id: tc.id,
|
|
@@ -1170,11 +1415,7 @@ function* synthesizeEventsFromCompletion(completion, thinkingEnabled) {
|
|
|
1170
1415
|
argsJson
|
|
1171
1416
|
};
|
|
1172
1417
|
}
|
|
1173
|
-
|
|
1174
|
-
try {
|
|
1175
|
-
args = JSON.parse(argsJson);
|
|
1176
|
-
} catch {
|
|
1177
|
-
}
|
|
1418
|
+
const args = parseToolArguments(argsJson);
|
|
1178
1419
|
yield {
|
|
1179
1420
|
type: "toolcall_done",
|
|
1180
1421
|
id: tc.id,
|
|
@@ -1202,11 +1443,7 @@ function completionToResponse(completion) {
|
|
|
1202
1443
|
const toolCalls = msg.tool_calls;
|
|
1203
1444
|
if (toolCalls) {
|
|
1204
1445
|
for (const tc of toolCalls) {
|
|
1205
|
-
|
|
1206
|
-
try {
|
|
1207
|
-
args = JSON.parse(tc.function?.arguments ?? "{}");
|
|
1208
|
-
} catch {
|
|
1209
|
-
}
|
|
1446
|
+
const args = parseToolArguments(tc.function?.arguments ?? "");
|
|
1210
1447
|
const toolCall = {
|
|
1211
1448
|
type: "tool_call",
|
|
1212
1449
|
id: tc.id,
|
|
@@ -1228,6 +1465,9 @@ function completionToResponse(completion) {
|
|
|
1228
1465
|
if (!cacheRead && typeof usageAny.cached_tokens === "number" && usageAny.cached_tokens > 0) {
|
|
1229
1466
|
cacheRead = usageAny.cached_tokens;
|
|
1230
1467
|
}
|
|
1468
|
+
if (!cacheRead && typeof usageAny.prompt_cache_hit_tokens === "number" && usageAny.prompt_cache_hit_tokens > 0) {
|
|
1469
|
+
cacheRead = usageAny.prompt_cache_hit_tokens;
|
|
1470
|
+
}
|
|
1231
1471
|
inputTokens = completion.usage.prompt_tokens - cacheRead;
|
|
1232
1472
|
}
|
|
1233
1473
|
const stopReason = normalizeOpenAIStopReason(choice?.finish_reason ?? null);
|
|
@@ -1242,19 +1482,19 @@ function completionToResponse(completion) {
|
|
|
1242
1482
|
}
|
|
1243
1483
|
function toError2(err, provider = "openai") {
|
|
1244
1484
|
if (err instanceof OpenAI.APIError) {
|
|
1245
|
-
let msg = err.message;
|
|
1246
1485
|
const body = err.error;
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
return new ProviderError(provider, msg, {
|
|
1486
|
+
const bodyMessage = typeof body?.message === "string" && body.message.trim() ? body.message.trim() : void 0;
|
|
1487
|
+
const modelName = typeof body?.model === "string" ? body.model : "";
|
|
1488
|
+
const cleanMessage = bodyMessage ?? err.message;
|
|
1489
|
+
let hint;
|
|
1490
|
+
if (modelName === "codex-mini-latest" || cleanMessage.includes("codex-mini-latest")) {
|
|
1491
|
+
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.";
|
|
1492
|
+
}
|
|
1493
|
+
const requestId = err.request_id ?? (typeof body?.request_id === "string" ? body.request_id : void 0);
|
|
1494
|
+
return new ProviderError(provider, cleanMessage, {
|
|
1257
1495
|
statusCode: err.status,
|
|
1496
|
+
...requestId ? { requestId } : {},
|
|
1497
|
+
...hint ? { hint } : {},
|
|
1258
1498
|
cause: err
|
|
1259
1499
|
});
|
|
1260
1500
|
}
|
|
@@ -1266,7 +1506,34 @@ function toError2(err, provider = "openai") {
|
|
|
1266
1506
|
|
|
1267
1507
|
// src/providers/openai-codex.ts
|
|
1268
1508
|
import os from "os";
|
|
1509
|
+
|
|
1510
|
+
// src/utils/diag.ts
|
|
1511
|
+
var _diagFn = null;
|
|
1512
|
+
function setProviderDiagnostic(fn) {
|
|
1513
|
+
_diagFn = fn;
|
|
1514
|
+
}
|
|
1515
|
+
function providerDiag(phase, data) {
|
|
1516
|
+
_diagFn?.(phase, data);
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
// src/providers/openai-codex.ts
|
|
1269
1520
|
var DEFAULT_BASE_URL = "https://chatgpt.com/backend-api";
|
|
1521
|
+
function isJsonObject3(value) {
|
|
1522
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
1523
|
+
}
|
|
1524
|
+
function parseToolArguments2(argsJson) {
|
|
1525
|
+
if (!argsJson) return {};
|
|
1526
|
+
try {
|
|
1527
|
+
const parsed = JSON.parse(argsJson);
|
|
1528
|
+
const unwrapped = typeof parsed === "string" ? JSON.parse(parsed) : parsed;
|
|
1529
|
+
return isJsonObject3(unwrapped) ? unwrapped : {};
|
|
1530
|
+
} catch {
|
|
1531
|
+
return {};
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
function outputTextKey(itemId, contentIndex) {
|
|
1535
|
+
return `${itemId ?? ""}:${contentIndex ?? 0}`;
|
|
1536
|
+
}
|
|
1270
1537
|
function streamOpenAICodex(options) {
|
|
1271
1538
|
return new StreamResult(runStream3(options));
|
|
1272
1539
|
}
|
|
@@ -1288,15 +1555,17 @@ async function* runStream3(options) {
|
|
|
1288
1555
|
if (options.tools?.length) {
|
|
1289
1556
|
body.tools = toCodexTools(options.tools);
|
|
1290
1557
|
}
|
|
1558
|
+
body.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ezcoder");
|
|
1559
|
+
if (options.cacheRetention === "long") {
|
|
1560
|
+
body.prompt_cache_retention = "24h";
|
|
1561
|
+
}
|
|
1291
1562
|
if (options.temperature != null && !options.thinking) {
|
|
1292
1563
|
body.temperature = options.temperature;
|
|
1293
1564
|
}
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
};
|
|
1299
|
-
}
|
|
1565
|
+
body.reasoning = {
|
|
1566
|
+
effort: options.thinking ?? "none",
|
|
1567
|
+
summary: "auto"
|
|
1568
|
+
};
|
|
1300
1569
|
const headers = {
|
|
1301
1570
|
"Content-Type": "application/json",
|
|
1302
1571
|
Accept: "text/event-stream",
|
|
@@ -1308,6 +1577,11 @@ async function* runStream3(options) {
|
|
|
1308
1577
|
if (options.accountId) {
|
|
1309
1578
|
headers["chatgpt-account-id"] = options.accountId;
|
|
1310
1579
|
}
|
|
1580
|
+
const cacheScopeId = body.prompt_cache_key;
|
|
1581
|
+
if (cacheScopeId) {
|
|
1582
|
+
headers["session_id"] = cacheScopeId;
|
|
1583
|
+
headers["x-client-request-id"] = cacheScopeId;
|
|
1584
|
+
}
|
|
1311
1585
|
const response = await fetch(url, {
|
|
1312
1586
|
method: "POST",
|
|
1313
1587
|
headers,
|
|
@@ -1316,19 +1590,23 @@ async function* runStream3(options) {
|
|
|
1316
1590
|
});
|
|
1317
1591
|
if (!response.ok) {
|
|
1318
1592
|
const text = await response.text().catch(() => "");
|
|
1319
|
-
|
|
1593
|
+
const parsed = parseCodexErrorBody(text);
|
|
1594
|
+
const message = parsed.message ?? `Codex API returned HTTP ${response.status}.`;
|
|
1595
|
+
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;
|
|
1596
|
+
let hint;
|
|
1320
1597
|
if (response.status === 400 && text.includes("not supported")) {
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
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.`;
|
|
1598
|
+
if (options.model === "gpt-5.5-pro") {
|
|
1599
|
+
hint = "Use gpt-5.5 instead. OpenAI's Codex model catalog does not list gpt-5.5-pro.";
|
|
1600
|
+
} else {
|
|
1601
|
+
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.";
|
|
1602
|
+
}
|
|
1603
|
+
} else if (response.status === 404 && text.includes("does not exist")) {
|
|
1604
|
+
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.";
|
|
1329
1605
|
}
|
|
1330
1606
|
throw new ProviderError("openai", message, {
|
|
1331
|
-
statusCode: response.status
|
|
1607
|
+
statusCode: response.status,
|
|
1608
|
+
...requestId ? { requestId } : {},
|
|
1609
|
+
...hint ? { hint } : {}
|
|
1332
1610
|
});
|
|
1333
1611
|
}
|
|
1334
1612
|
if (!response.body) {
|
|
@@ -1337,27 +1615,84 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1337
1615
|
const contentParts = [];
|
|
1338
1616
|
let textAccum = "";
|
|
1339
1617
|
const toolCalls = /* @__PURE__ */ new Map();
|
|
1618
|
+
const outputItemTypes = /* @__PURE__ */ new Map();
|
|
1619
|
+
const outputTextByPart = /* @__PURE__ */ new Map();
|
|
1340
1620
|
let inputTokens = 0;
|
|
1341
1621
|
let outputTokens = 0;
|
|
1622
|
+
let cacheRead = 0;
|
|
1623
|
+
const diagStart = Date.now();
|
|
1624
|
+
const diagSeen = /* @__PURE__ */ new Set();
|
|
1342
1625
|
for await (const event of parseSSE(response.body)) {
|
|
1343
1626
|
const type = event.type;
|
|
1344
1627
|
if (!type) continue;
|
|
1628
|
+
if (!diagSeen.has(type)) {
|
|
1629
|
+
diagSeen.add(type);
|
|
1630
|
+
providerDiag("codex_event_first", { type, sinceStartMs: Date.now() - diagStart });
|
|
1631
|
+
}
|
|
1345
1632
|
if (type === "error") {
|
|
1346
|
-
const
|
|
1347
|
-
|
|
1633
|
+
const nested = event.error ?? void 0;
|
|
1634
|
+
const message = nested?.message ?? event.message ?? "Codex stream emitted an error chunk without a message.";
|
|
1635
|
+
const code = nested?.code ?? nested?.type ?? event.code ?? "server_error";
|
|
1636
|
+
const requestId = extractCodexRequestId(message) ?? event.request_id;
|
|
1637
|
+
throw new ProviderError("openai", message, {
|
|
1638
|
+
...requestId != null ? { requestId } : {},
|
|
1639
|
+
...code === "server_error" ? { statusCode: 500 } : {}
|
|
1640
|
+
});
|
|
1348
1641
|
}
|
|
1349
1642
|
if (type === "response.failed") {
|
|
1350
|
-
const
|
|
1351
|
-
|
|
1643
|
+
const nested = event.error;
|
|
1644
|
+
const message = nested?.message ?? "Codex response failed.";
|
|
1645
|
+
const requestId = extractCodexRequestId(message) ?? event.request_id;
|
|
1646
|
+
throw new ProviderError("openai", message, {
|
|
1647
|
+
...requestId != null ? { requestId } : {}
|
|
1648
|
+
});
|
|
1352
1649
|
}
|
|
1353
1650
|
if (type === "response.output_text.delta") {
|
|
1354
1651
|
const delta = event.delta;
|
|
1355
|
-
|
|
1356
|
-
|
|
1652
|
+
const itemId = event.item_id;
|
|
1653
|
+
const contentIndex = event.content_index;
|
|
1654
|
+
const key = outputTextKey(itemId, contentIndex);
|
|
1655
|
+
outputTextByPart.set(key, `${outputTextByPart.get(key) ?? ""}${delta}`);
|
|
1656
|
+
if (itemId && outputItemTypes.get(itemId) === "reasoning") {
|
|
1657
|
+
if (options.thinking) yield { type: "thinking_delta", text: delta };
|
|
1658
|
+
} else {
|
|
1659
|
+
textAccum += delta;
|
|
1660
|
+
yield { type: "text_delta", text: delta };
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
if (type === "response.output_text.done") {
|
|
1664
|
+
const fullText = event.text;
|
|
1665
|
+
if (fullText) {
|
|
1666
|
+
const itemId = event.item_id;
|
|
1667
|
+
const contentIndex = event.content_index;
|
|
1668
|
+
const key = outputTextKey(itemId, contentIndex);
|
|
1669
|
+
const streamedText = outputTextByPart.get(key) ?? "";
|
|
1670
|
+
const missingText = streamedText ? fullText.slice(streamedText.length) : fullText;
|
|
1671
|
+
outputTextByPart.set(key, fullText);
|
|
1672
|
+
if (missingText && fullText.startsWith(streamedText)) {
|
|
1673
|
+
if (itemId && outputItemTypes.get(itemId) === "reasoning") {
|
|
1674
|
+
if (options.thinking) yield { type: "thinking_delta", text: missingText };
|
|
1675
|
+
} else {
|
|
1676
|
+
textAccum += missingText;
|
|
1677
|
+
yield { type: "text_delta", text: missingText };
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1357
1681
|
}
|
|
1358
|
-
if (type === "response.reasoning_summary_text.delta") {
|
|
1682
|
+
if (type === "response.reasoning_summary_text.delta" || type === "response.reasoning_summary.delta" || type === "response.reasoning_text.delta" || type === "response.reasoning.delta") {
|
|
1359
1683
|
const delta = event.delta;
|
|
1360
|
-
yield { type: "thinking_delta", text: delta };
|
|
1684
|
+
if (options.thinking) yield { type: "thinking_delta", text: delta };
|
|
1685
|
+
}
|
|
1686
|
+
if (type === "response.output_item.added") {
|
|
1687
|
+
const item = event.item;
|
|
1688
|
+
const itemId = item?.id;
|
|
1689
|
+
const itemType = item?.type;
|
|
1690
|
+
if (itemId && itemType) {
|
|
1691
|
+
outputItemTypes.set(itemId, itemType);
|
|
1692
|
+
}
|
|
1693
|
+
if (itemType === "reasoning" && options.thinking) {
|
|
1694
|
+
yield { type: "thinking_delta", text: "" };
|
|
1695
|
+
}
|
|
1361
1696
|
}
|
|
1362
1697
|
if (type === "response.output_item.added") {
|
|
1363
1698
|
const item = event.item;
|
|
@@ -1403,11 +1738,7 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1403
1738
|
const id = `${callId}|${itemId}`;
|
|
1404
1739
|
const tc = toolCalls.get(id);
|
|
1405
1740
|
if (tc) {
|
|
1406
|
-
|
|
1407
|
-
try {
|
|
1408
|
-
args = JSON.parse(tc.argsJson);
|
|
1409
|
-
} catch {
|
|
1410
|
-
}
|
|
1741
|
+
const args = parseToolArguments2(tc.argsJson);
|
|
1411
1742
|
yield {
|
|
1412
1743
|
type: "toolcall_done",
|
|
1413
1744
|
id: tc.id,
|
|
@@ -1421,7 +1752,8 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1421
1752
|
const resp = event.response;
|
|
1422
1753
|
const usage = resp?.usage;
|
|
1423
1754
|
if (usage) {
|
|
1424
|
-
|
|
1755
|
+
cacheRead = usage.input_tokens_details?.cached_tokens ?? 0;
|
|
1756
|
+
inputTokens = (usage.input_tokens ?? 0) - cacheRead;
|
|
1425
1757
|
outputTokens = usage.output_tokens ?? 0;
|
|
1426
1758
|
}
|
|
1427
1759
|
}
|
|
@@ -1430,11 +1762,7 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1430
1762
|
contentParts.push({ type: "text", text: textAccum });
|
|
1431
1763
|
}
|
|
1432
1764
|
for (const [, tc] of toolCalls) {
|
|
1433
|
-
|
|
1434
|
-
try {
|
|
1435
|
-
args = JSON.parse(tc.argsJson);
|
|
1436
|
-
} catch {
|
|
1437
|
-
}
|
|
1765
|
+
const args = parseToolArguments2(tc.argsJson);
|
|
1438
1766
|
const toolCall = {
|
|
1439
1767
|
type: "tool_call",
|
|
1440
1768
|
id: tc.id,
|
|
@@ -1451,7 +1779,7 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1451
1779
|
content: contentParts.length > 0 ? contentParts : textAccum || ""
|
|
1452
1780
|
},
|
|
1453
1781
|
stopReason,
|
|
1454
|
-
usage: { inputTokens, outputTokens }
|
|
1782
|
+
usage: { inputTokens, outputTokens, ...cacheRead > 0 && { cacheRead } }
|
|
1455
1783
|
};
|
|
1456
1784
|
yield { type: "done", stopReason };
|
|
1457
1785
|
return streamResponse;
|
|
@@ -1593,6 +1921,24 @@ function toCodexTools(tools) {
|
|
|
1593
1921
|
strict: null
|
|
1594
1922
|
}));
|
|
1595
1923
|
}
|
|
1924
|
+
function extractCodexRequestId(message) {
|
|
1925
|
+
const match = message.match(/request ID ([a-z0-9-]{8,})/i);
|
|
1926
|
+
return match?.[1];
|
|
1927
|
+
}
|
|
1928
|
+
function parseCodexErrorBody(text) {
|
|
1929
|
+
if (!text) return {};
|
|
1930
|
+
try {
|
|
1931
|
+
const parsed = JSON.parse(text);
|
|
1932
|
+
const error = parsed.error;
|
|
1933
|
+
const detail = parsed.detail;
|
|
1934
|
+
const message = error?.message ?? parsed.message ?? (typeof detail === "string" ? detail : void 0);
|
|
1935
|
+
const requestId = parsed.request_id ?? error?.request_id ?? (message ? extractCodexRequestId(message) : void 0);
|
|
1936
|
+
return { ...message ? { message } : {}, ...requestId ? { requestId } : {} };
|
|
1937
|
+
} catch {
|
|
1938
|
+
const trimmed = text.trim().slice(0, 240);
|
|
1939
|
+
return trimmed ? { message: trimmed } : {};
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1596
1942
|
|
|
1597
1943
|
// src/provider-registry.ts
|
|
1598
1944
|
var ProviderRegistryImpl = class {
|
|
@@ -1852,12 +2198,15 @@ export {
|
|
|
1852
2198
|
EventStream,
|
|
1853
2199
|
ProviderError,
|
|
1854
2200
|
StreamResult,
|
|
2201
|
+
formatError,
|
|
2202
|
+
formatErrorForDisplay,
|
|
1855
2203
|
palsuAssistantMessage,
|
|
1856
2204
|
palsuText,
|
|
1857
2205
|
palsuThinking,
|
|
1858
2206
|
palsuToolCall,
|
|
1859
2207
|
providerRegistry,
|
|
1860
2208
|
registerPalsuProvider,
|
|
2209
|
+
setProviderDiagnostic,
|
|
1861
2210
|
stream
|
|
1862
2211
|
};
|
|
1863
2212
|
//# sourceMappingURL=index.js.map
|