codex-multi-auth 2.9.2 → 2.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.
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +2 -1
- package/config/README.md +3 -1
- package/config/codex-legacy.json +300 -0
- package/config/codex-modern.json +96 -0
- package/config/schema/config.schema.json +23 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +62 -2
- package/dist/lib/accounts.d.ts +25 -1
- package/dist/lib/accounts.d.ts.map +1 -1
- package/dist/lib/accounts.js +26 -6
- package/dist/lib/capability-policy.d.ts.map +1 -1
- package/dist/lib/capability-policy.js +16 -1
- package/dist/lib/codex-manager/backend-settings-helpers.d.ts.map +1 -1
- package/dist/lib/codex-manager/backend-settings-helpers.js +10 -1
- package/dist/lib/codex-manager/backend-settings-schema.d.ts +18 -0
- package/dist/lib/codex-manager/backend-settings-schema.d.ts.map +1 -1
- package/dist/lib/codex-manager/backend-settings-schema.js +19 -0
- package/dist/lib/codex-manager/experimental-settings-prompt.d.ts +1 -0
- package/dist/lib/codex-manager/experimental-settings-prompt.d.ts.map +1 -1
- package/dist/lib/codex-manager/experimental-settings-prompt.js +12 -0
- package/dist/lib/codex-manager/experimental-settings-schema.d.ts +2 -0
- package/dist/lib/codex-manager/experimental-settings-schema.d.ts.map +1 -1
- package/dist/lib/codex-manager/experimental-settings-schema.js +2 -0
- package/dist/lib/config.d.ts +29 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +91 -1
- package/dist/lib/context-budget/model-context-windows.d.ts +25 -0
- package/dist/lib/context-budget/model-context-windows.d.ts.map +1 -0
- package/dist/lib/context-budget/model-context-windows.js +130 -0
- package/dist/lib/context-budget-guard.d.ts +100 -0
- package/dist/lib/context-budget-guard.d.ts.map +1 -0
- package/dist/lib/context-budget-guard.js +183 -0
- package/dist/lib/context-budget-response.d.ts +25 -0
- package/dist/lib/context-budget-response.d.ts.map +1 -0
- package/dist/lib/context-budget-response.js +57 -0
- package/dist/lib/context-overflow.d.ts.map +1 -1
- package/dist/lib/context-overflow.js +5 -60
- package/dist/lib/model-capability-matrix.d.ts.map +1 -1
- package/dist/lib/model-capability-matrix.js +9 -1
- package/dist/lib/request/error-classification.d.ts.map +1 -1
- package/dist/lib/request/error-classification.js +43 -2
- package/dist/lib/request/helpers/model-map.d.ts.map +1 -1
- package/dist/lib/request/helpers/model-map.js +181 -0
- package/dist/lib/request/rate-limit-decision.d.ts +4 -5
- package/dist/lib/request/rate-limit-decision.d.ts.map +1 -1
- package/dist/lib/request/rate-limit-decision.js +33 -4
- package/dist/lib/request/response-metadata.d.ts.map +1 -1
- package/dist/lib/request/response-metadata.js +1 -0
- package/dist/lib/request/stream-failover-runtime.d.ts +3 -1
- package/dist/lib/request/stream-failover-runtime.d.ts.map +1 -1
- package/dist/lib/request/stream-failover-runtime.js +7 -2
- package/dist/lib/runtime/context-budget-settings.d.ts +13 -0
- package/dist/lib/runtime/context-budget-settings.d.ts.map +1 -0
- package/dist/lib/runtime/context-budget-settings.js +8 -0
- package/dist/lib/runtime/loader-setup.d.ts +1 -0
- package/dist/lib/runtime/loader-setup.d.ts.map +1 -1
- package/dist/lib/runtime/loader-setup.js +1 -0
- package/dist/lib/runtime/rotation-account-selection.d.ts +23 -0
- package/dist/lib/runtime/rotation-account-selection.d.ts.map +1 -1
- package/dist/lib/runtime/rotation-account-selection.js +15 -6
- package/dist/lib/runtime/rotation-proxy-state.d.ts +2 -0
- package/dist/lib/runtime/rotation-proxy-state.d.ts.map +1 -1
- package/dist/lib/runtime/rotation-server-types.d.ts +11 -0
- package/dist/lib/runtime/rotation-server-types.d.ts.map +1 -1
- package/dist/lib/runtime-rotation-proxy.d.ts.map +1 -1
- package/dist/lib/runtime-rotation-proxy.js +251 -43
- package/dist/lib/schemas.d.ts +4 -0
- package/dist/lib/schemas.d.ts.map +1 -1
- package/dist/lib/schemas.js +10 -0
- package/dist/lib/synthetic-response.d.ts +31 -0
- package/dist/lib/synthetic-response.d.ts.map +1 -0
- package/dist/lib/synthetic-response.js +79 -0
- package/dist/lib/ui/ui-copy.d.ts +2 -1
- package/dist/lib/ui/ui-copy.d.ts.map +1 -1
- package/dist/lib/ui/ui-copy.js +2 -1
- package/dist/lib/usage/pricing.d.ts +1 -1
- package/dist/lib/usage/pricing.d.ts.map +1 -1
- package/dist/lib/usage/pricing.js +33 -0
- package/package.json +1 -1
- package/scripts/codex.js +153 -2
|
@@ -11,6 +11,38 @@ const CHATGPT_CODEX_UNSUPPORTED_MODEL_PATTERN = /model is not supported when usi
|
|
|
11
11
|
const NORMALIZED_UNSUPPORTED_MODEL_PATTERN = /the model ['"]([^'"]+)['"] is not currently available for this chatgpt account/i;
|
|
12
12
|
const MODEL_ACCESS_DENIED_PATTERN = /the model [`'"]([^`'"]+)[`'"] does not exist or you do not have access to it/i;
|
|
13
13
|
export const DEFAULT_UNSUPPORTED_CODEX_FALLBACK_CHAIN = {
|
|
14
|
+
// GPT-6 Astra rolls out org by org, so an account that is not entitled yet
|
|
15
|
+
// gets a real unsupported-model response for it. This chain only fires when
|
|
16
|
+
// the user has opted into `fallbackOnUnsupportedCodexModel` (default
|
|
17
|
+
// `false`), and only on that response, so it never silently swaps the model
|
|
18
|
+
// out from under a request the account could have served.
|
|
19
|
+
//
|
|
20
|
+
// This table is walked ONE HOP AT A TIME, not as a per-request candidate
|
|
21
|
+
// list. index.ts reassigns `model` to whatever came back and passes that as
|
|
22
|
+
// `requestedModel` on the next unsupported response, so reaching `gpt-5.5`
|
|
23
|
+
// from Astra requires `gpt-5.6-sol` to carry its own entry below. A second
|
|
24
|
+
// element here is only ever consulted when the first is already in
|
|
25
|
+
// `attemptedModels` for that same call.
|
|
26
|
+
//
|
|
27
|
+
// Depth is not free: every hop spends one of the shared per-request outbound
|
|
28
|
+
// attempts (`tryConsumeOutboundRequestAttempt`). A single-account balanced
|
|
29
|
+
// session gets a budget of 5, and the aeon walk needs exactly 5, so it fits
|
|
30
|
+
// with nothing spare. Spend an attempt on a retry or a stream failover and
|
|
31
|
+
// the tail hops become unreachable, ending as an attempt-budget-exhausted
|
|
32
|
+
// 503 rather than `gpt-5.4`. Hops are ordered most-valuable-first so what is
|
|
33
|
+
// lost first matters least. Do not add a hop to a GPT-6 row without
|
|
34
|
+
// re-checking that budget; `test/gpt6-astra-models.test.ts` asserts it.
|
|
35
|
+
"gpt-6-astra": ["gpt-5.6-sol", "gpt-5.5"],
|
|
36
|
+
// aeon steps to the flagship first: still GPT-6, still Astra, just without
|
|
37
|
+
// the long-horizon behaviour.
|
|
38
|
+
"gpt-6-astra-aeon": ["gpt-6-astra", "gpt-5.6-sol"],
|
|
39
|
+
// The hop that makes the Astra path reach a model every account has. GPT-5.6
|
|
40
|
+
// shipped without a chain entry, so an unsupported 5.6 response ended the
|
|
41
|
+
// walk; with Astra above it that would have stranded the fallback one rung
|
|
42
|
+
// short of the floor it documents. Terra and Luna are deliberately still
|
|
43
|
+
// absent: nothing steps into them, so giving them a hop would change 5.6
|
|
44
|
+
// behaviour beyond completing this path.
|
|
45
|
+
"gpt-5.6-sol": ["gpt-5.5"],
|
|
14
46
|
"gpt-5": ["gpt-5.5"],
|
|
15
47
|
"gpt-5-pro": ["gpt-5.5-pro"],
|
|
16
48
|
"gpt-5-chat-latest": ["gpt-5.5"],
|
|
@@ -43,7 +75,14 @@ function canonicalizeModelName(model) {
|
|
|
43
75
|
return stripped.replace(/-(none|minimal|low|medium|high|xhigh)$/i, "");
|
|
44
76
|
}
|
|
45
77
|
function normalizeFallbackChain(customChain) {
|
|
46
|
-
|
|
78
|
+
// Null-prototype, because both the keys written here and the keys read out of
|
|
79
|
+
// it are caller-controlled. On a plain object, a `customChain` entry named
|
|
80
|
+
// `__proto__` reassigns this object's prototype instead of adding a row, and
|
|
81
|
+
// a lookup for `constructor` returns `Object.prototype.constructor`, a
|
|
82
|
+
// truthy non-array whose `.length` is 1, so the emptiness check passes and
|
|
83
|
+
// the `for...of` below throws `targets is not iterable` inside the request
|
|
84
|
+
// path.
|
|
85
|
+
const normalized = Object.create(null);
|
|
47
86
|
for (const [key, values] of Object.entries(DEFAULT_UNSUPPORTED_CODEX_FALLBACK_CHAIN)) {
|
|
48
87
|
const normalizedKey = canonicalizeModelName(key);
|
|
49
88
|
if (!normalizedKey)
|
|
@@ -158,7 +197,9 @@ export function resolveUnsupportedCodexFallbackModel(options) {
|
|
|
158
197
|
}
|
|
159
198
|
const chain = normalizeFallbackChain(options.customChain);
|
|
160
199
|
const targets = chain[currentModel] ?? [];
|
|
161
|
-
|
|
200
|
+
// Belt and braces with the null-prototype chain above: a `customChain` the
|
|
201
|
+
// caller passed straight through could still carry a non-array value.
|
|
202
|
+
if (!Array.isArray(targets) || targets.length === 0)
|
|
162
203
|
return undefined;
|
|
163
204
|
for (const target of targets) {
|
|
164
205
|
if (!options.fallbackToGpt52OnUnsupportedGpt53 &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-map.d.ts","sourceRoot":"","sources":["../../../../lib/request/helpers/model-map.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EACX,oBAAoB,EACpB,mBAAmB,EACnB,MAAM,oBAAoB,CAAC;AAE5B,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,CAAC;AAE1D,MAAM,MAAM,iBAAiB,GAC1B,aAAa,GACb,WAAW,GACX,OAAO,GACP,SAAS,GACT,SAAS,CAAC;AAEb;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,iBAAiB,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,WAAW,EAMvC,CAAC;AAEX,MAAM,WAAW,iBAAiB;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,iBAAiB,CAAC;IAChC,sBAAsB,EAAE,oBAAoB,CAAC;IAC7C,yBAAyB,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC3D,YAAY,EAAE,iBAAiB,CAAC;CAChC;AA6CD,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AACnD,eAAO,MAAM,aAAa,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"model-map.d.ts","sourceRoot":"","sources":["../../../../lib/request/helpers/model-map.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EACX,oBAAoB,EACpB,mBAAmB,EACnB,MAAM,oBAAoB,CAAC;AAE5B,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,CAAC;AAE1D,MAAM,MAAM,iBAAiB,GAC1B,aAAa,GACb,WAAW,GACX,OAAO,GACP,SAAS,GACT,SAAS,CAAC;AAEb;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,iBAAiB,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,WAAW,EAMvC,CAAC;AAEX,MAAM,WAAW,iBAAiB;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,iBAAiB,CAAC;IAChC,sBAAsB,EAAE,oBAAoB,CAAC;IAC7C,yBAAyB,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC3D,YAAY,EAAE,iBAAiB,CAAC;CAChC;AA6CD,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AACnD,eAAO,MAAM,aAAa,YAAY,CAAC;AAevC,eAAO,MAAM,mBAAmB,gBAAgB,CAAC;AAOjD,eAAO,MAAM,uBAAuB,iGAO1B,CAAC;AAoIX;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CA+I9C,CAAC;AAEX,QAAA,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,CAAC;AAgI7C,OAAO,EAAE,SAAS,EAAE,CAAC;AAqOrB;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQtE;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAuCxE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAavE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,iBAAiB,CAEjF;AAeD;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CAC1C,KAAK,EAAE,MAAM,GAAG,SAAS,GACvB,mBAAmB,CASrB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAErD"}
|
|
@@ -60,6 +60,13 @@ export const DEFAULT_MODEL = "gpt-5.5";
|
|
|
60
60
|
// actual request routing and the legacy `gpt-5` alias remain opt-in per 2.5.0.
|
|
61
61
|
// Bare `gpt-5.6` aliases to Sol; we pin the canonical id so the probe display
|
|
62
62
|
// and report `modelSelection` read `gpt-5.6-sol` without a remap arrow.
|
|
63
|
+
//
|
|
64
|
+
// GPT-6 Astra deliberately does NOT lead the probe as of its 2026-09-03 launch.
|
|
65
|
+
// A probe only needs a response's quota headers, and Astra is still rolling out
|
|
66
|
+
// org by org, so leading with it would spend one failed request per probe for
|
|
67
|
+
// every account without entitlement yet and buy nothing. Move DEFAULT_PROBE_MODEL
|
|
68
|
+
// to `gpt-6-astra` once it is broadly available, and put `gpt-5.6-sol` directly
|
|
69
|
+
// behind it in QUOTA_PROBE_MODEL_CHAIN.
|
|
63
70
|
export const DEFAULT_PROBE_MODEL = "gpt-5.6-sol";
|
|
64
71
|
// Single source of truth for the live/quota probe fallback chain. Both the
|
|
65
72
|
// manager probe (lib/quota-probe.ts) and the runtime probe (lib/runtime/quota-probe.ts)
|
|
@@ -102,6 +109,57 @@ const GPT_5_6_LUNA_EFFORTS = [
|
|
|
102
109
|
"xhigh",
|
|
103
110
|
"max",
|
|
104
111
|
];
|
|
112
|
+
/**
|
|
113
|
+
* GPT-6 Astra, OpenAI's 2026-09-03 frontier release.
|
|
114
|
+
*
|
|
115
|
+
* There is no Sol/Terra/Luna split this generation: the announced lineup is the
|
|
116
|
+
* flagship plus `aeon`, a long-horizon variant built for runs measured in days.
|
|
117
|
+
* `gpt-6-astra` is the API model name OpenAI published at launch;
|
|
118
|
+
* `gpt-6-astra-aeon` is the second slug that shipped beside it in the Codex
|
|
119
|
+
* model list. "Astra Pro" is a plan tier, not a separate slug we have seen, so
|
|
120
|
+
* it is deliberately not registered as its own canonical model — the GPT-6
|
|
121
|
+
* resolver below claims `gpt-6-astra-pro` and every other unrecognised GPT-6 id
|
|
122
|
+
* for the flagship rather than letting it fall through to GPT-5.5.
|
|
123
|
+
*/
|
|
124
|
+
const GPT_6_ASTRA_MODEL = "gpt-6-astra";
|
|
125
|
+
const GPT_6_ASTRA_AEON_MODEL = "gpt-6-astra-aeon";
|
|
126
|
+
/** Bare `gpt-6` resolves to the flagship, mirroring bare `gpt-5.6` -> Sol. */
|
|
127
|
+
const GPT_6_FLAGSHIP_ALIAS = "gpt-6";
|
|
128
|
+
/**
|
|
129
|
+
* Astra inherits the GPT-5.6 frontier effort ladder: no `none`/`minimal`, and
|
|
130
|
+
* `ultra` at the top. OpenAI has published no default effort for Astra, so the
|
|
131
|
+
* flagship follows the tier it succeeds (Sol, `low`) and the long-horizon
|
|
132
|
+
* variant follows the catalog's other long-running models (`medium`).
|
|
133
|
+
*/
|
|
134
|
+
const GPT_6_ASTRA_EFFORTS = [
|
|
135
|
+
"low",
|
|
136
|
+
"medium",
|
|
137
|
+
"high",
|
|
138
|
+
"xhigh",
|
|
139
|
+
"max",
|
|
140
|
+
"ultra",
|
|
141
|
+
];
|
|
142
|
+
/**
|
|
143
|
+
* Cyber-specialty models from the upstream Codex catalog
|
|
144
|
+
* (openai/codex `codex-rs/models-manager/models.json`).
|
|
145
|
+
*
|
|
146
|
+
* They are hidden in the Codex picker and gated behind the Daybreak program,
|
|
147
|
+
* but the catalog marks them `supported_in_api`, so a client can and does name
|
|
148
|
+
* them. Until now every `gpt-daybreak-*` id missed the codex resolver (no
|
|
149
|
+
* `codex` token) and the general GPT-5 resolver (no `gpt 5` tokens) and landed
|
|
150
|
+
* on `DEFAULT_MODEL` — asking for the cyber-permissive model silently ran
|
|
151
|
+
* GPT-5.5. Reasoning ladders and defaults below are the catalog's own values.
|
|
152
|
+
*/
|
|
153
|
+
const DAYBREAK_BLUE_MODEL = "gpt-daybreak-blue-latest";
|
|
154
|
+
const DAYBREAK_RED_MODEL = "gpt-daybreak-red-latest";
|
|
155
|
+
const DAYBREAK_EFFORTS = [
|
|
156
|
+
"low",
|
|
157
|
+
"medium",
|
|
158
|
+
"high",
|
|
159
|
+
"xhigh",
|
|
160
|
+
"max",
|
|
161
|
+
"ultra",
|
|
162
|
+
];
|
|
105
163
|
const GPT_5_5_CANONICAL_MODEL = "gpt-5.5";
|
|
106
164
|
const GPT_5_5_PRO_CANONICAL_MODEL = "gpt-5.5-pro";
|
|
107
165
|
const GPT_5_5_RELEASE_MODEL = "gpt-5.5-2026-04-23";
|
|
@@ -180,6 +238,40 @@ export const MODEL_PROFILES = {
|
|
|
180
238
|
supportedReasoningEfforts: ["medium"],
|
|
181
239
|
capabilities: TOOL_CAPABILITIES.compactOnly,
|
|
182
240
|
},
|
|
241
|
+
// Like GPT-5.6, GPT-6 Astra ships its base instructions inline in the
|
|
242
|
+
// upstream model catalog rather than as a `gpt_6_prompt.md`, so it stays on
|
|
243
|
+
// the GPT-5.2 prompt family with every other post-5.2 general model. Adding
|
|
244
|
+
// a `gpt-6` prompt family here would also widen MODEL_FAMILIES, which is a
|
|
245
|
+
// persisted key space (`activeIndexByFamily`) and would need a storage
|
|
246
|
+
// migration to grow.
|
|
247
|
+
[GPT_6_ASTRA_MODEL]: {
|
|
248
|
+
normalizedModel: GPT_6_ASTRA_MODEL,
|
|
249
|
+
promptFamily: "gpt-5.2",
|
|
250
|
+
defaultReasoningEffort: "low",
|
|
251
|
+
supportedReasoningEfforts: GPT_6_ASTRA_EFFORTS,
|
|
252
|
+
capabilities: TOOL_CAPABILITIES.full,
|
|
253
|
+
},
|
|
254
|
+
[GPT_6_ASTRA_AEON_MODEL]: {
|
|
255
|
+
normalizedModel: GPT_6_ASTRA_AEON_MODEL,
|
|
256
|
+
promptFamily: "gpt-5.2",
|
|
257
|
+
defaultReasoningEffort: "medium",
|
|
258
|
+
supportedReasoningEfforts: GPT_6_ASTRA_EFFORTS,
|
|
259
|
+
capabilities: TOOL_CAPABILITIES.full,
|
|
260
|
+
},
|
|
261
|
+
[DAYBREAK_BLUE_MODEL]: {
|
|
262
|
+
normalizedModel: DAYBREAK_BLUE_MODEL,
|
|
263
|
+
promptFamily: "gpt-5.2",
|
|
264
|
+
defaultReasoningEffort: "low",
|
|
265
|
+
supportedReasoningEfforts: DAYBREAK_EFFORTS,
|
|
266
|
+
capabilities: TOOL_CAPABILITIES.full,
|
|
267
|
+
},
|
|
268
|
+
[DAYBREAK_RED_MODEL]: {
|
|
269
|
+
normalizedModel: DAYBREAK_RED_MODEL,
|
|
270
|
+
promptFamily: "gpt-5.2",
|
|
271
|
+
defaultReasoningEffort: "medium",
|
|
272
|
+
supportedReasoningEfforts: DAYBREAK_EFFORTS,
|
|
273
|
+
capabilities: TOOL_CAPABILITIES.full,
|
|
274
|
+
},
|
|
183
275
|
// GPT-5.6 ships its base instructions inline in the upstream model catalog
|
|
184
276
|
// rather than as a `gpt_5_6_prompt.md`, so these stay on the GPT-5.2 prompt
|
|
185
277
|
// family alongside the other post-5.2 general models.
|
|
@@ -282,6 +374,21 @@ function addGpt56Aliases() {
|
|
|
282
374
|
addEffortAliases(GPT_5_6_LUNA_MODEL, GPT_5_6_LUNA_MODEL, GPT_5_6_LUNA_EFFORTS);
|
|
283
375
|
addEffortAliases(GPT_5_6_FLAGSHIP_ALIAS, GPT_5_6_SOL_MODEL, GPT_5_6_SOL_TERRA_EFFORTS);
|
|
284
376
|
}
|
|
377
|
+
function addGpt6Aliases() {
|
|
378
|
+
addEffortAliases(GPT_6_ASTRA_MODEL, GPT_6_ASTRA_MODEL, GPT_6_ASTRA_EFFORTS);
|
|
379
|
+
addEffortAliases(GPT_6_ASTRA_AEON_MODEL, GPT_6_ASTRA_AEON_MODEL, GPT_6_ASTRA_EFFORTS);
|
|
380
|
+
addEffortAliases(GPT_6_FLAGSHIP_ALIAS, GPT_6_ASTRA_MODEL, GPT_6_ASTRA_EFFORTS);
|
|
381
|
+
// `astra` on its own is how the model is spoken about everywhere; accept it
|
|
382
|
+
// rather than letting it fall through to GPT-5.5.
|
|
383
|
+
addEffortAliases("astra", GPT_6_ASTRA_MODEL, GPT_6_ASTRA_EFFORTS);
|
|
384
|
+
addEffortAliases("astra-aeon", GPT_6_ASTRA_AEON_MODEL, GPT_6_ASTRA_EFFORTS);
|
|
385
|
+
}
|
|
386
|
+
function addDaybreakAliases() {
|
|
387
|
+
addEffortAliases(DAYBREAK_BLUE_MODEL, DAYBREAK_BLUE_MODEL, DAYBREAK_EFFORTS);
|
|
388
|
+
addEffortAliases(DAYBREAK_RED_MODEL, DAYBREAK_RED_MODEL, DAYBREAK_EFFORTS);
|
|
389
|
+
addEffortAliases("daybreak-blue", DAYBREAK_BLUE_MODEL, DAYBREAK_EFFORTS);
|
|
390
|
+
addEffortAliases("daybreak-red", DAYBREAK_RED_MODEL, DAYBREAK_EFFORTS);
|
|
391
|
+
}
|
|
285
392
|
function addGeneralAliases() {
|
|
286
393
|
addReasoningAliases(GPT_5_5_CANONICAL_MODEL, GPT_5_5_CANONICAL_MODEL);
|
|
287
394
|
addReasoningAliases(GPT_5_5_RELEASE_MODEL, GPT_5_5_CANONICAL_MODEL);
|
|
@@ -320,6 +427,8 @@ function addCodexAliases() {
|
|
|
320
427
|
addCodexAliases();
|
|
321
428
|
addGeneralAliases();
|
|
322
429
|
addGpt56Aliases();
|
|
430
|
+
addGpt6Aliases();
|
|
431
|
+
addDaybreakAliases();
|
|
323
432
|
export { MODEL_MAP };
|
|
324
433
|
function stripProviderPrefix(modelId) {
|
|
325
434
|
return modelId.includes("/") ? (modelId.split("/").pop() ?? modelId) : modelId;
|
|
@@ -395,6 +504,68 @@ function resolveCodexCatalogModel(modelId) {
|
|
|
395
504
|
* model than the caller asked for. Unrecognised tiers resolve to Sol, matching
|
|
396
505
|
* OpenAI's bare `gpt-5.6` alias.
|
|
397
506
|
*/
|
|
507
|
+
/**
|
|
508
|
+
* Resolve GPT-6 identifiers that are not exact aliases — a dated snapshot id
|
|
509
|
+
* (`gpt-6-astra-2026-09-03`), the "Astra Pro" plan tier (`gpt-6-astra-pro`), or
|
|
510
|
+
* any tier name OpenAI adds after this file was written.
|
|
511
|
+
*
|
|
512
|
+
* This is the same guard the 5.6 resolver exists for, one major version up:
|
|
513
|
+
* without it, `resolveGeneralGpt5CatalogModel` never matches (it requires a
|
|
514
|
+
* `gpt 5` token pair) and every unrecognised GPT-6 id lands on `DEFAULT_MODEL`,
|
|
515
|
+
* running GPT-5.5 for a caller who asked for the frontier model. `aeon` keeps
|
|
516
|
+
* its own canonical id because it is a behaviourally different model (long
|
|
517
|
+
* horizon), not a rename of the flagship; everything else resolves to the
|
|
518
|
+
* flagship, matching OpenAI's bare `gpt-6` alias.
|
|
519
|
+
*
|
|
520
|
+
* Ids carrying a `codex` token are left to `resolveCodexCatalogModel`, exactly
|
|
521
|
+
* as the 5.6 resolver defers them.
|
|
522
|
+
*/
|
|
523
|
+
function resolveGpt6CatalogModel(modelId) {
|
|
524
|
+
const tokens = tokenizeModelId(modelId);
|
|
525
|
+
const gptIndex = tokens.indexOf("gpt");
|
|
526
|
+
const versionToken = gptIndex === -1 ? undefined : tokens[gptIndex + 1];
|
|
527
|
+
// `gpt6` with no separator tokenizes as ONE token, so the `gpt` + `6` pair
|
|
528
|
+
// never forms and it used to fall through to GPT-5.5 while still passing
|
|
529
|
+
// capability-policy's catalog gate. Gate and resolver have to agree on the
|
|
530
|
+
// same id or the policy store keys state a request never reads.
|
|
531
|
+
const isGpt6 = versionToken === "6" || tokens.includes("gpt6");
|
|
532
|
+
// A bare `astra` token counts too. OpenAI's own launch material and every
|
|
533
|
+
// picker label say "Astra" without the `gpt-6` prefix, so `Astra Pro` and
|
|
534
|
+
// `astra-fast` reach this resolver with no version tokens at all; without
|
|
535
|
+
// this clause they miss every branch and land on GPT-5.5.
|
|
536
|
+
//
|
|
537
|
+
// It is anchored, not a free-floating substring: an id that names a
|
|
538
|
+
// DIFFERENT GPT major version does not get claimed for the frontier model
|
|
539
|
+
// just because `astra` appears in it, so `gpt-4-astra-x` is declined here
|
|
540
|
+
// rather than silently running GPT-6.
|
|
541
|
+
const namesOtherGptVersion = versionToken !== undefined &&
|
|
542
|
+
/^\d+$/.test(versionToken) &&
|
|
543
|
+
versionToken !== "6";
|
|
544
|
+
const isAstra = tokens.includes("astra") && !namesOtherGptVersion;
|
|
545
|
+
if ((!isGpt6 && !isAstra) || tokens.includes("codex")) {
|
|
546
|
+
return undefined;
|
|
547
|
+
}
|
|
548
|
+
if (tokens.includes("aeon"))
|
|
549
|
+
return GPT_6_ASTRA_AEON_MODEL;
|
|
550
|
+
return GPT_6_ASTRA_MODEL;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Resolve the Daybreak cyber models, including ids that are not exact aliases
|
|
554
|
+
* (a pinned `gpt-daybreak-red-2026-08-14`, say).
|
|
555
|
+
*
|
|
556
|
+
* `red` is the cyber-permissive variant and `blue` the defensive one; an
|
|
557
|
+
* unrecognised Daybreak id resolves to `blue`, the more restricted of the two,
|
|
558
|
+
* so a typo cannot silently upgrade a caller into the permissive model.
|
|
559
|
+
*/
|
|
560
|
+
function resolveDaybreakCatalogModel(modelId) {
|
|
561
|
+
const tokens = tokenizeModelId(modelId);
|
|
562
|
+
if (!tokens.includes("daybreak")) {
|
|
563
|
+
return undefined;
|
|
564
|
+
}
|
|
565
|
+
if (tokens.includes("red"))
|
|
566
|
+
return DAYBREAK_RED_MODEL;
|
|
567
|
+
return DAYBREAK_BLUE_MODEL;
|
|
568
|
+
}
|
|
398
569
|
function resolveGpt56CatalogModel(modelId) {
|
|
399
570
|
const tokens = tokenizeModelId(modelId);
|
|
400
571
|
const gptIndex = tokens.indexOf("gpt");
|
|
@@ -476,10 +647,20 @@ export function resolveNormalizedModel(model) {
|
|
|
476
647
|
if (mappedModel) {
|
|
477
648
|
return mappedModel;
|
|
478
649
|
}
|
|
650
|
+
// Daybreak first: its slugs carry neither a `codex` nor a `gpt 5` token, so
|
|
651
|
+
// every other resolver declines them and they would reach DEFAULT_MODEL.
|
|
652
|
+
const daybreakCatalogModel = resolveDaybreakCatalogModel(modelId);
|
|
653
|
+
if (daybreakCatalogModel) {
|
|
654
|
+
return daybreakCatalogModel;
|
|
655
|
+
}
|
|
479
656
|
const codexCatalogModel = resolveCodexCatalogModel(modelId);
|
|
480
657
|
if (codexCatalogModel) {
|
|
481
658
|
return codexCatalogModel;
|
|
482
659
|
}
|
|
660
|
+
const gpt6CatalogModel = resolveGpt6CatalogModel(modelId);
|
|
661
|
+
if (gpt6CatalogModel) {
|
|
662
|
+
return gpt6CatalogModel;
|
|
663
|
+
}
|
|
483
664
|
const gpt56CatalogModel = resolveGpt56CatalogModel(modelId);
|
|
484
665
|
if (gpt56CatalogModel) {
|
|
485
666
|
return gpt56CatalogModel;
|
|
@@ -60,11 +60,10 @@ export interface PinnedUnavailableContext {
|
|
|
60
60
|
recoveryBound?: "rate-limit" | "other" | "unknown";
|
|
61
61
|
/**
|
|
62
62
|
* The pin's CURRENT runtime skip reason, re-read from account state at the
|
|
63
|
-
* moment the 503 is built. `accountSkipReasons` holds the
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
* did not re-read runtime state.
|
|
63
|
+
* moment the 503 is built. `accountSkipReasons` holds the most recent
|
|
64
|
+
* selection or attempt verdict, which can be less specific than a cooldown
|
|
65
|
+
* or breaker created later in the same pass. Omitted when the caller did not
|
|
66
|
+
* re-read runtime state.
|
|
68
67
|
*/
|
|
69
68
|
currentSkipReason?: string | null;
|
|
70
69
|
now?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit-decision.d.ts","sourceRoot":"","sources":["../../../lib/request/rate-limit-decision.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAE5E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAe/C,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGlE;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,GAAG,OAAO,CAWjG;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAapF;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAoBlF;AAYD,wBAAgB,0BAA0B,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAuB3E;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBxE;AA0BD,wBAAgB,4BAA4B,CAC3C,OAAO,EAAE,OAAO,EAChB,kBAAkB,EAAE,MAAM,EAC1B,GAAG,EAAE,MAAM,GACT,MAAM,CAcR;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAE1E;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA0B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,kCAAkC,CAAC;IACzC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,mEAAmE;IACnE,UAAU,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAC;IACvC,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7C;AAQD,MAAM,WAAW,wBAAwB;IACxC;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAC;IACvC,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;;;;;;;;;;;;OAgBG;IACH,aAAa,CAAC,EAAE,YAAY,GAAG,OAAO,GAAG,SAAS,CAAC;IACnD
|
|
1
|
+
{"version":3,"file":"rate-limit-decision.d.ts","sourceRoot":"","sources":["../../../lib/request/rate-limit-decision.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAE5E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAe/C,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGlE;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,GAAG,OAAO,CAWjG;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAapF;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAoBlF;AAYD,wBAAgB,0BAA0B,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAuB3E;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBxE;AA0BD,wBAAgB,4BAA4B,CAC3C,OAAO,EAAE,OAAO,EAChB,kBAAkB,EAAE,MAAM,EAC1B,GAAG,EAAE,MAAM,GACT,MAAM,CAcR;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAE1E;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA0B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,kCAAkC,CAAC;IACzC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,mEAAmE;IACnE,UAAU,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAC;IACvC,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7C;AAQD,MAAM,WAAW,wBAAwB;IACxC;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAC;IACvC,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;;;;;;;;;;;;OAgBG;IACH,aAAa,CAAC,EAAE,YAAY,GAAG,OAAO,GAAG,SAAS,CAAC;IACnD;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAwKD,wBAAgB,+BAA+B,CAC9C,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACtC,kBAAkB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/C,OAAO,CAAC,EAAE,wBAAwB,GAChC,0BAA0B,CA8E5B"}
|
|
@@ -232,6 +232,34 @@ const BLOCKER_DESCRIPTIONS = new Map([
|
|
|
232
232
|
description,
|
|
233
233
|
]),
|
|
234
234
|
]);
|
|
235
|
+
// Retry-budget exhaustion can end immediately after an upstream attempt,
|
|
236
|
+
// before selection gets another pass to translate that attempt into a live
|
|
237
|
+
// cooldown or breaker. Keep these final verdicts operator-facing without
|
|
238
|
+
// treating them as live blockers: a concurrently opened circuit or cooldown
|
|
239
|
+
// must still take precedence in buildPinnedUnavailableErrorBody below.
|
|
240
|
+
const ATTEMPT_VERDICT_DESCRIPTIONS = new Map([
|
|
241
|
+
[
|
|
242
|
+
"auth-failure",
|
|
243
|
+
{
|
|
244
|
+
parenthetical: "authentication failure",
|
|
245
|
+
deadlineNoun: "available-again",
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
[
|
|
249
|
+
"network-error",
|
|
250
|
+
{
|
|
251
|
+
parenthetical: "upstream network error",
|
|
252
|
+
deadlineNoun: "available-again",
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
[
|
|
256
|
+
"server-error",
|
|
257
|
+
{
|
|
258
|
+
parenthetical: "upstream server error",
|
|
259
|
+
deadlineNoun: "available-again",
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
]);
|
|
235
263
|
/** Whether the sentence has real wording for this token, or must echo it raw. */
|
|
236
264
|
function isDescribedBlocker(skipReason) {
|
|
237
265
|
return BLOCKER_DESCRIPTIONS.has(skipReason);
|
|
@@ -252,7 +280,8 @@ function describePinnedBlocker(skipReason, rateLimitBoundsRecovery) {
|
|
|
252
280
|
deadline: DEADLINE_SENTENCES["available-again"],
|
|
253
281
|
};
|
|
254
282
|
}
|
|
255
|
-
const described = BLOCKER_DESCRIPTIONS.get(skipReason)
|
|
283
|
+
const described = BLOCKER_DESCRIPTIONS.get(skipReason) ??
|
|
284
|
+
ATTEMPT_VERDICT_DESCRIPTIONS.get(skipReason);
|
|
256
285
|
if (described === undefined) {
|
|
257
286
|
// Permanent blockers never reach the deadline clause (the call site
|
|
258
287
|
// suppresses their reset time), and future or internal tokens stay
|
|
@@ -311,9 +340,9 @@ export function buildPinnedUnavailableErrorBody(pinnedIndex, accountSkipReasons,
|
|
|
311
340
|
// recorded verdict that names a real blocker class wins, because the
|
|
312
341
|
// selection-only classes ("missing", "policy-blocked") have no
|
|
313
342
|
// runtime-state equivalent and would be lost. Otherwise the re-read runtime
|
|
314
|
-
// state is the truth and the recorded token is the
|
|
315
|
-
//
|
|
316
|
-
//
|
|
343
|
+
// state is the truth and the recorded token is only the earlier attempt
|
|
344
|
+
// verdict. This also preserves compatibility with legacy callers that may
|
|
345
|
+
// still supply an internal bookkeeping token.
|
|
317
346
|
const describedSkipReason = skipReason !== null && isDescribedBlocker(skipReason)
|
|
318
347
|
? skipReason
|
|
319
348
|
: context?.currentSkipReason ?? skipReason;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-metadata.d.ts","sourceRoot":"","sources":["../../../lib/request/response-metadata.ts"],"names":[],"mappings":"AASA,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAyBrE;AAED,wBAAgB,6BAA6B,CAC5C,OAAO,EAAE,OAAO,GACd,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"response-metadata.d.ts","sourceRoot":"","sources":["../../../lib/request/response-metadata.ts"],"names":[],"mappings":"AASA,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAyBrE;AAED,wBAAgB,6BAA6B,CAC5C,OAAO,EAAE,OAAO,GACd,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA2BxB"}
|
|
@@ -45,6 +45,7 @@ export function sanitizeResponseHeadersForLog(headers) {
|
|
|
45
45
|
"x-codex-secondary-window-minutes",
|
|
46
46
|
"x-codex-secondary-reset-at",
|
|
47
47
|
"x-codex-secondary-reset-after-seconds",
|
|
48
|
+
"x-codex-context-budget-percent",
|
|
48
49
|
"retry-after",
|
|
49
50
|
"x-ratelimit-reset",
|
|
50
51
|
"x-ratelimit-reset-requests",
|
|
@@ -11,5 +11,7 @@ export declare function forwardStreamingResponse(upstream: Response, res: Server
|
|
|
11
11
|
* chunk and is called before the write, so a slow observer delays the
|
|
12
12
|
* forward. Implementations are expected to swallow their own errors.
|
|
13
13
|
*/
|
|
14
|
-
onChunk?: (chunk: Uint8Array) => void
|
|
14
|
+
onChunk?: (chunk: Uint8Array) => void,
|
|
15
|
+
/** Additional response headers, applied after (so they can override) the forwarded upstream ones. */
|
|
16
|
+
extraHeaders?: Record<string, string>): Promise<boolean>;
|
|
15
17
|
//# sourceMappingURL=stream-failover-runtime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-failover-runtime.d.ts","sourceRoot":"","sources":["../../../lib/request/stream-failover-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AAEtF,eAAO,MAAM,kBAAkB,aAW7B,CAAC;AAWH,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUzF;AAED,wBAAsB,WAAW,CAAC,CAAC,EAClC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,IAAI,EACrB,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,CAAC,CAAC,CAmBZ;AAED,wBAAsB,aAAa,CAClC,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,SAAc,GACpB,OAAO,CAAC,MAAM,CAAC,CAuDjB;AAoBD,wBAAsB,wBAAwB,CAC7C,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,0BAA0B,EAClC,aAAa,EAAE,MAAM,IAAI,EACzB,oBAAoB,EAAE,MAAM;AAC5B;;;;;GAKG;AACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GACnC,OAAO,CAAC,OAAO,CAAC,CAsDlB"}
|
|
1
|
+
{"version":3,"file":"stream-failover-runtime.d.ts","sourceRoot":"","sources":["../../../lib/request/stream-failover-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AAEtF,eAAO,MAAM,kBAAkB,aAW7B,CAAC;AAWH,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUzF;AAED,wBAAsB,WAAW,CAAC,CAAC,EAClC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,IAAI,EACrB,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,CAAC,CAAC,CAmBZ;AAED,wBAAsB,aAAa,CAClC,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,SAAc,GACpB,OAAO,CAAC,MAAM,CAAC,CAuDjB;AAoBD,wBAAsB,wBAAwB,CAC7C,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,0BAA0B,EAClC,aAAa,EAAE,MAAM,IAAI,EACzB,oBAAoB,EAAE,MAAM;AAC5B;;;;;GAKG;AACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI;AACrC,qGAAqG;AACrG,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,OAAO,CAAC,OAAO,CAAC,CAsDlB"}
|
|
@@ -135,9 +135,14 @@ export async function forwardStreamingResponse(upstream, res, status, onStreamEr
|
|
|
135
135
|
* chunk and is called before the write, so a slow observer delays the
|
|
136
136
|
* forward. Implementations are expected to swallow their own errors.
|
|
137
137
|
*/
|
|
138
|
-
onChunk
|
|
138
|
+
onChunk,
|
|
139
|
+
/** Additional response headers, applied after (so they can override) the forwarded upstream ones. */
|
|
140
|
+
extraHeaders) {
|
|
139
141
|
status.streamsStarted += 1;
|
|
140
|
-
res.writeHead(upstream.status,
|
|
142
|
+
res.writeHead(upstream.status, {
|
|
143
|
+
...responseHeadersForClient(upstream.headers),
|
|
144
|
+
...extraHeaders,
|
|
145
|
+
});
|
|
141
146
|
if (!upstream.body) {
|
|
142
147
|
res.end();
|
|
143
148
|
return true;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function applyContextBudgetGuardSettingsFromConfig(pluginConfig: ReturnType<typeof import("../config.js").loadPluginConfig>, deps: {
|
|
2
|
+
configure: (options: {
|
|
3
|
+
enabled: boolean;
|
|
4
|
+
softPercent: number;
|
|
5
|
+
hardPercent: number;
|
|
6
|
+
modelWindowOverrides: Record<string, number>;
|
|
7
|
+
}) => void;
|
|
8
|
+
getContextBudgetGuardEnabled: (config: ReturnType<typeof import("../config.js").loadPluginConfig>) => boolean;
|
|
9
|
+
getContextBudgetGuardSoftPercent: (config: ReturnType<typeof import("../config.js").loadPluginConfig>) => number;
|
|
10
|
+
getContextBudgetGuardHardPercent: (config: ReturnType<typeof import("../config.js").loadPluginConfig>) => number;
|
|
11
|
+
getContextBudgetGuardModelWindowOverrides: (config: ReturnType<typeof import("../config.js").loadPluginConfig>) => Record<string, number>;
|
|
12
|
+
}): void;
|
|
13
|
+
//# sourceMappingURL=context-budget-settings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-budget-settings.d.ts","sourceRoot":"","sources":["../../../lib/runtime/context-budget-settings.ts"],"names":[],"mappings":"AAAA,wBAAgB,yCAAyC,CACxD,YAAY,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,EACxE,IAAI,EAAE;IACL,SAAS,EAAE,CAAC,OAAO,EAAE;QACpB,OAAO,EAAE,OAAO,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC7C,KAAK,IAAI,CAAC;IACX,4BAA4B,EAAE,CAC7B,MAAM,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,KAC9D,OAAO,CAAC;IACb,gCAAgC,EAAE,CACjC,MAAM,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,KAC9D,MAAM,CAAC;IACZ,gCAAgC,EAAE,CACjC,MAAM,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,KAC9D,MAAM,CAAC;IACZ,yCAAyC,EAAE,CAC1C,MAAM,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,KAC9D,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5B,GACC,IAAI,CAQN"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function applyContextBudgetGuardSettingsFromConfig(pluginConfig, deps) {
|
|
2
|
+
deps.configure({
|
|
3
|
+
enabled: deps.getContextBudgetGuardEnabled(pluginConfig),
|
|
4
|
+
softPercent: deps.getContextBudgetGuardSoftPercent(pluginConfig),
|
|
5
|
+
hardPercent: deps.getContextBudgetGuardHardPercent(pluginConfig),
|
|
6
|
+
modelWindowOverrides: deps.getContextBudgetGuardModelWindowOverrides(pluginConfig),
|
|
7
|
+
});
|
|
8
|
+
}
|
|
@@ -5,5 +5,6 @@ export declare function applyLoaderRuntimeSetup(params: {
|
|
|
5
5
|
ensureSessionAffinity: (pluginConfig: ReturnType<typeof import("../config.js").loadPluginConfig>) => void;
|
|
6
6
|
ensureRefreshGuardian: (pluginConfig: ReturnType<typeof import("../config.js").loadPluginConfig>) => void;
|
|
7
7
|
applyPreemptiveQuotaSettings: (pluginConfig: ReturnType<typeof import("../config.js").loadPluginConfig>) => void;
|
|
8
|
+
applyContextBudgetGuardSettings: (pluginConfig: ReturnType<typeof import("../config.js").loadPluginConfig>) => void;
|
|
8
9
|
}): void;
|
|
9
10
|
//# sourceMappingURL=loader-setup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader-setup.d.ts","sourceRoot":"","sources":["../../../lib/runtime/loader-setup.ts"],"names":[],"mappings":"AAAA,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC/C,YAAY,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,CAAC;IACzE,wBAAwB,EAAE,CACzB,YAAY,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,KACpE,IAAI,CAAC;IACV,wBAAwB,EAAE,CACzB,YAAY,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,KACpE,IAAI,CAAC;IACV,qBAAqB,EAAE,CACtB,YAAY,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,KACpE,IAAI,CAAC;IACV,qBAAqB,EAAE,CACtB,YAAY,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,KACpE,IAAI,CAAC;IACV,4BAA4B,EAAE,CAC7B,YAAY,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,KACpE,IAAI,CAAC;CACV,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"loader-setup.d.ts","sourceRoot":"","sources":["../../../lib/runtime/loader-setup.ts"],"names":[],"mappings":"AAAA,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC/C,YAAY,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,CAAC;IACzE,wBAAwB,EAAE,CACzB,YAAY,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,KACpE,IAAI,CAAC;IACV,wBAAwB,EAAE,CACzB,YAAY,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,KACpE,IAAI,CAAC;IACV,qBAAqB,EAAE,CACtB,YAAY,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,KACpE,IAAI,CAAC;IACV,qBAAqB,EAAE,CACtB,YAAY,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,KACpE,IAAI,CAAC;IACV,4BAA4B,EAAE,CAC7B,YAAY,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,KACpE,IAAI,CAAC;IACV,+BAA+B,EAAE,CAChC,YAAY,EAAE,UAAU,CAAC,cAAc,cAAc,EAAE,gBAAgB,CAAC,KACpE,IAAI,CAAC;CACV,GAAG,IAAI,CAOP"}
|
|
@@ -4,4 +4,5 @@ export function applyLoaderRuntimeSetup(params) {
|
|
|
4
4
|
params.ensureSessionAffinity(params.pluginConfig);
|
|
5
5
|
params.ensureRefreshGuardian(params.pluginConfig);
|
|
6
6
|
params.applyPreemptiveQuotaSettings(params.pluginConfig);
|
|
7
|
+
params.applyContextBudgetGuardSettings(params.pluginConfig);
|
|
7
8
|
}
|
|
@@ -34,5 +34,28 @@ export declare function chooseAccount(params: {
|
|
|
34
34
|
stickyBoostByAccount?: Record<number, number>;
|
|
35
35
|
pidOffsetEnabled?: boolean;
|
|
36
36
|
schedulingStrategy?: "hybrid" | "sequential";
|
|
37
|
+
/**
|
|
38
|
+
* Admit a pinned account that is only blocked by its own cooldown.
|
|
39
|
+
*
|
|
40
|
+
* Set by the proxy for the RETRY passes of one pinned request, never for
|
|
41
|
+
* the first pass. A cooldown exists to keep OTHER requests off a flaky
|
|
42
|
+
* account; a retry budget exists to give THIS request another attempt.
|
|
43
|
+
* Conflating them meant every transient branch cooled the pin down before
|
|
44
|
+
* the next selection pass and the budget could never be spent — a pinned
|
|
45
|
+
* request got exactly one upstream attempt under shipped defaults.
|
|
46
|
+
*
|
|
47
|
+
* Only the cooldown is waived. Rate limits, an open circuit, a disabled
|
|
48
|
+
* account, workspace and policy blocks all still reject the pin, and the
|
|
49
|
+
* cooldown itself stays on the account for everyone else and for the 503's
|
|
50
|
+
* `retry_after_ms`.
|
|
51
|
+
*
|
|
52
|
+
* One ordering note: `getAccountRuntimeSkipReason` reports the FIRST
|
|
53
|
+
* blocker it finds and checks the cooldown before the circuit, so an
|
|
54
|
+
* account that is both cooling down and circuit-open reads as a cooldown
|
|
55
|
+
* and is admitted here. That is safe: `consumeTokenWithReason` takes the
|
|
56
|
+
* breaker's admission slot immediately after selection and rejects it with
|
|
57
|
+
* `circuit-open`, which is also the more accurate skip reason to report.
|
|
58
|
+
*/
|
|
59
|
+
allowPinnedCooldown?: boolean;
|
|
37
60
|
}): ManagedAccount | null;
|
|
38
61
|
//# sourceMappingURL=rotation-account-selection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rotation-account-selection.d.ts","sourceRoot":"","sources":["../../../lib/runtime/rotation-account-selection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"rotation-account-selection.d.ts","sourceRoot":"","sources":["../../../lib/runtime/rotation-account-selection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAWnE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE;IACrC,cAAc,EAAE,cAAc,CAAC;IAC/B,oBAAoB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAClD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACrC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kBAAkB,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;IAC7C;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC9B,GAAG,cAAc,GAAG,IAAI,CA0JxB"}
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a runtime skip reason is a cooldown, the one blocker a pinned
|
|
3
|
+
* retry may waive. `getManagedAccountRuntimeSkipReason` emits either the
|
|
4
|
+
* bare token or `cooling-down:<reason>`.
|
|
5
|
+
*/
|
|
6
|
+
function isCooldownReason(reason) {
|
|
7
|
+
return reason === "cooling-down" || reason.startsWith("cooling-down:");
|
|
8
|
+
}
|
|
1
9
|
/**
|
|
2
10
|
* `chooseAccount` is a SYNC selector that internally advances the rotation
|
|
3
11
|
* cursor (the session-affinity-preferred branch and the round-robin fallback
|
|
@@ -17,15 +25,16 @@
|
|
|
17
25
|
* `test/runtime-rotation-proxy.test.ts`.
|
|
18
26
|
*/
|
|
19
27
|
export function chooseAccount(params) {
|
|
20
|
-
const { accountManager, sessionAffinityStore, sessionKey, family, model, attemptedIndexes, now, policy, pinnedIndex, skipReasons, stickyBoostByAccount, pidOffsetEnabled, schedulingStrategy, } = params;
|
|
28
|
+
const { accountManager, sessionAffinityStore, sessionKey, family, model, attemptedIndexes, now, policy, pinnedIndex, skipReasons, stickyBoostByAccount, pidOffsetEnabled, schedulingStrategy, allowPinnedCooldown, } = params;
|
|
21
29
|
// Manual pin (from `codex-multi-auth switch <n>`) overrides every other
|
|
22
30
|
// selection signal. We do NOT call markSwitched here — the proxy must not
|
|
23
31
|
// clobber the pin set by the CLI. See issue #474.
|
|
24
32
|
if (typeof pinnedIndex === "number") {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
// A pin has no alternative account to rotate to. Re-evaluate its live
|
|
34
|
+
// blockers on every pass so a healthy account can use the caller's bounded
|
|
35
|
+
// retry budget; attemptedIndexes remains authoritative for unpinned pool
|
|
36
|
+
// selection below. The proxy also carries an absolute loop guard for retry
|
|
37
|
+
// branches that do not advance their transient-attempt counter.
|
|
29
38
|
if (pinnedIndex < 0 || pinnedIndex >= accountManager.getAccountCount()) {
|
|
30
39
|
skipReasons?.set(pinnedIndex, "missing");
|
|
31
40
|
return null;
|
|
@@ -40,7 +49,7 @@ export function chooseAccount(params) {
|
|
|
40
49
|
return null;
|
|
41
50
|
}
|
|
42
51
|
const reason = accountManager.getAccountRuntimeSkipReason(pinnedIndex, family, model);
|
|
43
|
-
if (reason) {
|
|
52
|
+
if (reason && !(allowPinnedCooldown === true && isCooldownReason(reason))) {
|
|
44
53
|
skipReasons?.set(pinnedIndex, reason);
|
|
45
54
|
return null;
|
|
46
55
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AccountManager } from "../accounts.js";
|
|
2
|
+
import type { ContextBudgetGuard } from "../context-budget-guard.js";
|
|
2
3
|
import type { PreemptiveQuotaScheduler } from "../preemptive-quota-scheduler.js";
|
|
3
4
|
import type { RuntimeRotationProxyStatus } from "./rotation-server-types.js";
|
|
4
5
|
import type { SessionAffinityStore } from "../session-affinity.js";
|
|
@@ -29,6 +30,7 @@ export interface RotationProxyStateInit {
|
|
|
29
30
|
maxRequestBodyBytes: number;
|
|
30
31
|
quotaRemainingPercentThreshold: number;
|
|
31
32
|
preemptiveQuotaScheduler: PreemptiveQuotaScheduler;
|
|
33
|
+
contextBudgetGuard: ContextBudgetGuard;
|
|
32
34
|
sessionAffinityStore: SessionAffinityStore | null;
|
|
33
35
|
lastObservedAffinityGeneration: number;
|
|
34
36
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rotation-proxy-state.d.ts","sourceRoot":"","sources":["../../../lib/runtime/rotation-proxy-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAKjF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAC7E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEnE;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACtC,oBAAoB,EAAE,cAAc,CAAC;IACrC,gBAAgB,EAAE,SAAS,GAAG,QAAQ,CAAC;IACvC,kBAAkB,EAAE,QAAQ,GAAG,YAAY,CAAC;IAC5C,SAAS,EAAE,OAAO,KAAK,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,2BAA2B,EAAE,MAAM,CAAC;IACpC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,yBAAyB,EAAE,MAAM,CAAC;IAClC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,8BAA8B,EAAE,MAAM,CAAC;IACvC,wBAAwB,EAAE,wBAAwB,CAAC;IACnD,oBAAoB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAClD,8BAA8B,EAAE,MAAM,CAAC;IACvC;;;;;OAKG;IACH,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAmB,SAAQ,sBAAsB;IACjE,QAAQ,CAAC,oBAAoB,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IACnD,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC;IAC5C,QAAQ,CAAC,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IACzD,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yBAAyB,EAAE,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACjE,wBAAwB,EAAE,MAAM,CAAC;CACjC;AAID,gBAAgB;AAChB,wBAAgB,wBAAwB,CACvC,IAAI,EAAE,sBAAsB,GAC1B,kBAAkB,CAuBpB;AAED,gBAAgB;AAChB,wBAAsB,wBAAwB,CAC7C,KAAK,EAAE,kBAAkB,GACvB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAkDhC"}
|
|
1
|
+
{"version":3,"file":"rotation-proxy-state.d.ts","sourceRoot":"","sources":["../../../lib/runtime/rotation-proxy-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAKjF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAC7E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEnE;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACtC,oBAAoB,EAAE,cAAc,CAAC;IACrC,gBAAgB,EAAE,SAAS,GAAG,QAAQ,CAAC;IACvC,kBAAkB,EAAE,QAAQ,GAAG,YAAY,CAAC;IAC5C,SAAS,EAAE,OAAO,KAAK,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,2BAA2B,EAAE,MAAM,CAAC;IACpC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,yBAAyB,EAAE,MAAM,CAAC;IAClC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,8BAA8B,EAAE,MAAM,CAAC;IACvC,wBAAwB,EAAE,wBAAwB,CAAC;IACnD,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,oBAAoB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAClD,8BAA8B,EAAE,MAAM,CAAC;IACvC;;;;;OAKG;IACH,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAmB,SAAQ,sBAAsB;IACjE,QAAQ,CAAC,oBAAoB,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IACnD,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC;IAC5C,QAAQ,CAAC,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IACzD,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yBAAyB,EAAE,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACjE,wBAAwB,EAAE,MAAM,CAAC;CACjC;AAID,gBAAgB;AAChB,wBAAgB,wBAAwB,CACvC,IAAI,EAAE,sBAAsB,GAC1B,kBAAkB,CAuBpB;AAED,gBAAgB;AAChB,wBAAsB,wBAAwB,CAC7C,KAAK,EAAE,kBAAkB,GACvB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAkDhC"}
|
|
@@ -58,6 +58,17 @@ export interface RequestContext {
|
|
|
58
58
|
family: ModelFamily;
|
|
59
59
|
stream: boolean;
|
|
60
60
|
sessionKey: string | null;
|
|
61
|
+
/**
|
|
62
|
+
* `sessionKey` minus the `previous_response_id` fallback.
|
|
63
|
+
*
|
|
64
|
+
* `previous_response_id` changes on every turn, which is fine for session
|
|
65
|
+
* affinity (a fresh key just means "no pin yet") but wrong for anything
|
|
66
|
+
* that has to ACCUMULATE across turns: a per-turn key never finds what the
|
|
67
|
+
* previous turn stored, and leaves one dead map entry behind per request.
|
|
68
|
+
* Consumers that track state over a conversation use this instead, and
|
|
69
|
+
* no-op when it is null.
|
|
70
|
+
*/
|
|
71
|
+
stableSessionKey: string | null;
|
|
61
72
|
}
|
|
62
73
|
export type ExhaustionReason = "rate-limit" | "server-error" | "network-error" | "auth-failure" | "budget" | "deactivated" | "no-account";
|
|
63
74
|
export type RuntimeProxyHttpError = Error & {
|