@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.
@@ -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>;
@@ -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 selected = options.reasoningEffort === undefined ? undefined : String(options.reasoningEffort);
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 === selected
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 selectedEffort = options.reasoningEffort === undefined
238
- ? undefined : String(options.reasoningEffort);
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
  }
@@ -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(),
@@ -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 withTurnState(request, turnState) {
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: { ...metadata, 'x-codex-turn-state': turnState },
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(withTurnState(prepared.request, entry.turnState));
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(withTurnState(prepared.request, entry.turnState), justPrewarmed);
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
@@ -14,6 +14,7 @@ export type NativeCodexReplayDescriptor = {
14
14
  } | {
15
15
  type: 'function_call';
16
16
  id?: string;
17
+ namespace?: string;
17
18
  block: number;
18
19
  };
19
20
  export interface NativeCodexReplayState {
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
- || !onlyKeys(row, ['type', 'id', 'block'])) {
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 { type: 'function_call', ...(id === undefined ? {} : { id }), block: Number(row.block) };
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
  }
@@ -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: string;
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
- /** Parse only response.completed usage_metadata.amount and preserve its exact string value. */
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;
@@ -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
- /** Parse only response.completed usage_metadata.amount and preserve its exact string value. */
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 metadata = record(response?.usage_metadata);
14
- const amount = metadata?.amount;
15
- if (typeof amount !== 'string' || amount.length === 0
16
- || Buffer.byteLength(amount) > MAX_AMOUNT_BYTES)
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 { amount };
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) {
@@ -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 HTTP Responses body. */
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 HTTP Responses body. */
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
- return {
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 = "6478a751fde8884b2fdc76486fe23175a8e795d4";
4
- export declare const TRACKED_CODEX_RELEASE = "rust-v0.151.0";
5
- /** Whole release version sent to the Codex model-catalog endpoint. */
6
- export declare const CODEX_CLIENT_VERSION = "0.151.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 = '6478a751fde8884b2fdc76486fe23175a8e795d4';
4
- export const TRACKED_CODEX_RELEASE = 'rust-v0.151.0';
5
- /** Whole release version sent to the Codex model-catalog endpoint. */
6
- export const CODEX_CLIENT_VERSION = '0.151.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
@@ -8,6 +8,7 @@ export interface UsageWindow {
8
8
  export interface UsageLimitSummary {
9
9
  id: string;
10
10
  name?: string;
11
+ normalModelSlug?: string;
11
12
  primary?: UsageWindow;
12
13
  secondary?: UsageWindow;
13
14
  limitReached?: boolean;
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 limitReached = typeof row.limit_reached === 'boolean'
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
- limits.push(extra);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pure01fx/dsh-openai-codex-auth",
3
- "version": "0.7.3",
3
+ "version": "0.9.0",
4
4
  "description": "Native ChatGPT Codex provider, device-code-first login, and same-origin Web integration for DeepSeek Harness",
5
5
  "license": "MIT",
6
6
  "publishConfig": {