@kenkaiiii/gg-ai 4.3.164 → 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 +214 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +60 -3
- package/dist/index.d.ts +60 -3
- package/dist/index.js +212 -33
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
3
|
type Provider = "anthropic" | "xiaomi" | "openai" | "glm" | "moonshot" | "minimax" | "deepseek" | "openrouter" | "palsu";
|
|
4
|
-
type ThinkingLevel = "low" | "medium" | "high" | "
|
|
4
|
+
type ThinkingLevel = "low" | "medium" | "high" | "xhigh";
|
|
5
5
|
type CacheRetention = "none" | "short" | "long";
|
|
6
6
|
interface TextContent {
|
|
7
7
|
type: "text";
|
|
@@ -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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
3
|
type Provider = "anthropic" | "xiaomi" | "openai" | "glm" | "moonshot" | "minimax" | "deepseek" | "openrouter" | "palsu";
|
|
4
|
-
type ThinkingLevel = "low" | "medium" | "high" | "
|
|
4
|
+
type ThinkingLevel = "low" | "medium" | "high" | "xhigh";
|
|
5
5
|
type CacheRetention = "none" | "short" | "long";
|
|
6
6
|
interface TextContent {
|
|
7
7
|
type: "text";
|
|
@@ -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";
|
|
@@ -382,8 +526,8 @@ function supportsAdaptiveThinking(model) {
|
|
|
382
526
|
}
|
|
383
527
|
function toAnthropicThinking(level, maxTokens, model) {
|
|
384
528
|
if (supportsAdaptiveThinking(model)) {
|
|
385
|
-
let effort = level;
|
|
386
|
-
if (
|
|
529
|
+
let effort = level === "xhigh" ? "max" : level;
|
|
530
|
+
if (effort === "max" && !model.includes("opus")) {
|
|
387
531
|
effort = "high";
|
|
388
532
|
}
|
|
389
533
|
return {
|
|
@@ -392,7 +536,7 @@ function toAnthropicThinking(level, maxTokens, model) {
|
|
|
392
536
|
outputConfig: { effort }
|
|
393
537
|
};
|
|
394
538
|
}
|
|
395
|
-
const effectiveLevel = level === "
|
|
539
|
+
const effectiveLevel = level === "xhigh" ? "high" : level;
|
|
396
540
|
const budgetMap = {
|
|
397
541
|
low: Math.max(1024, Math.floor(maxTokens * 0.25)),
|
|
398
542
|
medium: Math.max(2048, Math.floor(maxTokens * 0.5)),
|
|
@@ -525,8 +669,12 @@ function toOpenAIToolChoice(choice) {
|
|
|
525
669
|
if (choice === "required") return "required";
|
|
526
670
|
return { type: "function", function: { name: choice.name } };
|
|
527
671
|
}
|
|
528
|
-
function
|
|
529
|
-
return
|
|
672
|
+
function isOpenAIProVariant(model) {
|
|
673
|
+
return /^gpt-5\.\d+-pro$/i.test(model);
|
|
674
|
+
}
|
|
675
|
+
function toOpenAIReasoningEffort(level, model) {
|
|
676
|
+
if (isOpenAIProVariant(model) && level === "low") return "medium";
|
|
677
|
+
return level;
|
|
530
678
|
}
|
|
531
679
|
function normalizeAnthropicStopReason(reason) {
|
|
532
680
|
switch (reason) {
|
|
@@ -949,8 +1097,10 @@ function messageToResponse(message) {
|
|
|
949
1097
|
}
|
|
950
1098
|
function toError(err) {
|
|
951
1099
|
if (err instanceof Anthropic.APIError) {
|
|
1100
|
+
const requestId = err.request_id ?? err.error?.request_id;
|
|
952
1101
|
return new ProviderError("anthropic", err.message, {
|
|
953
1102
|
statusCode: err.status,
|
|
1103
|
+
...requestId ? { requestId } : {},
|
|
954
1104
|
cause: err
|
|
955
1105
|
});
|
|
956
1106
|
}
|
|
@@ -993,7 +1143,7 @@ async function* runStream2(options) {
|
|
|
993
1143
|
...effectiveTemp != null && !options.thinking ? { temperature: effectiveTemp } : {},
|
|
994
1144
|
...options.topP != null ? { top_p: options.topP } : {},
|
|
995
1145
|
...options.stop ? { stop: options.stop } : {},
|
|
996
|
-
...options.thinking && !usesThinkingParam ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking) } : {},
|
|
1146
|
+
...options.thinking && !usesThinkingParam ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
|
|
997
1147
|
...options.tools?.length ? { tools: toOpenAITools(options.tools) } : {},
|
|
998
1148
|
...options.toolChoice && options.tools?.length ? { tool_choice: toOpenAIToolChoice(options.toolChoice) } : {},
|
|
999
1149
|
...useStreaming ? { stream_options: { include_usage: true } } : {}
|
|
@@ -1242,19 +1392,19 @@ function completionToResponse(completion) {
|
|
|
1242
1392
|
}
|
|
1243
1393
|
function toError2(err, provider = "openai") {
|
|
1244
1394
|
if (err instanceof OpenAI.APIError) {
|
|
1245
|
-
let msg = err.message;
|
|
1246
1395
|
const body = err.error;
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
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, {
|
|
1257
1405
|
statusCode: err.status,
|
|
1406
|
+
...requestId ? { requestId } : {},
|
|
1407
|
+
...hint ? { hint } : {},
|
|
1258
1408
|
cause: err
|
|
1259
1409
|
});
|
|
1260
1410
|
}
|
|
@@ -1316,19 +1466,19 @@ async function* runStream3(options) {
|
|
|
1316
1466
|
});
|
|
1317
1467
|
if (!response.ok) {
|
|
1318
1468
|
const text = await response.text().catch(() => "");
|
|
1319
|
-
|
|
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;
|
|
1320
1473
|
if (response.status === 400 && text.includes("not supported")) {
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
}
|
|
1325
|
-
if (response.status === 404 && text.includes("does not exist")) {
|
|
1326
|
-
message += `
|
|
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.`;
|
|
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.";
|
|
1329
1477
|
}
|
|
1330
1478
|
throw new ProviderError("openai", message, {
|
|
1331
|
-
statusCode: response.status
|
|
1479
|
+
statusCode: response.status,
|
|
1480
|
+
...requestId ? { requestId } : {},
|
|
1481
|
+
...hint ? { hint } : {}
|
|
1332
1482
|
});
|
|
1333
1483
|
}
|
|
1334
1484
|
if (!response.body) {
|
|
@@ -1343,12 +1493,22 @@ Hint: codex-mini-latest requires an OpenAI Pro ($200/mo) or Max subscription. GP
|
|
|
1343
1493
|
const type = event.type;
|
|
1344
1494
|
if (!type) continue;
|
|
1345
1495
|
if (type === "error") {
|
|
1346
|
-
const
|
|
1347
|
-
|
|
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
|
+
});
|
|
1348
1504
|
}
|
|
1349
1505
|
if (type === "response.failed") {
|
|
1350
|
-
const
|
|
1351
|
-
|
|
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
|
+
});
|
|
1352
1512
|
}
|
|
1353
1513
|
if (type === "response.output_text.delta") {
|
|
1354
1514
|
const delta = event.delta;
|
|
@@ -1593,6 +1753,23 @@ function toCodexTools(tools) {
|
|
|
1593
1753
|
strict: null
|
|
1594
1754
|
}));
|
|
1595
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
|
+
}
|
|
1596
1773
|
|
|
1597
1774
|
// src/provider-registry.ts
|
|
1598
1775
|
var ProviderRegistryImpl = class {
|
|
@@ -1852,6 +2029,8 @@ export {
|
|
|
1852
2029
|
GGAIError,
|
|
1853
2030
|
ProviderError,
|
|
1854
2031
|
StreamResult,
|
|
2032
|
+
formatError,
|
|
2033
|
+
formatErrorForDisplay,
|
|
1855
2034
|
palsuAssistantMessage,
|
|
1856
2035
|
palsuText,
|
|
1857
2036
|
palsuThinking,
|