@kenkaiiii/gg-ai 4.3.165 → 4.3.166
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 +204 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +59 -2
- package/dist/index.d.ts +59 -2
- package/dist/index.js +202 -27
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -292,17 +292,74 @@ declare class ProviderRegistryImpl {
|
|
|
292
292
|
/** Global provider registry. Import this to register custom providers. */
|
|
293
293
|
declare const providerRegistry: ProviderRegistryImpl;
|
|
294
294
|
|
|
295
|
+
/**
|
|
296
|
+
* Error model for gg-ai and downstream consumers.
|
|
297
|
+
*
|
|
298
|
+
* Every error users see should answer one question: "is this me or them?"
|
|
299
|
+
* That answer drives whether they retry, switch model, log in, or report a
|
|
300
|
+
* ggcoder bug. The `FormattedError` shape captures it in plain English:
|
|
301
|
+
*
|
|
302
|
+
* ✗ OpenAI returned an error.
|
|
303
|
+
* An error occurred while processing your request...
|
|
304
|
+
* → This is an OpenAI issue, not ggcoder. Retry — if it persists, check status.openai.com.
|
|
305
|
+
*
|
|
306
|
+
* ✗ ggcoder hit an unexpected error.
|
|
307
|
+
* Cannot read property 'foo' of undefined
|
|
308
|
+
* → This is a ggcoder bug — please report it.
|
|
309
|
+
*/
|
|
310
|
+
type ErrorSource = "provider" | "ggcoder" | "network" | "auth";
|
|
311
|
+
interface FormattedError {
|
|
312
|
+
/** Plain-English headline, e.g. "OpenAI returned an error." */
|
|
313
|
+
headline: string;
|
|
314
|
+
/** Machine-readable classification. */
|
|
315
|
+
source: ErrorSource;
|
|
316
|
+
/** Detailed message body from the underlying error (no JSON, no tag prefix). */
|
|
317
|
+
message: string;
|
|
318
|
+
/** Action line — tells the user whether to retry, switch model, log in, or report a bug. */
|
|
319
|
+
guidance: string;
|
|
320
|
+
/** Provider name when source === "provider". */
|
|
321
|
+
provider?: string;
|
|
322
|
+
/** HTTP status code if known. */
|
|
323
|
+
statusCode?: number;
|
|
324
|
+
/** Provider request ID, kept for telemetry / debug — not shown by default. */
|
|
325
|
+
requestId?: string;
|
|
326
|
+
}
|
|
295
327
|
declare class GGAIError extends Error {
|
|
296
|
-
|
|
328
|
+
readonly source: ErrorSource;
|
|
329
|
+
readonly requestId?: string;
|
|
330
|
+
readonly hint?: string;
|
|
331
|
+
constructor(message: string, options?: {
|
|
332
|
+
source?: ErrorSource;
|
|
333
|
+
requestId?: string;
|
|
334
|
+
hint?: string;
|
|
335
|
+
cause?: unknown;
|
|
336
|
+
});
|
|
297
337
|
}
|
|
298
338
|
declare class ProviderError extends GGAIError {
|
|
299
339
|
readonly provider: string;
|
|
300
340
|
readonly statusCode?: number;
|
|
301
341
|
constructor(provider: string, message: string, options?: {
|
|
302
342
|
statusCode?: number;
|
|
343
|
+
requestId?: string;
|
|
344
|
+
hint?: string;
|
|
303
345
|
cause?: unknown;
|
|
304
346
|
});
|
|
305
347
|
}
|
|
348
|
+
/**
|
|
349
|
+
* Normalise any thrown value into a structured display object. Always returns
|
|
350
|
+
* a non-empty `headline` and `guidance` so the UI never has to second-guess
|
|
351
|
+
* what to show the user.
|
|
352
|
+
*/
|
|
353
|
+
declare function formatError(err: unknown): FormattedError;
|
|
354
|
+
/**
|
|
355
|
+
* Render a FormattedError as a multi-line string for terminal display.
|
|
356
|
+
*
|
|
357
|
+
* Format:
|
|
358
|
+
* <headline>
|
|
359
|
+
* <message>
|
|
360
|
+
* → <guidance>
|
|
361
|
+
*/
|
|
362
|
+
declare function formatErrorForDisplay(err: unknown): string;
|
|
306
363
|
|
|
307
364
|
interface PalsuProviderState {
|
|
308
365
|
callCount: number;
|
|
@@ -373,4 +430,4 @@ interface PalsuProviderConfig {
|
|
|
373
430
|
*/
|
|
374
431
|
declare function registerPalsuProvider(config?: PalsuProviderConfig): PalsuProviderHandle;
|
|
375
432
|
|
|
376
|
-
export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, type ErrorEvent, EventStream, GGAIError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderEntry, ProviderError, type ProviderStreamFn, type RawContent, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, providerRegistry, registerPalsuProvider, stream };
|
|
433
|
+
export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, type ErrorEvent, type ErrorSource, EventStream, type FormattedError, GGAIError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderEntry, ProviderError, type ProviderStreamFn, type RawContent, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, formatError, formatErrorForDisplay, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, providerRegistry, registerPalsuProvider, stream };
|
package/dist/index.d.ts
CHANGED
|
@@ -292,17 +292,74 @@ declare class ProviderRegistryImpl {
|
|
|
292
292
|
/** Global provider registry. Import this to register custom providers. */
|
|
293
293
|
declare const providerRegistry: ProviderRegistryImpl;
|
|
294
294
|
|
|
295
|
+
/**
|
|
296
|
+
* Error model for gg-ai and downstream consumers.
|
|
297
|
+
*
|
|
298
|
+
* Every error users see should answer one question: "is this me or them?"
|
|
299
|
+
* That answer drives whether they retry, switch model, log in, or report a
|
|
300
|
+
* ggcoder bug. The `FormattedError` shape captures it in plain English:
|
|
301
|
+
*
|
|
302
|
+
* ✗ OpenAI returned an error.
|
|
303
|
+
* An error occurred while processing your request...
|
|
304
|
+
* → This is an OpenAI issue, not ggcoder. Retry — if it persists, check status.openai.com.
|
|
305
|
+
*
|
|
306
|
+
* ✗ ggcoder hit an unexpected error.
|
|
307
|
+
* Cannot read property 'foo' of undefined
|
|
308
|
+
* → This is a ggcoder bug — please report it.
|
|
309
|
+
*/
|
|
310
|
+
type ErrorSource = "provider" | "ggcoder" | "network" | "auth";
|
|
311
|
+
interface FormattedError {
|
|
312
|
+
/** Plain-English headline, e.g. "OpenAI returned an error." */
|
|
313
|
+
headline: string;
|
|
314
|
+
/** Machine-readable classification. */
|
|
315
|
+
source: ErrorSource;
|
|
316
|
+
/** Detailed message body from the underlying error (no JSON, no tag prefix). */
|
|
317
|
+
message: string;
|
|
318
|
+
/** Action line — tells the user whether to retry, switch model, log in, or report a bug. */
|
|
319
|
+
guidance: string;
|
|
320
|
+
/** Provider name when source === "provider". */
|
|
321
|
+
provider?: string;
|
|
322
|
+
/** HTTP status code if known. */
|
|
323
|
+
statusCode?: number;
|
|
324
|
+
/** Provider request ID, kept for telemetry / debug — not shown by default. */
|
|
325
|
+
requestId?: string;
|
|
326
|
+
}
|
|
295
327
|
declare class GGAIError extends Error {
|
|
296
|
-
|
|
328
|
+
readonly source: ErrorSource;
|
|
329
|
+
readonly requestId?: string;
|
|
330
|
+
readonly hint?: string;
|
|
331
|
+
constructor(message: string, options?: {
|
|
332
|
+
source?: ErrorSource;
|
|
333
|
+
requestId?: string;
|
|
334
|
+
hint?: string;
|
|
335
|
+
cause?: unknown;
|
|
336
|
+
});
|
|
297
337
|
}
|
|
298
338
|
declare class ProviderError extends GGAIError {
|
|
299
339
|
readonly provider: string;
|
|
300
340
|
readonly statusCode?: number;
|
|
301
341
|
constructor(provider: string, message: string, options?: {
|
|
302
342
|
statusCode?: number;
|
|
343
|
+
requestId?: string;
|
|
344
|
+
hint?: string;
|
|
303
345
|
cause?: unknown;
|
|
304
346
|
});
|
|
305
347
|
}
|
|
348
|
+
/**
|
|
349
|
+
* Normalise any thrown value into a structured display object. Always returns
|
|
350
|
+
* a non-empty `headline` and `guidance` so the UI never has to second-guess
|
|
351
|
+
* what to show the user.
|
|
352
|
+
*/
|
|
353
|
+
declare function formatError(err: unknown): FormattedError;
|
|
354
|
+
/**
|
|
355
|
+
* Render a FormattedError as a multi-line string for terminal display.
|
|
356
|
+
*
|
|
357
|
+
* Format:
|
|
358
|
+
* <headline>
|
|
359
|
+
* <message>
|
|
360
|
+
* → <guidance>
|
|
361
|
+
*/
|
|
362
|
+
declare function formatErrorForDisplay(err: unknown): string;
|
|
306
363
|
|
|
307
364
|
interface PalsuProviderState {
|
|
308
365
|
callCount: number;
|
|
@@ -373,4 +430,4 @@ interface PalsuProviderConfig {
|
|
|
373
430
|
*/
|
|
374
431
|
declare function registerPalsuProvider(config?: PalsuProviderConfig): PalsuProviderHandle;
|
|
375
432
|
|
|
376
|
-
export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, type ErrorEvent, EventStream, GGAIError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderEntry, ProviderError, type ProviderStreamFn, type RawContent, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, providerRegistry, registerPalsuProvider, stream };
|
|
433
|
+
export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, type ErrorEvent, type ErrorSource, EventStream, type FormattedError, GGAIError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderEntry, ProviderError, type ProviderStreamFn, type RawContent, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, formatError, formatErrorForDisplay, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, providerRegistry, registerPalsuProvider, stream };
|
package/dist/index.js
CHANGED
|
@@ -1,20 +1,164 @@
|
|
|
1
1
|
// src/errors.ts
|
|
2
2
|
var GGAIError = 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 = "GGAIError";
|
|
9
|
+
this.source = options?.source ?? "ggcoder";
|
|
10
|
+
this.requestId = options?.requestId;
|
|
11
|
+
this.hint = options?.hint;
|
|
6
12
|
}
|
|
7
13
|
};
|
|
8
14
|
var ProviderError = class extends GGAIError {
|
|
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 GGAIError) {
|
|
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("ggcoder", 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 ggcoder 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 `ggcoder 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 "ggcoder":
|
|
96
|
+
return {
|
|
97
|
+
headline: "ggcoder hit an unexpected error.",
|
|
98
|
+
source,
|
|
99
|
+
message,
|
|
100
|
+
guidance: hint ?? "This looks like a ggcoder 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 "ggcoder";
|
|
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 \`ggcoder 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 ggcoder 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 ggcoder 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 ggcoder 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 ggcoder.`;
|
|
144
|
+
}
|
|
145
|
+
if (statusCode === 503 || lower.includes("service unavailable")) {
|
|
146
|
+
return `${name} is temporarily unavailable. Retry shortly \u2014 not a ggcoder 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 ggcoder. Retry \u2014 if it keeps happening, check ${status}.` : `This is an error from ${name}, not ggcoder. Retry \u2014 if it keeps happening, try a different model with /model.`;
|
|
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 ggcoder 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 ggcoder. Retry \u2014 if it persists, check ${status}.` : `This is an error from ${name}, not ggcoder. Retry \u2014 if it persists, try a different model with /model.`;
|
|
161
|
+
}
|
|
18
162
|
|
|
19
163
|
// src/providers/anthropic.ts
|
|
20
164
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -953,8 +1097,10 @@ function messageToResponse(message) {
|
|
|
953
1097
|
}
|
|
954
1098
|
function toError(err) {
|
|
955
1099
|
if (err instanceof Anthropic.APIError) {
|
|
1100
|
+
const requestId = err.request_id ?? err.error?.request_id;
|
|
956
1101
|
return new ProviderError("anthropic", err.message, {
|
|
957
1102
|
statusCode: err.status,
|
|
1103
|
+
...requestId ? { requestId } : {},
|
|
958
1104
|
cause: err
|
|
959
1105
|
});
|
|
960
1106
|
}
|
|
@@ -1246,19 +1392,19 @@ function completionToResponse(completion) {
|
|
|
1246
1392
|
}
|
|
1247
1393
|
function toError2(err, provider = "openai") {
|
|
1248
1394
|
if (err instanceof OpenAI.APIError) {
|
|
1249
|
-
let msg = err.message;
|
|
1250
1395
|
const body = err.error;
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
return new ProviderError(provider, msg, {
|
|
1396
|
+
const bodyMessage = typeof body?.message === "string" && body.message.trim() ? body.message.trim() : void 0;
|
|
1397
|
+
const modelName = typeof body?.model === "string" ? body.model : "";
|
|
1398
|
+
const cleanMessage = bodyMessage ?? err.message;
|
|
1399
|
+
let hint;
|
|
1400
|
+
if (modelName === "codex-mini-latest" || cleanMessage.includes("codex-mini-latest")) {
|
|
1401
|
+
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.";
|
|
1402
|
+
}
|
|
1403
|
+
const requestId = err.request_id ?? (typeof body?.request_id === "string" ? body.request_id : void 0);
|
|
1404
|
+
return new ProviderError(provider, cleanMessage, {
|
|
1261
1405
|
statusCode: err.status,
|
|
1406
|
+
...requestId ? { requestId } : {},
|
|
1407
|
+
...hint ? { hint } : {},
|
|
1262
1408
|
cause: err
|
|
1263
1409
|
});
|
|
1264
1410
|
}
|
|
@@ -1320,19 +1466,19 @@ async function* runStream3(options) {
|
|
|
1320
1466
|
});
|
|
1321
1467
|
if (!response.ok) {
|
|
1322
1468
|
const text = await response.text().catch(() => "");
|
|
1323
|
-
|
|
1469
|
+
const parsed = parseCodexErrorBody(text);
|
|
1470
|
+
const message = parsed.message ?? `Codex API returned HTTP ${response.status}.`;
|
|
1471
|
+
const requestId = parsed.requestId ?? response.headers.get("x-request-id") ?? response.headers.get("openai-request-id") ?? void 0;
|
|
1472
|
+
let hint;
|
|
1324
1473
|
if (response.status === 400 && text.includes("not supported")) {
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
}
|
|
1329
|
-
if (response.status === 404 && text.includes("does not exist")) {
|
|
1330
|
-
message += `
|
|
1331
|
-
|
|
1332
|
-
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.`;
|
|
1474
|
+
hint = 'Codex models require a ChatGPT Plus ($20/mo) or Pro ($200/mo) subscription. The "codex-spark" variants require ChatGPT Pro. Check your subscription at https://chatgpt.com/settings.';
|
|
1475
|
+
} else if (response.status === 404 && text.includes("does not exist")) {
|
|
1476
|
+
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.";
|
|
1333
1477
|
}
|
|
1334
1478
|
throw new ProviderError("openai", message, {
|
|
1335
|
-
statusCode: response.status
|
|
1479
|
+
statusCode: response.status,
|
|
1480
|
+
...requestId ? { requestId } : {},
|
|
1481
|
+
...hint ? { hint } : {}
|
|
1336
1482
|
});
|
|
1337
1483
|
}
|
|
1338
1484
|
if (!response.body) {
|
|
@@ -1347,12 +1493,22 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1347
1493
|
const type = event.type;
|
|
1348
1494
|
if (!type) continue;
|
|
1349
1495
|
if (type === "error") {
|
|
1350
|
-
const
|
|
1351
|
-
|
|
1496
|
+
const nested = event.error ?? void 0;
|
|
1497
|
+
const message = nested?.message ?? event.message ?? "Codex stream emitted an error chunk without a message.";
|
|
1498
|
+
const code = nested?.code ?? nested?.type ?? event.code ?? "server_error";
|
|
1499
|
+
const requestId = extractCodexRequestId(message) ?? event.request_id;
|
|
1500
|
+
throw new ProviderError("openai", message, {
|
|
1501
|
+
...requestId != null ? { requestId } : {},
|
|
1502
|
+
...code === "server_error" ? { statusCode: 500 } : {}
|
|
1503
|
+
});
|
|
1352
1504
|
}
|
|
1353
1505
|
if (type === "response.failed") {
|
|
1354
|
-
const
|
|
1355
|
-
|
|
1506
|
+
const nested = event.error;
|
|
1507
|
+
const message = nested?.message ?? "Codex response failed.";
|
|
1508
|
+
const requestId = extractCodexRequestId(message) ?? event.request_id;
|
|
1509
|
+
throw new ProviderError("openai", message, {
|
|
1510
|
+
...requestId != null ? { requestId } : {}
|
|
1511
|
+
});
|
|
1356
1512
|
}
|
|
1357
1513
|
if (type === "response.output_text.delta") {
|
|
1358
1514
|
const delta = event.delta;
|
|
@@ -1597,6 +1753,23 @@ function toCodexTools(tools) {
|
|
|
1597
1753
|
strict: null
|
|
1598
1754
|
}));
|
|
1599
1755
|
}
|
|
1756
|
+
function extractCodexRequestId(message) {
|
|
1757
|
+
const match = message.match(/request ID ([a-z0-9-]{8,})/i);
|
|
1758
|
+
return match?.[1];
|
|
1759
|
+
}
|
|
1760
|
+
function parseCodexErrorBody(text) {
|
|
1761
|
+
if (!text) return {};
|
|
1762
|
+
try {
|
|
1763
|
+
const parsed = JSON.parse(text);
|
|
1764
|
+
const error = parsed.error;
|
|
1765
|
+
const message = error?.message ?? parsed.message;
|
|
1766
|
+
const requestId = parsed.request_id ?? error?.request_id ?? (message ? extractCodexRequestId(message) : void 0);
|
|
1767
|
+
return { ...message ? { message } : {}, ...requestId ? { requestId } : {} };
|
|
1768
|
+
} catch {
|
|
1769
|
+
const trimmed = text.trim().slice(0, 240);
|
|
1770
|
+
return trimmed ? { message: trimmed } : {};
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1600
1773
|
|
|
1601
1774
|
// src/provider-registry.ts
|
|
1602
1775
|
var ProviderRegistryImpl = class {
|
|
@@ -1856,6 +2029,8 @@ export {
|
|
|
1856
2029
|
GGAIError,
|
|
1857
2030
|
ProviderError,
|
|
1858
2031
|
StreamResult,
|
|
2032
|
+
formatError,
|
|
2033
|
+
formatErrorForDisplay,
|
|
1859
2034
|
palsuAssistantMessage,
|
|
1860
2035
|
palsuText,
|
|
1861
2036
|
palsuThinking,
|