@opengeni/codex 0.2.7 → 0.2.9
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/api-client.d.ts +55 -0
- package/dist/billing.d.ts +11 -0
- package/dist/bounded-operation.d.ts +16 -0
- package/dist/constants.d.ts +33 -35
- package/dist/device-code.d.ts +36 -0
- package/dist/fetch.d.ts +84 -0
- package/dist/index.d.ts +13 -515
- package/dist/index.js +49 -4
- package/dist/index.js.map +1 -1
- package/dist/mcp-sanitize.d.ts +33 -0
- package/dist/model-output-truncation.d.ts +36 -0
- package/dist/normalize.d.ts +8 -0
- package/dist/oversized-image-card.d.ts +17 -0
- package/dist/refresh.d.ts +28 -0
- package/dist/request-context.d.ts +99 -0
- package/dist/reset-credits.d.ts +33 -0
- package/dist/response-timeout.d.ts +28 -0
- package/dist/usage-normalize.d.ts +61 -0
- package/package.json +3 -3
- package/src/fetch.ts +67 -2
- package/src/normalize.ts +6 -3
- package/src/request-context.ts +20 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,515 +1,13 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
|
|
14
|
-
declare function isCodexBilledModel(model: string | null | undefined): boolean;
|
|
15
|
-
|
|
16
|
-
type CodexFetch = (input: string | URL, init?: RequestInit) => Promise<Response>;
|
|
17
|
-
type CodexDeviceStart = {
|
|
18
|
-
deviceAuthId: string;
|
|
19
|
-
userCode: string;
|
|
20
|
-
verificationUri: string;
|
|
21
|
-
intervalSeconds: number;
|
|
22
|
-
};
|
|
23
|
-
type CodexTokens = {
|
|
24
|
-
idToken: string;
|
|
25
|
-
accessToken: string;
|
|
26
|
-
refreshToken: string;
|
|
27
|
-
};
|
|
28
|
-
type CodexPollResult = {
|
|
29
|
-
status: "pending";
|
|
30
|
-
} | {
|
|
31
|
-
status: "expired";
|
|
32
|
-
} | {
|
|
33
|
-
status: "authorized";
|
|
34
|
-
authorizationCode: string;
|
|
35
|
-
codeVerifier: string;
|
|
36
|
-
};
|
|
37
|
-
declare class CodexDeviceError extends Error {
|
|
38
|
-
constructor(message: string);
|
|
39
|
-
}
|
|
40
|
-
/** Step 1: POST {auth}/deviceauth/usercode {client_id}. device_code_auth.rs:67-95 */
|
|
41
|
-
declare function startDeviceCode(fetchImpl?: CodexFetch): Promise<CodexDeviceStart>;
|
|
42
|
-
/** Step 3 (single, non-blocking): POST {auth}/deviceauth/token. 403/404 => pending. device_code_auth.rs:106-145 */
|
|
43
|
-
declare function pollDeviceCode(input: {
|
|
44
|
-
deviceAuthId: string;
|
|
45
|
-
userCode: string;
|
|
46
|
-
}, fetchImpl?: CodexFetch): Promise<CodexPollResult>;
|
|
47
|
-
/** Step 4: POST {issuer}/oauth/token form-encoded grant_type=authorization_code. server.rs:732-766 */
|
|
48
|
-
declare function exchangeDeviceCode(input: {
|
|
49
|
-
authorizationCode: string;
|
|
50
|
-
codeVerifier: string;
|
|
51
|
-
}, fetchImpl?: CodexFetch): Promise<CodexTokens>;
|
|
52
|
-
|
|
53
|
-
/** Permanent — the workspace must reconnect (status => needs_relogin). */
|
|
54
|
-
declare class CodexReloginRequired extends Error {
|
|
55
|
-
constructor(message: string);
|
|
56
|
-
}
|
|
57
|
-
/** Transient — safe to retry later. */
|
|
58
|
-
declare class CodexRefreshTransient extends Error {
|
|
59
|
-
constructor(message: string);
|
|
60
|
-
}
|
|
61
|
-
/** Only present fields are returned (the server may rotate any subset). */
|
|
62
|
-
type CodexRefreshTokens = {
|
|
63
|
-
idToken?: string | undefined;
|
|
64
|
-
accessToken?: string | undefined;
|
|
65
|
-
refreshToken?: string | undefined;
|
|
66
|
-
};
|
|
67
|
-
/** POST {issuer}/oauth/token JSON {client_id, grant_type:"refresh_token", refresh_token}. manager.rs:1336-1340 */
|
|
68
|
-
declare function refreshCodexToken(refreshToken: string, fetchImpl?: CodexFetch, timeoutMs?: number): Promise<CodexRefreshTokens>;
|
|
69
|
-
/** Decode a JWT payload (base64url, no signature check). */
|
|
70
|
-
declare function decodeJwtPayload(jwt: string): Record<string, unknown> | null;
|
|
71
|
-
/** access-token `exp` claim -> Date | null. token_data.rs:101-105 */
|
|
72
|
-
declare function accessTokenExpiry(accessToken: string): Date | null;
|
|
73
|
-
/** id_token -> {chatgptAccountId, planType, isFedramp}. server.rs:827-832; token_data.rs:71-99 */
|
|
74
|
-
declare function parseIdToken(idToken: string): {
|
|
75
|
-
chatgptAccountId: string | null;
|
|
76
|
-
planType: string | null;
|
|
77
|
-
isFedramp: boolean;
|
|
78
|
-
email: string | null;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
/** Mutates a parsed Responses request body in place and returns it. Pure + synchronous + unit-testable. */
|
|
82
|
-
declare function normalizeCodexRequestBody(body: Record<string, unknown>, resolveModel: (slug: string) => string): Record<string, unknown>;
|
|
83
|
-
/**
|
|
84
|
-
* Build a longest-prefix model resolver. Catalog slugs come from GET /models
|
|
85
|
-
* (api-client.ts). One leading `namespace/` segment is stripped first; an
|
|
86
|
-
* unknown slug returns the fallback (caller should log — spec §1.4 step 4).
|
|
87
|
-
*/
|
|
88
|
-
declare function buildModelResolver(liveSlugs: readonly string[], fallbackSlug: string): (slug: string) => string;
|
|
89
|
-
|
|
90
|
-
declare const CODEX_RATE_LIMIT_RESET_OUTCOMES: readonly ["reset", "nothingToReset", "noCredit", "alreadyRedeemed"];
|
|
91
|
-
type CodexRateLimitResetOutcome = (typeof CODEX_RATE_LIMIT_RESET_OUTCOMES)[number];
|
|
92
|
-
type CodexRateLimitResetType = "codexRateLimits" | "unknown";
|
|
93
|
-
type CodexRateLimitResetCreditStatus = "available" | "redeeming" | "redeemed" | "unknown";
|
|
94
|
-
type CodexRateLimitResetCredit = {
|
|
95
|
-
id: string;
|
|
96
|
-
resetType: CodexRateLimitResetType;
|
|
97
|
-
status: CodexRateLimitResetCreditStatus;
|
|
98
|
-
/** Unix seconds, matching account/rateLimits/read in Codex v0.144.6. */
|
|
99
|
-
grantedAt: number;
|
|
100
|
-
/** Unix seconds, or null when the provider says the credit does not expire. */
|
|
101
|
-
expiresAt: number | null;
|
|
102
|
-
title: string | null;
|
|
103
|
-
description: string | null;
|
|
104
|
-
};
|
|
105
|
-
type CodexRateLimitResetCreditsDetails = {
|
|
106
|
-
availableCount: number;
|
|
107
|
-
credits: CodexRateLimitResetCredit[];
|
|
108
|
-
};
|
|
109
|
-
type CodexRateLimitResetCreditsSummary = {
|
|
110
|
-
availableCount: number;
|
|
111
|
-
/** null means the provider supplied an authoritative count but no detail rows. */
|
|
112
|
-
credits: null;
|
|
113
|
-
};
|
|
114
|
-
type CodexRateLimitResetConsumeResponse = {
|
|
115
|
-
outcome: CodexRateLimitResetOutcome;
|
|
116
|
-
};
|
|
117
|
-
/** Parse the exact detailed-credit backend response. Unknown rows stay view-only. */
|
|
118
|
-
declare function parseCodexRateLimitResetCreditsDetails(payload: unknown): CodexRateLimitResetCreditsDetails | null;
|
|
119
|
-
/** Parse the count-only summary carried by GET /wham/usage. */
|
|
120
|
-
declare function parseCodexRateLimitResetCreditsSummary(payload: unknown): CodexRateLimitResetCreditsSummary | null;
|
|
121
|
-
/** Parse one of the exact four v0.144.6 consume outcomes. Unknowns fail closed. */
|
|
122
|
-
declare function parseCodexRateLimitResetConsumeResponse(payload: unknown): CodexRateLimitResetConsumeResponse | null;
|
|
123
|
-
|
|
124
|
-
/** The 5-hour (primary) window's `limit_window_seconds`. */
|
|
125
|
-
declare const CODEX_FIVE_HOUR_WINDOW_SECONDS = 18000;
|
|
126
|
-
/** The weekly (secondary) window's `limit_window_seconds`. */
|
|
127
|
-
declare const CODEX_WEEKLY_WINDOW_SECONDS = 604800;
|
|
128
|
-
/** One normalized usage window (applied to BOTH primary_window and secondary_window). */
|
|
129
|
-
type CodexUsageWindow = {
|
|
130
|
-
used: number;
|
|
131
|
-
limit: number;
|
|
132
|
-
remaining: number;
|
|
133
|
-
percent: number;
|
|
134
|
-
resetAt: string | null;
|
|
135
|
-
resetAfterSeconds: number | null;
|
|
136
|
-
limitWindowSeconds: number;
|
|
137
|
-
};
|
|
138
|
-
/** One additional (per-feature) limit (forward-compat; P2 renders nothing from it). */
|
|
139
|
-
type CodexAdditionalLimit = {
|
|
140
|
-
limitName: string;
|
|
141
|
-
meteredFeature: string;
|
|
142
|
-
fiveHour: CodexUsageWindow | null;
|
|
143
|
-
weekly: CodexUsageWindow | null;
|
|
144
|
-
};
|
|
145
|
-
type CodexUsageStatus = "ok" | "limit_reached" | "error" | "no-data";
|
|
146
|
-
/** The normalized usage payload — the P2/P3 contract. */
|
|
147
|
-
type CodexUsagePayload = {
|
|
148
|
-
status: CodexUsageStatus;
|
|
149
|
-
planType: string | null;
|
|
150
|
-
fiveHour: CodexUsageWindow | null;
|
|
151
|
-
weekly: CodexUsageWindow | null;
|
|
152
|
-
limitReached: boolean;
|
|
153
|
-
fetchedAt: string;
|
|
154
|
-
/**
|
|
155
|
-
* Authoritative count-only reset-credit summary from the usage response.
|
|
156
|
-
* Detail rows are fetched separately and are never synthesized from this.
|
|
157
|
-
*/
|
|
158
|
-
rateLimitResetCredits: CodexRateLimitResetCreditsSummary | null;
|
|
159
|
-
/** Present only on a refresh/auth failure path; carries the precise reason. */
|
|
160
|
-
reason?: "needs_relogin" | undefined;
|
|
161
|
-
additionalLimits?: CodexAdditionalLimit[] | undefined;
|
|
162
|
-
credits?: {
|
|
163
|
-
hasCredits: boolean;
|
|
164
|
-
unlimited: boolean;
|
|
165
|
-
overageLimitReached: boolean;
|
|
166
|
-
balance: string;
|
|
167
|
-
} | undefined;
|
|
168
|
-
};
|
|
169
|
-
/**
|
|
170
|
-
* Build a normalized window from the PERSISTED cache columns (used_percent +
|
|
171
|
-
* absolute reset timestamp). The same 0–100 synthesis as the live path, with the
|
|
172
|
-
* skew-free countdown derived from `resetAt − now` at read time. Returns null when
|
|
173
|
-
* there is no cached percent yet. `limitWindowSeconds` is the constant that
|
|
174
|
-
* identifies the window (18000 ⇒ 5h, 604800 ⇒ weekly).
|
|
175
|
-
*/
|
|
176
|
-
declare function buildCodexUsageWindowFromCache(usedPercent: number | null | undefined, resetAt: Date | string | null | undefined, limitWindowSeconds: number): CodexUsageWindow | null;
|
|
177
|
-
/**
|
|
178
|
-
* Normalize a /wham/usage fetch result into the P2/P3 contract.
|
|
179
|
-
*
|
|
180
|
-
* @param httpStatus the HTTP status from fetchCodexUsage (404 ⇒ a limit body)
|
|
181
|
-
* @param rawPayload the parsed JSON body (or null when the body was unreadable)
|
|
182
|
-
*/
|
|
183
|
-
declare function normalizeCodexUsage(httpStatus: number, rawPayload: unknown): CodexUsagePayload;
|
|
184
|
-
|
|
185
|
-
type CodexAuthHeaders = {
|
|
186
|
-
accessToken: string;
|
|
187
|
-
chatgptAccountId: string | null;
|
|
188
|
-
isFedramp: boolean;
|
|
189
|
-
clientVersion: string;
|
|
190
|
-
};
|
|
191
|
-
type ResetCreditFetchFailureReason = "http_error" | "invalid_response" | "network_error" | "timeout";
|
|
192
|
-
/** GET /codex/models — login-check + live catalog. A 200 means the token is accepted. spec §1.4/§F */
|
|
193
|
-
declare function fetchCodexModels(a: CodexAuthHeaders, fetchImpl?: CodexFetch, timeoutMs?: number): Promise<{
|
|
194
|
-
ok: boolean;
|
|
195
|
-
status: number;
|
|
196
|
-
slugs: string[];
|
|
197
|
-
}>;
|
|
198
|
-
/** GET /wham/usage — authoritative limits. NB the WHAM base is /backend-api, NOT /codex (spec §1.8a). */
|
|
199
|
-
declare function fetchCodexUsage(a: CodexAuthHeaders, fetchImpl?: CodexFetch, timeoutMs?: number): Promise<{
|
|
200
|
-
status: number;
|
|
201
|
-
payload: unknown;
|
|
202
|
-
}>;
|
|
203
|
-
/**
|
|
204
|
-
* GET /wham/rate-limit-reset-credits — detailed earned reset credits.
|
|
205
|
-
*
|
|
206
|
-
* A non-2xx or malformed body returns an explicit non-ok result. The caller may
|
|
207
|
-
* fall back to the count-only summary embedded in /wham/usage, but must never
|
|
208
|
-
* invent actionable rows from that count.
|
|
209
|
-
*/
|
|
210
|
-
declare function fetchCodexRateLimitResetCredits(a: CodexAuthHeaders, fetchImpl?: CodexFetch, timeoutMs?: number): Promise<{
|
|
211
|
-
ok: true;
|
|
212
|
-
status: number;
|
|
213
|
-
details: CodexRateLimitResetCreditsDetails;
|
|
214
|
-
} | {
|
|
215
|
-
ok: false;
|
|
216
|
-
status: number;
|
|
217
|
-
reason: ResetCreditFetchFailureReason;
|
|
218
|
-
}>;
|
|
219
|
-
/**
|
|
220
|
-
* POST /wham/rate-limit-reset-credits/consume with the exact v0.144.6 body.
|
|
221
|
-
* `idempotencyKey` identifies one logical human redemption and MUST be reused
|
|
222
|
-
* by the server on retries. Supplying `creditId` is preferred; omission leaves
|
|
223
|
-
* provider selection in control and is therefore not used by OpenGeni's
|
|
224
|
-
* human-only flow.
|
|
225
|
-
*/
|
|
226
|
-
declare function consumeCodexRateLimitResetCredit(a: CodexAuthHeaders, input: {
|
|
227
|
-
idempotencyKey: string;
|
|
228
|
-
creditId?: string | undefined;
|
|
229
|
-
}, fetchImpl?: CodexFetch, timeoutMs?: number): Promise<{
|
|
230
|
-
ok: true;
|
|
231
|
-
status: number;
|
|
232
|
-
result: CodexRateLimitResetConsumeResponse;
|
|
233
|
-
} | {
|
|
234
|
-
ok: false;
|
|
235
|
-
status: number;
|
|
236
|
-
reason: ResetCreditFetchFailureReason | "invalid_request";
|
|
237
|
-
}>;
|
|
238
|
-
|
|
239
|
-
type CodexTokenSnapshot = {
|
|
240
|
-
accessToken: string;
|
|
241
|
-
chatgptAccountId: string | null;
|
|
242
|
-
isFedramp: boolean;
|
|
243
|
-
};
|
|
244
|
-
/**
|
|
245
|
-
* Multi-account P4 (Part A): a full usage snapshot scraped FOR FREE from the
|
|
246
|
-
* `x-codex-primary-*` / `x-codex-secondary-*` response headers the codex backend
|
|
247
|
-
* stamps on every `/codex/responses` turn (success AND 429 hard-cap). Integer-
|
|
248
|
-
* identical to GET /wham/usage but with zero extra round-trip. parseCodexUsageHeaders
|
|
249
|
-
* returns this only when BOTH windows parse, so a write is always a full 5-column
|
|
250
|
-
* snapshot (no partial-window clobber). Shape mirrors db's CodexAccountUsageSnapshot
|
|
251
|
-
* (non-null here: a partial read is filtered to null upstream, never half-written).
|
|
252
|
-
*/
|
|
253
|
-
type CodexUsageHeaderSnapshot = {
|
|
254
|
-
primaryUsedPercent: number;
|
|
255
|
-
primaryResetAt: Date;
|
|
256
|
-
secondaryUsedPercent: number;
|
|
257
|
-
secondaryResetAt: Date;
|
|
258
|
-
checkedAt: Date;
|
|
259
|
-
};
|
|
260
|
-
type CodexResponseTimeoutClass = "connect" | "headers" | "idle_stream" | "whole_request";
|
|
261
|
-
type CodexResponseTimeoutPolicy = {
|
|
262
|
-
/** Maximum wait for response headers, including DNS/TCP/TLS establishment. */
|
|
263
|
-
headersTimeoutMs: number;
|
|
264
|
-
/** Maximum silence between response-body chunks after headers arrive. */
|
|
265
|
-
streamIdleTimeoutMs: number;
|
|
266
|
-
/** Maximum wall time for one logical Responses request. */
|
|
267
|
-
wholeRequestTimeoutMs: number;
|
|
268
|
-
/**
|
|
269
|
-
* Reserved compatibility field. It is currently normalized to zero because
|
|
270
|
-
* an absent response does not prove that the provider never accepted a
|
|
271
|
-
* request, so automatic replay is not safe without an operation receipt.
|
|
272
|
-
*/
|
|
273
|
-
noByteRetries: number;
|
|
274
|
-
retryBackoffMs: number;
|
|
275
|
-
};
|
|
276
|
-
type CodexModelRequestEvent = {
|
|
277
|
-
requestId: string;
|
|
278
|
-
transportAttempt: number;
|
|
279
|
-
phase: "started" | "headers" | "first_byte" | "completed" | "failed" | "timed_out";
|
|
280
|
-
model?: string;
|
|
281
|
-
durationMs: number;
|
|
282
|
-
responseObserved: boolean;
|
|
283
|
-
timeoutPolicy: CodexResponseTimeoutPolicy;
|
|
284
|
-
timeoutClass?: CodexResponseTimeoutClass;
|
|
285
|
-
providerRequestId?: string;
|
|
286
|
-
status?: number;
|
|
287
|
-
willRetry?: boolean;
|
|
288
|
-
};
|
|
289
|
-
type CodexRequestContext = {
|
|
290
|
-
clientVersion: string;
|
|
291
|
-
/**
|
|
292
|
-
* Stable per-session affinity id, sent as the `session_id` header on every
|
|
293
|
-
* request. This is the backend's STICKY CACHE-ROUTING key — measured
|
|
294
|
-
* 2026-07-12 with byte-identical ~99k-token gpt-5.6-sol requests on one idle
|
|
295
|
-
* account: without the header, repeat requests hit the prompt cache ~50% of
|
|
296
|
-
* the time (a per-request routing lottery across cache shards; matches the
|
|
297
|
-
* prod fleet's 48.6%); with a stable session_id, 10/10 requests hit at the
|
|
298
|
-
* 99.0% ceiling — Codex CLI parity (the CLI always sends it; its own last-3d
|
|
299
|
-
* token-weighted rate here is 94%). `prompt_cache_key` in the body only
|
|
300
|
-
* influences routing and does NOT pin it. Use the SAME value as
|
|
301
|
-
* prompt_cache_key (the OpenGeni sessionId) so routing and cache key agree.
|
|
302
|
-
*/
|
|
303
|
-
sessionId?: string;
|
|
304
|
-
/** Worker-supplied: proactive refresh + single-flight + db persist. */
|
|
305
|
-
getToken: () => Promise<CodexTokenSnapshot>;
|
|
306
|
-
/** Forced refresh used for the 401 retry. */
|
|
307
|
-
refresh: () => Promise<CodexTokenSnapshot>;
|
|
308
|
-
/** Model-slug resolver (longest-prefix against the live catalog). */
|
|
309
|
-
resolveModel: (slug: string) => string;
|
|
310
|
-
/**
|
|
311
|
-
* Multi-account P4 (Part A): fire-and-forget usage-header sink. Called by
|
|
312
|
-
* codexSubscriptionFetch on EVERY response (sync, non-throwing, never awaited)
|
|
313
|
-
* with the parsed full-window snapshot. The worker records the latest into the
|
|
314
|
-
* P2 usage cache once per turn in its `finally` — packages/codex stays db-free.
|
|
315
|
-
*/
|
|
316
|
-
onUsageHeaders?: (snapshot: CodexUsageHeaderSnapshot) => void;
|
|
317
|
-
/** Optional per-run override, primarily for deterministic transport tests. */
|
|
318
|
-
responseTimeoutPolicy?: Partial<CodexResponseTimeoutPolicy>;
|
|
319
|
-
/** Worker-owned durable audit sink; payloads never contain request bodies or auth. */
|
|
320
|
-
onModelRequestEvent?: (event: CodexModelRequestEvent) => Promise<void> | void;
|
|
321
|
-
/** Stable request identity supplied by the owning durable execution. */
|
|
322
|
-
nextRequestId?: () => string;
|
|
323
|
-
};
|
|
324
|
-
declare const codexRequestStorage: AsyncLocalStorage<CodexRequestContext>;
|
|
325
|
-
|
|
326
|
-
declare const CODEX_RESPONSE_TIMEOUT_ERROR_TYPE = "opengeni_codex_response_timeout";
|
|
327
|
-
declare const DEFAULT_CODEX_RESPONSE_TIMEOUT_POLICY: CodexResponseTimeoutPolicy;
|
|
328
|
-
declare function resolveCodexResponseTimeoutPolicy(override: Partial<CodexResponseTimeoutPolicy> | undefined): CodexResponseTimeoutPolicy;
|
|
329
|
-
declare class CodexResponseTimeoutError extends Error {
|
|
330
|
-
readonly timeoutClass: CodexResponseTimeoutClass;
|
|
331
|
-
readonly requestId: string;
|
|
332
|
-
readonly responseObserved: boolean;
|
|
333
|
-
readonly code = "opengeni_codex_response_timeout";
|
|
334
|
-
readonly type = "opengeni_codex_response_timeout";
|
|
335
|
-
constructor(timeoutClass: CodexResponseTimeoutClass, requestId: string, responseObserved: boolean, message?: string);
|
|
336
|
-
}
|
|
337
|
-
type CodexResponseTimeoutInfo = {
|
|
338
|
-
timeoutClass: CodexResponseTimeoutClass;
|
|
339
|
-
requestId: string | null;
|
|
340
|
-
responseObserved: boolean;
|
|
341
|
-
message: string;
|
|
342
|
-
};
|
|
343
|
-
/**
|
|
344
|
-
* Recover structured transport timeouts through SDK wrapping. The optional
|
|
345
|
-
* legacy match is deliberately opt-in: `Request timed out.` alone has no
|
|
346
|
-
* provider provenance and the worker enables it only for a confirmed Codex
|
|
347
|
-
* subscription turn.
|
|
348
|
-
*/
|
|
349
|
-
declare function classifyCodexResponseTimeoutError(error: unknown, options?: {
|
|
350
|
-
allowLegacyRequestTimeout?: boolean;
|
|
351
|
-
}): CodexResponseTimeoutInfo | null;
|
|
352
|
-
declare function isPreHeadersTimeoutError(error: unknown): CodexResponseTimeoutClass | null;
|
|
353
|
-
|
|
354
|
-
type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
355
|
-
/**
|
|
356
|
-
* Internal provenance marker copied onto buffered non-OK Codex responses.
|
|
357
|
-
* OpenAI's APIError preserves response headers, which lets the worker
|
|
358
|
-
* distinguish a model-provider refusal from an unrelated sandbox/MCP HTTP
|
|
359
|
-
* error that happened during the same Codex turn.
|
|
360
|
-
*/
|
|
361
|
-
declare const CODEX_TRANSPORT_ERROR_HEADER = "x-opengeni-codex-transport-error";
|
|
362
|
-
/** True only for an error produced from this Codex transport's non-OK response. */
|
|
363
|
-
declare function isCodexTransportError(error: unknown): boolean;
|
|
364
|
-
/**
|
|
365
|
-
* Multi-account P4 (Part A): scrape the full usage snapshot the codex backend
|
|
366
|
-
* stamps on every `/codex/responses` response in `x-codex-primary-*` /
|
|
367
|
-
* `x-codex-secondary-*` headers (integer-identical to GET /wham/usage, for free).
|
|
368
|
-
*
|
|
369
|
-
* CRITICAL clobber-fix: return null unless BOTH windows expose a valid used-percent
|
|
370
|
-
* integer. recordCodexAccountUsage writes all five columns unconditionally, so a
|
|
371
|
-
* primary-only snapshot would null the weekly column. Both windows are always
|
|
372
|
-
* emitted together on `/codex/responses`; gating on both makes every write a full
|
|
373
|
-
* 5-column snapshot byte-identical to the poll path, and a malformed/absent header
|
|
374
|
-
* set simply no-ops (the /wham/usage poll fallback still covers it).
|
|
375
|
-
*/
|
|
376
|
-
declare function parseCodexUsageHeaders(headers: Headers): CodexUsageHeaderSnapshot | null;
|
|
377
|
-
declare function codexSubscriptionFetch(base?: FetchLike): FetchLike;
|
|
378
|
-
/** The codex backend's hard-cap error type (ChatGPT/Codex usage limit reached). */
|
|
379
|
-
declare const CODEX_USAGE_LIMIT_ERROR_TYPE = "usage_limit_reached";
|
|
380
|
-
type CodexUsageLimitInfo = {
|
|
381
|
-
/** Seconds until the usage cap resets, when the backend reported it. */
|
|
382
|
-
resetsInSeconds: number | null;
|
|
383
|
-
};
|
|
384
|
-
/**
|
|
385
|
-
* Classify a thrown error as a ChatGPT/Codex usage-cap (429 usage_limit_reached)
|
|
386
|
-
* and extract the reset window. The SDK surfaces the codex backend's 429 as an
|
|
387
|
-
* OpenAI APIError whose `.type` (and `.error.type`) is `usage_limit_reached` and
|
|
388
|
-
* whose `.error.resets_in_seconds` carries the cap reset. Walks the cause chain
|
|
389
|
-
* and tolerates the message-only shape so it survives any SDK re-wrapping.
|
|
390
|
-
* Returns null for anything that is not a usage cap.
|
|
391
|
-
*/
|
|
392
|
-
declare function classifyCodexUsageLimitError(error: unknown): CodexUsageLimitInfo | null;
|
|
393
|
-
type CodexSseFailureProjection = {
|
|
394
|
-
status: number;
|
|
395
|
-
error: {
|
|
396
|
-
type: string;
|
|
397
|
-
code: string;
|
|
398
|
-
message: string;
|
|
399
|
-
param?: string;
|
|
400
|
-
event_type?: string;
|
|
401
|
-
response_id?: string;
|
|
402
|
-
response_status?: string;
|
|
403
|
-
diagnostic_truncated?: true;
|
|
404
|
-
};
|
|
405
|
-
headers: Headers;
|
|
406
|
-
};
|
|
407
|
-
/**
|
|
408
|
-
* A provider terminal carried inside an accepted HTTP-200 stream. The OpenAI
|
|
409
|
-
* SDK cannot turn that late terminal into a non-2xx APIError because headers
|
|
410
|
-
* have already been accepted, so the body transform throws this equivalent
|
|
411
|
-
* bounded shape. Provider-supplied message/param text is intentionally absent:
|
|
412
|
-
* the worker may persist Error.message, while identifiers/classifications are
|
|
413
|
-
* sufficient for retry, compaction, and incident diagnostics.
|
|
414
|
-
*/
|
|
415
|
-
declare class CodexStreamingTerminalError extends Error {
|
|
416
|
-
readonly status: number;
|
|
417
|
-
readonly code: string;
|
|
418
|
-
readonly type: string;
|
|
419
|
-
readonly eventType?: string;
|
|
420
|
-
readonly responseId?: string;
|
|
421
|
-
readonly responseStatus?: string;
|
|
422
|
-
readonly headers: Headers;
|
|
423
|
-
readonly error: Record<string, unknown>;
|
|
424
|
-
constructor(projection: CodexSseFailureProjection, publicMessage: string);
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
/**
|
|
428
|
-
* Maps connector tool names to a Responses-API-legal charset and back. One
|
|
429
|
-
* instance per codex_apps transport (i.e. per turn): tools/list populates it,
|
|
430
|
-
* tools/call reads it. Idempotent across repeat listings.
|
|
431
|
-
*/
|
|
432
|
-
declare class ToolNameMapper {
|
|
433
|
-
private readonly sanitizedToOriginal;
|
|
434
|
-
private readonly used;
|
|
435
|
-
/** Return a legal, unique name (<= EFFECTIVE_MAX_TOOL_NAME_LEN, so `<prefix>__name` <= 64) for `original`, recording the reverse mapping. */
|
|
436
|
-
sanitize(original: string): string;
|
|
437
|
-
/** Reverse a sanitized name back to the MCP server's original, if known. */
|
|
438
|
-
toOriginal(sanitized: string): string | undefined;
|
|
439
|
-
}
|
|
440
|
-
/** Sanitize a single JSON body (application/json MCP response). */
|
|
441
|
-
declare function sanitizeMcpJsonBody(text: string, mapper?: ToolNameMapper, namespaceSink?: Set<string>): string;
|
|
442
|
-
/** Sanitize an SSE body: each JSON-RPC message rides on a `data:` line. */
|
|
443
|
-
declare function sanitizeMcpSseBody(text: string, mapper?: ToolNameMapper, namespaceSink?: Set<string>): string;
|
|
444
|
-
/** Reverse a sanitized tools/call name back to the original; returns null if no rewrite is needed. */
|
|
445
|
-
declare function remapToolCallRequestBody(body: string, mapper: ToolNameMapper): string | null;
|
|
446
|
-
/**
|
|
447
|
-
* Wrap a base fetch so the codex_apps MCP transport is Responses-API-compatible:
|
|
448
|
-
* tools/list responses get their names sanitized + bad outputSchemas dropped (and
|
|
449
|
-
* the name mapping recorded), and tools/call requests get their name reversed back
|
|
450
|
-
* to the MCP server's original. Only the POST request/response is buffered; the
|
|
451
|
-
* long-lived GET notification SSE stream is passed through untouched.
|
|
452
|
-
*
|
|
453
|
-
* P4 (Part B.1): an optional `namespaceSink` Set accumulates the ORIGINAL-dotted
|
|
454
|
-
* connector namespaces seen across every tools/list this turn (captured before the
|
|
455
|
-
* dot is sanitized away). The worker reads the (live, by-reference) Set after the
|
|
456
|
-
* turn to cache the serving account's connector set — packages/codex stays db-free.
|
|
457
|
-
*/
|
|
458
|
-
declare function codexAppsSanitizingFetch(base?: FetchLike, namespaceSink?: Set<string>): FetchLike;
|
|
459
|
-
|
|
460
|
-
/**
|
|
461
|
-
* Protocol-valid image shown to the model when an inline tool image exceeds the
|
|
462
|
-
* hard model-input allowance. The image channel cannot carry a text marker, so
|
|
463
|
-
* the omission itself is rendered as a legible PNG instead of corrupting the
|
|
464
|
-
* original base64 or pretending the placeholder is the real screenshot.
|
|
465
|
-
*
|
|
466
|
-
* Generated with the dependency-free bitmap/PNG encoder documented in
|
|
467
|
-
* `scripts/gen-screenshot-error-card.mjs`; the source image is 1,076x284 RGBA
|
|
468
|
-
* and 5,255 bytes. Rendered text:
|
|
469
|
-
*
|
|
470
|
-
* SCREEN CAPTURE OMITTED
|
|
471
|
-
* THE SCREEN CAPTURE IS TOO LARGE.
|
|
472
|
-
* THIS IS A PLACEHOLDER, NOT THE REAL SCREEN.
|
|
473
|
-
* DO NOT SAY THIS IS THE REAL SCREEN.
|
|
474
|
-
* TELL THE USER TO TAKE A SMALLER CAPTURE.
|
|
475
|
-
*/
|
|
476
|
-
declare const MODEL_TOOL_OUTPUT_OVERSIZED_IMAGE_CARD_DATA_URL = "data:image/png;base64,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";
|
|
477
|
-
|
|
478
|
-
/**
|
|
479
|
-
* Canonical model-facing tool-output truncation.
|
|
480
|
-
*
|
|
481
|
-
* Ported from openai/codex `rust-v0.144.6` (commit
|
|
482
|
-
* 5d1fbf26c43abc65a203928b2e31561cb039e06d):
|
|
483
|
-
*
|
|
484
|
-
* - `codex-rs/utils/string/src/truncate.rs`
|
|
485
|
-
* - `codex-rs/utils/output-truncation/src/lib.rs`
|
|
486
|
-
* - `codex-rs/core/src/context_manager/history.rs`
|
|
487
|
-
*
|
|
488
|
-
* The live gpt-5.6 model catalog declares a 10,000-token truncation policy.
|
|
489
|
-
* Codex applies a 1.2x allowance before serializing a function-call output, so
|
|
490
|
-
* the effective textual payload budget is 12,000 approximate tokens. Images,
|
|
491
|
-
* files, and encrypted content are preserved; textual content shares one
|
|
492
|
-
* sequential budget and carries an explicit head/tail truncation marker.
|
|
493
|
-
*
|
|
494
|
-
* This module deliberately has no database or Agents SDK dependency. Both the
|
|
495
|
-
* runtime request seam and the database history boundary call the same pure
|
|
496
|
-
* function, so replayed conversation truth is identical to live model input.
|
|
497
|
-
*/
|
|
498
|
-
|
|
499
|
-
type ModelHistoryItem = Record<string, unknown>;
|
|
500
|
-
declare const CODEX_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS = 10000;
|
|
501
|
-
declare const CODEX_TOOL_OUTPUT_SERIALIZATION_ALLOWANCE = 1.2;
|
|
502
|
-
declare const DEFAULT_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS = 10000;
|
|
503
|
-
declare const MODEL_TOOL_OUTPUT_OPAQUE_PAYLOAD_MAX_BYTES: number;
|
|
504
|
-
declare function modelToolOutputSerializationBudgetTokens(policyTokens?: number): number;
|
|
505
|
-
declare function approximateTokenCount(value: string): number;
|
|
506
|
-
/** Exact Codex-style middle truncation for a token policy. */
|
|
507
|
-
declare function truncateMiddleWithTokenBudget(value: string, maxTokens: number): string;
|
|
508
|
-
/**
|
|
509
|
-
* Bound every model-visible tool-result item. Non-result items are returned by
|
|
510
|
-
* reference. Result items are cloned only when their textual output changes.
|
|
511
|
-
*/
|
|
512
|
-
declare function boundModelToolOutputItem<T extends ModelHistoryItem>(item: T, policyTokens?: number): T;
|
|
513
|
-
declare function boundModelToolOutputItems<T extends ModelHistoryItem>(items: readonly T[], policyTokens?: number): T[];
|
|
514
|
-
|
|
515
|
-
export { CODEX_FIVE_HOUR_WINDOW_SECONDS, CODEX_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS, CODEX_RATE_LIMIT_RESET_OUTCOMES, CODEX_RESPONSE_TIMEOUT_ERROR_TYPE, CODEX_TOOL_OUTPUT_SERIALIZATION_ALLOWANCE, CODEX_TRANSPORT_ERROR_HEADER, CODEX_USAGE_LIMIT_ERROR_TYPE, CODEX_WEEKLY_WINDOW_SECONDS, type CodexAdditionalLimit, type CodexAuthHeaders, CodexDeviceError, type CodexDeviceStart, type CodexFetch, type CodexModelRequestEvent, type CodexPollResult, type CodexRateLimitResetConsumeResponse, type CodexRateLimitResetCredit, type CodexRateLimitResetCreditStatus, type CodexRateLimitResetCreditsDetails, type CodexRateLimitResetCreditsSummary, type CodexRateLimitResetOutcome, type CodexRateLimitResetType, type CodexRefreshTokens, CodexRefreshTransient, CodexReloginRequired, type CodexRequestContext, type CodexResponseTimeoutClass, CodexResponseTimeoutError, type CodexResponseTimeoutInfo, type CodexResponseTimeoutPolicy, type CodexSseFailureProjection, CodexStreamingTerminalError, type CodexTokenSnapshot, type CodexTokens, type CodexUsageHeaderSnapshot, type CodexUsageLimitInfo, type CodexUsagePayload, type CodexUsageStatus, type CodexUsageWindow, DEFAULT_CODEX_RESPONSE_TIMEOUT_POLICY, DEFAULT_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS, type FetchLike, MODEL_TOOL_OUTPUT_OPAQUE_PAYLOAD_MAX_BYTES, MODEL_TOOL_OUTPUT_OVERSIZED_IMAGE_CARD_DATA_URL, type ModelHistoryItem, type ResetCreditFetchFailureReason, ToolNameMapper, accessTokenExpiry, approximateTokenCount, boundModelToolOutputItem, boundModelToolOutputItems, buildCodexUsageWindowFromCache, buildModelResolver, classifyCodexResponseTimeoutError, classifyCodexUsageLimitError, codexAppsSanitizingFetch, codexRequestStorage, codexSubscriptionFetch, consumeCodexRateLimitResetCredit, decodeJwtPayload, exchangeDeviceCode, fetchCodexModels, fetchCodexRateLimitResetCredits, fetchCodexUsage, isCodexBilledModel, isCodexTransportError, isPreHeadersTimeoutError, modelToolOutputSerializationBudgetTokens, normalizeCodexRequestBody, normalizeCodexUsage, parseCodexRateLimitResetConsumeResponse, parseCodexRateLimitResetCreditsDetails, parseCodexRateLimitResetCreditsSummary, parseCodexUsageHeaders, parseIdToken, pollDeviceCode, refreshCodexToken, remapToolCallRequestBody, resolveCodexResponseTimeoutPolicy, sanitizeMcpJsonBody, sanitizeMcpSseBody, startDeviceCode, truncateMiddleWithTokenBudget };
|
|
1
|
+
export * from "./constants";
|
|
2
|
+
export * from "./billing";
|
|
3
|
+
export * from "./device-code";
|
|
4
|
+
export * from "./refresh";
|
|
5
|
+
export * from "./normalize";
|
|
6
|
+
export * from "./usage-normalize";
|
|
7
|
+
export * from "./reset-credits";
|
|
8
|
+
export * from "./api-client";
|
|
9
|
+
export * from "./request-context";
|
|
10
|
+
export * from "./response-timeout";
|
|
11
|
+
export * from "./fetch";
|
|
12
|
+
export * from "./mcp-sanitize";
|
|
13
|
+
export * from "./model-output-truncation";
|
package/dist/index.js
CHANGED
|
@@ -261,7 +261,8 @@ var CODEX_ALLOWED_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
|
261
261
|
"stream",
|
|
262
262
|
"include",
|
|
263
263
|
"prompt_cache_key",
|
|
264
|
-
"text"
|
|
264
|
+
"text",
|
|
265
|
+
"service_tier"
|
|
265
266
|
]);
|
|
266
267
|
function normalizeCodexRequestBody(body, resolveModel) {
|
|
267
268
|
body.store = false;
|
|
@@ -652,6 +653,11 @@ async function consumeCodexRateLimitResetCredit(a, input, fetchImpl = fetch, tim
|
|
|
652
653
|
// src/request-context.ts
|
|
653
654
|
import { AsyncLocalStorage } from "async_hooks";
|
|
654
655
|
var codexRequestStorage = new AsyncLocalStorage();
|
|
656
|
+
function withCodexRequestOverrides(overrides, fn) {
|
|
657
|
+
const current = codexRequestStorage.getStore();
|
|
658
|
+
if (!current) return fn();
|
|
659
|
+
return codexRequestStorage.run({ ...current, ...overrides }, fn);
|
|
660
|
+
}
|
|
655
661
|
|
|
656
662
|
// src/response-timeout.ts
|
|
657
663
|
var CODEX_RESPONSE_TIMEOUT_ERROR_TYPE = "opengeni_codex_response_timeout";
|
|
@@ -767,6 +773,31 @@ function isCodexTransportError(error) {
|
|
|
767
773
|
}
|
|
768
774
|
return false;
|
|
769
775
|
}
|
|
776
|
+
function classifyCodexEncryptedArtifactRejection(error) {
|
|
777
|
+
if (!isCodexTransportError(error)) return null;
|
|
778
|
+
let current = error;
|
|
779
|
+
for (let depth = 0; depth < 6 && current && typeof current === "object"; depth += 1) {
|
|
780
|
+
const value = current;
|
|
781
|
+
const body = value.error && typeof value.error === "object" ? value.error : null;
|
|
782
|
+
const status = Number(value.status ?? body?.status);
|
|
783
|
+
const message = [
|
|
784
|
+
typeof value.message === "string" ? value.message : "",
|
|
785
|
+
typeof body?.message === "string" ? body.message : "",
|
|
786
|
+
typeof value.code === "string" ? value.code : "",
|
|
787
|
+
typeof body?.code === "string" ? body.code : "",
|
|
788
|
+
typeof value.type === "string" ? value.type : "",
|
|
789
|
+
typeof body?.type === "string" ? body.type : ""
|
|
790
|
+
].join(" ").toLowerCase();
|
|
791
|
+
const unsupportedFieldShape = /(?:invalid value|supported values?|unsupported|unknown (?:field|parameter|value))/.test(
|
|
792
|
+
message
|
|
793
|
+
);
|
|
794
|
+
if (status === 400 && !unsupportedFieldShape && /(?:encrypted[_ ]content|encrypted reasoning|reasoning artifact)/.test(message) && /(?:decrypt(?:ed|ion)?|could not be parsed|cannot be parsed|failed to parse)/.test(message)) {
|
|
795
|
+
return { status: 400, kind: "encrypted_content_rejected" };
|
|
796
|
+
}
|
|
797
|
+
current = value.cause;
|
|
798
|
+
}
|
|
799
|
+
return null;
|
|
800
|
+
}
|
|
770
801
|
function parseIntHeader(value) {
|
|
771
802
|
if (value === null) {
|
|
772
803
|
return null;
|
|
@@ -930,7 +961,9 @@ async function observedResponse(res, audit, externalSignal) {
|
|
|
930
961
|
if (externalSignal?.aborted) {
|
|
931
962
|
abortFromOutside();
|
|
932
963
|
} else {
|
|
933
|
-
externalSignal?.addEventListener("abort", abortFromOutside, {
|
|
964
|
+
externalSignal?.addEventListener("abort", abortFromOutside, {
|
|
965
|
+
once: true
|
|
966
|
+
});
|
|
934
967
|
}
|
|
935
968
|
},
|
|
936
969
|
async pull(controller) {
|
|
@@ -990,7 +1023,11 @@ async function observedResponse(res, audit, externalSignal) {
|
|
|
990
1023
|
});
|
|
991
1024
|
const headers = new Headers(res.headers);
|
|
992
1025
|
headers.delete("content-length");
|
|
993
|
-
return new Response(body, {
|
|
1026
|
+
return new Response(body, {
|
|
1027
|
+
status: res.status,
|
|
1028
|
+
statusText: res.statusText,
|
|
1029
|
+
headers
|
|
1030
|
+
});
|
|
994
1031
|
}
|
|
995
1032
|
function timeoutErrorResponse(info) {
|
|
996
1033
|
return new Response(
|
|
@@ -1045,6 +1082,12 @@ function codexSubscriptionFetch(base = globalThis.fetch) {
|
|
|
1045
1082
|
}
|
|
1046
1083
|
headers.delete("OpenAI-Beta");
|
|
1047
1084
|
headers.delete("x-api-key");
|
|
1085
|
+
if (ctx.betaFeatures && ctx.betaFeatures.length > 0) {
|
|
1086
|
+
headers.set("x-codex-beta-features", ctx.betaFeatures.join(","));
|
|
1087
|
+
}
|
|
1088
|
+
if (ctx.turnMetadata && Object.keys(ctx.turnMetadata).length > 0) {
|
|
1089
|
+
headers.set("x-codex-turn-metadata", JSON.stringify(ctx.turnMetadata));
|
|
1090
|
+
}
|
|
1048
1091
|
let callerWantsStream = true;
|
|
1049
1092
|
let model;
|
|
1050
1093
|
const nextInit = { ...init, headers };
|
|
@@ -2234,6 +2277,7 @@ export {
|
|
|
2234
2277
|
boundModelToolOutputItems,
|
|
2235
2278
|
buildCodexUsageWindowFromCache,
|
|
2236
2279
|
buildModelResolver,
|
|
2280
|
+
classifyCodexEncryptedArtifactRejection,
|
|
2237
2281
|
classifyCodexResponseTimeoutError,
|
|
2238
2282
|
classifyCodexUsageLimitError,
|
|
2239
2283
|
codexAppsSanitizingFetch,
|
|
@@ -2263,6 +2307,7 @@ export {
|
|
|
2263
2307
|
sanitizeMcpJsonBody,
|
|
2264
2308
|
sanitizeMcpSseBody,
|
|
2265
2309
|
startDeviceCode,
|
|
2266
|
-
truncateMiddleWithTokenBudget
|
|
2310
|
+
truncateMiddleWithTokenBudget,
|
|
2311
|
+
withCodexRequestOverrides
|
|
2267
2312
|
};
|
|
2268
2313
|
//# sourceMappingURL=index.js.map
|