@prestyj/ai 4.3.161 → 4.3.200
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 +431 -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 +428 -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,9 @@ 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
|
+
}
|
|
607
773
|
function createClient(options) {
|
|
608
774
|
const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
|
|
609
775
|
return new import_sdk.default({
|
|
@@ -616,7 +782,10 @@ function createClient(options) {
|
|
|
616
782
|
maxRetries: 2,
|
|
617
783
|
...isOAuth ? {
|
|
618
784
|
defaultHeaders: {
|
|
619
|
-
|
|
785
|
+
// Anthropic's OAuth edge validates the claude-cli version. Callers
|
|
786
|
+
// (ezcoder) resolve the live version at runtime; the literal here
|
|
787
|
+
// is the offline fallback for direct gg-ai consumers.
|
|
788
|
+
"user-agent": options.userAgent ?? "claude-cli/2.1.75 (external, cli)",
|
|
620
789
|
"x-app": "cli"
|
|
621
790
|
}
|
|
622
791
|
} : {}
|
|
@@ -630,6 +799,7 @@ async function* runStream(options) {
|
|
|
630
799
|
const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
|
|
631
800
|
const useStreaming = options.streaming !== false;
|
|
632
801
|
const cacheControl = toAnthropicCacheControl(options.cacheRetention, options.baseUrl);
|
|
802
|
+
const supportsFirstPartyToolExtras = !options.baseUrl || options.baseUrl.includes("api.anthropic.com");
|
|
633
803
|
const downgradedMessages = downgradeUnsupportedImages(options.messages, options.supportsImages);
|
|
634
804
|
const { system: rawSystem, messages } = toAnthropicMessages(downgradedMessages, cacheControl);
|
|
635
805
|
const system = isOAuth ? [
|
|
@@ -660,13 +830,28 @@ async function* runStream(options) {
|
|
|
660
830
|
...options.temperature != null && !thinking ? { temperature: options.temperature } : {},
|
|
661
831
|
...options.topP != null ? { top_p: options.topP } : {},
|
|
662
832
|
...options.stop ? { stop_sequences: options.stop } : {},
|
|
663
|
-
...options.tools?.length || options.serverTools?.length || options.webSearch ? {
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
833
|
+
...options.tools?.length || options.serverTools?.length || options.webSearch ? (() => {
|
|
834
|
+
const reservedServerNames = /* @__PURE__ */ new Set();
|
|
835
|
+
if (options.webSearch) reservedServerNames.add("web_search");
|
|
836
|
+
for (const t of options.serverTools ?? []) {
|
|
837
|
+
const name = t.name;
|
|
838
|
+
if (name) reservedServerNames.add(name);
|
|
839
|
+
}
|
|
840
|
+
const clientTools = options.tools?.length ? toAnthropicTools(
|
|
841
|
+
options.tools.filter((t) => !reservedServerNames.has(t.name)),
|
|
842
|
+
{
|
|
843
|
+
...supportsFirstPartyToolExtras && cacheControl ? { cacheControl } : {},
|
|
844
|
+
...supportsFirstPartyToolExtras ? { enableFineGrainedToolStreaming: true } : {}
|
|
845
|
+
}
|
|
846
|
+
) : [];
|
|
847
|
+
return {
|
|
848
|
+
tools: [
|
|
849
|
+
...clientTools,
|
|
850
|
+
...options.serverTools ?? [],
|
|
851
|
+
...options.webSearch ? [{ type: "web_search_20250305", name: "web_search" }] : []
|
|
852
|
+
]
|
|
853
|
+
};
|
|
854
|
+
})() : {},
|
|
670
855
|
...options.toolChoice && options.tools?.length ? { tool_choice: toAnthropicToolChoice(options.toolChoice) } : {},
|
|
671
856
|
...(() => {
|
|
672
857
|
const contextEdits = [
|
|
@@ -743,6 +928,7 @@ async function* runStream(options) {
|
|
|
743
928
|
if (block.type === "tool_use") {
|
|
744
929
|
accum.toolId = block.id;
|
|
745
930
|
accum.toolName = block.name;
|
|
931
|
+
accum.input = block.input;
|
|
746
932
|
} else if (block.type === "server_tool_use") {
|
|
747
933
|
accum.toolId = block.id;
|
|
748
934
|
accum.toolName = block.name;
|
|
@@ -751,7 +937,11 @@ async function* runStream(options) {
|
|
|
751
937
|
accum.raw = block;
|
|
752
938
|
}
|
|
753
939
|
blocks.set(idx, accum);
|
|
754
|
-
|
|
940
|
+
if (block.type === "thinking") {
|
|
941
|
+
yield { type: "thinking_delta", text: "" };
|
|
942
|
+
} else {
|
|
943
|
+
yield keepalive;
|
|
944
|
+
}
|
|
755
945
|
break;
|
|
756
946
|
}
|
|
757
947
|
case "content_block_delta": {
|
|
@@ -794,10 +984,13 @@ async function* runStream(options) {
|
|
|
794
984
|
});
|
|
795
985
|
yield keepalive;
|
|
796
986
|
} else if (accum.type === "tool_use") {
|
|
797
|
-
let args = {};
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
987
|
+
let args = isJsonObject(accum.input) ? accum.input : {};
|
|
988
|
+
if (accum.argsJson) {
|
|
989
|
+
try {
|
|
990
|
+
const parsed = JSON.parse(accum.argsJson);
|
|
991
|
+
args = isJsonObject(parsed) ? parsed : {};
|
|
992
|
+
} catch {
|
|
993
|
+
}
|
|
801
994
|
}
|
|
802
995
|
const tc = {
|
|
803
996
|
type: "tool_call",
|
|
@@ -995,8 +1188,15 @@ function messageToResponse(message) {
|
|
|
995
1188
|
}
|
|
996
1189
|
function toError(err) {
|
|
997
1190
|
if (err instanceof import_sdk.default.APIError) {
|
|
998
|
-
|
|
1191
|
+
const errorBody = err.error;
|
|
1192
|
+
const nestedError = errorBody?.error;
|
|
1193
|
+
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;
|
|
1194
|
+
const bodyMessage = typeof nestedError?.message === "string" ? nestedError.message : typeof errorBody?.message === "string" ? errorBody.message : void 0;
|
|
1195
|
+
const bodyType = typeof nestedError?.type === "string" ? nestedError.type : typeof errorBody?.type === "string" ? errorBody.type : typeof err.type === "string" ? err.type : void 0;
|
|
1196
|
+
const message = bodyType && bodyMessage ? `${bodyType}: ${bodyMessage}` : bodyMessage ?? err.message;
|
|
1197
|
+
return new ProviderError("anthropic", message, {
|
|
999
1198
|
statusCode: err.status,
|
|
1199
|
+
...requestId ? { requestId } : {},
|
|
1000
1200
|
cause: err
|
|
1001
1201
|
});
|
|
1002
1202
|
}
|
|
@@ -1008,6 +1208,38 @@ function toError(err) {
|
|
|
1008
1208
|
|
|
1009
1209
|
// src/providers/openai.ts
|
|
1010
1210
|
var import_openai = __toESM(require("openai"), 1);
|
|
1211
|
+
|
|
1212
|
+
// src/providers/prompt-cache-key.ts
|
|
1213
|
+
var MAX_PROMPT_CACHE_KEY_LENGTH = 64;
|
|
1214
|
+
function normalizePromptCacheKey(key) {
|
|
1215
|
+
if (key.length <= MAX_PROMPT_CACHE_KEY_LENGTH) return key;
|
|
1216
|
+
const hash = fnv1aHash(key);
|
|
1217
|
+
const prefixLength = MAX_PROMPT_CACHE_KEY_LENGTH - hash.length - 1;
|
|
1218
|
+
return `${key.slice(0, prefixLength)}:${hash}`;
|
|
1219
|
+
}
|
|
1220
|
+
function fnv1aHash(value) {
|
|
1221
|
+
let hash = 2166136261;
|
|
1222
|
+
for (let index = 0; index < value.length; index++) {
|
|
1223
|
+
hash ^= value.charCodeAt(index);
|
|
1224
|
+
hash = Math.imul(hash, 16777619);
|
|
1225
|
+
}
|
|
1226
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
// src/providers/openai.ts
|
|
1230
|
+
function isJsonObject2(value) {
|
|
1231
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
1232
|
+
}
|
|
1233
|
+
function parseToolArguments(argsJson) {
|
|
1234
|
+
if (!argsJson) return {};
|
|
1235
|
+
try {
|
|
1236
|
+
const parsed = JSON.parse(argsJson);
|
|
1237
|
+
const unwrapped = typeof parsed === "string" ? JSON.parse(parsed) : parsed;
|
|
1238
|
+
return isJsonObject2(unwrapped) ? unwrapped : {};
|
|
1239
|
+
} catch {
|
|
1240
|
+
return {};
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1011
1243
|
function createClient2(options) {
|
|
1012
1244
|
return new import_openai.default({
|
|
1013
1245
|
apiKey: options.apiKey,
|
|
@@ -1039,19 +1271,22 @@ async function* runStream2(options) {
|
|
|
1039
1271
|
...effectiveTemp != null && !options.thinking ? { temperature: effectiveTemp } : {},
|
|
1040
1272
|
...options.topP != null ? { top_p: options.topP } : {},
|
|
1041
1273
|
...options.stop ? { stop: options.stop } : {},
|
|
1042
|
-
...options.thinking && !usesThinkingParam ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking) } : {},
|
|
1274
|
+
...options.thinking && !usesThinkingParam ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
|
|
1043
1275
|
...options.tools?.length ? { tools: toOpenAITools(options.tools) } : {},
|
|
1044
1276
|
...options.toolChoice && options.tools?.length ? { tool_choice: toOpenAIToolChoice(options.toolChoice) } : {},
|
|
1045
1277
|
...useStreaming ? { stream_options: { include_usage: true } } : {}
|
|
1046
1278
|
};
|
|
1047
1279
|
if (options.provider === "openai" || options.provider === "moonshot") {
|
|
1048
1280
|
const paramsAny = params;
|
|
1049
|
-
paramsAny.prompt_cache_key = "ezcoder";
|
|
1281
|
+
paramsAny.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ezcoder");
|
|
1050
1282
|
const retention = options.cacheRetention ?? "short";
|
|
1051
1283
|
if (retention === "long") {
|
|
1052
1284
|
paramsAny.prompt_cache_retention = "24h";
|
|
1053
1285
|
}
|
|
1054
1286
|
}
|
|
1287
|
+
if (options.provider === "openai" && options.serviceTier) {
|
|
1288
|
+
params.service_tier = options.serviceTier;
|
|
1289
|
+
}
|
|
1055
1290
|
if (usesThinkingParam) {
|
|
1056
1291
|
if (options.thinking) {
|
|
1057
1292
|
params.thinking = { type: "enabled" };
|
|
@@ -1109,6 +1344,9 @@ async function* runStream2(options) {
|
|
|
1109
1344
|
if (!cacheRead && typeof usageAny.cached_tokens === "number" && usageAny.cached_tokens > 0) {
|
|
1110
1345
|
cacheRead = usageAny.cached_tokens;
|
|
1111
1346
|
}
|
|
1347
|
+
if (!cacheRead && typeof usageAny.prompt_cache_hit_tokens === "number" && usageAny.prompt_cache_hit_tokens > 0) {
|
|
1348
|
+
cacheRead = usageAny.prompt_cache_hit_tokens;
|
|
1349
|
+
}
|
|
1112
1350
|
inputTokens = chunk.usage.prompt_tokens - cacheRead;
|
|
1113
1351
|
}
|
|
1114
1352
|
if (!choice) continue;
|
|
@@ -1159,11 +1397,7 @@ async function* runStream2(options) {
|
|
|
1159
1397
|
contentParts.push({ type: "text", text: textAccum });
|
|
1160
1398
|
}
|
|
1161
1399
|
for (const [, tc] of toolCallAccum) {
|
|
1162
|
-
|
|
1163
|
-
try {
|
|
1164
|
-
args = JSON.parse(tc.argsJson);
|
|
1165
|
-
} catch {
|
|
1166
|
-
}
|
|
1400
|
+
const args = parseToolArguments(tc.argsJson);
|
|
1167
1401
|
const toolCall = {
|
|
1168
1402
|
type: "tool_call",
|
|
1169
1403
|
id: tc.id,
|
|
@@ -1216,11 +1450,7 @@ function* synthesizeEventsFromCompletion(completion, thinkingEnabled) {
|
|
|
1216
1450
|
argsJson
|
|
1217
1451
|
};
|
|
1218
1452
|
}
|
|
1219
|
-
|
|
1220
|
-
try {
|
|
1221
|
-
args = JSON.parse(argsJson);
|
|
1222
|
-
} catch {
|
|
1223
|
-
}
|
|
1453
|
+
const args = parseToolArguments(argsJson);
|
|
1224
1454
|
yield {
|
|
1225
1455
|
type: "toolcall_done",
|
|
1226
1456
|
id: tc.id,
|
|
@@ -1248,11 +1478,7 @@ function completionToResponse(completion) {
|
|
|
1248
1478
|
const toolCalls = msg.tool_calls;
|
|
1249
1479
|
if (toolCalls) {
|
|
1250
1480
|
for (const tc of toolCalls) {
|
|
1251
|
-
|
|
1252
|
-
try {
|
|
1253
|
-
args = JSON.parse(tc.function?.arguments ?? "{}");
|
|
1254
|
-
} catch {
|
|
1255
|
-
}
|
|
1481
|
+
const args = parseToolArguments(tc.function?.arguments ?? "");
|
|
1256
1482
|
const toolCall = {
|
|
1257
1483
|
type: "tool_call",
|
|
1258
1484
|
id: tc.id,
|
|
@@ -1274,6 +1500,9 @@ function completionToResponse(completion) {
|
|
|
1274
1500
|
if (!cacheRead && typeof usageAny.cached_tokens === "number" && usageAny.cached_tokens > 0) {
|
|
1275
1501
|
cacheRead = usageAny.cached_tokens;
|
|
1276
1502
|
}
|
|
1503
|
+
if (!cacheRead && typeof usageAny.prompt_cache_hit_tokens === "number" && usageAny.prompt_cache_hit_tokens > 0) {
|
|
1504
|
+
cacheRead = usageAny.prompt_cache_hit_tokens;
|
|
1505
|
+
}
|
|
1277
1506
|
inputTokens = completion.usage.prompt_tokens - cacheRead;
|
|
1278
1507
|
}
|
|
1279
1508
|
const stopReason = normalizeOpenAIStopReason(choice?.finish_reason ?? null);
|
|
@@ -1288,19 +1517,19 @@ function completionToResponse(completion) {
|
|
|
1288
1517
|
}
|
|
1289
1518
|
function toError2(err, provider = "openai") {
|
|
1290
1519
|
if (err instanceof import_openai.default.APIError) {
|
|
1291
|
-
let msg = err.message;
|
|
1292
1520
|
const body = err.error;
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
return new ProviderError(provider, msg, {
|
|
1521
|
+
const bodyMessage = typeof body?.message === "string" && body.message.trim() ? body.message.trim() : void 0;
|
|
1522
|
+
const modelName = typeof body?.model === "string" ? body.model : "";
|
|
1523
|
+
const cleanMessage = bodyMessage ?? err.message;
|
|
1524
|
+
let hint;
|
|
1525
|
+
if (modelName === "codex-mini-latest" || cleanMessage.includes("codex-mini-latest")) {
|
|
1526
|
+
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.";
|
|
1527
|
+
}
|
|
1528
|
+
const requestId = err.request_id ?? (typeof body?.request_id === "string" ? body.request_id : void 0);
|
|
1529
|
+
return new ProviderError(provider, cleanMessage, {
|
|
1303
1530
|
statusCode: err.status,
|
|
1531
|
+
...requestId ? { requestId } : {},
|
|
1532
|
+
...hint ? { hint } : {},
|
|
1304
1533
|
cause: err
|
|
1305
1534
|
});
|
|
1306
1535
|
}
|
|
@@ -1312,7 +1541,34 @@ function toError2(err, provider = "openai") {
|
|
|
1312
1541
|
|
|
1313
1542
|
// src/providers/openai-codex.ts
|
|
1314
1543
|
var import_node_os = __toESM(require("os"), 1);
|
|
1544
|
+
|
|
1545
|
+
// src/utils/diag.ts
|
|
1546
|
+
var _diagFn = null;
|
|
1547
|
+
function setProviderDiagnostic(fn) {
|
|
1548
|
+
_diagFn = fn;
|
|
1549
|
+
}
|
|
1550
|
+
function providerDiag(phase, data) {
|
|
1551
|
+
_diagFn?.(phase, data);
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
// src/providers/openai-codex.ts
|
|
1315
1555
|
var DEFAULT_BASE_URL = "https://chatgpt.com/backend-api";
|
|
1556
|
+
function isJsonObject3(value) {
|
|
1557
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
1558
|
+
}
|
|
1559
|
+
function parseToolArguments2(argsJson) {
|
|
1560
|
+
if (!argsJson) return {};
|
|
1561
|
+
try {
|
|
1562
|
+
const parsed = JSON.parse(argsJson);
|
|
1563
|
+
const unwrapped = typeof parsed === "string" ? JSON.parse(parsed) : parsed;
|
|
1564
|
+
return isJsonObject3(unwrapped) ? unwrapped : {};
|
|
1565
|
+
} catch {
|
|
1566
|
+
return {};
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
function outputTextKey(itemId, contentIndex) {
|
|
1570
|
+
return `${itemId ?? ""}:${contentIndex ?? 0}`;
|
|
1571
|
+
}
|
|
1316
1572
|
function streamOpenAICodex(options) {
|
|
1317
1573
|
return new StreamResult(runStream3(options));
|
|
1318
1574
|
}
|
|
@@ -1334,15 +1590,17 @@ async function* runStream3(options) {
|
|
|
1334
1590
|
if (options.tools?.length) {
|
|
1335
1591
|
body.tools = toCodexTools(options.tools);
|
|
1336
1592
|
}
|
|
1593
|
+
body.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ezcoder");
|
|
1594
|
+
if (options.cacheRetention === "long") {
|
|
1595
|
+
body.prompt_cache_retention = "24h";
|
|
1596
|
+
}
|
|
1337
1597
|
if (options.temperature != null && !options.thinking) {
|
|
1338
1598
|
body.temperature = options.temperature;
|
|
1339
1599
|
}
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
};
|
|
1345
|
-
}
|
|
1600
|
+
body.reasoning = {
|
|
1601
|
+
effort: options.thinking ?? "none",
|
|
1602
|
+
summary: "auto"
|
|
1603
|
+
};
|
|
1346
1604
|
const headers = {
|
|
1347
1605
|
"Content-Type": "application/json",
|
|
1348
1606
|
Accept: "text/event-stream",
|
|
@@ -1354,6 +1612,11 @@ async function* runStream3(options) {
|
|
|
1354
1612
|
if (options.accountId) {
|
|
1355
1613
|
headers["chatgpt-account-id"] = options.accountId;
|
|
1356
1614
|
}
|
|
1615
|
+
const cacheScopeId = body.prompt_cache_key;
|
|
1616
|
+
if (cacheScopeId) {
|
|
1617
|
+
headers["session_id"] = cacheScopeId;
|
|
1618
|
+
headers["x-client-request-id"] = cacheScopeId;
|
|
1619
|
+
}
|
|
1357
1620
|
const response = await fetch(url, {
|
|
1358
1621
|
method: "POST",
|
|
1359
1622
|
headers,
|
|
@@ -1362,19 +1625,23 @@ async function* runStream3(options) {
|
|
|
1362
1625
|
});
|
|
1363
1626
|
if (!response.ok) {
|
|
1364
1627
|
const text = await response.text().catch(() => "");
|
|
1365
|
-
|
|
1628
|
+
const parsed = parseCodexErrorBody(text);
|
|
1629
|
+
const message = parsed.message ?? `Codex API returned HTTP ${response.status}.`;
|
|
1630
|
+
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;
|
|
1631
|
+
let hint;
|
|
1366
1632
|
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.`;
|
|
1633
|
+
if (options.model === "gpt-5.5-pro") {
|
|
1634
|
+
hint = "Use gpt-5.5 instead. OpenAI's Codex model catalog does not list gpt-5.5-pro.";
|
|
1635
|
+
} else {
|
|
1636
|
+
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.";
|
|
1637
|
+
}
|
|
1638
|
+
} else if (response.status === 404 && text.includes("does not exist")) {
|
|
1639
|
+
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
1640
|
}
|
|
1376
1641
|
throw new ProviderError("openai", message, {
|
|
1377
|
-
statusCode: response.status
|
|
1642
|
+
statusCode: response.status,
|
|
1643
|
+
...requestId ? { requestId } : {},
|
|
1644
|
+
...hint ? { hint } : {}
|
|
1378
1645
|
});
|
|
1379
1646
|
}
|
|
1380
1647
|
if (!response.body) {
|
|
@@ -1383,27 +1650,84 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1383
1650
|
const contentParts = [];
|
|
1384
1651
|
let textAccum = "";
|
|
1385
1652
|
const toolCalls = /* @__PURE__ */ new Map();
|
|
1653
|
+
const outputItemTypes = /* @__PURE__ */ new Map();
|
|
1654
|
+
const outputTextByPart = /* @__PURE__ */ new Map();
|
|
1386
1655
|
let inputTokens = 0;
|
|
1387
1656
|
let outputTokens = 0;
|
|
1657
|
+
let cacheRead = 0;
|
|
1658
|
+
const diagStart = Date.now();
|
|
1659
|
+
const diagSeen = /* @__PURE__ */ new Set();
|
|
1388
1660
|
for await (const event of parseSSE(response.body)) {
|
|
1389
1661
|
const type = event.type;
|
|
1390
1662
|
if (!type) continue;
|
|
1663
|
+
if (!diagSeen.has(type)) {
|
|
1664
|
+
diagSeen.add(type);
|
|
1665
|
+
providerDiag("codex_event_first", { type, sinceStartMs: Date.now() - diagStart });
|
|
1666
|
+
}
|
|
1391
1667
|
if (type === "error") {
|
|
1392
|
-
const
|
|
1393
|
-
|
|
1668
|
+
const nested = event.error ?? void 0;
|
|
1669
|
+
const message = nested?.message ?? event.message ?? "Codex stream emitted an error chunk without a message.";
|
|
1670
|
+
const code = nested?.code ?? nested?.type ?? event.code ?? "server_error";
|
|
1671
|
+
const requestId = extractCodexRequestId(message) ?? event.request_id;
|
|
1672
|
+
throw new ProviderError("openai", message, {
|
|
1673
|
+
...requestId != null ? { requestId } : {},
|
|
1674
|
+
...code === "server_error" ? { statusCode: 500 } : {}
|
|
1675
|
+
});
|
|
1394
1676
|
}
|
|
1395
1677
|
if (type === "response.failed") {
|
|
1396
|
-
const
|
|
1397
|
-
|
|
1678
|
+
const nested = event.error;
|
|
1679
|
+
const message = nested?.message ?? "Codex response failed.";
|
|
1680
|
+
const requestId = extractCodexRequestId(message) ?? event.request_id;
|
|
1681
|
+
throw new ProviderError("openai", message, {
|
|
1682
|
+
...requestId != null ? { requestId } : {}
|
|
1683
|
+
});
|
|
1398
1684
|
}
|
|
1399
1685
|
if (type === "response.output_text.delta") {
|
|
1400
1686
|
const delta = event.delta;
|
|
1401
|
-
|
|
1402
|
-
|
|
1687
|
+
const itemId = event.item_id;
|
|
1688
|
+
const contentIndex = event.content_index;
|
|
1689
|
+
const key = outputTextKey(itemId, contentIndex);
|
|
1690
|
+
outputTextByPart.set(key, `${outputTextByPart.get(key) ?? ""}${delta}`);
|
|
1691
|
+
if (itemId && outputItemTypes.get(itemId) === "reasoning") {
|
|
1692
|
+
if (options.thinking) yield { type: "thinking_delta", text: delta };
|
|
1693
|
+
} else {
|
|
1694
|
+
textAccum += delta;
|
|
1695
|
+
yield { type: "text_delta", text: delta };
|
|
1696
|
+
}
|
|
1403
1697
|
}
|
|
1404
|
-
if (type === "response.
|
|
1698
|
+
if (type === "response.output_text.done") {
|
|
1699
|
+
const fullText = event.text;
|
|
1700
|
+
if (fullText) {
|
|
1701
|
+
const itemId = event.item_id;
|
|
1702
|
+
const contentIndex = event.content_index;
|
|
1703
|
+
const key = outputTextKey(itemId, contentIndex);
|
|
1704
|
+
const streamedText = outputTextByPart.get(key) ?? "";
|
|
1705
|
+
const missingText = streamedText ? fullText.slice(streamedText.length) : fullText;
|
|
1706
|
+
outputTextByPart.set(key, fullText);
|
|
1707
|
+
if (missingText && fullText.startsWith(streamedText)) {
|
|
1708
|
+
if (itemId && outputItemTypes.get(itemId) === "reasoning") {
|
|
1709
|
+
if (options.thinking) yield { type: "thinking_delta", text: missingText };
|
|
1710
|
+
} else {
|
|
1711
|
+
textAccum += missingText;
|
|
1712
|
+
yield { type: "text_delta", text: missingText };
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
if (type === "response.reasoning_summary_text.delta" || type === "response.reasoning_summary.delta" || type === "response.reasoning_text.delta" || type === "response.reasoning.delta") {
|
|
1405
1718
|
const delta = event.delta;
|
|
1406
|
-
yield { type: "thinking_delta", text: delta };
|
|
1719
|
+
if (options.thinking) yield { type: "thinking_delta", text: delta };
|
|
1720
|
+
}
|
|
1721
|
+
if (type === "response.output_item.added") {
|
|
1722
|
+
const item = event.item;
|
|
1723
|
+
const itemId = item?.id;
|
|
1724
|
+
const itemType = item?.type;
|
|
1725
|
+
if (itemId && itemType) {
|
|
1726
|
+
outputItemTypes.set(itemId, itemType);
|
|
1727
|
+
}
|
|
1728
|
+
if (itemType === "reasoning" && options.thinking) {
|
|
1729
|
+
yield { type: "thinking_delta", text: "" };
|
|
1730
|
+
}
|
|
1407
1731
|
}
|
|
1408
1732
|
if (type === "response.output_item.added") {
|
|
1409
1733
|
const item = event.item;
|
|
@@ -1449,11 +1773,7 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1449
1773
|
const id = `${callId}|${itemId}`;
|
|
1450
1774
|
const tc = toolCalls.get(id);
|
|
1451
1775
|
if (tc) {
|
|
1452
|
-
|
|
1453
|
-
try {
|
|
1454
|
-
args = JSON.parse(tc.argsJson);
|
|
1455
|
-
} catch {
|
|
1456
|
-
}
|
|
1776
|
+
const args = parseToolArguments2(tc.argsJson);
|
|
1457
1777
|
yield {
|
|
1458
1778
|
type: "toolcall_done",
|
|
1459
1779
|
id: tc.id,
|
|
@@ -1467,7 +1787,8 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1467
1787
|
const resp = event.response;
|
|
1468
1788
|
const usage = resp?.usage;
|
|
1469
1789
|
if (usage) {
|
|
1470
|
-
|
|
1790
|
+
cacheRead = usage.input_tokens_details?.cached_tokens ?? 0;
|
|
1791
|
+
inputTokens = (usage.input_tokens ?? 0) - cacheRead;
|
|
1471
1792
|
outputTokens = usage.output_tokens ?? 0;
|
|
1472
1793
|
}
|
|
1473
1794
|
}
|
|
@@ -1476,11 +1797,7 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1476
1797
|
contentParts.push({ type: "text", text: textAccum });
|
|
1477
1798
|
}
|
|
1478
1799
|
for (const [, tc] of toolCalls) {
|
|
1479
|
-
|
|
1480
|
-
try {
|
|
1481
|
-
args = JSON.parse(tc.argsJson);
|
|
1482
|
-
} catch {
|
|
1483
|
-
}
|
|
1800
|
+
const args = parseToolArguments2(tc.argsJson);
|
|
1484
1801
|
const toolCall = {
|
|
1485
1802
|
type: "tool_call",
|
|
1486
1803
|
id: tc.id,
|
|
@@ -1497,7 +1814,7 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1497
1814
|
content: contentParts.length > 0 ? contentParts : textAccum || ""
|
|
1498
1815
|
},
|
|
1499
1816
|
stopReason,
|
|
1500
|
-
usage: { inputTokens, outputTokens }
|
|
1817
|
+
usage: { inputTokens, outputTokens, ...cacheRead > 0 && { cacheRead } }
|
|
1501
1818
|
};
|
|
1502
1819
|
yield { type: "done", stopReason };
|
|
1503
1820
|
return streamResponse;
|
|
@@ -1639,6 +1956,24 @@ function toCodexTools(tools) {
|
|
|
1639
1956
|
strict: null
|
|
1640
1957
|
}));
|
|
1641
1958
|
}
|
|
1959
|
+
function extractCodexRequestId(message) {
|
|
1960
|
+
const match = message.match(/request ID ([a-z0-9-]{8,})/i);
|
|
1961
|
+
return match?.[1];
|
|
1962
|
+
}
|
|
1963
|
+
function parseCodexErrorBody(text) {
|
|
1964
|
+
if (!text) return {};
|
|
1965
|
+
try {
|
|
1966
|
+
const parsed = JSON.parse(text);
|
|
1967
|
+
const error = parsed.error;
|
|
1968
|
+
const detail = parsed.detail;
|
|
1969
|
+
const message = error?.message ?? parsed.message ?? (typeof detail === "string" ? detail : void 0);
|
|
1970
|
+
const requestId = parsed.request_id ?? error?.request_id ?? (message ? extractCodexRequestId(message) : void 0);
|
|
1971
|
+
return { ...message ? { message } : {}, ...requestId ? { requestId } : {} };
|
|
1972
|
+
} catch {
|
|
1973
|
+
const trimmed = text.trim().slice(0, 240);
|
|
1974
|
+
return trimmed ? { message: trimmed } : {};
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1642
1977
|
|
|
1643
1978
|
// src/provider-registry.ts
|
|
1644
1979
|
var ProviderRegistryImpl = class {
|
|
@@ -1899,12 +2234,15 @@ function registerPalsuProvider(config) {
|
|
|
1899
2234
|
EventStream,
|
|
1900
2235
|
ProviderError,
|
|
1901
2236
|
StreamResult,
|
|
2237
|
+
formatError,
|
|
2238
|
+
formatErrorForDisplay,
|
|
1902
2239
|
palsuAssistantMessage,
|
|
1903
2240
|
palsuText,
|
|
1904
2241
|
palsuThinking,
|
|
1905
2242
|
palsuToolCall,
|
|
1906
2243
|
providerRegistry,
|
|
1907
2244
|
registerPalsuProvider,
|
|
2245
|
+
setProviderDiagnostic,
|
|
1908
2246
|
stream
|
|
1909
2247
|
});
|
|
1910
2248
|
//# sourceMappingURL=index.cjs.map
|