@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.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,9 @@ 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
|
+
}
|
|
561
724
|
function createClient(options) {
|
|
562
725
|
const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
|
|
563
726
|
return new Anthropic({
|
|
@@ -570,7 +733,10 @@ function createClient(options) {
|
|
|
570
733
|
maxRetries: 2,
|
|
571
734
|
...isOAuth ? {
|
|
572
735
|
defaultHeaders: {
|
|
573
|
-
|
|
736
|
+
// Anthropic's OAuth edge validates the claude-cli version. Callers
|
|
737
|
+
// (ezcoder) resolve the live version at runtime; the literal here
|
|
738
|
+
// is the offline fallback for direct gg-ai consumers.
|
|
739
|
+
"user-agent": options.userAgent ?? "claude-cli/2.1.75 (external, cli)",
|
|
574
740
|
"x-app": "cli"
|
|
575
741
|
}
|
|
576
742
|
} : {}
|
|
@@ -584,6 +750,7 @@ async function* runStream(options) {
|
|
|
584
750
|
const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
|
|
585
751
|
const useStreaming = options.streaming !== false;
|
|
586
752
|
const cacheControl = toAnthropicCacheControl(options.cacheRetention, options.baseUrl);
|
|
753
|
+
const supportsFirstPartyToolExtras = !options.baseUrl || options.baseUrl.includes("api.anthropic.com");
|
|
587
754
|
const downgradedMessages = downgradeUnsupportedImages(options.messages, options.supportsImages);
|
|
588
755
|
const { system: rawSystem, messages } = toAnthropicMessages(downgradedMessages, cacheControl);
|
|
589
756
|
const system = isOAuth ? [
|
|
@@ -614,13 +781,28 @@ async function* runStream(options) {
|
|
|
614
781
|
...options.temperature != null && !thinking ? { temperature: options.temperature } : {},
|
|
615
782
|
...options.topP != null ? { top_p: options.topP } : {},
|
|
616
783
|
...options.stop ? { stop_sequences: options.stop } : {},
|
|
617
|
-
...options.tools?.length || options.serverTools?.length || options.webSearch ? {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
784
|
+
...options.tools?.length || options.serverTools?.length || options.webSearch ? (() => {
|
|
785
|
+
const reservedServerNames = /* @__PURE__ */ new Set();
|
|
786
|
+
if (options.webSearch) reservedServerNames.add("web_search");
|
|
787
|
+
for (const t of options.serverTools ?? []) {
|
|
788
|
+
const name = t.name;
|
|
789
|
+
if (name) reservedServerNames.add(name);
|
|
790
|
+
}
|
|
791
|
+
const clientTools = options.tools?.length ? toAnthropicTools(
|
|
792
|
+
options.tools.filter((t) => !reservedServerNames.has(t.name)),
|
|
793
|
+
{
|
|
794
|
+
...supportsFirstPartyToolExtras && cacheControl ? { cacheControl } : {},
|
|
795
|
+
...supportsFirstPartyToolExtras ? { enableFineGrainedToolStreaming: true } : {}
|
|
796
|
+
}
|
|
797
|
+
) : [];
|
|
798
|
+
return {
|
|
799
|
+
tools: [
|
|
800
|
+
...clientTools,
|
|
801
|
+
...options.serverTools ?? [],
|
|
802
|
+
...options.webSearch ? [{ type: "web_search_20250305", name: "web_search" }] : []
|
|
803
|
+
]
|
|
804
|
+
};
|
|
805
|
+
})() : {},
|
|
624
806
|
...options.toolChoice && options.tools?.length ? { tool_choice: toAnthropicToolChoice(options.toolChoice) } : {},
|
|
625
807
|
...(() => {
|
|
626
808
|
const contextEdits = [
|
|
@@ -697,6 +879,7 @@ async function* runStream(options) {
|
|
|
697
879
|
if (block.type === "tool_use") {
|
|
698
880
|
accum.toolId = block.id;
|
|
699
881
|
accum.toolName = block.name;
|
|
882
|
+
accum.input = block.input;
|
|
700
883
|
} else if (block.type === "server_tool_use") {
|
|
701
884
|
accum.toolId = block.id;
|
|
702
885
|
accum.toolName = block.name;
|
|
@@ -705,7 +888,11 @@ async function* runStream(options) {
|
|
|
705
888
|
accum.raw = block;
|
|
706
889
|
}
|
|
707
890
|
blocks.set(idx, accum);
|
|
708
|
-
|
|
891
|
+
if (block.type === "thinking") {
|
|
892
|
+
yield { type: "thinking_delta", text: "" };
|
|
893
|
+
} else {
|
|
894
|
+
yield keepalive;
|
|
895
|
+
}
|
|
709
896
|
break;
|
|
710
897
|
}
|
|
711
898
|
case "content_block_delta": {
|
|
@@ -748,10 +935,13 @@ async function* runStream(options) {
|
|
|
748
935
|
});
|
|
749
936
|
yield keepalive;
|
|
750
937
|
} else if (accum.type === "tool_use") {
|
|
751
|
-
let args = {};
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
938
|
+
let args = isJsonObject(accum.input) ? accum.input : {};
|
|
939
|
+
if (accum.argsJson) {
|
|
940
|
+
try {
|
|
941
|
+
const parsed = JSON.parse(accum.argsJson);
|
|
942
|
+
args = isJsonObject(parsed) ? parsed : {};
|
|
943
|
+
} catch {
|
|
944
|
+
}
|
|
755
945
|
}
|
|
756
946
|
const tc = {
|
|
757
947
|
type: "tool_call",
|
|
@@ -949,8 +1139,15 @@ function messageToResponse(message) {
|
|
|
949
1139
|
}
|
|
950
1140
|
function toError(err) {
|
|
951
1141
|
if (err instanceof Anthropic.APIError) {
|
|
952
|
-
|
|
1142
|
+
const errorBody = err.error;
|
|
1143
|
+
const nestedError = errorBody?.error;
|
|
1144
|
+
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;
|
|
1145
|
+
const bodyMessage = typeof nestedError?.message === "string" ? nestedError.message : typeof errorBody?.message === "string" ? errorBody.message : void 0;
|
|
1146
|
+
const bodyType = typeof nestedError?.type === "string" ? nestedError.type : typeof errorBody?.type === "string" ? errorBody.type : typeof err.type === "string" ? err.type : void 0;
|
|
1147
|
+
const message = bodyType && bodyMessage ? `${bodyType}: ${bodyMessage}` : bodyMessage ?? err.message;
|
|
1148
|
+
return new ProviderError("anthropic", message, {
|
|
953
1149
|
statusCode: err.status,
|
|
1150
|
+
...requestId ? { requestId } : {},
|
|
954
1151
|
cause: err
|
|
955
1152
|
});
|
|
956
1153
|
}
|
|
@@ -962,6 +1159,38 @@ function toError(err) {
|
|
|
962
1159
|
|
|
963
1160
|
// src/providers/openai.ts
|
|
964
1161
|
import OpenAI from "openai";
|
|
1162
|
+
|
|
1163
|
+
// src/providers/prompt-cache-key.ts
|
|
1164
|
+
var MAX_PROMPT_CACHE_KEY_LENGTH = 64;
|
|
1165
|
+
function normalizePromptCacheKey(key) {
|
|
1166
|
+
if (key.length <= MAX_PROMPT_CACHE_KEY_LENGTH) return key;
|
|
1167
|
+
const hash = fnv1aHash(key);
|
|
1168
|
+
const prefixLength = MAX_PROMPT_CACHE_KEY_LENGTH - hash.length - 1;
|
|
1169
|
+
return `${key.slice(0, prefixLength)}:${hash}`;
|
|
1170
|
+
}
|
|
1171
|
+
function fnv1aHash(value) {
|
|
1172
|
+
let hash = 2166136261;
|
|
1173
|
+
for (let index = 0; index < value.length; index++) {
|
|
1174
|
+
hash ^= value.charCodeAt(index);
|
|
1175
|
+
hash = Math.imul(hash, 16777619);
|
|
1176
|
+
}
|
|
1177
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
// src/providers/openai.ts
|
|
1181
|
+
function isJsonObject2(value) {
|
|
1182
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
1183
|
+
}
|
|
1184
|
+
function parseToolArguments(argsJson) {
|
|
1185
|
+
if (!argsJson) return {};
|
|
1186
|
+
try {
|
|
1187
|
+
const parsed = JSON.parse(argsJson);
|
|
1188
|
+
const unwrapped = typeof parsed === "string" ? JSON.parse(parsed) : parsed;
|
|
1189
|
+
return isJsonObject2(unwrapped) ? unwrapped : {};
|
|
1190
|
+
} catch {
|
|
1191
|
+
return {};
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
965
1194
|
function createClient2(options) {
|
|
966
1195
|
return new OpenAI({
|
|
967
1196
|
apiKey: options.apiKey,
|
|
@@ -993,19 +1222,22 @@ async function* runStream2(options) {
|
|
|
993
1222
|
...effectiveTemp != null && !options.thinking ? { temperature: effectiveTemp } : {},
|
|
994
1223
|
...options.topP != null ? { top_p: options.topP } : {},
|
|
995
1224
|
...options.stop ? { stop: options.stop } : {},
|
|
996
|
-
...options.thinking && !usesThinkingParam ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking) } : {},
|
|
1225
|
+
...options.thinking && !usesThinkingParam ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
|
|
997
1226
|
...options.tools?.length ? { tools: toOpenAITools(options.tools) } : {},
|
|
998
1227
|
...options.toolChoice && options.tools?.length ? { tool_choice: toOpenAIToolChoice(options.toolChoice) } : {},
|
|
999
1228
|
...useStreaming ? { stream_options: { include_usage: true } } : {}
|
|
1000
1229
|
};
|
|
1001
1230
|
if (options.provider === "openai" || options.provider === "moonshot") {
|
|
1002
1231
|
const paramsAny = params;
|
|
1003
|
-
paramsAny.prompt_cache_key = "ezcoder";
|
|
1232
|
+
paramsAny.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ezcoder");
|
|
1004
1233
|
const retention = options.cacheRetention ?? "short";
|
|
1005
1234
|
if (retention === "long") {
|
|
1006
1235
|
paramsAny.prompt_cache_retention = "24h";
|
|
1007
1236
|
}
|
|
1008
1237
|
}
|
|
1238
|
+
if (options.provider === "openai" && options.serviceTier) {
|
|
1239
|
+
params.service_tier = options.serviceTier;
|
|
1240
|
+
}
|
|
1009
1241
|
if (usesThinkingParam) {
|
|
1010
1242
|
if (options.thinking) {
|
|
1011
1243
|
params.thinking = { type: "enabled" };
|
|
@@ -1063,6 +1295,9 @@ async function* runStream2(options) {
|
|
|
1063
1295
|
if (!cacheRead && typeof usageAny.cached_tokens === "number" && usageAny.cached_tokens > 0) {
|
|
1064
1296
|
cacheRead = usageAny.cached_tokens;
|
|
1065
1297
|
}
|
|
1298
|
+
if (!cacheRead && typeof usageAny.prompt_cache_hit_tokens === "number" && usageAny.prompt_cache_hit_tokens > 0) {
|
|
1299
|
+
cacheRead = usageAny.prompt_cache_hit_tokens;
|
|
1300
|
+
}
|
|
1066
1301
|
inputTokens = chunk.usage.prompt_tokens - cacheRead;
|
|
1067
1302
|
}
|
|
1068
1303
|
if (!choice) continue;
|
|
@@ -1113,11 +1348,7 @@ async function* runStream2(options) {
|
|
|
1113
1348
|
contentParts.push({ type: "text", text: textAccum });
|
|
1114
1349
|
}
|
|
1115
1350
|
for (const [, tc] of toolCallAccum) {
|
|
1116
|
-
|
|
1117
|
-
try {
|
|
1118
|
-
args = JSON.parse(tc.argsJson);
|
|
1119
|
-
} catch {
|
|
1120
|
-
}
|
|
1351
|
+
const args = parseToolArguments(tc.argsJson);
|
|
1121
1352
|
const toolCall = {
|
|
1122
1353
|
type: "tool_call",
|
|
1123
1354
|
id: tc.id,
|
|
@@ -1170,11 +1401,7 @@ function* synthesizeEventsFromCompletion(completion, thinkingEnabled) {
|
|
|
1170
1401
|
argsJson
|
|
1171
1402
|
};
|
|
1172
1403
|
}
|
|
1173
|
-
|
|
1174
|
-
try {
|
|
1175
|
-
args = JSON.parse(argsJson);
|
|
1176
|
-
} catch {
|
|
1177
|
-
}
|
|
1404
|
+
const args = parseToolArguments(argsJson);
|
|
1178
1405
|
yield {
|
|
1179
1406
|
type: "toolcall_done",
|
|
1180
1407
|
id: tc.id,
|
|
@@ -1202,11 +1429,7 @@ function completionToResponse(completion) {
|
|
|
1202
1429
|
const toolCalls = msg.tool_calls;
|
|
1203
1430
|
if (toolCalls) {
|
|
1204
1431
|
for (const tc of toolCalls) {
|
|
1205
|
-
|
|
1206
|
-
try {
|
|
1207
|
-
args = JSON.parse(tc.function?.arguments ?? "{}");
|
|
1208
|
-
} catch {
|
|
1209
|
-
}
|
|
1432
|
+
const args = parseToolArguments(tc.function?.arguments ?? "");
|
|
1210
1433
|
const toolCall = {
|
|
1211
1434
|
type: "tool_call",
|
|
1212
1435
|
id: tc.id,
|
|
@@ -1228,6 +1451,9 @@ function completionToResponse(completion) {
|
|
|
1228
1451
|
if (!cacheRead && typeof usageAny.cached_tokens === "number" && usageAny.cached_tokens > 0) {
|
|
1229
1452
|
cacheRead = usageAny.cached_tokens;
|
|
1230
1453
|
}
|
|
1454
|
+
if (!cacheRead && typeof usageAny.prompt_cache_hit_tokens === "number" && usageAny.prompt_cache_hit_tokens > 0) {
|
|
1455
|
+
cacheRead = usageAny.prompt_cache_hit_tokens;
|
|
1456
|
+
}
|
|
1231
1457
|
inputTokens = completion.usage.prompt_tokens - cacheRead;
|
|
1232
1458
|
}
|
|
1233
1459
|
const stopReason = normalizeOpenAIStopReason(choice?.finish_reason ?? null);
|
|
@@ -1242,19 +1468,19 @@ function completionToResponse(completion) {
|
|
|
1242
1468
|
}
|
|
1243
1469
|
function toError2(err, provider = "openai") {
|
|
1244
1470
|
if (err instanceof OpenAI.APIError) {
|
|
1245
|
-
let msg = err.message;
|
|
1246
1471
|
const body = err.error;
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
return new ProviderError(provider, msg, {
|
|
1472
|
+
const bodyMessage = typeof body?.message === "string" && body.message.trim() ? body.message.trim() : void 0;
|
|
1473
|
+
const modelName = typeof body?.model === "string" ? body.model : "";
|
|
1474
|
+
const cleanMessage = bodyMessage ?? err.message;
|
|
1475
|
+
let hint;
|
|
1476
|
+
if (modelName === "codex-mini-latest" || cleanMessage.includes("codex-mini-latest")) {
|
|
1477
|
+
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.";
|
|
1478
|
+
}
|
|
1479
|
+
const requestId = err.request_id ?? (typeof body?.request_id === "string" ? body.request_id : void 0);
|
|
1480
|
+
return new ProviderError(provider, cleanMessage, {
|
|
1257
1481
|
statusCode: err.status,
|
|
1482
|
+
...requestId ? { requestId } : {},
|
|
1483
|
+
...hint ? { hint } : {},
|
|
1258
1484
|
cause: err
|
|
1259
1485
|
});
|
|
1260
1486
|
}
|
|
@@ -1266,7 +1492,34 @@ function toError2(err, provider = "openai") {
|
|
|
1266
1492
|
|
|
1267
1493
|
// src/providers/openai-codex.ts
|
|
1268
1494
|
import os from "os";
|
|
1495
|
+
|
|
1496
|
+
// src/utils/diag.ts
|
|
1497
|
+
var _diagFn = null;
|
|
1498
|
+
function setProviderDiagnostic(fn) {
|
|
1499
|
+
_diagFn = fn;
|
|
1500
|
+
}
|
|
1501
|
+
function providerDiag(phase, data) {
|
|
1502
|
+
_diagFn?.(phase, data);
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
// src/providers/openai-codex.ts
|
|
1269
1506
|
var DEFAULT_BASE_URL = "https://chatgpt.com/backend-api";
|
|
1507
|
+
function isJsonObject3(value) {
|
|
1508
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
1509
|
+
}
|
|
1510
|
+
function parseToolArguments2(argsJson) {
|
|
1511
|
+
if (!argsJson) return {};
|
|
1512
|
+
try {
|
|
1513
|
+
const parsed = JSON.parse(argsJson);
|
|
1514
|
+
const unwrapped = typeof parsed === "string" ? JSON.parse(parsed) : parsed;
|
|
1515
|
+
return isJsonObject3(unwrapped) ? unwrapped : {};
|
|
1516
|
+
} catch {
|
|
1517
|
+
return {};
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
function outputTextKey(itemId, contentIndex) {
|
|
1521
|
+
return `${itemId ?? ""}:${contentIndex ?? 0}`;
|
|
1522
|
+
}
|
|
1270
1523
|
function streamOpenAICodex(options) {
|
|
1271
1524
|
return new StreamResult(runStream3(options));
|
|
1272
1525
|
}
|
|
@@ -1288,15 +1541,17 @@ async function* runStream3(options) {
|
|
|
1288
1541
|
if (options.tools?.length) {
|
|
1289
1542
|
body.tools = toCodexTools(options.tools);
|
|
1290
1543
|
}
|
|
1544
|
+
body.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ezcoder");
|
|
1545
|
+
if (options.cacheRetention === "long") {
|
|
1546
|
+
body.prompt_cache_retention = "24h";
|
|
1547
|
+
}
|
|
1291
1548
|
if (options.temperature != null && !options.thinking) {
|
|
1292
1549
|
body.temperature = options.temperature;
|
|
1293
1550
|
}
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
};
|
|
1299
|
-
}
|
|
1551
|
+
body.reasoning = {
|
|
1552
|
+
effort: options.thinking ?? "none",
|
|
1553
|
+
summary: "auto"
|
|
1554
|
+
};
|
|
1300
1555
|
const headers = {
|
|
1301
1556
|
"Content-Type": "application/json",
|
|
1302
1557
|
Accept: "text/event-stream",
|
|
@@ -1308,6 +1563,11 @@ async function* runStream3(options) {
|
|
|
1308
1563
|
if (options.accountId) {
|
|
1309
1564
|
headers["chatgpt-account-id"] = options.accountId;
|
|
1310
1565
|
}
|
|
1566
|
+
const cacheScopeId = body.prompt_cache_key;
|
|
1567
|
+
if (cacheScopeId) {
|
|
1568
|
+
headers["session_id"] = cacheScopeId;
|
|
1569
|
+
headers["x-client-request-id"] = cacheScopeId;
|
|
1570
|
+
}
|
|
1311
1571
|
const response = await fetch(url, {
|
|
1312
1572
|
method: "POST",
|
|
1313
1573
|
headers,
|
|
@@ -1316,19 +1576,23 @@ async function* runStream3(options) {
|
|
|
1316
1576
|
});
|
|
1317
1577
|
if (!response.ok) {
|
|
1318
1578
|
const text = await response.text().catch(() => "");
|
|
1319
|
-
|
|
1579
|
+
const parsed = parseCodexErrorBody(text);
|
|
1580
|
+
const message = parsed.message ?? `Codex API returned HTTP ${response.status}.`;
|
|
1581
|
+
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;
|
|
1582
|
+
let hint;
|
|
1320
1583
|
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.`;
|
|
1584
|
+
if (options.model === "gpt-5.5-pro") {
|
|
1585
|
+
hint = "Use gpt-5.5 instead. OpenAI's Codex model catalog does not list gpt-5.5-pro.";
|
|
1586
|
+
} else {
|
|
1587
|
+
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.";
|
|
1588
|
+
}
|
|
1589
|
+
} else if (response.status === 404 && text.includes("does not exist")) {
|
|
1590
|
+
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
1591
|
}
|
|
1330
1592
|
throw new ProviderError("openai", message, {
|
|
1331
|
-
statusCode: response.status
|
|
1593
|
+
statusCode: response.status,
|
|
1594
|
+
...requestId ? { requestId } : {},
|
|
1595
|
+
...hint ? { hint } : {}
|
|
1332
1596
|
});
|
|
1333
1597
|
}
|
|
1334
1598
|
if (!response.body) {
|
|
@@ -1337,27 +1601,84 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1337
1601
|
const contentParts = [];
|
|
1338
1602
|
let textAccum = "";
|
|
1339
1603
|
const toolCalls = /* @__PURE__ */ new Map();
|
|
1604
|
+
const outputItemTypes = /* @__PURE__ */ new Map();
|
|
1605
|
+
const outputTextByPart = /* @__PURE__ */ new Map();
|
|
1340
1606
|
let inputTokens = 0;
|
|
1341
1607
|
let outputTokens = 0;
|
|
1608
|
+
let cacheRead = 0;
|
|
1609
|
+
const diagStart = Date.now();
|
|
1610
|
+
const diagSeen = /* @__PURE__ */ new Set();
|
|
1342
1611
|
for await (const event of parseSSE(response.body)) {
|
|
1343
1612
|
const type = event.type;
|
|
1344
1613
|
if (!type) continue;
|
|
1614
|
+
if (!diagSeen.has(type)) {
|
|
1615
|
+
diagSeen.add(type);
|
|
1616
|
+
providerDiag("codex_event_first", { type, sinceStartMs: Date.now() - diagStart });
|
|
1617
|
+
}
|
|
1345
1618
|
if (type === "error") {
|
|
1346
|
-
const
|
|
1347
|
-
|
|
1619
|
+
const nested = event.error ?? void 0;
|
|
1620
|
+
const message = nested?.message ?? event.message ?? "Codex stream emitted an error chunk without a message.";
|
|
1621
|
+
const code = nested?.code ?? nested?.type ?? event.code ?? "server_error";
|
|
1622
|
+
const requestId = extractCodexRequestId(message) ?? event.request_id;
|
|
1623
|
+
throw new ProviderError("openai", message, {
|
|
1624
|
+
...requestId != null ? { requestId } : {},
|
|
1625
|
+
...code === "server_error" ? { statusCode: 500 } : {}
|
|
1626
|
+
});
|
|
1348
1627
|
}
|
|
1349
1628
|
if (type === "response.failed") {
|
|
1350
|
-
const
|
|
1351
|
-
|
|
1629
|
+
const nested = event.error;
|
|
1630
|
+
const message = nested?.message ?? "Codex response failed.";
|
|
1631
|
+
const requestId = extractCodexRequestId(message) ?? event.request_id;
|
|
1632
|
+
throw new ProviderError("openai", message, {
|
|
1633
|
+
...requestId != null ? { requestId } : {}
|
|
1634
|
+
});
|
|
1352
1635
|
}
|
|
1353
1636
|
if (type === "response.output_text.delta") {
|
|
1354
1637
|
const delta = event.delta;
|
|
1355
|
-
|
|
1356
|
-
|
|
1638
|
+
const itemId = event.item_id;
|
|
1639
|
+
const contentIndex = event.content_index;
|
|
1640
|
+
const key = outputTextKey(itemId, contentIndex);
|
|
1641
|
+
outputTextByPart.set(key, `${outputTextByPart.get(key) ?? ""}${delta}`);
|
|
1642
|
+
if (itemId && outputItemTypes.get(itemId) === "reasoning") {
|
|
1643
|
+
if (options.thinking) yield { type: "thinking_delta", text: delta };
|
|
1644
|
+
} else {
|
|
1645
|
+
textAccum += delta;
|
|
1646
|
+
yield { type: "text_delta", text: delta };
|
|
1647
|
+
}
|
|
1357
1648
|
}
|
|
1358
|
-
if (type === "response.
|
|
1649
|
+
if (type === "response.output_text.done") {
|
|
1650
|
+
const fullText = event.text;
|
|
1651
|
+
if (fullText) {
|
|
1652
|
+
const itemId = event.item_id;
|
|
1653
|
+
const contentIndex = event.content_index;
|
|
1654
|
+
const key = outputTextKey(itemId, contentIndex);
|
|
1655
|
+
const streamedText = outputTextByPart.get(key) ?? "";
|
|
1656
|
+
const missingText = streamedText ? fullText.slice(streamedText.length) : fullText;
|
|
1657
|
+
outputTextByPart.set(key, fullText);
|
|
1658
|
+
if (missingText && fullText.startsWith(streamedText)) {
|
|
1659
|
+
if (itemId && outputItemTypes.get(itemId) === "reasoning") {
|
|
1660
|
+
if (options.thinking) yield { type: "thinking_delta", text: missingText };
|
|
1661
|
+
} else {
|
|
1662
|
+
textAccum += missingText;
|
|
1663
|
+
yield { type: "text_delta", text: missingText };
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
if (type === "response.reasoning_summary_text.delta" || type === "response.reasoning_summary.delta" || type === "response.reasoning_text.delta" || type === "response.reasoning.delta") {
|
|
1359
1669
|
const delta = event.delta;
|
|
1360
|
-
yield { type: "thinking_delta", text: delta };
|
|
1670
|
+
if (options.thinking) yield { type: "thinking_delta", text: delta };
|
|
1671
|
+
}
|
|
1672
|
+
if (type === "response.output_item.added") {
|
|
1673
|
+
const item = event.item;
|
|
1674
|
+
const itemId = item?.id;
|
|
1675
|
+
const itemType = item?.type;
|
|
1676
|
+
if (itemId && itemType) {
|
|
1677
|
+
outputItemTypes.set(itemId, itemType);
|
|
1678
|
+
}
|
|
1679
|
+
if (itemType === "reasoning" && options.thinking) {
|
|
1680
|
+
yield { type: "thinking_delta", text: "" };
|
|
1681
|
+
}
|
|
1361
1682
|
}
|
|
1362
1683
|
if (type === "response.output_item.added") {
|
|
1363
1684
|
const item = event.item;
|
|
@@ -1403,11 +1724,7 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1403
1724
|
const id = `${callId}|${itemId}`;
|
|
1404
1725
|
const tc = toolCalls.get(id);
|
|
1405
1726
|
if (tc) {
|
|
1406
|
-
|
|
1407
|
-
try {
|
|
1408
|
-
args = JSON.parse(tc.argsJson);
|
|
1409
|
-
} catch {
|
|
1410
|
-
}
|
|
1727
|
+
const args = parseToolArguments2(tc.argsJson);
|
|
1411
1728
|
yield {
|
|
1412
1729
|
type: "toolcall_done",
|
|
1413
1730
|
id: tc.id,
|
|
@@ -1421,7 +1738,8 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1421
1738
|
const resp = event.response;
|
|
1422
1739
|
const usage = resp?.usage;
|
|
1423
1740
|
if (usage) {
|
|
1424
|
-
|
|
1741
|
+
cacheRead = usage.input_tokens_details?.cached_tokens ?? 0;
|
|
1742
|
+
inputTokens = (usage.input_tokens ?? 0) - cacheRead;
|
|
1425
1743
|
outputTokens = usage.output_tokens ?? 0;
|
|
1426
1744
|
}
|
|
1427
1745
|
}
|
|
@@ -1430,11 +1748,7 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1430
1748
|
contentParts.push({ type: "text", text: textAccum });
|
|
1431
1749
|
}
|
|
1432
1750
|
for (const [, tc] of toolCalls) {
|
|
1433
|
-
|
|
1434
|
-
try {
|
|
1435
|
-
args = JSON.parse(tc.argsJson);
|
|
1436
|
-
} catch {
|
|
1437
|
-
}
|
|
1751
|
+
const args = parseToolArguments2(tc.argsJson);
|
|
1438
1752
|
const toolCall = {
|
|
1439
1753
|
type: "tool_call",
|
|
1440
1754
|
id: tc.id,
|
|
@@ -1451,7 +1765,7 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1451
1765
|
content: contentParts.length > 0 ? contentParts : textAccum || ""
|
|
1452
1766
|
},
|
|
1453
1767
|
stopReason,
|
|
1454
|
-
usage: { inputTokens, outputTokens }
|
|
1768
|
+
usage: { inputTokens, outputTokens, ...cacheRead > 0 && { cacheRead } }
|
|
1455
1769
|
};
|
|
1456
1770
|
yield { type: "done", stopReason };
|
|
1457
1771
|
return streamResponse;
|
|
@@ -1593,6 +1907,24 @@ function toCodexTools(tools) {
|
|
|
1593
1907
|
strict: null
|
|
1594
1908
|
}));
|
|
1595
1909
|
}
|
|
1910
|
+
function extractCodexRequestId(message) {
|
|
1911
|
+
const match = message.match(/request ID ([a-z0-9-]{8,})/i);
|
|
1912
|
+
return match?.[1];
|
|
1913
|
+
}
|
|
1914
|
+
function parseCodexErrorBody(text) {
|
|
1915
|
+
if (!text) return {};
|
|
1916
|
+
try {
|
|
1917
|
+
const parsed = JSON.parse(text);
|
|
1918
|
+
const error = parsed.error;
|
|
1919
|
+
const detail = parsed.detail;
|
|
1920
|
+
const message = error?.message ?? parsed.message ?? (typeof detail === "string" ? detail : void 0);
|
|
1921
|
+
const requestId = parsed.request_id ?? error?.request_id ?? (message ? extractCodexRequestId(message) : void 0);
|
|
1922
|
+
return { ...message ? { message } : {}, ...requestId ? { requestId } : {} };
|
|
1923
|
+
} catch {
|
|
1924
|
+
const trimmed = text.trim().slice(0, 240);
|
|
1925
|
+
return trimmed ? { message: trimmed } : {};
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1596
1928
|
|
|
1597
1929
|
// src/provider-registry.ts
|
|
1598
1930
|
var ProviderRegistryImpl = class {
|
|
@@ -1852,12 +2184,15 @@ export {
|
|
|
1852
2184
|
EventStream,
|
|
1853
2185
|
ProviderError,
|
|
1854
2186
|
StreamResult,
|
|
2187
|
+
formatError,
|
|
2188
|
+
formatErrorForDisplay,
|
|
1855
2189
|
palsuAssistantMessage,
|
|
1856
2190
|
palsuText,
|
|
1857
2191
|
palsuThinking,
|
|
1858
2192
|
palsuToolCall,
|
|
1859
2193
|
providerRegistry,
|
|
1860
2194
|
registerPalsuProvider,
|
|
2195
|
+
setProviderDiagnostic,
|
|
1861
2196
|
stream
|
|
1862
2197
|
};
|
|
1863
2198
|
//# sourceMappingURL=index.js.map
|