@pure01fx/dsh-openai-codex-auth 0.7.3 → 0.9.0
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 +19 -0
- package/README.md +16 -5
- package/client.js +147 -4
- package/lib/catalog.d.ts +5 -0
- package/lib/catalog.js +19 -0
- package/lib/index.d.ts +42 -3
- package/lib/index.js +771 -158
- package/lib/native-adapter.d.ts +7 -0
- package/lib/native-adapter.js +22 -10
- package/lib/native-http.js +8 -0
- package/lib/native-websocket.js +18 -5
- package/lib/replay.d.ts +1 -0
- package/lib/replay.js +8 -2
- package/lib/response-usage.d.ts +4 -2
- package/lib/response-usage.js +26 -6
- package/lib/responses.d.ts +8 -1
- package/lib/responses.js +71 -9
- package/lib/upstream.d.ts +4 -4
- package/lib/upstream.js +4 -4
- package/lib/usage.d.ts +1 -0
- package/lib/usage.js +10 -3
- package/package.json +1 -1
package/lib/native-adapter.d.ts
CHANGED
|
@@ -18,12 +18,19 @@ export declare function nativeCodexWireReasoningEffort(effort: string | undefine
|
|
|
18
18
|
/** Request-scoped native Codex transport owned by this package. */
|
|
19
19
|
export interface NativeCodexTransportMode {
|
|
20
20
|
serviceTier?: typeof CODEX_FAST_SERVICE_TIER;
|
|
21
|
+
/** Enables the model-specific Responses Lite request and routing contract. */
|
|
22
|
+
responsesLite?: {
|
|
23
|
+
defaultVerbosity?: string;
|
|
24
|
+
instructionsTemplate?: string;
|
|
25
|
+
};
|
|
21
26
|
publicModel?: string;
|
|
22
27
|
authorityHash?: string;
|
|
23
28
|
/** Turn-scoped sticky routing state captured from a provider response. */
|
|
24
29
|
turnState?: string;
|
|
25
30
|
/** @internal Receives a newly observed bounded turn-state token. */
|
|
26
31
|
captureTurnState?: (state: string) => void;
|
|
32
|
+
/** @internal Pins WebSocket reconnects and HTTP fallback to one account. */
|
|
33
|
+
pinnedAccountId?: string;
|
|
27
34
|
}
|
|
28
35
|
export interface NativeCodexTransport {
|
|
29
36
|
stream(options: GenerateOptions, mode?: NativeCodexTransportMode): AsyncIterable<StreamChunk>;
|
package/lib/native-adapter.js
CHANGED
|
@@ -53,6 +53,20 @@ function supportsFast(model) {
|
|
|
53
53
|
return model.serviceTiers.some(tier => tier.id === CODEX_FAST_SERVICE_TIER)
|
|
54
54
|
|| model.additionalSpeedTiers.includes('fast');
|
|
55
55
|
}
|
|
56
|
+
function responsesLiteMode(model, requestedModel = model?.slug) {
|
|
57
|
+
if (model !== undefined && !model.useResponsesLite)
|
|
58
|
+
return {};
|
|
59
|
+
// Never downgrade the tracked Lite-only Astra slug to Standard Responses during catalog outages.
|
|
60
|
+
if (model === undefined && requestedModel !== 'gpt-6-astra')
|
|
61
|
+
return {};
|
|
62
|
+
return {
|
|
63
|
+
responsesLite: {
|
|
64
|
+
defaultVerbosity: model?.defaultVerbosity ?? 'low',
|
|
65
|
+
...model?.instructionsTemplate === undefined ? {}
|
|
66
|
+
: { instructionsTemplate: model.instructionsTemplate },
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
56
70
|
function fastRoutes(models) {
|
|
57
71
|
const exact = new Set(models.map(model => model.slug));
|
|
58
72
|
const routes = new Map();
|
|
@@ -81,9 +95,10 @@ export function nativeCodexWireReasoningEffort(effort, model) {
|
|
|
81
95
|
return [...supported].reverse().find(level => level.effort !== 'ultra')?.effort ?? 'medium';
|
|
82
96
|
}
|
|
83
97
|
function withWireReasoning(options, model) {
|
|
84
|
-
const
|
|
98
|
+
const explicit = options.reasoningEffort === undefined ? undefined : String(options.reasoningEffort);
|
|
99
|
+
const selected = explicit ?? (model?.useResponsesLite ? model.defaultReasoningLevel : undefined);
|
|
85
100
|
const wire = nativeCodexWireReasoningEffort(selected, model);
|
|
86
|
-
return wire === undefined || wire ===
|
|
101
|
+
return wire === undefined || wire === explicit
|
|
87
102
|
? options
|
|
88
103
|
: { ...options, reasoningEffort: ReasoningEffortId(wire) };
|
|
89
104
|
}
|
|
@@ -217,7 +232,7 @@ export class NativeCodexAdapter extends LlmAdapter {
|
|
|
217
232
|
this.assertNotAborted(options.signal);
|
|
218
233
|
const exact = view.models.find(candidate => candidate.slug === options.model);
|
|
219
234
|
if (exact !== undefined) {
|
|
220
|
-
yield* this.transport.stream(withWireReasoning(options, exact));
|
|
235
|
+
yield* this.transport.stream(withWireReasoning(options, exact), responsesLiteMode(exact));
|
|
221
236
|
return;
|
|
222
237
|
}
|
|
223
238
|
const fast = fastRoutes(view.models).get(options.model);
|
|
@@ -231,16 +246,13 @@ export class NativeCodexAdapter extends LlmAdapter {
|
|
|
231
246
|
serviceTier: CODEX_FAST_SERVICE_TIER,
|
|
232
247
|
publicModel: options.model,
|
|
233
248
|
authorityHash: view.authorityHash,
|
|
249
|
+
...responsesLiteMode(fast),
|
|
234
250
|
});
|
|
235
251
|
return;
|
|
236
252
|
}
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
const model = selectedEffort === 'ultra'
|
|
240
|
-
? (await this.catalog?.list(options.signal) ?? [])
|
|
241
|
-
.find(candidate => candidate.slug === options.model)
|
|
242
|
-
: undefined;
|
|
253
|
+
const model = (await this.catalog?.list(options.signal) ?? [])
|
|
254
|
+
.find(candidate => candidate.slug === options.model);
|
|
243
255
|
this.assertNotAborted(options.signal);
|
|
244
|
-
yield* this.transport.stream(withWireReasoning(options, model));
|
|
256
|
+
yield* this.transport.stream(withWireReasoning(options, model), responsesLiteMode(model, options.model));
|
|
245
257
|
}
|
|
246
258
|
}
|
package/lib/native-http.js
CHANGED
|
@@ -436,6 +436,7 @@ export class NativeCodexHttpTransport {
|
|
|
436
436
|
let transientRetries = 0;
|
|
437
437
|
let connectionRetryDelayMs = INITIAL_CONNECTION_RETRY_DELAY_MS;
|
|
438
438
|
let recovered = false;
|
|
439
|
+
let pinnedAccountId = mode.pinnedAccountId;
|
|
439
440
|
while (true) {
|
|
440
441
|
throwIfAborted(generation.signal);
|
|
441
442
|
const watchdog = attemptWatchdog(generation.signal, this.requestTimeoutMs, this.idleTimeoutMs);
|
|
@@ -445,6 +446,11 @@ export class NativeCodexHttpTransport {
|
|
|
445
446
|
try {
|
|
446
447
|
credential = await this.options.resolveCredential(watchdog.signal);
|
|
447
448
|
throwIfAborted(watchdog.signal);
|
|
449
|
+
if (pinnedAccountId === undefined)
|
|
450
|
+
pinnedAccountId = credential.accountId;
|
|
451
|
+
else if (credential.accountId !== pinnedAccountId) {
|
|
452
|
+
throw fixedFailure('native Codex account changed during request', 'AUTH');
|
|
453
|
+
}
|
|
448
454
|
if (mode.serviceTier !== undefined
|
|
449
455
|
&& (mode.authorityHash === undefined
|
|
450
456
|
|| nativeCodexAuthorityHash(credential.accountId) !== mode.authorityHash)) {
|
|
@@ -464,6 +470,8 @@ export class NativeCodexHttpTransport {
|
|
|
464
470
|
'x-codex-routing-hint': routingHint,
|
|
465
471
|
...(activeTurnState === undefined ? {} : { 'x-codex-turn-state': activeTurnState }),
|
|
466
472
|
...(generation.purpose === 'compaction' ? { 'x-openai-subagent': 'compact' } : {}),
|
|
473
|
+
...(mode.responsesLite === undefined
|
|
474
|
+
? {} : { 'x-openai-internal-codex-responses-lite': 'true' }),
|
|
467
475
|
accept: 'text/event-stream',
|
|
468
476
|
'content-type': 'application/json',
|
|
469
477
|
...attributionHeaders(),
|
package/lib/native-websocket.js
CHANGED
|
@@ -106,8 +106,8 @@ function turnKey(generation) {
|
|
|
106
106
|
return createHash('sha256')
|
|
107
107
|
.update(`${generation.purpose ?? 'ordinary'}:handbuilt`).digest('base64url');
|
|
108
108
|
}
|
|
109
|
-
function
|
|
110
|
-
if (turnState === undefined)
|
|
109
|
+
function withRequestMetadata(request, turnState, responsesLite) {
|
|
110
|
+
if (turnState === undefined && !responsesLite)
|
|
111
111
|
return request;
|
|
112
112
|
const metadata = typeof request.client_metadata === 'object'
|
|
113
113
|
&& request.client_metadata !== null && !Array.isArray(request.client_metadata)
|
|
@@ -115,7 +115,12 @@ function withTurnState(request, turnState) {
|
|
|
115
115
|
: {};
|
|
116
116
|
return {
|
|
117
117
|
...request,
|
|
118
|
-
client_metadata: {
|
|
118
|
+
client_metadata: {
|
|
119
|
+
...metadata,
|
|
120
|
+
...(turnState === undefined ? {} : { 'x-codex-turn-state': turnState }),
|
|
121
|
+
...(responsesLite
|
|
122
|
+
? { ws_request_header_x_openai_internal_codex_responses_lite: 'true' } : {}),
|
|
123
|
+
},
|
|
119
124
|
};
|
|
120
125
|
}
|
|
121
126
|
function normalizedOutputItem(event) {
|
|
@@ -140,6 +145,7 @@ function normalizedOutputItem(event) {
|
|
|
140
145
|
if (item.type === 'function_call') {
|
|
141
146
|
return {
|
|
142
147
|
type: 'function_call', ...(id === undefined ? {} : { id }),
|
|
148
|
+
...(typeof item.namespace === 'string' ? { namespace: item.namespace } : {}),
|
|
143
149
|
call_id: item.call_id, name: item.name, arguments: item.arguments,
|
|
144
150
|
};
|
|
145
151
|
}
|
|
@@ -446,12 +452,12 @@ export class NativeCodexWebSocketTransport {
|
|
|
446
452
|
let justPrewarmed = false;
|
|
447
453
|
if (!entry.prewarmAttempted) {
|
|
448
454
|
entry.prewarmAttempted = true;
|
|
449
|
-
const warm = entry.protocol.prewarm(
|
|
455
|
+
const warm = entry.protocol.prewarm(withRequestMetadata(prepared.request, entry.turnState, prepared.mode.responsesLite !== undefined));
|
|
450
456
|
for await (const _chunk of this.exchange(entry, warm.payload, prepared.generation, prepared.mode, credential.accountId, true, signal)) { /* prewarm is invisible */ }
|
|
451
457
|
entry.prewarmSucceeded = true;
|
|
452
458
|
justPrewarmed = true;
|
|
453
459
|
}
|
|
454
|
-
const plan = entry.protocol.plan(
|
|
460
|
+
const plan = entry.protocol.plan(withRequestMetadata(prepared.request, entry.turnState, prepared.mode.responsesLite !== undefined), justPrewarmed);
|
|
455
461
|
yield* this.exchange(entry, plan.payload, prepared.generation, prepared.mode, credential.accountId, false, signal);
|
|
456
462
|
if (this.options.onCompleted !== undefined) {
|
|
457
463
|
try {
|
|
@@ -500,10 +506,12 @@ export class NativeCodexWebSocketTransport {
|
|
|
500
506
|
if (entry.turnState === undefined)
|
|
501
507
|
entry.turnState = state;
|
|
502
508
|
},
|
|
509
|
+
...(pinnedAccountId === undefined ? {} : { pinnedAccountId }),
|
|
503
510
|
});
|
|
504
511
|
let reconnects = 0;
|
|
505
512
|
let connectionRetryDelayMs = INITIAL_CONNECTION_RETRY_DELAY_MS;
|
|
506
513
|
let recovered = false;
|
|
514
|
+
let pinnedAccountId = mode.pinnedAccountId;
|
|
507
515
|
let requestCompleted = false;
|
|
508
516
|
try {
|
|
509
517
|
if (entry.disabled) {
|
|
@@ -518,6 +526,11 @@ export class NativeCodexWebSocketTransport {
|
|
|
518
526
|
try {
|
|
519
527
|
const credential = await this.options.resolveCredential(signal);
|
|
520
528
|
attemptedCredential = credential;
|
|
529
|
+
if (pinnedAccountId === undefined)
|
|
530
|
+
pinnedAccountId = credential.accountId;
|
|
531
|
+
else if (credential.accountId !== pinnedAccountId) {
|
|
532
|
+
throw failure('native Codex account changed during request', 'AUTH');
|
|
533
|
+
}
|
|
521
534
|
this.assertFastAuthority(credential, mode);
|
|
522
535
|
for await (const chunk of this.attempt(entry, prepared, credential, signal)) {
|
|
523
536
|
emitted = true;
|
package/lib/replay.d.ts
CHANGED
package/lib/replay.js
CHANGED
|
@@ -86,11 +86,16 @@ function parseDescriptor(value) {
|
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
88
|
if (row.type === 'function_call') {
|
|
89
|
+
const namespace = row.namespace === undefined ? undefined : boundedString(row.namespace);
|
|
89
90
|
if (!Number.isSafeInteger(row.block) || Number(row.block) < 0
|
|
90
|
-
||
|
|
91
|
+
|| (row.namespace !== undefined && namespace === undefined)
|
|
92
|
+
|| !onlyKeys(row, ['type', 'id', 'namespace', 'block'])) {
|
|
91
93
|
throw failure('native Codex function replay descriptor is invalid');
|
|
92
94
|
}
|
|
93
|
-
return {
|
|
95
|
+
return {
|
|
96
|
+
type: 'function_call', ...(id === undefined ? {} : { id }),
|
|
97
|
+
...(namespace === undefined ? {} : { namespace }), block: Number(row.block),
|
|
98
|
+
};
|
|
94
99
|
}
|
|
95
100
|
throw failure('native Codex replay descriptor type is unsupported');
|
|
96
101
|
}
|
|
@@ -220,6 +225,7 @@ export function replayAssistantInput(content, source) {
|
|
|
220
225
|
const block = blockAt(content, used, item.block, 'tool-call');
|
|
221
226
|
input.push({
|
|
222
227
|
type: 'function_call', ...(item.id === undefined ? {} : { id: item.id }),
|
|
228
|
+
...(item.namespace === undefined ? {} : { namespace: item.namespace }),
|
|
223
229
|
call_id: String(block.id), name: block.name, arguments: block.arguments,
|
|
224
230
|
});
|
|
225
231
|
}
|
package/lib/response-usage.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/** Bounded per-response usage metadata emitted by the Codex Responses API. */
|
|
2
2
|
export interface CodexResponseUsageMetadata {
|
|
3
3
|
/** Exact provider representation; never coerce this high-precision value to a number. */
|
|
4
|
-
amount
|
|
4
|
+
amount?: string;
|
|
5
|
+
/** Complete bounded `response.usage` JSON, including fields unknown to this client. */
|
|
6
|
+
metadata?: unknown;
|
|
5
7
|
}
|
|
6
8
|
export interface CodexResponseUsageObservation {
|
|
7
9
|
accountId: string;
|
|
8
10
|
metadata: CodexResponseUsageMetadata;
|
|
9
11
|
}
|
|
10
12
|
export type CodexResponseUsageCallback = (observation: CodexResponseUsageObservation) => void;
|
|
11
|
-
/**
|
|
13
|
+
/** Preserve exact billing amount and the complete bounded response.usage payload. */
|
|
12
14
|
export declare function parseCodexResponseUsageMetadata(value: unknown): CodexResponseUsageMetadata | undefined;
|
|
13
15
|
/** Publish optional response usage without allowing diagnostics to fail generation. */
|
|
14
16
|
export declare function publishCodexResponseUsage(accountId: string, metadata: CodexResponseUsageMetadata | undefined, callback: CodexResponseUsageCallback | undefined, warn: ((message: string) => void) | undefined): void;
|
package/lib/response-usage.js
CHANGED
|
@@ -1,21 +1,41 @@
|
|
|
1
1
|
/** Bounded per-response usage metadata emitted by the Codex Responses API. */
|
|
2
2
|
const MAX_AMOUNT_BYTES = 256;
|
|
3
|
+
const MAX_RAW_USAGE_BYTES = 64 * 1024;
|
|
3
4
|
function record(value) {
|
|
4
5
|
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
5
6
|
? value : undefined;
|
|
6
7
|
}
|
|
7
|
-
|
|
8
|
+
function boundedJson(value) {
|
|
9
|
+
if (value === undefined || value === null)
|
|
10
|
+
return undefined;
|
|
11
|
+
try {
|
|
12
|
+
const encoded = JSON.stringify(value);
|
|
13
|
+
if (encoded === undefined || Buffer.byteLength(encoded) > MAX_RAW_USAGE_BYTES)
|
|
14
|
+
return undefined;
|
|
15
|
+
return JSON.parse(encoded);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Preserve exact billing amount and the complete bounded response.usage payload. */
|
|
8
22
|
export function parseCodexResponseUsageMetadata(value) {
|
|
9
23
|
const event = record(value);
|
|
10
24
|
if (event?.type !== 'response.completed')
|
|
11
25
|
return undefined;
|
|
12
26
|
const response = record(event.response);
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
27
|
+
const usageMetadata = record(response?.usage_metadata);
|
|
28
|
+
const rawAmount = usageMetadata?.amount;
|
|
29
|
+
const amount = typeof rawAmount === 'string' && rawAmount.length > 0
|
|
30
|
+
&& Buffer.byteLength(rawAmount) <= MAX_AMOUNT_BYTES
|
|
31
|
+
? rawAmount : undefined;
|
|
32
|
+
const metadata = boundedJson(response?.usage);
|
|
33
|
+
if (amount === undefined && metadata === undefined)
|
|
17
34
|
return undefined;
|
|
18
|
-
return {
|
|
35
|
+
return {
|
|
36
|
+
...amount === undefined ? {} : { amount },
|
|
37
|
+
...metadata === undefined ? {} : { metadata },
|
|
38
|
+
};
|
|
19
39
|
}
|
|
20
40
|
/** Publish optional response usage without allowing diagnostics to fail generation. */
|
|
21
41
|
export function publishCodexResponseUsage(accountId, metadata, callback, warn) {
|
package/lib/responses.d.ts
CHANGED
|
@@ -26,14 +26,20 @@ export interface ResponsesRequestInput {
|
|
|
26
26
|
input: Record<string, unknown>[];
|
|
27
27
|
}
|
|
28
28
|
export declare function toResponsesTools(tools: readonly ToolSchema[]): Record<string, unknown>[];
|
|
29
|
+
/** Responses Lite loads ordinary DSH functions through one canonical namespace. */
|
|
30
|
+
export declare function toResponsesLiteTools(tools: readonly ToolSchema[]): Record<string, unknown>[];
|
|
29
31
|
/** Convert resolved DSH messages into Responses instructions and ordered input items. */
|
|
30
32
|
export declare function toResponsesInput(messages: readonly ResolvedMessage[], system?: string): ResponsesRequestInput;
|
|
31
33
|
/** Bound call ids while preserving every function call/result correlation. */
|
|
32
34
|
export declare function normalizeCodexCallIds(input: readonly Record<string, unknown>[]): Record<string, unknown>[];
|
|
33
35
|
export interface ResponsesRequestMode {
|
|
34
36
|
serviceTier?: 'priority';
|
|
37
|
+
responsesLite?: {
|
|
38
|
+
defaultVerbosity?: string;
|
|
39
|
+
instructionsTemplate?: string;
|
|
40
|
+
};
|
|
35
41
|
}
|
|
36
|
-
/** Build the canonical Standard/Fast
|
|
42
|
+
/** Build the canonical Standard/Fast or model-specific Responses Lite body. */
|
|
37
43
|
export declare function codexRequestBody(options: GenerateOptions, messages: readonly ResolvedMessage[], mode?: ResponsesRequestMode): Record<string, unknown>;
|
|
38
44
|
export interface ResponsesUsage {
|
|
39
45
|
input_tokens: number;
|
|
@@ -55,6 +61,7 @@ interface ResponsesOutputItem {
|
|
|
55
61
|
id?: string;
|
|
56
62
|
call_id?: string;
|
|
57
63
|
name?: string;
|
|
64
|
+
namespace?: string;
|
|
58
65
|
arguments?: string;
|
|
59
66
|
encrypted_content?: string;
|
|
60
67
|
summary?: unknown[];
|
package/lib/responses.js
CHANGED
|
@@ -7,6 +7,15 @@ export const DEFAULT_CODEX_INSTRUCTIONS = 'You are Codex, an AI coding agent. He
|
|
|
7
7
|
const CALL_ID_MAX_LENGTH = 64;
|
|
8
8
|
const CALL_ID_PREFIX = 'call_';
|
|
9
9
|
const MAX_RETAINED_RESPONSE_BYTES = 64 * 1024 * 1024;
|
|
10
|
+
const UUID_NAMESPACE_OID = Buffer.from('6ba7b8129dad11d180b400c04fd430c8', 'hex');
|
|
11
|
+
function uuidV5(namespace, name) {
|
|
12
|
+
const bytes = createHash('sha1').update(namespace).update(name).digest().subarray(0, 16);
|
|
13
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x50;
|
|
14
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
15
|
+
const hex = bytes.toString('hex');
|
|
16
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
17
|
+
}
|
|
18
|
+
function uuidBytes(value) { return Buffer.from(value.replaceAll('-', ''), 'hex'); }
|
|
10
19
|
function fixedError(message, code) { return new LlmError(message, code); }
|
|
11
20
|
function imageItem(image) {
|
|
12
21
|
if (!/^image[/][a-z0-9.+-]+$/i.test(image.mediaType) || image.dataBase64.length === 0) {
|
|
@@ -32,6 +41,13 @@ export function toResponsesTools(tools) {
|
|
|
32
41
|
type: 'function', name: tool.name, description: tool.description, parameters: tool.parameters,
|
|
33
42
|
}));
|
|
34
43
|
}
|
|
44
|
+
/** Responses Lite loads ordinary DSH functions through one canonical namespace. */
|
|
45
|
+
export function toResponsesLiteTools(tools) {
|
|
46
|
+
const functions = toResponsesTools(tools);
|
|
47
|
+
return functions.length === 0 ? [] : [{
|
|
48
|
+
type: 'namespace', name: 'functions', description: '', tools: functions,
|
|
49
|
+
}];
|
|
50
|
+
}
|
|
35
51
|
/** Convert resolved DSH messages into Responses instructions and ordered input items. */
|
|
36
52
|
export function toResponsesInput(messages, system) {
|
|
37
53
|
const input = [];
|
|
@@ -144,29 +160,72 @@ function assertSupportedOptions(options) {
|
|
|
144
160
|
throw fixedError('native Codex does not support stop sequences', 'UNSUPPORTED');
|
|
145
161
|
}
|
|
146
162
|
}
|
|
147
|
-
/** Build the canonical Standard/Fast
|
|
163
|
+
/** Build the canonical Standard/Fast or model-specific Responses Lite body. */
|
|
148
164
|
export function codexRequestBody(options, messages, mode = {}) {
|
|
149
165
|
assertSupportedOptions(options);
|
|
150
166
|
if (mode.serviceTier !== undefined && mode.serviceTier !== 'priority') {
|
|
151
167
|
throw fixedError('native Codex service tier is invalid', 'INVALID_ARGS');
|
|
152
168
|
}
|
|
153
169
|
const resolved = toResponsesInput(messages, options.system);
|
|
154
|
-
|
|
170
|
+
const instructions = resolved.instructions ?? DEFAULT_CODEX_INSTRUCTIONS;
|
|
171
|
+
const input = normalizeCodexCallIds(resolved.input);
|
|
172
|
+
const common = {
|
|
155
173
|
model: options.model,
|
|
156
|
-
instructions: resolved.instructions ?? DEFAULT_CODEX_INSTRUCTIONS,
|
|
157
|
-
input: normalizeCodexCallIds(resolved.input),
|
|
158
|
-
...options.tools !== undefined && options.tools.length > 0
|
|
159
|
-
? { tools: toResponsesTools(options.tools) } : {},
|
|
160
174
|
tool_choice: 'auto',
|
|
161
|
-
parallel_tool_calls: true,
|
|
162
|
-
...options.reasoningEffort === undefined ? {}
|
|
163
|
-
: { reasoning: { effort: String(options.reasoningEffort), summary: 'auto' } },
|
|
164
175
|
store: false,
|
|
165
176
|
stream: true,
|
|
166
177
|
include: ['reasoning.encrypted_content'],
|
|
167
178
|
...mode.serviceTier === undefined ? {} : { service_tier: mode.serviceTier },
|
|
168
179
|
...options.sessionId === undefined ? {} : { prompt_cache_key: String(options.sessionId) },
|
|
169
180
|
};
|
|
181
|
+
if (mode.responsesLite === undefined) {
|
|
182
|
+
return {
|
|
183
|
+
...common,
|
|
184
|
+
instructions,
|
|
185
|
+
input,
|
|
186
|
+
...options.tools !== undefined && options.tools.length > 0
|
|
187
|
+
? { tools: toResponsesTools(options.tools) } : {},
|
|
188
|
+
parallel_tool_calls: true,
|
|
189
|
+
...options.reasoningEffort === undefined ? {}
|
|
190
|
+
: { reasoning: { effort: String(options.reasoningEffort), summary: 'auto' } },
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
const tools = toResponsesLiteTools(options.tools ?? []);
|
|
194
|
+
const baseInstructions = mode.responsesLite.instructionsTemplate ?? instructions;
|
|
195
|
+
const contextualInstructions = mode.responsesLite.instructionsTemplate !== undefined
|
|
196
|
+
&& resolved.instructions !== undefined && resolved.instructions !== baseInstructions
|
|
197
|
+
? [{
|
|
198
|
+
type: 'message', role: 'developer',
|
|
199
|
+
content: [{ type: 'input_text', text: resolved.instructions }],
|
|
200
|
+
}]
|
|
201
|
+
: [];
|
|
202
|
+
const prefixNamespace = uuidBytes(uuidV5(UUID_NAMESPACE_OID, String(options.sessionId ?? options.model)));
|
|
203
|
+
const prefix = [{
|
|
204
|
+
type: 'additional_tools',
|
|
205
|
+
id: `at_${uuidV5(prefixNamespace, JSON.stringify(tools))}`,
|
|
206
|
+
role: 'developer',
|
|
207
|
+
tools,
|
|
208
|
+
}, {
|
|
209
|
+
type: 'message',
|
|
210
|
+
id: `msg_${uuidV5(prefixNamespace, baseInstructions)}`,
|
|
211
|
+
role: 'developer',
|
|
212
|
+
content: [{ type: 'input_text', text: baseInstructions }],
|
|
213
|
+
internal_chat_message_metadata_passthrough: {
|
|
214
|
+
content_item_kinds: ['model.base_instructions'],
|
|
215
|
+
},
|
|
216
|
+
}];
|
|
217
|
+
return {
|
|
218
|
+
...common,
|
|
219
|
+
input: [...prefix, ...contextualInstructions, ...input],
|
|
220
|
+
parallel_tool_calls: false,
|
|
221
|
+
reasoning: {
|
|
222
|
+
...options.reasoningEffort === undefined ? {} : { effort: String(options.reasoningEffort) },
|
|
223
|
+
summary: 'auto',
|
|
224
|
+
context: 'all_turns',
|
|
225
|
+
},
|
|
226
|
+
...mode.responsesLite.defaultVerbosity === undefined ? {}
|
|
227
|
+
: { text: { verbosity: mode.responsesLite.defaultVerbosity } },
|
|
228
|
+
};
|
|
170
229
|
}
|
|
171
230
|
function tokenCount(value, field, fallback) {
|
|
172
231
|
if (value === undefined && fallback !== undefined)
|
|
@@ -371,6 +430,8 @@ export class ResponsesStreamTranslator {
|
|
|
371
430
|
if (item.type === 'function_call') {
|
|
372
431
|
if (item.call_id === undefined || item.call_id.length === 0
|
|
373
432
|
|| item.name === undefined || item.name.length === 0
|
|
433
|
+
|| (item.namespace !== undefined && (typeof item.namespace !== 'string'
|
|
434
|
+
|| item.namespace.length === 0 || Buffer.byteLength(item.namespace) > 256))
|
|
374
435
|
|| typeof item.arguments !== 'string') {
|
|
375
436
|
throw fixedError('native Codex function call has invalid content', 'MALFORMED_RESPONSE');
|
|
376
437
|
}
|
|
@@ -391,6 +452,7 @@ export class ResponsesStreamTranslator {
|
|
|
391
452
|
if (this.replayContext !== undefined)
|
|
392
453
|
this.replayCapture?.add({
|
|
393
454
|
type: 'function_call', ...(replayId === undefined ? {} : { id: replayId }),
|
|
455
|
+
...(item.namespace === undefined ? {} : { namespace: item.namespace }),
|
|
394
456
|
block: block.index,
|
|
395
457
|
});
|
|
396
458
|
}
|
package/lib/upstream.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Single source of truth for the OpenAI Codex revision this adapter tracks. */
|
|
2
2
|
export declare const TRACKED_CODEX_REPOSITORY = "https://github.com/openai/codex.git";
|
|
3
|
-
export declare const TRACKED_CODEX_COMMIT = "
|
|
4
|
-
export declare const TRACKED_CODEX_RELEASE = "
|
|
5
|
-
/** Whole release version sent to the Codex model-catalog endpoint. */
|
|
6
|
-
export declare const CODEX_CLIENT_VERSION = "0.
|
|
3
|
+
export declare const TRACKED_CODEX_COMMIT = "ddf04ad26789d040f9ef6a96736f76602e35a6cc";
|
|
4
|
+
export declare const TRACKED_CODEX_RELEASE = "main@ddf04ad";
|
|
5
|
+
/** Whole stable release version sent to the Codex model-catalog endpoint. */
|
|
6
|
+
export declare const CODEX_CLIENT_VERSION = "0.153.4";
|
package/lib/upstream.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Single source of truth for the OpenAI Codex revision this adapter tracks. */
|
|
2
2
|
export const TRACKED_CODEX_REPOSITORY = 'https://github.com/openai/codex.git';
|
|
3
|
-
export const TRACKED_CODEX_COMMIT = '
|
|
4
|
-
export const TRACKED_CODEX_RELEASE = '
|
|
5
|
-
/** Whole release version sent to the Codex model-catalog endpoint. */
|
|
6
|
-
export const CODEX_CLIENT_VERSION = '0.
|
|
3
|
+
export const TRACKED_CODEX_COMMIT = 'ddf04ad26789d040f9ef6a96736f76602e35a6cc';
|
|
4
|
+
export const TRACKED_CODEX_RELEASE = 'main@ddf04ad';
|
|
5
|
+
/** Whole stable release version sent to the Codex model-catalog endpoint. */
|
|
6
|
+
export const CODEX_CLIENT_VERSION = '0.153.4';
|
package/lib/usage.d.ts
CHANGED
package/lib/usage.js
CHANGED
|
@@ -33,9 +33,11 @@ function usageLimit(id, name, value) {
|
|
|
33
33
|
const row = value;
|
|
34
34
|
const primary = usageWindow(row.primary_window ?? row.primary);
|
|
35
35
|
const secondary = usageWindow(row.secondary_window ?? row.secondary);
|
|
36
|
-
const
|
|
36
|
+
const explicitLimitReached = typeof row.limit_reached === 'boolean'
|
|
37
37
|
? row.limit_reached
|
|
38
38
|
: typeof row.limitReached === 'boolean' ? row.limitReached : undefined;
|
|
39
|
+
const allowed = typeof row.allowed === 'boolean' ? row.allowed : undefined;
|
|
40
|
+
const limitReached = explicitLimitReached ?? (allowed === undefined ? undefined : !allowed);
|
|
39
41
|
if (primary === undefined && secondary === undefined && limitReached === undefined)
|
|
40
42
|
return undefined;
|
|
41
43
|
return {
|
|
@@ -71,8 +73,13 @@ export function normalizeUsage(value) {
|
|
|
71
73
|
if (id === undefined || id === 'codex' || limits.some(limit => limit.id === id))
|
|
72
74
|
continue;
|
|
73
75
|
const extra = usageLimit(id, boundedUsageText(row.limit_name ?? row.limitName), row.rate_limit ?? row.rateLimit);
|
|
74
|
-
if (extra !== undefined)
|
|
75
|
-
|
|
76
|
+
if (extra !== undefined) {
|
|
77
|
+
const normalModelSlug = boundedUsageText(row.normal_model_slug ?? row.normalModelSlug);
|
|
78
|
+
limits.push({
|
|
79
|
+
...extra,
|
|
80
|
+
...normalModelSlug === undefined ? {} : { normalModelSlug },
|
|
81
|
+
});
|
|
82
|
+
}
|
|
76
83
|
}
|
|
77
84
|
}
|
|
78
85
|
const sortedLimits = sortedUsageLimits(limits);
|
package/package.json
CHANGED