@pure01fx/dsh-openai-codex-auth 0.10.0 → 0.11.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.
@@ -20,11 +20,9 @@ export interface NativeCodexHttpOptions {
20
20
  endpoint?: string;
21
21
  requestTimeoutMs?: number;
22
22
  streamIdleTimeoutMs?: number;
23
- maxSseEventBytes?: number;
24
23
  maxTransientRetries?: number;
25
24
  initialRetryDelayMs?: number;
26
25
  maxRetryDelayMs?: number;
27
- maxRequestBodyBytes?: number;
28
26
  random?: () => number;
29
27
  sleep?: (delayMs: number, signal?: AbortSignal) => Promise<void>;
30
28
  createRequestId?: () => string;
@@ -37,7 +35,6 @@ export interface NativeCodexPreparedRequest {
37
35
  generation: GenerateOptions;
38
36
  mode: NativeCodexTransportMode;
39
37
  request: Record<string, unknown>;
40
- body: string;
41
38
  routingId: string;
42
39
  routingHint: string;
43
40
  }
@@ -51,7 +48,6 @@ export declare class NativeCodexHttpTransport {
51
48
  private readonly maxRetries;
52
49
  private readonly initialDelayMs;
53
50
  private readonly maxDelayMs;
54
- private readonly maxBodyBytes;
55
51
  constructor(options: NativeCodexHttpOptions);
56
52
  private retryDelay;
57
53
  private wait;
@@ -16,7 +16,6 @@ const DEFAULT_INITIAL_RETRY_DELAY_MS = 200;
16
16
  const DEFAULT_MAX_RETRY_DELAY_MS = 10_000;
17
17
  const INITIAL_CONNECTION_RETRY_DELAY_MS = 5_000;
18
18
  const MAX_CONNECTION_RETRY_DELAY_MS = 60_000;
19
- const DEFAULT_MAX_REQUEST_BODY_BYTES = 24 * 1024 * 1024;
20
19
  const MAX_ERROR_BODY_BYTES = 64 * 1024;
21
20
  function aborted(message = 'native Codex request was aborted') {
22
21
  return new LlmError(message, 'ABORTED');
@@ -357,7 +356,6 @@ export class NativeCodexHttpTransport {
357
356
  maxRetries;
358
357
  initialDelayMs;
359
358
  maxDelayMs;
360
- maxBodyBytes;
361
359
  constructor(options) {
362
360
  this.options = options;
363
361
  this.fetchImpl = options.fetch ?? fetch;
@@ -367,7 +365,6 @@ export class NativeCodexHttpTransport {
367
365
  this.maxRetries = safeRetryCount(options.maxTransientRetries);
368
366
  this.initialDelayMs = safePositiveInteger(options.initialRetryDelayMs, DEFAULT_INITIAL_RETRY_DELAY_MS, 'initial retry delay');
369
367
  this.maxDelayMs = safePositiveInteger(options.maxRetryDelayMs, DEFAULT_MAX_RETRY_DELAY_MS, 'maximum retry delay');
370
- this.maxBodyBytes = safePositiveInteger(options.maxRequestBodyBytes, DEFAULT_MAX_REQUEST_BODY_BYTES, 'request body limit');
371
368
  }
372
369
  retryDelay(retry, providerDelay) {
373
370
  if (providerDelay !== undefined)
@@ -410,24 +407,28 @@ export class NativeCodexHttpTransport {
410
407
  sessionId: stablePromptCacheKey(sessionId),
411
408
  };
412
409
  let request;
413
- let body;
414
410
  try {
415
411
  request = codexRequestBody(wireOptions, messages, mode);
416
- body = JSON.stringify(request);
417
412
  }
418
413
  catch (error) {
419
414
  if (error instanceof LlmError)
420
415
  throw error;
421
416
  throw fixedFailure('native Codex request could not be encoded', 'INVALID_ARGS', { cause: error });
422
417
  }
423
- if (Buffer.byteLength(body) > this.maxBodyBytes) {
424
- throw fixedFailure('native Codex request exceeded the size limit', 'REQUEST_TOO_LARGE');
425
- }
426
- return { generation, mode, request, body, routingId, routingHint };
418
+ // WebSocket chooses a full request or an incremental suffix after preparation.
419
+ // Serialize only in the selected transport.
420
+ return { generation, mode, request, routingId, routingHint };
427
421
  }
428
422
  async *stream(generation, mode = {}) {
429
423
  const prepared = await this.prepare(generation, mode);
430
- const { body, routingId, routingHint } = prepared;
424
+ const { request, routingId, routingHint } = prepared;
425
+ let body;
426
+ try {
427
+ body = JSON.stringify(request);
428
+ }
429
+ catch (error) {
430
+ throw fixedFailure('native Codex request could not be encoded', 'INVALID_ARGS', { cause: error });
431
+ }
431
432
  let activeTurnState = mode.turnState;
432
433
  if (activeTurnState !== undefined
433
434
  && (activeTurnState.length === 0 || Buffer.byteLength(activeTurnState) > 4096
@@ -553,9 +554,6 @@ export class NativeCodexHttpTransport {
553
554
  for await (const chunk of streamResponses(response.body, {
554
555
  signal: watchdog.signal,
555
556
  onActivity: watchdog.pulse,
556
- ...this.options.maxSseEventBytes === undefined
557
- ? {}
558
- : { maxEventBytes: this.options.maxSseEventBytes },
559
557
  onMalformedEvent: () => {
560
558
  this.options.warn?.('native Codex ignored a malformed SSE event');
561
559
  },
@@ -1,7 +1,6 @@
1
1
  /** Pure WebSocket v2 previous-response and incremental suffix state. */
2
2
  import { createHash } from 'node:crypto';
3
3
  import { LlmError } from '@deepseek-ai/dsh-llm';
4
- const MAX_RESPONSE_ID_BYTES = 256;
5
4
  const IGNORED_REUSE_FIELDS = new Set([
6
5
  'input', 'previous_response_id', 'generate', 'client_metadata',
7
6
  'stream_options', 'access_programs',
@@ -84,8 +83,7 @@ export class NativeCodexWebSocketSessionState {
84
83
  return { ...plan, payload: { ...plan.payload, generate: false } };
85
84
  }
86
85
  complete(responseId, outputItems) {
87
- if (this.pending === undefined || responseId.length === 0
88
- || Buffer.byteLength(responseId) > MAX_RESPONSE_ID_BYTES) {
86
+ if (this.pending === undefined || responseId.length === 0) {
89
87
  this.reset();
90
88
  throw failure('native Codex WebSocket completion identity is invalid');
91
89
  }
@@ -17,7 +17,6 @@ export interface NativeCodexWebSocketConnectOptions {
17
17
  headers: Record<string, string>;
18
18
  signal?: AbortSignal;
19
19
  connectTimeoutMs?: number;
20
- maxFrameBytes?: number;
21
20
  }
22
21
  export interface NativeCodexWebSocketFactory {
23
22
  connect(options: NativeCodexWebSocketConnectOptions): Promise<NativeCodexWebSocket>;
@@ -1,4 +1,4 @@
1
- /** Bounded Node WebSocket client seam with injectable deterministic factories. */
1
+ /** Node WebSocket client seam with injectable deterministic factories. */
2
2
  import { LlmError, ProviderRequestId } from '@deepseek-ai/dsh-llm';
3
3
  import { HttpsProxyAgent } from 'https-proxy-agent';
4
4
  import { getProxyForUrl } from 'proxy-from-env';
@@ -6,8 +6,6 @@ import { nativeCodexEndpoint } from './endpoint.js';
6
6
  import { NATIVE_CODEX_CONNECTION_FAILED_CODE, isNativeCodexConnectionFailure, } from './native-adapter.js';
7
7
  import WebSocket from 'ws';
8
8
  const DEFAULT_CONNECT_TIMEOUT_MS = 10_000;
9
- const DEFAULT_MAX_FRAME_BYTES = 64 * 1024 * 1024;
10
- const MAX_QUEUED_BYTES = 64 * 1024 * 1024;
11
9
  function failure(message, code, cause) {
12
10
  return new LlmError(message, code, cause === undefined ? undefined : { cause });
13
11
  }
@@ -54,25 +52,20 @@ export function nativeCodexWebSocketUrl(endpoint) {
54
52
  class NodeNativeCodexWebSocket {
55
53
  socket;
56
54
  responseHeaders;
57
- maxFrameBytes;
58
55
  queue = [];
59
- queuedBytes = 0;
60
56
  waiters = [];
61
57
  ended = false;
62
- constructor(socket, responseHeaders, maxFrameBytes) {
58
+ constructor(socket, responseHeaders) {
63
59
  this.socket = socket;
64
60
  this.responseHeaders = responseHeaders;
65
- this.maxFrameBytes = maxFrameBytes;
66
61
  socket.on('message', (data, isBinary) => {
67
62
  if (isBinary) {
68
63
  this.fail(failure('native Codex WebSocket returned a binary frame', 'WS_PROTOCOL_ERROR'));
69
64
  return;
70
65
  }
71
- if (data.byteLength > maxFrameBytes) {
72
- this.fail(failure('native Codex WebSocket frame exceeded the size limit', 'WS_FRAME_TOO_LARGE'));
73
- return;
74
- }
75
- this.push({ type: 'text', text: data.toString('utf8') }, data.byteLength);
66
+ const buffer = Array.isArray(data) ? Buffer.concat(data)
67
+ : Buffer.isBuffer(data) ? data : Buffer.from(data);
68
+ this.push({ type: 'text', text: buffer.toString('utf8') });
76
69
  });
77
70
  socket.on('close', (code, reason) => {
78
71
  this.ended = true;
@@ -82,7 +75,7 @@ class NodeNativeCodexWebSocket {
82
75
  this.fail(failure('native Codex WebSocket transport failed', 'WS_RETRYABLE', error));
83
76
  });
84
77
  }
85
- push(value, bytes = 0) {
78
+ push(value) {
86
79
  const waiter = this.waiters.shift();
87
80
  if (waiter !== undefined) {
88
81
  if (value instanceof LlmError)
@@ -91,12 +84,7 @@ class NodeNativeCodexWebSocket {
91
84
  waiter.resolve(value);
92
85
  return;
93
86
  }
94
- if (this.queuedBytes + bytes > MAX_QUEUED_BYTES) {
95
- this.fail(failure('native Codex WebSocket queued too much response data', 'WS_RESPONSE_TOO_LARGE'));
96
- return;
97
- }
98
- this.queue.push({ value, bytes });
99
- this.queuedBytes += bytes;
87
+ this.queue.push(value);
100
88
  }
101
89
  fail(error) {
102
90
  if (!this.ended)
@@ -106,9 +94,8 @@ class NodeNativeCodexWebSocket {
106
94
  for (const waiter of waiters)
107
95
  waiter.reject(error);
108
96
  this.queue.length = 0;
109
- this.queuedBytes = 0;
110
97
  if (waiters.length === 0)
111
- this.queue.push({ value: error, bytes: 0 });
98
+ this.queue.push(error);
112
99
  }
113
100
  async send(text, signal) {
114
101
  if (signal?.aborted)
@@ -124,7 +111,7 @@ class NodeNativeCodexWebSocket {
124
111
  signal?.addEventListener('abort', abort, { once: true });
125
112
  this.socket.send(text, (error) => {
126
113
  signal?.removeEventListener('abort', abort);
127
- if (error === undefined)
114
+ if (error === undefined || error === null)
128
115
  resolve();
129
116
  else
130
117
  reject(failure('native Codex WebSocket send failed', 'WS_RETRYABLE', error));
@@ -136,10 +123,9 @@ class NodeNativeCodexWebSocket {
136
123
  throw abortFailure(signal);
137
124
  const queued = this.queue.shift();
138
125
  if (queued !== undefined) {
139
- this.queuedBytes -= queued.bytes;
140
- if (queued.value instanceof LlmError)
141
- throw queued.value;
142
- return queued.value;
126
+ if (queued instanceof LlmError)
127
+ throw queued;
128
+ return queued;
143
129
  }
144
130
  return new Promise((resolve, reject) => {
145
131
  let waiter;
@@ -169,7 +155,6 @@ class NodeNativeCodexWebSocket {
169
155
  export class NodeNativeCodexWebSocketFactory {
170
156
  async connect(options) {
171
157
  const timeout = positive(options.connectTimeoutMs, DEFAULT_CONNECT_TIMEOUT_MS, 'connect timeout');
172
- const maximum = positive(options.maxFrameBytes, DEFAULT_MAX_FRAME_BYTES, 'frame limit');
173
158
  if (options.signal?.aborted)
174
159
  throw abortFailure(options.signal);
175
160
  return new Promise((resolve, reject) => {
@@ -180,7 +165,8 @@ export class NodeNativeCodexWebSocketFactory {
180
165
  headers: options.headers,
181
166
  ...(agent === undefined ? {} : { agent }),
182
167
  handshakeTimeout: timeout,
183
- maxPayload: maximum,
168
+ // ws uses zero to disable its default message-size ceiling.
169
+ maxPayload: 0,
184
170
  perMessageDeflate: true,
185
171
  });
186
172
  const abort = () => {
@@ -211,7 +197,7 @@ export class NodeNativeCodexWebSocketFactory {
211
197
  });
212
198
  socket.on('open', () => {
213
199
  options.signal?.removeEventListener('abort', abort);
214
- resolve(new NodeNativeCodexWebSocket(socket, responseHeaders, maximum));
200
+ resolve(new NodeNativeCodexWebSocket(socket, responseHeaders));
215
201
  });
216
202
  socket.on('error', (error) => {
217
203
  options.signal?.removeEventListener('abort', abort);
@@ -6,7 +6,6 @@ export interface NativeCodexWebSocketTransportOptions extends NativeCodexHttpOpt
6
6
  webSocketFactory?: NativeCodexWebSocketFactory;
7
7
  webSocketConnectTimeoutMs?: number;
8
8
  webSocketIdleTimeoutMs?: number;
9
- maxWebSocketFrameBytes?: number;
10
9
  maxWebSocketSessions?: number;
11
10
  webSocketSessionIdleMs?: number;
12
11
  maxWebSocketReconnects?: number;
@@ -19,7 +18,6 @@ export declare class NativeCodexWebSocketTransport implements NativeCodexTranspo
19
18
  private readonly sessions;
20
19
  private readonly connectTimeoutMs;
21
20
  private readonly idleTimeoutMs;
22
- private readonly maxFrameBytes;
23
21
  private readonly maxSessions;
24
22
  private readonly sessionIdleMs;
25
23
  private readonly maxReconnects;
@@ -12,7 +12,6 @@ import { NodeNativeCodexWebSocketFactory, } from './native-websocket-socket.js';
12
12
  import { NativeCodexWebSocketSessionState } from './native-websocket-session.js';
13
13
  const WS_BETA = 'responses_websockets=2026-02-06';
14
14
  const DEFAULT_IDLE_TIMEOUT_MS = 300_000;
15
- const DEFAULT_MAX_FRAME_BYTES = 64 * 1024 * 1024;
16
15
  const DEFAULT_MAX_SESSIONS = 32;
17
16
  const DEFAULT_SESSION_IDLE_MS = 30 * 60_000;
18
17
  const DEFAULT_MAX_RECONNECTS = 5;
@@ -21,14 +20,13 @@ const DEFAULT_MAX_RETRY_DELAY_MS = 10_000;
21
20
  const INITIAL_CONNECTION_RETRY_DELAY_MS = 5_000;
22
21
  const MAX_CONNECTION_RETRY_DELAY_MS = 60_000;
23
22
  const MAX_TURN_STATE_BYTES = 4096;
24
- const MAX_RETAINED_OUTPUT_BYTES = 64 * 1024 * 1024;
25
23
  function failure(message, code, cause) {
26
24
  return new LlmError(message, code, cause === undefined ? undefined : { cause });
27
25
  }
28
26
  function reconnectable(code) {
29
27
  return [
30
28
  'WS_RETRYABLE', 'WS_RETRYABLE_RESET', 'WS_PROTOCOL_ERROR',
31
- 'WS_FRAME_TOO_LARGE', 'WS_RESPONSE_TOO_LARGE', 'TIMEOUT',
29
+ 'TIMEOUT',
32
30
  NATIVE_CODEX_CONNECTION_FAILED_CODE,
33
31
  ].includes(code);
34
32
  }
@@ -211,7 +209,6 @@ export class NativeCodexWebSocketTransport {
211
209
  sessions = new Map();
212
210
  connectTimeoutMs;
213
211
  idleTimeoutMs;
214
- maxFrameBytes;
215
212
  maxSessions;
216
213
  sessionIdleMs;
217
214
  maxReconnects;
@@ -226,7 +223,6 @@ export class NativeCodexWebSocketTransport {
226
223
  this.factory = options.webSocketFactory ?? new NodeNativeCodexWebSocketFactory();
227
224
  this.connectTimeoutMs = boundedPositive(options.webSocketConnectTimeoutMs, 10_000, 120_000, 'WebSocket connect timeout');
228
225
  this.idleTimeoutMs = boundedPositive(options.webSocketIdleTimeoutMs, DEFAULT_IDLE_TIMEOUT_MS, 60 * 60_000, 'WebSocket idle timeout');
229
- this.maxFrameBytes = boundedPositive(options.maxWebSocketFrameBytes, DEFAULT_MAX_FRAME_BYTES, DEFAULT_MAX_FRAME_BYTES, 'WebSocket frame limit');
230
226
  this.maxSessions = boundedPositive(options.maxWebSocketSessions, DEFAULT_MAX_SESSIONS, 256, 'WebSocket session limit');
231
227
  this.sessionIdleMs = boundedPositive(options.webSocketSessionIdleMs, DEFAULT_SESSION_IDLE_MS, 24 * 60 * 60_000, 'WebSocket session idle limit');
232
228
  this.maxReconnects = retryCount(options.maxWebSocketReconnects);
@@ -338,7 +334,6 @@ export class NativeCodexWebSocketTransport {
338
334
  headers: this.headers(prepared, credential),
339
335
  signal,
340
336
  connectTimeoutMs: this.connectTimeoutMs,
341
- maxFrameBytes: this.maxFrameBytes,
342
337
  });
343
338
  if (this.disposed) {
344
339
  socket.close();
@@ -381,16 +376,12 @@ export class NativeCodexWebSocketTransport {
381
376
  if (entry.socket === undefined)
382
377
  throw failure('native Codex WebSocket is unavailable', 'WS_RETRYABLE');
383
378
  const encoded = JSON.stringify(payload);
384
- if (Buffer.byteLength(encoded) > 24 * 1024 * 1024) {
385
- throw failure('native Codex WebSocket request exceeded the size limit', 'REQUEST_TOO_LARGE');
386
- }
387
379
  await entry.socket.send(encoded, signal);
388
380
  const translator = new ResponsesStreamTranslator(prewarm ? undefined : {
389
381
  provider: generation.provider,
390
382
  model: mode.publicModel ?? generation.model,
391
383
  });
392
384
  const outputItems = [];
393
- let outputBytes = 0;
394
385
  while (true) {
395
386
  const text = await this.receive(entry, signal);
396
387
  let event;
@@ -420,14 +411,8 @@ export class NativeCodexWebSocketTransport {
420
411
  entry.turnState = nextTurnState;
421
412
  }
422
413
  const output = normalizedOutputItem(event);
423
- if (output !== undefined) {
424
- const nextOutputBytes = outputBytes + Buffer.byteLength(JSON.stringify(output));
425
- if (nextOutputBytes > MAX_RETAINED_OUTPUT_BYTES) {
426
- throw failure('native Codex WebSocket retained output exceeded the size limit', 'WS_RESPONSE_TOO_LARGE');
427
- }
414
+ if (output !== undefined)
428
415
  outputItems.push(output);
429
- outputBytes = nextOutputBytes;
430
- }
431
416
  if (event.type === 'response.completed') {
432
417
  const response = typeof event.response === 'object'
433
418
  && event.response !== null
package/lib/replay.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- /** Bounded, versioned Codex Responses continuation state. */
1
+ /** Versioned Codex Responses continuation state. */
2
2
  import { type ContentBlock } from '@deepseek-ai/dsh-llm';
3
3
  export declare const NATIVE_CODEX_REPLAY_KIND = "openai-codex-native.responses-replay";
4
4
  export declare const NATIVE_CODEX_REPLAY_VERSION = 1;
@@ -33,12 +33,11 @@ export interface NativeCodexReplaySource {
33
33
  export declare function replayableItemId(value: string | undefined): string | undefined;
34
34
  /** True only for legacy raw state or an rc.2 envelope emitted by this package. */
35
35
  export declare function hasNativeCodexReplayKind(value: unknown): boolean;
36
- /** Attempt-local byte-bounded accumulator; no ciphertext can grow unchecked before completion. */
36
+ /** Attempt-local accumulator for completed replay descriptors. */
37
37
  export declare class NativeCodexReplayCapture {
38
38
  private readonly provider;
39
39
  private readonly model;
40
40
  private readonly descriptors;
41
- private stateBytes;
42
41
  constructor(provider: string, model: string);
43
42
  add(item: NativeCodexReplayDescriptor): void;
44
43
  finish(): NativeCodexReplayState | undefined;
package/lib/replay.js CHANGED
@@ -1,10 +1,7 @@
1
- /** Bounded, versioned Codex Responses continuation state. */
1
+ /** Versioned Codex Responses continuation state. */
2
2
  import { LlmError } from '@deepseek-ai/dsh-llm';
3
3
  export const NATIVE_CODEX_REPLAY_KIND = 'openai-codex-native.responses-replay';
4
4
  export const NATIVE_CODEX_REPLAY_VERSION = 1;
5
- const MAX_REPLAY_ITEM_ID_BYTES = 256;
6
- const MAX_REPLAY_CIPHERTEXT_BYTES = 64 * 1024 * 1024;
7
- const MAX_REPLAY_STATE_BYTES = 64 * 1024 * 1024;
8
5
  function failure(message, code = 'INVALID_REPLAY_STATE') {
9
6
  return new LlmError(message, code);
10
7
  }
@@ -17,30 +14,22 @@ function onlyKeys(row, keys) {
17
14
  const allowed = new Set(keys);
18
15
  return Object.keys(row).every(key => allowed.has(key));
19
16
  }
20
- function boundedString(value, maximum = 256) {
21
- return typeof value === 'string' && value.length > 0
22
- && Buffer.byteLength(value) <= maximum ? value : undefined;
17
+ function nonemptyString(value) {
18
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
23
19
  }
24
20
  /** Preserve only server item IDs that Codex itself would replay. */
25
21
  export function replayableItemId(value) {
26
22
  if (value === undefined)
27
23
  return undefined;
28
- if (Buffer.byteLength(value) > MAX_REPLAY_ITEM_ID_BYTES) {
29
- throw failure('native Codex response item identity exceeded the replay limit', 'MALFORMED_RESPONSE');
30
- }
31
24
  const split = value.indexOf('_');
32
25
  return split > 0 && split < value.length - 1 ? value : undefined;
33
26
  }
34
- function safeStateSize(value, code) {
35
- let serialized;
27
+ function validateStateJson(value) {
36
28
  try {
37
- serialized = JSON.stringify(value);
29
+ JSON.stringify(value);
38
30
  }
39
31
  catch {
40
- throw failure('native Codex replay state is not lossless JSON', code);
41
- }
42
- if (Buffer.byteLength(serialized) > MAX_REPLAY_STATE_BYTES) {
43
- throw failure('native Codex replay state exceeded the size limit', code);
32
+ throw failure('native Codex replay state is not lossless JSON');
44
33
  }
45
34
  }
46
35
  function validateBlockArray(value) {
@@ -59,7 +48,7 @@ function parseDescriptor(value) {
59
48
  if (row === undefined || typeof row.type !== 'string') {
60
49
  throw failure('native Codex replay descriptor is invalid');
61
50
  }
62
- const id = row.id === undefined ? undefined : boundedString(row.id, MAX_REPLAY_ITEM_ID_BYTES);
51
+ const id = row.id === undefined ? undefined : nonemptyString(row.id);
63
52
  const split = id?.indexOf('_') ?? -1;
64
53
  if (row.id !== undefined && (id === undefined || split <= 0 || split >= id.length - 1)) {
65
54
  throw failure('native Codex replay item identity is invalid');
@@ -74,7 +63,7 @@ function parseDescriptor(value) {
74
63
  if (row.type === 'reasoning') {
75
64
  const blocks = validateBlockArray(row.blocks);
76
65
  const encryptedContent = row.encryptedContent === undefined
77
- ? undefined : boundedString(row.encryptedContent, MAX_REPLAY_CIPHERTEXT_BYTES);
66
+ ? undefined : nonemptyString(row.encryptedContent);
78
67
  if (blocks === undefined
79
68
  || (row.encryptedContent !== undefined && encryptedContent === undefined)
80
69
  || !onlyKeys(row, ['type', 'id', 'blocks', 'encryptedContent'])) {
@@ -86,7 +75,7 @@ function parseDescriptor(value) {
86
75
  };
87
76
  }
88
77
  if (row.type === 'function_call') {
89
- const namespace = row.namespace === undefined ? undefined : boundedString(row.namespace);
78
+ const namespace = row.namespace === undefined ? undefined : nonemptyString(row.namespace);
90
79
  if (!Number.isSafeInteger(row.block) || Number(row.block) < 0
91
80
  || (row.namespace !== undefined && namespace === undefined)
92
81
  || !onlyKeys(row, ['type', 'id', 'namespace', 'block'])) {
@@ -109,15 +98,15 @@ export function hasNativeCodexReplayKind(value) {
109
98
  }
110
99
  function parseState(value) {
111
100
  const payload = replayPayload(value);
112
- safeStateSize(payload, 'INVALID_REPLAY_STATE');
101
+ validateStateJson(payload);
113
102
  const row = object(payload);
114
103
  if (row === undefined || row.kind !== NATIVE_CODEX_REPLAY_KIND
115
104
  || row.version !== NATIVE_CODEX_REPLAY_VERSION
116
105
  || !onlyKeys(row, ['kind', 'version', 'provider', 'model', 'items'])) {
117
106
  throw failure('native Codex replay state kind or version is invalid');
118
107
  }
119
- const provider = boundedString(row.provider);
120
- const model = boundedString(row.model, 512);
108
+ const provider = nonemptyString(row.provider);
109
+ const model = nonemptyString(row.model);
121
110
  if (provider === undefined || model === undefined || !Array.isArray(row.items)
122
111
  || row.items.length === 0) {
123
112
  throw failure('native Codex replay state metadata is invalid');
@@ -131,35 +120,17 @@ function parseState(value) {
131
120
  items,
132
121
  };
133
122
  }
134
- /** Attempt-local byte-bounded accumulator; no ciphertext can grow unchecked before completion. */
123
+ /** Attempt-local accumulator for completed replay descriptors. */
135
124
  export class NativeCodexReplayCapture {
136
125
  provider;
137
126
  model;
138
127
  descriptors = [];
139
- stateBytes;
140
128
  constructor(provider, model) {
141
129
  this.provider = provider;
142
130
  this.model = model;
143
- this.stateBytes = Buffer.byteLength(JSON.stringify({
144
- kind: NATIVE_CODEX_REPLAY_KIND,
145
- version: NATIVE_CODEX_REPLAY_VERSION,
146
- provider,
147
- model,
148
- items: [],
149
- }));
150
131
  }
151
132
  add(item) {
152
- if (item.type === 'reasoning' && item.encryptedContent !== undefined
153
- && Buffer.byteLength(item.encryptedContent) > MAX_REPLAY_CIPHERTEXT_BYTES) {
154
- throw failure('native Codex encrypted reasoning exceeded the replay limit', 'MALFORMED_RESPONSE');
155
- }
156
- const itemBytes = Buffer.byteLength(JSON.stringify(item));
157
- const nextBytes = this.stateBytes + itemBytes + (this.descriptors.length === 0 ? 0 : 1);
158
- if (nextBytes > MAX_REPLAY_STATE_BYTES) {
159
- throw failure('native Codex replay state exceeded the size limit', 'REPLAY_STATE_TOO_LARGE');
160
- }
161
133
  this.descriptors.push(item);
162
- this.stateBytes = nextBytes;
163
134
  }
164
135
  finish() {
165
136
  return createNativeCodexReplayState(this.provider, this.model, this.descriptors);
@@ -176,7 +147,6 @@ export function createNativeCodexReplayState(provider, model, items) {
176
147
  model,
177
148
  items: items.map(item => ({ ...item })),
178
149
  };
179
- safeStateSize(state, 'REPLAY_STATE_TOO_LARGE');
180
150
  try {
181
151
  return parseState(state);
182
152
  }
@@ -1,4 +1,4 @@
1
- import { CallId, LlmError, type ContentBlock, type GenerateOptions, type StreamChunk, type TokenUsage, type ToolSchema } from '@deepseek-ai/dsh-llm';
1
+ import { ToolCallId, LlmError, type ContentBlock, type GenerateOptions, type StreamChunk, type TokenUsage, type ToolSchema } from '@deepseek-ai/dsh-llm';
2
2
  import { type ParseSseOptions } from './sse.js';
3
3
  import { type NativeCodexReplaySource } from './replay.js';
4
4
  export declare const DEFAULT_CODEX_INSTRUCTIONS = "You are Codex, an AI coding agent. Help the user with software engineering tasks.";
@@ -11,7 +11,7 @@ export interface ResolvedImagePart {
11
11
  }
12
12
  export interface ResolvedToolResultPart {
13
13
  type: 'tool-result';
14
- toolCallId: CallId;
14
+ toolCallId: ToolCallId;
15
15
  content: readonly ResolvedContentPart[];
16
16
  isError?: boolean;
17
17
  }
@@ -109,11 +109,9 @@ export declare class ResponsesStreamTranslator {
109
109
  private readonly order;
110
110
  private readonly replayCapture;
111
111
  private nextIndex;
112
- private retainedBytes;
113
112
  private sawToolCall;
114
113
  terminated: boolean;
115
114
  constructor(replayContext?: ResponsesReplayContext | undefined);
116
- private reserve;
117
115
  private append;
118
116
  private fill;
119
117
  private open;
package/lib/responses.js CHANGED
@@ -1,12 +1,11 @@
1
1
  /** Pure DSH-to-Codex Responses request and stream translation. */
2
2
  import { createHash } from 'node:crypto';
3
- import { CallId, CONTEXT_WINDOW_EXCEEDED_CODE, EMPTY_RESPONSE_CODE, isContextWindowExceededError, isQuotaExceededError, LlmError, QUOTA_EXCEEDED_CODE, } from '@deepseek-ai/dsh-llm';
3
+ import { ToolCallId, CONTEXT_WINDOW_EXCEEDED_CODE, EMPTY_RESPONSE_CODE, isContextWindowExceededError, isQuotaExceededError, LlmError, QUOTA_EXCEEDED_CODE, } from '@deepseek-ai/dsh-llm';
4
4
  import { parseSse } from './sse.js';
5
5
  import { NativeCodexReplayCapture, replayAssistantInput, replayableItemId, } from './replay.js';
6
6
  export const DEFAULT_CODEX_INSTRUCTIONS = 'You are Codex, an AI coding agent. Help the user with software engineering tasks.';
7
7
  const CALL_ID_MAX_LENGTH = 64;
8
8
  const CALL_ID_PREFIX = 'call_';
9
- const MAX_RETAINED_RESPONSE_BYTES = 64 * 1024 * 1024;
10
9
  const UUID_NAMESPACE_OID = Buffer.from('6ba7b8129dad11d180b400c04fd430c8', 'hex');
11
10
  function uuidV5(namespace, name) {
12
11
  const bytes = createHash('sha1').update(namespace).update(name).digest().subarray(0, 16);
@@ -312,7 +311,7 @@ function closeBlock(block) {
312
311
  return { type: 'text', text: block.text };
313
312
  if (block.kind === 'reasoning')
314
313
  return { type: 'reasoning', text: block.text };
315
- return { type: 'tool-call', id: CallId(block.callId), name: block.name ?? '', arguments: block.text };
314
+ return { type: 'tool-call', id: ToolCallId(block.callId), name: block.name ?? '', arguments: block.text };
316
315
  }
317
316
  /** Stateful, transport-free Responses event to DSH chunk translator. */
318
317
  export class ResponsesStreamTranslator {
@@ -321,7 +320,6 @@ export class ResponsesStreamTranslator {
321
320
  order = [];
322
321
  replayCapture;
323
322
  nextIndex = 0;
324
- retainedBytes = 0;
325
323
  sawToolCall = false;
326
324
  terminated = false;
327
325
  constructor(replayContext) {
@@ -330,26 +328,15 @@ export class ResponsesStreamTranslator {
330
328
  ? undefined
331
329
  : new NativeCodexReplayCapture(replayContext.provider, replayContext.model);
332
330
  }
333
- reserve(bytes) {
334
- const nextBytes = this.retainedBytes + bytes;
335
- if (!Number.isSafeInteger(nextBytes) || nextBytes > MAX_RETAINED_RESPONSE_BYTES) {
336
- throw fixedError('native Codex response retained content exceeded the size limit', 'RESPONSE_TOO_LARGE');
337
- }
338
- this.retainedBytes = nextBytes;
339
- }
340
331
  append(block, delta) {
341
- this.reserve(Buffer.byteLength(delta));
342
332
  block.text += delta;
343
333
  }
344
334
  fill(block, text) {
345
335
  if (block.text.length > 0)
346
336
  return;
347
- this.reserve(Buffer.byteLength(text));
348
337
  block.text = text;
349
338
  }
350
339
  open(key, kind, chunks, callId = '', name) {
351
- this.reserve(128 + Buffer.byteLength(key) + Buffer.byteLength(callId)
352
- + (name === undefined ? 0 : Buffer.byteLength(name)));
353
340
  const block = {
354
341
  index: this.nextIndex++, kind, text: '', callId,
355
342
  ...name === undefined ? {} : { name },
@@ -398,7 +385,7 @@ export class ResponsesStreamTranslator {
398
385
  this.sawToolCall = true;
399
386
  const block = this.open(`${item.id}:call`, 'tool-call', chunks, item.call_id, item.name);
400
387
  chunks.push({
401
- type: 'tool-call-delta', index: block.index, id: CallId(block.callId),
388
+ type: 'tool-call-delta', index: block.index, id: ToolCallId(block.callId),
402
389
  name: item.name, argumentsDelta: '',
403
390
  });
404
391
  return chunks;
@@ -430,7 +417,7 @@ export class ResponsesStreamTranslator {
430
417
  const delta = eventDelta(event);
431
418
  this.append(block, delta);
432
419
  chunks.push({
433
- type: 'tool-call-delta', index: block.index, id: CallId(block.callId),
420
+ type: 'tool-call-delta', index: block.index, id: ToolCallId(block.callId),
434
421
  ...block.name === undefined ? {} : { name: block.name }, argumentsDelta: delta,
435
422
  });
436
423
  return chunks;
@@ -445,7 +432,7 @@ export class ResponsesStreamTranslator {
445
432
  if (item.call_id === undefined || item.call_id.length === 0
446
433
  || item.name === undefined || item.name.length === 0
447
434
  || (item.namespace !== undefined && (typeof item.namespace !== 'string'
448
- || item.namespace.length === 0 || Buffer.byteLength(item.namespace) > 256))
435
+ || item.namespace.length === 0))
449
436
  || typeof item.arguments !== 'string') {
450
437
  throw fixedError('native Codex function call has invalid content', 'MALFORMED_RESPONSE');
451
438
  }
package/lib/sse.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- export declare const DEFAULT_MAX_SSE_EVENT_BYTES: number;
2
1
  export interface SseEvent {
3
2
  data: string;
4
3
  event?: string;
@@ -7,7 +6,6 @@ export interface ParseSseOptions {
7
6
  signal?: AbortSignal;
8
7
  onActivity?: () => void;
9
8
  onBytes?: (bytes: number) => void;
10
- maxEventBytes?: number;
11
9
  }
12
- /** Decode a byte stream into bounded SSE frames. */
10
+ /** Decode a byte stream into SSE frames. */
13
11
  export declare function parseSse(stream: ReadableStream<Uint8Array>, options?: ParseSseOptions): AsyncGenerator<SseEvent>;