@ottocode/sdk 0.1.280 → 0.1.282

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ottocode/sdk",
3
- "version": "0.1.280",
3
+ "version": "0.1.282",
4
4
  "description": "AI agent SDK for building intelligent assistants - tree-shakable and comprehensive",
5
5
  "author": "nitishxyz",
6
6
  "license": "MIT",
@@ -15,8 +15,10 @@ const TOKEN_EXPIRY_BUFFER_MS = 5 * 60 * 1000;
15
15
  const TOKEN_REFRESH_MAX_RETRIES = 2;
16
16
  const TOKEN_REFRESH_RETRY_DELAY_MS = 1000;
17
17
  const CODEX_INSTALLATION_ID = crypto.randomUUID();
18
- const CODEX_REQUEST_TIMEOUT_MS = 120_000;
19
- const CODEX_STREAM_IDLE_TIMEOUT_MS = 120_000;
18
+ const CODEX_REQUEST_TIMEOUT_MS = 20_000;
19
+ const CODEX_STREAM_IDLE_TIMEOUT_MS = 20_000;
20
+ const CODEX_REQUEST_MAX_RETRIES = 3;
21
+ const CODEX_REQUEST_RETRY_DELAY_MS = 500;
20
22
 
21
23
  type OpenAIOAuthSessionState = {
22
24
  responseId?: string;
@@ -110,6 +112,20 @@ function getCodexStreamIdleTimeoutMs() {
110
112
  );
111
113
  }
112
114
 
115
+ function getCodexRequestMaxRetries() {
116
+ return parsePositiveIntegerEnv(
117
+ 'OTTO_OPENAI_OAUTH_REQUEST_MAX_RETRIES',
118
+ CODEX_REQUEST_MAX_RETRIES,
119
+ );
120
+ }
121
+
122
+ function getCodexRequestRetryDelayMs() {
123
+ return parsePositiveIntegerEnv(
124
+ 'OTTO_OPENAI_OAUTH_REQUEST_RETRY_DELAY_MS',
125
+ CODEX_REQUEST_RETRY_DELAY_MS,
126
+ );
127
+ }
128
+
113
129
  export function clearOpenAIOAuthSessionState(sessionId?: string) {
114
130
  if (sessionId) {
115
131
  openAIOAuthSessionState.delete(sessionId);
@@ -470,6 +486,49 @@ async function fetchWithCodexRequestTimeout(
470
486
  });
471
487
  }
472
488
 
489
+ const maxRetries = getCodexRequestMaxRetries();
490
+ let lastError: unknown;
491
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
492
+ const attemptStartedAt = Date.now();
493
+ try {
494
+ return await fetchCodexRequestAttemptWithTimeout(url, init, {
495
+ ...args,
496
+ requestStartedAt: attemptStartedAt,
497
+ });
498
+ } catch (error) {
499
+ lastError = error;
500
+ if (init.signal?.aborted || attempt >= maxRetries) {
501
+ throw error;
502
+ }
503
+
504
+ const retryDelayMs = getCodexRequestRetryDelayMs() * (attempt + 1);
505
+ loggerWarn('[openai-oauth] request attempt failed before response', {
506
+ sessionId: args.sessionId,
507
+ model: args.model,
508
+ attempt: attempt + 1,
509
+ maxRetries,
510
+ nextAttempt: attempt + 2,
511
+ timeoutMs: getCodexRequestTimeoutMs(),
512
+ durationMs: Date.now() - attemptStartedAt,
513
+ retryDelayMs,
514
+ error: summarizeError(error),
515
+ });
516
+ await sleep(retryDelayMs);
517
+ }
518
+ }
519
+
520
+ throw lastError;
521
+ }
522
+
523
+ async function fetchCodexRequestAttemptWithTimeout(
524
+ url: string,
525
+ init: RequestInit,
526
+ args: {
527
+ sessionId?: string;
528
+ model?: string;
529
+ requestStartedAt: number;
530
+ },
531
+ ) {
473
532
  const timeoutMs = getCodexRequestTimeoutMs();
474
533
  const controller = new AbortController();
475
534
  const timeout = setTimeout(() => {