@gajae-code/ai 0.16.1 → 0.16.3
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/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.16.3] - 2026-09-04
|
|
6
|
+
|
|
7
|
+
## [0.16.2] - 2026-09-04
|
|
8
|
+
|
|
9
|
+
- OpenAI Codex GPT-5.6 Sol selections now reject a known non-Pro ChatGPT OAuth account before dispatch, instead of allowing a binding that fails later with the provider's raw entitlement error. The same rejection is normalized for HTTP and streaming provider responses with guidance to choose a callable model or use an API-key credential.
|
|
10
|
+
|
|
5
11
|
## [0.16.1] - 2026-09-03
|
|
6
12
|
|
|
7
13
|
### Added
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model entitlement facts shared by Codex credential selection and provider
|
|
3
|
+
* error presentation.
|
|
4
|
+
*
|
|
5
|
+
* GPT-5.6 Sol is a Pro-tier ChatGPT Codex model. The usage endpoint is the
|
|
6
|
+
* authority for the account tier; this module only names the model policy and
|
|
7
|
+
* keeps the provider's deterministic rejection wording in one place.
|
|
8
|
+
*/
|
|
9
|
+
export declare function requiresOpenAICodexProModel(provider: string, modelId: string | undefined): boolean;
|
|
10
|
+
export declare function requiresStrictOpenAICodexProModel(provider: string, modelId: string | undefined): boolean;
|
|
11
|
+
export declare function isOpenAICodexChatGPTEntitlementError(message: string | undefined, code?: string): boolean;
|
|
12
|
+
export declare function formatOpenAICodexChatGPTEntitlementError(modelId: string | undefined): string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/ai",
|
|
4
|
-
"version": "0.16.
|
|
4
|
+
"version": "0.16.3",
|
|
5
5
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
6
6
|
"homepage": "https://gajae-code.com",
|
|
7
7
|
"author": "Yeachan-Heo and Gajae Code Contributors",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@anthropic-ai/sdk": "^0.94.0",
|
|
42
42
|
"@bufbuild/protobuf": "^2.12.0",
|
|
43
|
-
"@gajae-code/natives": "0.16.
|
|
44
|
-
"@gajae-code/utils": "0.16.
|
|
43
|
+
"@gajae-code/natives": "0.16.3",
|
|
44
|
+
"@gajae-code/utils": "0.16.3",
|
|
45
45
|
"openai": "^6.36.0",
|
|
46
46
|
"partial-json": "^0.1.7",
|
|
47
47
|
"zod": "4.4.3"
|
package/src/auth-storage.ts
CHANGED
|
@@ -26,6 +26,11 @@ import type {
|
|
|
26
26
|
UsageReport,
|
|
27
27
|
} from "./usage";
|
|
28
28
|
|
|
29
|
+
import {
|
|
30
|
+
formatOpenAICodexChatGPTEntitlementError,
|
|
31
|
+
requiresOpenAICodexProModel,
|
|
32
|
+
requiresStrictOpenAICodexProModel,
|
|
33
|
+
} from "./utils/codex-entitlement";
|
|
29
34
|
import { getOAuthApiKey, getOAuthProvider, refreshOAuthToken, resolveOAuthStorageProvider } from "./utils/oauth";
|
|
30
35
|
import { loginDeepInfra } from "./utils/oauth/deepinfra";
|
|
31
36
|
import { loginDeepSeek } from "./utils/oauth/deepseek";
|
|
@@ -1140,10 +1145,6 @@ export function readBrokerErrorBody(error: unknown): string | undefined {
|
|
|
1140
1145
|
}
|
|
1141
1146
|
}
|
|
1142
1147
|
|
|
1143
|
-
function requiresOpenAICodexProModel(provider: string, modelId: string | undefined): boolean {
|
|
1144
|
-
return provider === "openai-codex" && typeof modelId === "string" && modelId.includes("-spark");
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
1148
|
function getUsagePlanType(report: UsageReport | null): string | undefined {
|
|
1148
1149
|
const metadata = report?.metadata;
|
|
1149
1150
|
if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) return undefined;
|
|
@@ -4955,6 +4956,19 @@ export class AuthStorage {
|
|
|
4955
4956
|
// non-Pro accounts can still attempt Spark requests (e.g. trial/grandfathered access).
|
|
4956
4957
|
const enforceProRequirement =
|
|
4957
4958
|
requiresProModel && candidates.some(candidate => hasOpenAICodexProPlan(candidate.usage));
|
|
4959
|
+
// Spark retains its historical Plus fallback for grandfathered accounts.
|
|
4960
|
+
// Sol is different: a confirmed non-Pro plan cannot call it, so reject the
|
|
4961
|
+
// model before returning an OAuth bearer and letting the turn fail remotely.
|
|
4962
|
+
const strictProRequirement = requiresStrictOpenAICodexProModel(provider, options?.modelId);
|
|
4963
|
+
if (
|
|
4964
|
+
strictProRequirement &&
|
|
4965
|
+
candidates.length > 0 &&
|
|
4966
|
+
candidates.every(
|
|
4967
|
+
candidate => getUsagePlanType(candidate.usage) !== undefined && !hasOpenAICodexProPlan(candidate.usage),
|
|
4968
|
+
)
|
|
4969
|
+
) {
|
|
4970
|
+
throw new Error(formatOpenAICodexChatGPTEntitlementError(options?.modelId));
|
|
4971
|
+
}
|
|
4958
4972
|
|
|
4959
4973
|
const fallback = candidates[0];
|
|
4960
4974
|
|
|
@@ -51,6 +51,10 @@ import {
|
|
|
51
51
|
normalizeSystemPrompts,
|
|
52
52
|
sanitizeOpenAIResponsesHistoryItemsForReplay,
|
|
53
53
|
} from "../utils";
|
|
54
|
+
import {
|
|
55
|
+
formatOpenAICodexChatGPTEntitlementError,
|
|
56
|
+
isOpenAICodexChatGPTEntitlementError,
|
|
57
|
+
} from "../utils/codex-entitlement";
|
|
54
58
|
import { AssistantMessageEventStream } from "../utils/event-stream";
|
|
55
59
|
import { STREAM_FIRST_EVENT_TIMEOUT_PROVIDER_CODE, transportFailureFacts } from "../utils/fallback-transport";
|
|
56
60
|
import { finalizeErrorMessage, type RawHttpRequestDump } from "../utils/http-inspector";
|
|
@@ -1234,7 +1238,7 @@ function handleCodexStreamEvent(args: {
|
|
|
1234
1238
|
}
|
|
1235
1239
|
|
|
1236
1240
|
if (eventType === "error" || eventType === "response.failed") {
|
|
1237
|
-
throw createCodexProviderStreamError(rawEvent);
|
|
1241
|
+
throw createCodexProviderStreamError(rawEvent, model.id);
|
|
1238
1242
|
}
|
|
1239
1243
|
|
|
1240
1244
|
return firstTokenTime;
|
|
@@ -2853,7 +2857,11 @@ async function openCodexSseEventStream(
|
|
|
2853
2857
|
updateCodexSessionMetadataFromHeaders(state, response.headers);
|
|
2854
2858
|
if (!response.ok) {
|
|
2855
2859
|
const info = await parseCodexError(response);
|
|
2856
|
-
const error = new Error(
|
|
2860
|
+
const error = new Error(
|
|
2861
|
+
isOpenAICodexChatGPTEntitlementError(info.message, info.code)
|
|
2862
|
+
? formatOpenAICodexChatGPTEntitlementError(body.model)
|
|
2863
|
+
: info.friendlyMessage || info.message,
|
|
2864
|
+
);
|
|
2857
2865
|
(error as { headers?: Headers; status?: number }).headers = response.headers;
|
|
2858
2866
|
(error as { headers?: Headers; status?: number }).status = response.status;
|
|
2859
2867
|
(error as { code?: string }).code = info.code;
|
|
@@ -3235,11 +3243,12 @@ function isRetryableCodexFailureEvent(rawEvent: Record<string, unknown>): boolea
|
|
|
3235
3243
|
return !!message && CODEX_RETRYABLE_EVENT_MESSAGE.test(message);
|
|
3236
3244
|
}
|
|
3237
3245
|
|
|
3238
|
-
function createCodexProviderStreamError(rawEvent: Record<string, unknown
|
|
3246
|
+
function createCodexProviderStreamError(rawEvent: Record<string, unknown>, modelId: string): CodexProviderStreamError {
|
|
3239
3247
|
const code = getCodexEventErrorCode(rawEvent);
|
|
3240
3248
|
const message = getCodexEventErrorMessage(rawEvent);
|
|
3241
|
-
const formattedMessage =
|
|
3242
|
-
|
|
3249
|
+
const formattedMessage = isOpenAICodexChatGPTEntitlementError(message, code)
|
|
3250
|
+
? formatOpenAICodexChatGPTEntitlementError(modelId)
|
|
3251
|
+
: typeof rawEvent.type === "string" && rawEvent.type === "error"
|
|
3243
3252
|
? formatCodexErrorEvent(rawEvent, code, message)
|
|
3244
3253
|
: (formatCodexFailure(rawEvent) ?? "Codex response failed");
|
|
3245
3254
|
return new CodexProviderStreamError(
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model entitlement facts shared by Codex credential selection and provider
|
|
3
|
+
* error presentation.
|
|
4
|
+
*
|
|
5
|
+
* GPT-5.6 Sol is a Pro-tier ChatGPT Codex model. The usage endpoint is the
|
|
6
|
+
* authority for the account tier; this module only names the model policy and
|
|
7
|
+
* keeps the provider's deterministic rejection wording in one place.
|
|
8
|
+
*/
|
|
9
|
+
export declare function requiresOpenAICodexProModel(provider: string, modelId: string | undefined): boolean;
|
|
10
|
+
export declare function requiresStrictOpenAICodexProModel(provider: string, modelId: string | undefined): boolean;
|
|
11
|
+
export declare function isOpenAICodexChatGPTEntitlementError(message: string | undefined, code?: string): boolean;
|
|
12
|
+
export declare function formatOpenAICodexChatGPTEntitlementError(modelId: string | undefined): string;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model entitlement facts shared by Codex credential selection and provider
|
|
3
|
+
* error presentation.
|
|
4
|
+
*
|
|
5
|
+
* GPT-5.6 Sol is a Pro-tier ChatGPT Codex model. The usage endpoint is the
|
|
6
|
+
* authority for the account tier; this module only names the model policy and
|
|
7
|
+
* keeps the provider's deterministic rejection wording in one place.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export function requiresOpenAICodexProModel(provider: string, modelId: string | undefined): boolean {
|
|
11
|
+
return (
|
|
12
|
+
provider === "openai-codex" &&
|
|
13
|
+
typeof modelId === "string" &&
|
|
14
|
+
(modelId.toLowerCase().includes("-spark") || modelId.toLowerCase() === "gpt-5.6-sol")
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function requiresStrictOpenAICodexProModel(provider: string, modelId: string | undefined): boolean {
|
|
19
|
+
return provider === "openai-codex" && modelId?.toLowerCase() === "gpt-5.6-sol";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function isOpenAICodexChatGPTEntitlementError(message: string | undefined, code?: string): boolean {
|
|
23
|
+
return (
|
|
24
|
+
/\bnot supported when using codex with a chatgpt account\b/i.test(message ?? "") &&
|
|
25
|
+
(code === undefined || code.toLowerCase() === "invalid_request_error")
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function formatOpenAICodexChatGPTEntitlementError(modelId: string | undefined): string {
|
|
30
|
+
const safeModelId = modelId
|
|
31
|
+
?.replace(/[\x00-\x1f\x7f-\x9f]+/gu, " ")
|
|
32
|
+
.trim()
|
|
33
|
+
.slice(0, 128);
|
|
34
|
+
const model = safeModelId ? ` model "${safeModelId}"` : " model";
|
|
35
|
+
return `This ChatGPT Codex account cannot use${model}. Select a model available to this ChatGPT account, such as "gpt-5.5", or use an API-key credential that supports the model.`;
|
|
36
|
+
}
|