@pure01fx/dsh-openai-codex-auth 0.6.1 → 0.7.1
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 +14 -0
- package/README.md +2 -0
- package/lib/native-websocket-session.js +0 -5
- package/lib/native-websocket-socket.js +3 -4
- package/lib/native-websocket.js +10 -16
- package/lib/replay.d.ts +2 -3
- package/lib/replay.js +13 -22
- package/lib/responses.d.ts +4 -2
- package/lib/responses.js +29 -32
- package/lib/sse.js +1 -1
- package/package.json +20 -17
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.7.1
|
|
6
|
+
|
|
7
|
+
### Native stream compatibility
|
|
8
|
+
|
|
9
|
+
- Aligns long native Codex streams with codex-rs by removing aggregate event/wire-byte, output-item, and replay-item ceilings, using a 300-second WebSocket idle timeout, and retaining 64 MiB single-event/frame, queued-byte, translated-content, retained-output, and replay-state safeguards.
|
|
10
|
+
|
|
11
|
+
## 0.7.0
|
|
12
|
+
|
|
13
|
+
### DSH 0.1.1 compatibility
|
|
14
|
+
|
|
15
|
+
- Targets DeepSeek Harness `0.1.1-rc.2` across Host peers, runtime helpers, development contracts, and generated artifacts.
|
|
16
|
+
- Emits successful native continuation metadata through the rc.2 `ReplayEnvelope.response` contract while continuing to read legacy raw replay state from existing sessions.
|
|
17
|
+
- Removes the duplicate runtime dependency on `@deepseek-ai/dsh-credentials`, keeping the Host credentials service as a peer-owned singleton.
|
|
18
|
+
|
|
5
19
|
## 0.6.1
|
|
6
20
|
|
|
7
21
|
### WebSocket reliability
|
package/README.md
CHANGED
|
@@ -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_OUTPUT_ITEMS = 2048;
|
|
5
4
|
const MAX_RESPONSE_ID_BYTES = 256;
|
|
6
5
|
const IGNORED_REUSE_FIELDS = new Set([
|
|
7
6
|
'input', 'previous_response_id', 'generate', 'client_metadata',
|
|
@@ -90,10 +89,6 @@ export class NativeCodexWebSocketSessionState {
|
|
|
90
89
|
this.reset();
|
|
91
90
|
throw failure('native Codex WebSocket completion identity is invalid');
|
|
92
91
|
}
|
|
93
|
-
if (outputItems.length > MAX_OUTPUT_ITEMS) {
|
|
94
|
-
this.reset();
|
|
95
|
-
throw failure('native Codex WebSocket response has too many items');
|
|
96
|
-
}
|
|
97
92
|
this.completed = {
|
|
98
93
|
propertyHash: this.pending.propertyHash,
|
|
99
94
|
contextLength: this.pending.inputLength + outputItems.length,
|
|
@@ -4,9 +4,8 @@ import { nativeCodexEndpoint } from './endpoint.js';
|
|
|
4
4
|
import { NATIVE_CODEX_CONNECTION_FAILED_CODE, isNativeCodexConnectionFailure, } from './native-adapter.js';
|
|
5
5
|
import WebSocket from 'ws';
|
|
6
6
|
const DEFAULT_CONNECT_TIMEOUT_MS = 10_000;
|
|
7
|
-
const DEFAULT_MAX_FRAME_BYTES = 1024 * 1024;
|
|
8
|
-
const
|
|
9
|
-
const MAX_QUEUED_BYTES = 24 * 1024 * 1024;
|
|
7
|
+
const DEFAULT_MAX_FRAME_BYTES = 64 * 1024 * 1024;
|
|
8
|
+
const MAX_QUEUED_BYTES = 64 * 1024 * 1024;
|
|
10
9
|
function failure(message, code, cause) {
|
|
11
10
|
return new LlmError(message, code, cause === undefined ? undefined : { cause });
|
|
12
11
|
}
|
|
@@ -83,7 +82,7 @@ class NodeNativeCodexWebSocket {
|
|
|
83
82
|
waiter.resolve(value);
|
|
84
83
|
return;
|
|
85
84
|
}
|
|
86
|
-
if (this.
|
|
85
|
+
if (this.queuedBytes + bytes > MAX_QUEUED_BYTES) {
|
|
87
86
|
this.fail(failure('native Codex WebSocket queued too much response data', 'WS_RESPONSE_TOO_LARGE'));
|
|
88
87
|
return;
|
|
89
88
|
}
|
package/lib/native-websocket.js
CHANGED
|
@@ -11,8 +11,8 @@ import { ResponsesStreamTranslator, codexResponseTurnState, } from './responses.
|
|
|
11
11
|
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
|
-
const DEFAULT_IDLE_TIMEOUT_MS =
|
|
15
|
-
const DEFAULT_MAX_FRAME_BYTES = 1024 * 1024;
|
|
14
|
+
const DEFAULT_IDLE_TIMEOUT_MS = 300_000;
|
|
15
|
+
const DEFAULT_MAX_FRAME_BYTES = 64 * 1024 * 1024;
|
|
16
16
|
const DEFAULT_MAX_SESSIONS = 32;
|
|
17
17
|
const DEFAULT_SESSION_IDLE_MS = 30 * 60_000;
|
|
18
18
|
const DEFAULT_MAX_RECONNECTS = 5;
|
|
@@ -21,9 +21,7 @@ const DEFAULT_MAX_RETRY_DELAY_MS = 10_000;
|
|
|
21
21
|
const INITIAL_CONNECTION_RETRY_DELAY_MS = 5_000;
|
|
22
22
|
const MAX_CONNECTION_RETRY_DELAY_MS = 60_000;
|
|
23
23
|
const MAX_TURN_STATE_BYTES = 4096;
|
|
24
|
-
const
|
|
25
|
-
const MAX_OUTPUT_ITEMS_PER_RESPONSE = 2048;
|
|
26
|
-
const MAX_RESPONSE_BYTES = 24 * 1024 * 1024;
|
|
24
|
+
const MAX_RETAINED_OUTPUT_BYTES = 64 * 1024 * 1024;
|
|
27
25
|
function failure(message, code, cause) {
|
|
28
26
|
return new LlmError(message, code, cause === undefined ? undefined : { cause });
|
|
29
27
|
}
|
|
@@ -221,7 +219,7 @@ export class NativeCodexWebSocketTransport {
|
|
|
221
219
|
this.factory = options.webSocketFactory ?? new NodeNativeCodexWebSocketFactory();
|
|
222
220
|
this.connectTimeoutMs = boundedPositive(options.webSocketConnectTimeoutMs, 10_000, 120_000, 'WebSocket connect timeout');
|
|
223
221
|
this.idleTimeoutMs = boundedPositive(options.webSocketIdleTimeoutMs, DEFAULT_IDLE_TIMEOUT_MS, 60 * 60_000, 'WebSocket idle timeout');
|
|
224
|
-
this.maxFrameBytes = boundedPositive(options.maxWebSocketFrameBytes, DEFAULT_MAX_FRAME_BYTES,
|
|
222
|
+
this.maxFrameBytes = boundedPositive(options.maxWebSocketFrameBytes, DEFAULT_MAX_FRAME_BYTES, DEFAULT_MAX_FRAME_BYTES, 'WebSocket frame limit');
|
|
225
223
|
this.maxSessions = boundedPositive(options.maxWebSocketSessions, DEFAULT_MAX_SESSIONS, 256, 'WebSocket session limit');
|
|
226
224
|
this.sessionIdleMs = boundedPositive(options.webSocketSessionIdleMs, DEFAULT_SESSION_IDLE_MS, 24 * 60 * 60_000, 'WebSocket session idle limit');
|
|
227
225
|
this.maxReconnects = retryCount(options.maxWebSocketReconnects);
|
|
@@ -385,14 +383,9 @@ export class NativeCodexWebSocketTransport {
|
|
|
385
383
|
model: mode.publicModel ?? generation.model,
|
|
386
384
|
});
|
|
387
385
|
const outputItems = [];
|
|
388
|
-
let
|
|
389
|
-
|
|
390
|
-
while (events++ < MAX_EVENTS_PER_RESPONSE) {
|
|
386
|
+
let outputBytes = 0;
|
|
387
|
+
while (true) {
|
|
391
388
|
const text = await this.receive(entry, signal);
|
|
392
|
-
responseBytes += Buffer.byteLength(text);
|
|
393
|
-
if (responseBytes > MAX_RESPONSE_BYTES) {
|
|
394
|
-
throw failure('native Codex WebSocket response exceeded the size limit', 'WS_RESPONSE_TOO_LARGE');
|
|
395
|
-
}
|
|
396
389
|
let event;
|
|
397
390
|
try {
|
|
398
391
|
event = JSON.parse(text);
|
|
@@ -421,10 +414,12 @@ export class NativeCodexWebSocketTransport {
|
|
|
421
414
|
}
|
|
422
415
|
const output = normalizedOutputItem(event);
|
|
423
416
|
if (output !== undefined) {
|
|
424
|
-
|
|
425
|
-
|
|
417
|
+
const nextOutputBytes = outputBytes + Buffer.byteLength(JSON.stringify(output));
|
|
418
|
+
if (nextOutputBytes > MAX_RETAINED_OUTPUT_BYTES) {
|
|
419
|
+
throw failure('native Codex WebSocket retained output exceeded the size limit', 'WS_RESPONSE_TOO_LARGE');
|
|
426
420
|
}
|
|
427
421
|
outputItems.push(output);
|
|
422
|
+
outputBytes = nextOutputBytes;
|
|
428
423
|
}
|
|
429
424
|
if (event.type === 'response.completed') {
|
|
430
425
|
const response = typeof event.response === 'object'
|
|
@@ -444,7 +439,6 @@ export class NativeCodexWebSocketTransport {
|
|
|
444
439
|
return;
|
|
445
440
|
}
|
|
446
441
|
}
|
|
447
|
-
throw failure('native Codex WebSocket response had too many events', 'WS_PROTOCOL_ERROR');
|
|
448
442
|
}
|
|
449
443
|
async *attempt(entry, prepared, credential, signal) {
|
|
450
444
|
await this.ensureSocket(entry, prepared, credential, signal);
|
package/lib/replay.d.ts
CHANGED
|
@@ -30,14 +30,13 @@ export interface NativeCodexReplaySource {
|
|
|
30
30
|
}
|
|
31
31
|
/** Preserve only server item IDs that Codex itself would replay. */
|
|
32
32
|
export declare function replayableItemId(value: string | undefined): string | undefined;
|
|
33
|
-
/** True only for
|
|
33
|
+
/** True only for legacy raw state or an rc.2 envelope emitted by this package. */
|
|
34
34
|
export declare function hasNativeCodexReplayKind(value: unknown): boolean;
|
|
35
|
-
/** Attempt-local bounded accumulator; no ciphertext can grow unchecked before completion. */
|
|
35
|
+
/** Attempt-local byte-bounded accumulator; no ciphertext can grow unchecked before completion. */
|
|
36
36
|
export declare class NativeCodexReplayCapture {
|
|
37
37
|
private readonly provider;
|
|
38
38
|
private readonly model;
|
|
39
39
|
private readonly descriptors;
|
|
40
|
-
private references;
|
|
41
40
|
private stateBytes;
|
|
42
41
|
constructor(provider: string, model: string);
|
|
43
42
|
add(item: NativeCodexReplayDescriptor): void;
|
package/lib/replay.js
CHANGED
|
@@ -2,11 +2,9 @@
|
|
|
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_DESCRIPTORS = 128;
|
|
6
|
-
const MAX_REPLAY_BLOCK_REFS = 256;
|
|
7
5
|
const MAX_REPLAY_ITEM_ID_BYTES = 256;
|
|
8
|
-
const MAX_REPLAY_CIPHERTEXT_BYTES = 1024 * 1024;
|
|
9
|
-
const MAX_REPLAY_STATE_BYTES =
|
|
6
|
+
const MAX_REPLAY_CIPHERTEXT_BYTES = 64 * 1024 * 1024;
|
|
7
|
+
const MAX_REPLAY_STATE_BYTES = 64 * 1024 * 1024;
|
|
10
8
|
function failure(message, code = 'INVALID_REPLAY_STATE') {
|
|
11
9
|
return new LlmError(message, code);
|
|
12
10
|
}
|
|
@@ -96,13 +94,18 @@ function parseDescriptor(value) {
|
|
|
96
94
|
}
|
|
97
95
|
throw failure('native Codex replay descriptor type is unsupported');
|
|
98
96
|
}
|
|
99
|
-
|
|
97
|
+
function replayPayload(value) {
|
|
98
|
+
const response = object(value)?.response;
|
|
99
|
+
return object(response)?.kind === NATIVE_CODEX_REPLAY_KIND ? response : value;
|
|
100
|
+
}
|
|
101
|
+
/** True only for legacy raw state or an rc.2 envelope emitted by this package. */
|
|
100
102
|
export function hasNativeCodexReplayKind(value) {
|
|
101
|
-
return object(value)?.kind === NATIVE_CODEX_REPLAY_KIND;
|
|
103
|
+
return object(replayPayload(value))?.kind === NATIVE_CODEX_REPLAY_KIND;
|
|
102
104
|
}
|
|
103
105
|
function parseState(value) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
+
const payload = replayPayload(value);
|
|
107
|
+
safeStateSize(payload, 'INVALID_REPLAY_STATE');
|
|
108
|
+
const row = object(payload);
|
|
106
109
|
if (row === undefined || row.kind !== NATIVE_CODEX_REPLAY_KIND
|
|
107
110
|
|| row.version !== NATIVE_CODEX_REPLAY_VERSION
|
|
108
111
|
|| !onlyKeys(row, ['kind', 'version', 'provider', 'model', 'items'])) {
|
|
@@ -111,13 +114,10 @@ function parseState(value) {
|
|
|
111
114
|
const provider = boundedString(row.provider);
|
|
112
115
|
const model = boundedString(row.model, 512);
|
|
113
116
|
if (provider === undefined || model === undefined || !Array.isArray(row.items)
|
|
114
|
-
|| row.items.length === 0
|
|
117
|
+
|| row.items.length === 0) {
|
|
115
118
|
throw failure('native Codex replay state metadata is invalid');
|
|
116
119
|
}
|
|
117
120
|
const items = row.items.map(parseDescriptor);
|
|
118
|
-
const refs = items.reduce((total, item) => total + (item.type === 'function_call' ? 1 : item.blocks.length), 0);
|
|
119
|
-
if (refs > MAX_REPLAY_BLOCK_REFS)
|
|
120
|
-
throw failure('native Codex replay state has too many block references');
|
|
121
121
|
return {
|
|
122
122
|
kind: NATIVE_CODEX_REPLAY_KIND,
|
|
123
123
|
version: NATIVE_CODEX_REPLAY_VERSION,
|
|
@@ -126,12 +126,11 @@ function parseState(value) {
|
|
|
126
126
|
items,
|
|
127
127
|
};
|
|
128
128
|
}
|
|
129
|
-
/** Attempt-local bounded accumulator; no ciphertext can grow unchecked before completion. */
|
|
129
|
+
/** Attempt-local byte-bounded accumulator; no ciphertext can grow unchecked before completion. */
|
|
130
130
|
export class NativeCodexReplayCapture {
|
|
131
131
|
provider;
|
|
132
132
|
model;
|
|
133
133
|
descriptors = [];
|
|
134
|
-
references = 0;
|
|
135
134
|
stateBytes;
|
|
136
135
|
constructor(provider, model) {
|
|
137
136
|
this.provider = provider;
|
|
@@ -145,13 +144,6 @@ export class NativeCodexReplayCapture {
|
|
|
145
144
|
}));
|
|
146
145
|
}
|
|
147
146
|
add(item) {
|
|
148
|
-
if (this.descriptors.length >= MAX_REPLAY_DESCRIPTORS) {
|
|
149
|
-
throw failure('native Codex response has too many replay descriptors', 'MALFORMED_RESPONSE');
|
|
150
|
-
}
|
|
151
|
-
const addedReferences = item.type === 'function_call' ? 1 : item.blocks.length;
|
|
152
|
-
if (this.references + addedReferences > MAX_REPLAY_BLOCK_REFS) {
|
|
153
|
-
throw failure('native Codex response has too many replay block references', 'MALFORMED_RESPONSE');
|
|
154
|
-
}
|
|
155
147
|
if (item.type === 'reasoning' && item.encryptedContent !== undefined
|
|
156
148
|
&& Buffer.byteLength(item.encryptedContent) > MAX_REPLAY_CIPHERTEXT_BYTES) {
|
|
157
149
|
throw failure('native Codex encrypted reasoning exceeded the replay limit', 'MALFORMED_RESPONSE');
|
|
@@ -162,7 +154,6 @@ export class NativeCodexReplayCapture {
|
|
|
162
154
|
throw failure('native Codex replay state exceeded the size limit', 'REPLAY_STATE_TOO_LARGE');
|
|
163
155
|
}
|
|
164
156
|
this.descriptors.push(item);
|
|
165
|
-
this.references += addedReferences;
|
|
166
157
|
this.stateBytes = nextBytes;
|
|
167
158
|
}
|
|
168
159
|
finish() {
|
package/lib/responses.d.ts
CHANGED
|
@@ -100,9 +100,13 @@ export declare class ResponsesStreamTranslator {
|
|
|
100
100
|
private readonly order;
|
|
101
101
|
private readonly replayCapture;
|
|
102
102
|
private nextIndex;
|
|
103
|
+
private retainedBytes;
|
|
103
104
|
private sawToolCall;
|
|
104
105
|
terminated: boolean;
|
|
105
106
|
constructor(replayContext?: ResponsesReplayContext | undefined);
|
|
107
|
+
private reserve;
|
|
108
|
+
private append;
|
|
109
|
+
private fill;
|
|
106
110
|
private open;
|
|
107
111
|
private close;
|
|
108
112
|
private closeItem;
|
|
@@ -114,8 +118,6 @@ export interface StreamResponsesOptions extends ParseSseOptions {
|
|
|
114
118
|
onMalformedEvent?: () => void;
|
|
115
119
|
onEvent?: (event: ResponsesStreamEvent) => void;
|
|
116
120
|
replayContext?: ResponsesReplayContext;
|
|
117
|
-
maxResponseBytes?: number;
|
|
118
|
-
maxResponseEvents?: number;
|
|
119
121
|
}
|
|
120
122
|
/** Validate one opaque sticky turn token before retaining or forwarding it. */
|
|
121
123
|
export declare function boundedCodexTurnState(value: unknown): string | undefined;
|
package/lib/responses.js
CHANGED
|
@@ -6,6 +6,7 @@ import { NativeCodexReplayCapture, replayAssistantInput, replayableItemId, } fro
|
|
|
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;
|
|
9
10
|
function fixedError(message, code) { return new LlmError(message, code); }
|
|
10
11
|
function imageItem(image) {
|
|
11
12
|
if (!/^image[/][a-z0-9.+-]+$/i.test(image.mediaType) || image.dataBase64.length === 0) {
|
|
@@ -242,6 +243,7 @@ export class ResponsesStreamTranslator {
|
|
|
242
243
|
order = [];
|
|
243
244
|
replayCapture;
|
|
244
245
|
nextIndex = 0;
|
|
246
|
+
retainedBytes = 0;
|
|
245
247
|
sawToolCall = false;
|
|
246
248
|
terminated = false;
|
|
247
249
|
constructor(replayContext) {
|
|
@@ -250,7 +252,26 @@ export class ResponsesStreamTranslator {
|
|
|
250
252
|
? undefined
|
|
251
253
|
: new NativeCodexReplayCapture(replayContext.provider, replayContext.model);
|
|
252
254
|
}
|
|
255
|
+
reserve(bytes) {
|
|
256
|
+
const nextBytes = this.retainedBytes + bytes;
|
|
257
|
+
if (!Number.isSafeInteger(nextBytes) || nextBytes > MAX_RETAINED_RESPONSE_BYTES) {
|
|
258
|
+
throw fixedError('native Codex response retained content exceeded the size limit', 'RESPONSE_TOO_LARGE');
|
|
259
|
+
}
|
|
260
|
+
this.retainedBytes = nextBytes;
|
|
261
|
+
}
|
|
262
|
+
append(block, delta) {
|
|
263
|
+
this.reserve(Buffer.byteLength(delta));
|
|
264
|
+
block.text += delta;
|
|
265
|
+
}
|
|
266
|
+
fill(block, text) {
|
|
267
|
+
if (block.text.length > 0)
|
|
268
|
+
return;
|
|
269
|
+
this.reserve(Buffer.byteLength(text));
|
|
270
|
+
block.text = text;
|
|
271
|
+
}
|
|
253
272
|
open(key, kind, chunks, callId = '', name) {
|
|
273
|
+
this.reserve(128 + Buffer.byteLength(key) + Buffer.byteLength(callId)
|
|
274
|
+
+ (name === undefined ? 0 : Buffer.byteLength(name)));
|
|
254
275
|
const block = {
|
|
255
276
|
index: this.nextIndex++, kind, text: '', callId,
|
|
256
277
|
...name === undefined ? {} : { name },
|
|
@@ -308,7 +329,7 @@ export class ResponsesStreamTranslator {
|
|
|
308
329
|
const key = `${eventItemId(event)}:text:${String(event.content_index ?? 0)}`;
|
|
309
330
|
const block = this.blocks.get(key) ?? this.open(key, 'text', chunks);
|
|
310
331
|
const delta = eventDelta(event);
|
|
311
|
-
block
|
|
332
|
+
this.append(block, delta);
|
|
312
333
|
chunks.push({ type: 'text-delta', index: block.index, text: delta });
|
|
313
334
|
return chunks;
|
|
314
335
|
}
|
|
@@ -316,7 +337,7 @@ export class ResponsesStreamTranslator {
|
|
|
316
337
|
const key = `${eventItemId(event)}:summary:${String(event.summary_index ?? 0)}`;
|
|
317
338
|
const block = this.blocks.get(key) ?? this.open(key, 'reasoning', chunks);
|
|
318
339
|
const delta = eventDelta(event);
|
|
319
|
-
block
|
|
340
|
+
this.append(block, delta);
|
|
320
341
|
chunks.push({ type: 'reasoning-delta', index: block.index, text: delta });
|
|
321
342
|
return chunks;
|
|
322
343
|
}
|
|
@@ -329,7 +350,7 @@ export class ResponsesStreamTranslator {
|
|
|
329
350
|
throw fixedError('native Codex function arguments have no open call', 'MALFORMED_RESPONSE');
|
|
330
351
|
}
|
|
331
352
|
const delta = eventDelta(event);
|
|
332
|
-
block
|
|
353
|
+
this.append(block, delta);
|
|
333
354
|
chunks.push({
|
|
334
355
|
type: 'tool-call-delta', index: block.index, id: CallId(block.callId),
|
|
335
356
|
...block.name === undefined ? {} : { name: block.name }, argumentsDelta: delta,
|
|
@@ -360,8 +381,7 @@ export class ResponsesStreamTranslator {
|
|
|
360
381
|
}
|
|
361
382
|
block.callId = item.call_id;
|
|
362
383
|
block.name = item.name;
|
|
363
|
-
|
|
364
|
-
block.text = item.arguments;
|
|
384
|
+
this.fill(block, item.arguments);
|
|
365
385
|
this.close(key, chunks);
|
|
366
386
|
if (this.replayContext !== undefined)
|
|
367
387
|
this.replayCapture?.add({
|
|
@@ -385,8 +405,7 @@ export class ResponsesStreamTranslator {
|
|
|
385
405
|
if (block.text.length > 0 && block.text !== part.text) {
|
|
386
406
|
throw fixedError('native Codex text changed during streaming', 'MALFORMED_RESPONSE');
|
|
387
407
|
}
|
|
388
|
-
|
|
389
|
-
block.text = part.text;
|
|
408
|
+
this.fill(block, part.text);
|
|
390
409
|
refs.push(block.index);
|
|
391
410
|
this.close(key, chunks);
|
|
392
411
|
}
|
|
@@ -417,8 +436,7 @@ export class ResponsesStreamTranslator {
|
|
|
417
436
|
if (block.text.length > 0 && block.text !== text) {
|
|
418
437
|
throw fixedError('native Codex reasoning summary changed during streaming', 'MALFORMED_RESPONSE');
|
|
419
438
|
}
|
|
420
|
-
|
|
421
|
-
block.text = text;
|
|
439
|
+
this.fill(block, text);
|
|
422
440
|
refs.push(block.index);
|
|
423
441
|
this.close(key, chunks);
|
|
424
442
|
}
|
|
@@ -466,7 +484,7 @@ export class ResponsesStreamTranslator {
|
|
|
466
484
|
} } }
|
|
467
485
|
: {
|
|
468
486
|
type: 'finish', reason: { kind: this.sawToolCall ? 'tool-calls' : 'stop' },
|
|
469
|
-
...(replayState === undefined ? {} : { replayState }),
|
|
487
|
+
...(replayState === undefined ? {} : { replayState: { response: replayState } }),
|
|
470
488
|
});
|
|
471
489
|
return chunks;
|
|
472
490
|
}
|
|
@@ -528,29 +546,8 @@ export function codexResponseTurnState(event) {
|
|
|
528
546
|
}
|
|
529
547
|
/** Consume framed SSE JSON into DSH chunks. */
|
|
530
548
|
export async function* streamResponses(stream, options = {}) {
|
|
531
|
-
const byteLimit = options.maxResponseBytes ?? 24 * 1024 * 1024;
|
|
532
|
-
const eventLimit = options.maxResponseEvents ?? 4096;
|
|
533
|
-
if (!Number.isSafeInteger(byteLimit) || byteLimit <= 0 || byteLimit > 24 * 1024 * 1024
|
|
534
|
-
|| !Number.isSafeInteger(eventLimit) || eventLimit <= 0 || eventLimit > 4096) {
|
|
535
|
-
throw fixedError('native Codex response limit is invalid', 'INVALID_CONFIG');
|
|
536
|
-
}
|
|
537
|
-
let responseBytes = 0;
|
|
538
|
-
let responseEvents = 0;
|
|
539
549
|
const translator = new ResponsesStreamTranslator(options.replayContext);
|
|
540
|
-
for await (const frame of parseSse(stream, {
|
|
541
|
-
...options,
|
|
542
|
-
onBytes: (bytes) => {
|
|
543
|
-
options.onBytes?.(bytes);
|
|
544
|
-
responseBytes += bytes;
|
|
545
|
-
if (responseBytes > byteLimit) {
|
|
546
|
-
throw fixedError('native Codex response exceeded the size limit', 'RESPONSE_TOO_LARGE');
|
|
547
|
-
}
|
|
548
|
-
},
|
|
549
|
-
})) {
|
|
550
|
-
responseEvents += 1;
|
|
551
|
-
if (responseEvents > eventLimit) {
|
|
552
|
-
throw fixedError('native Codex response had too many events', 'RESPONSE_TOO_LARGE');
|
|
553
|
-
}
|
|
550
|
+
for await (const frame of parseSse(stream, options)) {
|
|
554
551
|
let event;
|
|
555
552
|
try {
|
|
556
553
|
event = JSON.parse(frame.data);
|
package/lib/sse.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Bounded, cancellable Server-Sent Events byte framing. */
|
|
2
2
|
import { LlmError } from '@deepseek-ai/dsh-llm';
|
|
3
|
-
export const DEFAULT_MAX_SSE_EVENT_BYTES = 1024 * 1024;
|
|
3
|
+
export const DEFAULT_MAX_SSE_EVENT_BYTES = 64 * 1024 * 1024;
|
|
4
4
|
function aborted() {
|
|
5
5
|
return new LlmError('native Codex SSE stream was cancelled', 'ABORTED');
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pure01fx/dsh-openai-codex-auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
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": {
|
|
@@ -69,7 +69,15 @@
|
|
|
69
69
|
"CHANGELOG.md",
|
|
70
70
|
"LICENSE"
|
|
71
71
|
],
|
|
72
|
+
"scripts": {
|
|
73
|
+
"build": "tsc",
|
|
74
|
+
"test": "vitest run",
|
|
75
|
+
"prepack": "pnpm build"
|
|
76
|
+
},
|
|
72
77
|
"dsh": {
|
|
78
|
+
"engines": {
|
|
79
|
+
"dsh": "0.1.1-rc.2"
|
|
80
|
+
},
|
|
73
81
|
"bundle": {
|
|
74
82
|
"patch": "./cordis.patch.yml"
|
|
75
83
|
},
|
|
@@ -84,30 +92,25 @@
|
|
|
84
92
|
},
|
|
85
93
|
"peerDependencies": {
|
|
86
94
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
87
|
-
"@deepseek-ai/dsh-credentials": "0.1.
|
|
88
|
-
"@deepseek-ai/dsh-host-webserver": "0.1.
|
|
89
|
-
"@deepseek-ai/dsh-llm": "0.1.
|
|
95
|
+
"@deepseek-ai/dsh-credentials": "0.1.1-rc.2",
|
|
96
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
|
|
97
|
+
"@deepseek-ai/dsh-llm": "0.1.1-rc.2"
|
|
90
98
|
},
|
|
91
99
|
"dependencies": {
|
|
92
|
-
"@deepseek-ai/dsh-atomic-write": "0.1.
|
|
93
|
-
"@deepseek-ai/dsh-
|
|
94
|
-
"@deepseek-ai/dsh-home-paths": "0.1.0-rc.6",
|
|
100
|
+
"@deepseek-ai/dsh-atomic-write": "0.1.1-rc.2",
|
|
101
|
+
"@deepseek-ai/dsh-home-paths": "0.1.1-rc.2",
|
|
95
102
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
96
103
|
"ws": "8.21.3"
|
|
97
104
|
},
|
|
98
105
|
"devDependencies": {
|
|
99
106
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
100
|
-
"@deepseek-ai/dsh-agent": "0.1.
|
|
101
|
-
"@deepseek-ai/dsh-credentials": "0.1.
|
|
102
|
-
"@deepseek-ai/dsh-host-webserver": "0.1.
|
|
103
|
-
"@deepseek-ai/dsh-llm": "0.1.
|
|
104
|
-
"@deepseek-ai/dsh-session": "0.1.
|
|
107
|
+
"@deepseek-ai/dsh-agent": "0.1.1-rc.2",
|
|
108
|
+
"@deepseek-ai/dsh-credentials": "0.1.1-rc.2",
|
|
109
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
|
|
110
|
+
"@deepseek-ai/dsh-llm": "0.1.1-rc.2",
|
|
111
|
+
"@deepseek-ai/dsh-session": "0.1.1-rc.2",
|
|
105
112
|
"@types/node": "^22.20.0",
|
|
106
113
|
"typescript": "^6.0.3",
|
|
107
114
|
"vitest": "^4.1.8"
|
|
108
|
-
},
|
|
109
|
-
"scripts": {
|
|
110
|
-
"build": "tsc",
|
|
111
|
-
"test": "vitest run"
|
|
112
115
|
}
|
|
113
|
-
}
|
|
116
|
+
}
|