codex-multi-auth 2.1.2 → 2.1.4

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.
@@ -70,15 +70,39 @@ export function rewriteTopLevelModelProvider(rawConfig) {
70
70
  output.push(rewrittenLine);
71
71
  return output.join(lineEnding);
72
72
  }
73
- function extractTopLevelModelProviderLine(rawConfig) {
73
+ export function enableTopLevelResponseStorage(rawConfig) {
74
+ const lineEnding = rawConfig.includes("\r\n") ? "\r\n" : "\n";
75
+ const lines = rawConfig.length > 0 ? rawConfig.split(/\r?\n/) : [];
76
+ const output = [];
77
+ let inTopLevel = true;
78
+ for (const line of lines) {
79
+ if (readTomlTableName(line) !== null) {
80
+ inTopLevel = false;
81
+ output.push(line);
82
+ continue;
83
+ }
84
+ if (inTopLevel &&
85
+ /^\s*disable_response_storage\s*=\s*true\s*(?:#.*)?$/i.test(line)) {
86
+ output.push("disable_response_storage = false");
87
+ continue;
88
+ }
89
+ output.push(line);
90
+ }
91
+ return output.join(lineEnding);
92
+ }
93
+ function extractTopLevelLine(rawConfig, key) {
94
+ const pattern = new RegExp(`^\\s*${key}\\s*=`);
74
95
  for (const line of rawConfig.split(/\r?\n/)) {
75
96
  if (readTomlTableName(line) !== null)
76
97
  return null;
77
- if (/^\s*model_provider\s*=/.test(line))
98
+ if (pattern.test(line))
78
99
  return line;
79
100
  }
80
101
  return null;
81
102
  }
103
+ function extractTopLevelModelProviderLine(rawConfig) {
104
+ return extractTopLevelLine(rawConfig, "model_provider");
105
+ }
82
106
  export function restoreTopLevelModelProvider(currentConfig, originalConfig) {
83
107
  const lineEnding = currentConfig.includes("\r\n") ? "\r\n" : "\n";
84
108
  const originalLine = extractTopLevelModelProviderLine(originalConfig);
@@ -98,6 +122,33 @@ export function restoreTopLevelModelProvider(currentConfig, originalConfig) {
98
122
  }
99
123
  return output.join(lineEnding);
100
124
  }
125
+ export function restoreTopLevelResponseStorage(currentConfig, originalConfig) {
126
+ const lineEnding = currentConfig.includes("\r\n") ? "\r\n" : "\n";
127
+ const originalLine = extractTopLevelLine(originalConfig, "disable_response_storage");
128
+ if (!originalLine)
129
+ return currentConfig;
130
+ const lines = currentConfig.length > 0 ? currentConfig.split(/\r?\n/) : [];
131
+ const output = [];
132
+ let handled = false;
133
+ let inTopLevel = true;
134
+ for (const line of lines) {
135
+ if (readTomlTableName(line) !== null) {
136
+ inTopLevel = false;
137
+ output.push(line);
138
+ continue;
139
+ }
140
+ if (!handled &&
141
+ inTopLevel &&
142
+ /^\s*disable_response_storage\s*=/.test(line) &&
143
+ readTomlTableName(line) === null) {
144
+ output.push(originalLine);
145
+ handled = true;
146
+ continue;
147
+ }
148
+ output.push(line);
149
+ }
150
+ return output.join(lineEnding);
151
+ }
101
152
  export function ensureTomlTrailingNewline(value) {
102
153
  return value.replace(/[\r\n]*$/, "\n");
103
154
  }
@@ -118,11 +169,13 @@ export function rewriteConfigTomlForRuntimeRotationProvider(rawConfig, baseUrl,
118
169
  const lineEnding = rawConfig.includes("\r\n") ? "\r\n" : "\n";
119
170
  const withoutOldProvider = removeRuntimeRotationProviderBlock(rawConfig).replace(/[\r\n]*$/, "");
120
171
  const withModelProvider = rewriteTopLevelModelProvider(withoutOldProvider).replace(/[\r\n]*$/, "");
172
+ const withResponseStorage = enableTopLevelResponseStorage(withModelProvider).replace(/[\r\n]*$/, "");
121
173
  const providerBlock = createRuntimeRotationProviderBlock(baseUrl, clientApiKey).join(lineEnding);
122
- return `${withModelProvider}${lineEnding}${lineEnding}${providerBlock}${lineEnding}`;
174
+ return `${withResponseStorage}${lineEnding}${lineEnding}${providerBlock}${lineEnding}`;
123
175
  }
124
176
  export function restoreConfigTomlFromRuntimeRotationProvider(currentConfig, originalConfig) {
125
177
  const withoutProvider = removeRuntimeRotationProviderBlock(currentConfig);
126
- return ensureTomlTrailingNewline(restoreTopLevelModelProvider(withoutProvider, originalConfig).replace(/[\r\n]*$/, ""));
178
+ const withResponseStorage = restoreTopLevelResponseStorage(withoutProvider, originalConfig);
179
+ return ensureTomlTrailingNewline(restoreTopLevelModelProvider(withResponseStorage, originalConfig).replace(/[\r\n]*$/, ""));
127
180
  }
128
181
  //# sourceMappingURL=config-toml.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-toml.js","sourceRoot":"","sources":["../../../lib/runtime/config-toml.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config-toml.js","sourceRoot":"","sources":["../../../lib/runtime/config-toml.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-rotation-proxy.d.ts","sourceRoot":"","sources":["../../lib/runtime-rotation-proxy.ts"],"names":[],"mappings":"AAGA,OAAO,EACN,cAAc,EAGd,MAAM,eAAe,CAAC;AAiCvB,MAAM,WAAW,0BAA0B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,SAAS,EAAE,MAAM,0BAA0B,CAAC;CAC5C;AAED,MAAM,WAAW,0BAA0B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,2BAA2B;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAosBD,wBAAsB,yBAAyB,CAC9C,OAAO,EAAE,2BAA2B,GAClC,OAAO,CAAC,0BAA0B,CAAC,CAkcrC"}
1
+ {"version":3,"file":"runtime-rotation-proxy.d.ts","sourceRoot":"","sources":["../../lib/runtime-rotation-proxy.ts"],"names":[],"mappings":"AAGA,OAAO,EACN,cAAc,EAGd,MAAM,eAAe,CAAC;AAkCvB,MAAM,WAAW,0BAA0B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,SAAS,EAAE,MAAM,0BAA0B,CAAC;CAC5C;AAED,MAAM,WAAW,0BAA0B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,2BAA2B;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAwyBD,wBAAsB,yBAAyB,CAC9C,OAAO,EAAE,2BAA2B,GAClC,OAAO,CAAC,0BAA0B,CAAC,CAkkBrC"}
@@ -7,6 +7,7 @@ import { getModelFamily } from "./prompts/codex.js";
7
7
  import { queuedRefresh } from "./refresh-queue.js";
8
8
  import { mutateRuntimeObservabilitySnapshot } from "./runtime/runtime-observability.js";
9
9
  import { createRuntimeUsageRecorder, evaluateRuntimePolicy, loadRuntimePolicyState, } from "./policy/runtime-policy.js";
10
+ import { isWorkspaceDisabledError } from "./request/fetch-helpers.js";
10
11
  import { SessionAffinityStore } from "./session-affinity.js";
11
12
  import { isRecord } from "./utils.js";
12
13
  const DEFAULT_HOST = "127.0.0.1";
@@ -14,6 +15,7 @@ const DEFAULT_QUOTA_REMAINING_THRESHOLD = 10;
14
15
  const DEFAULT_AUTH_FAILURE_COOLDOWN_MS = 30_000;
15
16
  const DEFAULT_MAX_RUNTIME_ACCOUNT_ATTEMPTS = 4;
16
17
  const MAX_REQUEST_BODY_BYTES = 64 * 1024 * 1024;
18
+ const MAX_THREAD_GOAL_FALLBACKS = 512;
17
19
  const HOP_BY_HOP_HEADERS = new Set([
18
20
  "connection",
19
21
  "content-length",
@@ -46,12 +48,24 @@ const ALLOWED_MODELS_PATHS = new Set([
46
48
  URL_PATHS.MODELS,
47
49
  `/v1${URL_PATHS.MODELS}`,
48
50
  ]);
51
+ const ALLOWED_THREAD_GOAL_PATHS = new Set([
52
+ "/thread/goal/get",
53
+ "/thread/goal/set",
54
+ "/codex/thread/goal/get",
55
+ "/codex/thread/goal/set",
56
+ ]);
49
57
  function isResponsesPath(pathname) {
50
58
  return ALLOWED_RESPONSES_PATHS.has(pathname);
51
59
  }
52
60
  function isModelsPath(pathname) {
53
61
  return ALLOWED_MODELS_PATHS.has(pathname);
54
62
  }
63
+ function isThreadGoalPath(pathname) {
64
+ return ALLOWED_THREAD_GOAL_PATHS.has(pathname);
65
+ }
66
+ function normalizeThreadGoalUpstreamPath(pathname) {
67
+ return pathname.startsWith("/codex/") ? pathname : `/codex${pathname}`;
68
+ }
55
69
  function headersFromIncoming(req) {
56
70
  const headers = new Headers();
57
71
  for (const [key, value] of Object.entries(req.headers)) {
@@ -191,6 +205,33 @@ function readStringRecordValue(record, key) {
191
205
  ? value.trim()
192
206
  : null;
193
207
  }
208
+ function readStringSearchParam(searchParams, key) {
209
+ const value = searchParams.get(key);
210
+ return value && value.trim().length > 0 ? value.trim() : null;
211
+ }
212
+ function isThreadGoalFallbackStatus(status) {
213
+ return status === HTTP_STATUS.FORBIDDEN;
214
+ }
215
+ function setThreadGoalFallback(fallbacks, key, goal) {
216
+ if (fallbacks.has(key)) {
217
+ fallbacks.delete(key);
218
+ }
219
+ fallbacks.set(key, goal);
220
+ while (fallbacks.size > MAX_THREAD_GOAL_FALLBACKS) {
221
+ const oldestKey = fallbacks.keys().next().value;
222
+ if (typeof oldestKey !== "string")
223
+ break;
224
+ fallbacks.delete(oldestKey);
225
+ }
226
+ }
227
+ function getThreadGoalFallback(fallbacks, key) {
228
+ if (!fallbacks.has(key))
229
+ return null;
230
+ const goal = fallbacks.get(key) ?? null;
231
+ fallbacks.delete(key);
232
+ fallbacks.set(key, goal);
233
+ return goal;
234
+ }
194
235
  function resolveSessionKey(headers, parsedBody) {
195
236
  const headerKey = headers.get(OPENAI_HEADERS.SESSION_ID) ??
196
237
  headers.get(OPENAI_HEADERS.CONVERSATION_ID) ??
@@ -246,6 +287,28 @@ function buildModelsRequestContext(req) {
246
287
  sessionKey: null,
247
288
  };
248
289
  }
290
+ function buildThreadGoalRequestContext(req, body, pathname) {
291
+ const headers = headersFromIncoming(req);
292
+ const parsedBody = parseRequestBody(body);
293
+ const searchParams = new URL(req.url ?? "/", "http://127.0.0.1").searchParams;
294
+ const queryThreadKey = readStringSearchParam(searchParams, "thread_id") ??
295
+ readStringSearchParam(searchParams, "threadId");
296
+ const bodyThreadKey = parsedBody
297
+ ? (readStringRecordValue(parsedBody, "thread_id") ??
298
+ readStringRecordValue(parsedBody, "threadId"))
299
+ : null;
300
+ const sessionKey = bodyThreadKey ?? queryThreadKey ?? resolveSessionKey(headers, parsedBody);
301
+ return {
302
+ body,
303
+ headers,
304
+ method: req.method === "GET" ? "GET" : "POST",
305
+ upstreamPath: normalizeThreadGoalUpstreamPath(pathname),
306
+ model: null,
307
+ family: "codex",
308
+ stream: false,
309
+ sessionKey,
310
+ };
311
+ }
249
312
  function buildUpstreamUrl(req, upstreamBaseUrl, upstreamPath) {
250
313
  const incomingUrl = new URL(req.url ?? "/", "http://127.0.0.1");
251
314
  const upstream = new URL(upstreamBaseUrl);
@@ -386,6 +449,29 @@ async function readErrorBody(response) {
386
449
  return "";
387
450
  }
388
451
  }
452
+ function extractErrorCodeFromBody(bodyText) {
453
+ if (!bodyText.trim())
454
+ return null;
455
+ try {
456
+ const parsed = JSON.parse(bodyText);
457
+ if (!isRecord(parsed))
458
+ return null;
459
+ const directCode = parsed.code;
460
+ if (typeof directCode === "string" && directCode.trim()) {
461
+ return directCode.trim();
462
+ }
463
+ const maybeError = parsed.error;
464
+ if (!isRecord(maybeError))
465
+ return null;
466
+ const nestedCode = maybeError.code;
467
+ return typeof nestedCode === "string" && nestedCode.trim()
468
+ ? nestedCode.trim()
469
+ : null;
470
+ }
471
+ catch {
472
+ return null;
473
+ }
474
+ }
389
475
  function getQuotaWindowWaitMs(headers, prefix, now) {
390
476
  const resetAfterSeconds = Number.parseInt(headers.get(`${prefix}-reset-after-seconds`) ?? "", 10);
391
477
  if (Number.isFinite(resetAfterSeconds) && resetAfterSeconds > 0) {
@@ -465,7 +551,7 @@ function writeJson(res, status, payload) {
465
551
  function writeMethodOrPathError(res) {
466
552
  writeJson(res, 404, {
467
553
  error: {
468
- message: "Runtime rotation proxy only accepts Responses API and model discovery requests.",
554
+ message: "Runtime rotation proxy only accepts Responses API, model discovery, and Codex thread goal requests.",
469
555
  code: "runtime_rotation_proxy_not_found",
470
556
  },
471
557
  });
@@ -593,13 +679,16 @@ export async function startRuntimeRotationProxy(options) {
593
679
  lastAccountId: null,
594
680
  lastAccountUpdatedAt: null,
595
681
  };
682
+ const threadGoalFallbacks = new Map();
596
683
  const handleRequest = async (req, res) => {
597
684
  let usageRecorder = null;
598
685
  try {
599
686
  const incomingUrl = new URL(req.url ?? "/", "http://127.0.0.1");
600
687
  const isResponsesRequest = req.method === "POST" && isResponsesPath(incomingUrl.pathname);
601
688
  const isModelsRequest = req.method === "GET" && isModelsPath(incomingUrl.pathname);
602
- if (!isResponsesRequest && !isModelsRequest) {
689
+ const isThreadGoalRequest = (req.method === "GET" || req.method === "POST") &&
690
+ isThreadGoalPath(incomingUrl.pathname);
691
+ if (!isResponsesRequest && !isModelsRequest && !isThreadGoalRequest) {
603
692
  writeMethodOrPathError(res);
604
693
  return;
605
694
  }
@@ -609,9 +698,14 @@ export async function startRuntimeRotationProxy(options) {
609
698
  return;
610
699
  }
611
700
  status.totalRequests += 1;
701
+ const requestBody = isResponsesRequest || (isThreadGoalRequest && req.method === "POST")
702
+ ? await readRequestBody(req, maxRequestBodyBytes)
703
+ : Buffer.alloc(0);
612
704
  const context = isModelsRequest
613
705
  ? buildModelsRequestContext(req)
614
- : buildResponsesRequestContext(req, await readRequestBody(req, maxRequestBodyBytes));
706
+ : isThreadGoalRequest
707
+ ? buildThreadGoalRequestContext(req, requestBody, incomingUrl.pathname)
708
+ : buildResponsesRequestContext(req, requestBody);
615
709
  const requestStartedAt = now();
616
710
  let policyDecision = null;
617
711
  let projectKey = null;
@@ -632,7 +726,11 @@ export async function startRuntimeRotationProxy(options) {
632
726
  }
633
727
  usageRecorder = createRuntimeUsageRecorder({
634
728
  source: "runtime-proxy",
635
- operation: isModelsRequest ? "models" : "responses",
729
+ operation: isModelsRequest
730
+ ? "models"
731
+ : isThreadGoalRequest
732
+ ? "thread-goal"
733
+ : "responses",
636
734
  model: context.model,
637
735
  projectKey,
638
736
  requestId: context.sessionKey,
@@ -670,8 +768,12 @@ export async function startRuntimeRotationProxy(options) {
670
768
  const upstreamUrl = buildUpstreamUrl(req, upstreamBaseUrl, context.upstreamPath);
671
769
  const attemptedIndexes = new Set();
672
770
  let exhaustionReason = "no-account";
673
- const accountAttemptLimit = Math.max(1, Math.min(accountManager.getAccountCount(), maxRuntimeAccountAttempts));
674
- while (attemptedIndexes.size < accountAttemptLimit) {
771
+ const accountCount = accountManager.getAccountCount();
772
+ const transientAttemptLimit = Math.max(1, Math.min(accountCount, maxRuntimeAccountAttempts));
773
+ let transientAttempts = 0;
774
+ let transientExhaustionReason = null;
775
+ while (attemptedIndexes.size < accountCount &&
776
+ transientAttempts < transientAttemptLimit) {
675
777
  const selected = chooseAccount({
676
778
  accountManager,
677
779
  sessionAffinityStore,
@@ -702,6 +804,8 @@ export async function startRuntimeRotationProxy(options) {
702
804
  exhaustionReason = "auth-failure";
703
805
  if (!refreshed.retryable)
704
806
  continue;
807
+ transientAttempts += 1;
808
+ transientExhaustionReason = "auth-failure";
705
809
  status.retries += 1;
706
810
  status.rotations += 1;
707
811
  continue;
@@ -712,6 +816,8 @@ export async function startRuntimeRotationProxy(options) {
712
816
  accountManager.recordFailure(refreshed.account, context.family, context.model);
713
817
  accountManager.markAccountCoolingDown(refreshed.account, DEFAULT_AUTH_FAILURE_COOLDOWN_MS, "auth-failure");
714
818
  exhaustionReason = "auth-failure";
819
+ transientAttempts += 1;
820
+ transientExhaustionReason = "auth-failure";
715
821
  status.retries += 1;
716
822
  status.rotations += 1;
717
823
  continue;
@@ -740,6 +846,8 @@ export async function startRuntimeRotationProxy(options) {
740
846
  accountManager.markAccountCoolingDown(refreshed.account, networkErrorCooldownMs, "network-error");
741
847
  accountManager.saveToDiskDebounced();
742
848
  exhaustionReason = "network-error";
849
+ transientAttempts += 1;
850
+ transientExhaustionReason = "network-error";
743
851
  status.retries += 1;
744
852
  status.rotations += 1;
745
853
  continue;
@@ -755,10 +863,75 @@ export async function startRuntimeRotationProxy(options) {
755
863
  accountManager.markRateLimitedWithReason(refreshed.account, retryAfterMs, context.family, "quota", context.model);
756
864
  accountManager.saveToDiskDebounced();
757
865
  exhaustionReason = "rate-limit";
866
+ transientAttempts += 1;
867
+ transientExhaustionReason = "rate-limit";
758
868
  status.retries += 1;
759
869
  status.rotations += 1;
760
870
  continue;
761
871
  }
872
+ if (upstream.status === 402 || upstream.status === HTTP_STATUS.FORBIDDEN) {
873
+ const bodyText = await readErrorBody(upstream);
874
+ const errorCode = extractErrorCodeFromBody(bodyText);
875
+ if (isWorkspaceDisabledError(upstream.status, errorCode, bodyText)) {
876
+ const accountWasEnabled = accountManager.getAccountByIndex(refreshed.account.index)?.enabled !==
877
+ false;
878
+ accountManager.refundToken(refreshed.account, context.family, context.model);
879
+ if (accountWasEnabled) {
880
+ accountManager.recordFailure(refreshed.account, context.family, context.model);
881
+ accountManager.setAccountEnabled(refreshed.account.index, false);
882
+ accountManager.saveToDiskDebounced();
883
+ }
884
+ sessionAffinityStore?.forgetSession(context.sessionKey);
885
+ exhaustionReason = "deactivated";
886
+ status.retries += 1;
887
+ status.rotations += 1;
888
+ continue;
889
+ }
890
+ if (isThreadGoalRequest && isThreadGoalFallbackStatus(upstream.status)) {
891
+ const parsedGoalBody = parseRequestBody(context.body);
892
+ const fallbackKey = context.sessionKey;
893
+ const goal = typeof parsedGoalBody?.goal === "string" ? parsedGoalBody.goal : null;
894
+ if (!fallbackKey) {
895
+ await usageRecorder.record({
896
+ outcome: "failure",
897
+ statusCode: HTTP_STATUS.BAD_REQUEST,
898
+ errorCode: "thread_goal_session_key_required",
899
+ account: refreshed.account,
900
+ });
901
+ writeJson(res, HTTP_STATUS.BAD_REQUEST, {
902
+ error: {
903
+ message: "Thread goal fallback requires a thread_id, threadId, or session header.",
904
+ code: "thread_goal_session_key_required",
905
+ },
906
+ });
907
+ return;
908
+ }
909
+ await usageRecorder.record({
910
+ outcome: "failure",
911
+ statusCode: upstream.status,
912
+ errorCode: "thread_goal_upstream_blocked",
913
+ account: refreshed.account,
914
+ });
915
+ if (context.upstreamPath.endsWith("/set")) {
916
+ setThreadGoalFallback(threadGoalFallbacks, fallbackKey, goal);
917
+ writeJson(res, HTTP_STATUS.OK, { ok: true, goal });
918
+ return;
919
+ }
920
+ writeJson(res, HTTP_STATUS.OK, {
921
+ goal: getThreadGoalFallback(threadGoalFallbacks, fallbackKey),
922
+ });
923
+ return;
924
+ }
925
+ res.writeHead(upstream.status, responseHeadersForClient(upstream.headers));
926
+ res.end(bodyText);
927
+ await usageRecorder.record({
928
+ outcome: "failure",
929
+ statusCode: upstream.status,
930
+ errorCode,
931
+ account: refreshed.account,
932
+ });
933
+ return;
934
+ }
762
935
  if (upstream.status === HTTP_STATUS.UNAUTHORIZED) {
763
936
  await readErrorBody(upstream);
764
937
  accountManager.refundToken(refreshed.account, context.family, context.model);
@@ -766,6 +939,8 @@ export async function startRuntimeRotationProxy(options) {
766
939
  accountManager.markAccountCoolingDown(refreshed.account, DEFAULT_AUTH_FAILURE_COOLDOWN_MS, "auth-failure");
767
940
  accountManager.saveToDiskDebounced();
768
941
  exhaustionReason = "auth-failure";
942
+ transientAttempts += 1;
943
+ transientExhaustionReason = "auth-failure";
769
944
  status.retries += 1;
770
945
  status.rotations += 1;
771
946
  continue;
@@ -777,10 +952,22 @@ export async function startRuntimeRotationProxy(options) {
777
952
  accountManager.markAccountCoolingDown(refreshed.account, serverErrorCooldownMs, "server-error");
778
953
  accountManager.saveToDiskDebounced();
779
954
  exhaustionReason = "server-error";
955
+ transientAttempts += 1;
956
+ transientExhaustionReason = "server-error";
780
957
  status.retries += 1;
781
958
  status.rotations += 1;
782
959
  continue;
783
960
  }
961
+ if (isThreadGoalRequest && upstream.status >= 400) {
962
+ const forwarded = await forwardStreamingResponse(upstream, res, status, () => undefined, streamStallTimeoutMs);
963
+ await usageRecorder.record({
964
+ outcome: "failure",
965
+ statusCode: upstream.status,
966
+ errorCode: forwarded ? "thread_goal_upstream_error" : "stream_forward_failed",
967
+ account: refreshed.account,
968
+ });
969
+ return;
970
+ }
784
971
  accountManager.recordSuccess(refreshed.account, context.family, context.model);
785
972
  const nearExhaustionWaitMs = getQuotaNearExhaustionWaitMs(upstream.headers, quotaRemainingPercentThreshold, now());
786
973
  if (nearExhaustionWaitMs > 0) {
@@ -806,10 +993,14 @@ export async function startRuntimeRotationProxy(options) {
806
993
  });
807
994
  return;
808
995
  }
809
- if (attemptedIndexes.size >= accountAttemptLimit &&
810
- accountAttemptLimit < accountManager.getAccountCount()) {
996
+ if (transientAttempts >= transientAttemptLimit &&
997
+ attemptedIndexes.size < accountCount) {
811
998
  exhaustionReason = "budget";
812
999
  }
1000
+ else if (exhaustionReason === "deactivated" &&
1001
+ transientExhaustionReason) {
1002
+ exhaustionReason = transientExhaustionReason;
1003
+ }
813
1004
  await usageRecorder?.record({
814
1005
  outcome: "failure",
815
1006
  statusCode: normalizeExhaustionStatus(exhaustionReason),