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.
Files changed (81) hide show
  1. package/.codex-plugin/plugin.json +1 -1
  2. package/README.md +2 -1
  3. package/config/README.md +3 -1
  4. package/config/codex-legacy.json +300 -0
  5. package/config/codex-modern.json +96 -0
  6. package/config/schema/config.schema.json +23 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +62 -2
  9. package/dist/lib/accounts.d.ts +25 -1
  10. package/dist/lib/accounts.d.ts.map +1 -1
  11. package/dist/lib/accounts.js +26 -6
  12. package/dist/lib/capability-policy.d.ts.map +1 -1
  13. package/dist/lib/capability-policy.js +16 -1
  14. package/dist/lib/codex-manager/backend-settings-helpers.d.ts.map +1 -1
  15. package/dist/lib/codex-manager/backend-settings-helpers.js +10 -1
  16. package/dist/lib/codex-manager/backend-settings-schema.d.ts +18 -0
  17. package/dist/lib/codex-manager/backend-settings-schema.d.ts.map +1 -1
  18. package/dist/lib/codex-manager/backend-settings-schema.js +19 -0
  19. package/dist/lib/codex-manager/experimental-settings-prompt.d.ts +1 -0
  20. package/dist/lib/codex-manager/experimental-settings-prompt.d.ts.map +1 -1
  21. package/dist/lib/codex-manager/experimental-settings-prompt.js +12 -0
  22. package/dist/lib/codex-manager/experimental-settings-schema.d.ts +2 -0
  23. package/dist/lib/codex-manager/experimental-settings-schema.d.ts.map +1 -1
  24. package/dist/lib/codex-manager/experimental-settings-schema.js +2 -0
  25. package/dist/lib/config.d.ts +29 -0
  26. package/dist/lib/config.d.ts.map +1 -1
  27. package/dist/lib/config.js +91 -1
  28. package/dist/lib/context-budget/model-context-windows.d.ts +25 -0
  29. package/dist/lib/context-budget/model-context-windows.d.ts.map +1 -0
  30. package/dist/lib/context-budget/model-context-windows.js +130 -0
  31. package/dist/lib/context-budget-guard.d.ts +100 -0
  32. package/dist/lib/context-budget-guard.d.ts.map +1 -0
  33. package/dist/lib/context-budget-guard.js +183 -0
  34. package/dist/lib/context-budget-response.d.ts +25 -0
  35. package/dist/lib/context-budget-response.d.ts.map +1 -0
  36. package/dist/lib/context-budget-response.js +57 -0
  37. package/dist/lib/context-overflow.d.ts.map +1 -1
  38. package/dist/lib/context-overflow.js +5 -60
  39. package/dist/lib/model-capability-matrix.d.ts.map +1 -1
  40. package/dist/lib/model-capability-matrix.js +9 -1
  41. package/dist/lib/request/error-classification.d.ts.map +1 -1
  42. package/dist/lib/request/error-classification.js +43 -2
  43. package/dist/lib/request/helpers/model-map.d.ts.map +1 -1
  44. package/dist/lib/request/helpers/model-map.js +181 -0
  45. package/dist/lib/request/rate-limit-decision.d.ts +4 -5
  46. package/dist/lib/request/rate-limit-decision.d.ts.map +1 -1
  47. package/dist/lib/request/rate-limit-decision.js +33 -4
  48. package/dist/lib/request/response-metadata.d.ts.map +1 -1
  49. package/dist/lib/request/response-metadata.js +1 -0
  50. package/dist/lib/request/stream-failover-runtime.d.ts +3 -1
  51. package/dist/lib/request/stream-failover-runtime.d.ts.map +1 -1
  52. package/dist/lib/request/stream-failover-runtime.js +7 -2
  53. package/dist/lib/runtime/context-budget-settings.d.ts +13 -0
  54. package/dist/lib/runtime/context-budget-settings.d.ts.map +1 -0
  55. package/dist/lib/runtime/context-budget-settings.js +8 -0
  56. package/dist/lib/runtime/loader-setup.d.ts +1 -0
  57. package/dist/lib/runtime/loader-setup.d.ts.map +1 -1
  58. package/dist/lib/runtime/loader-setup.js +1 -0
  59. package/dist/lib/runtime/rotation-account-selection.d.ts +23 -0
  60. package/dist/lib/runtime/rotation-account-selection.d.ts.map +1 -1
  61. package/dist/lib/runtime/rotation-account-selection.js +15 -6
  62. package/dist/lib/runtime/rotation-proxy-state.d.ts +2 -0
  63. package/dist/lib/runtime/rotation-proxy-state.d.ts.map +1 -1
  64. package/dist/lib/runtime/rotation-server-types.d.ts +11 -0
  65. package/dist/lib/runtime/rotation-server-types.d.ts.map +1 -1
  66. package/dist/lib/runtime-rotation-proxy.d.ts.map +1 -1
  67. package/dist/lib/runtime-rotation-proxy.js +251 -43
  68. package/dist/lib/schemas.d.ts +4 -0
  69. package/dist/lib/schemas.d.ts.map +1 -1
  70. package/dist/lib/schemas.js +10 -0
  71. package/dist/lib/synthetic-response.d.ts +31 -0
  72. package/dist/lib/synthetic-response.d.ts.map +1 -0
  73. package/dist/lib/synthetic-response.js +79 -0
  74. package/dist/lib/ui/ui-copy.d.ts +2 -1
  75. package/dist/lib/ui/ui-copy.d.ts.map +1 -1
  76. package/dist/lib/ui/ui-copy.js +2 -1
  77. package/dist/lib/usage/pricing.d.ts +1 -1
  78. package/dist/lib/usage/pricing.d.ts.map +1 -1
  79. package/dist/lib/usage/pricing.js +33 -0
  80. package/package.json +1 -1
  81. package/scripts/codex.js +153 -2
@@ -0,0 +1,130 @@
1
+ import { getNormalizedModel } from "../request/helpers/model-map.js";
2
+ /**
3
+ * Context-window size estimates for the Context Budget Guard.
4
+ *
5
+ * Unlike `lib/usage/pricing.ts`, the numbers below are NOT published,
6
+ * contractual facts. Per `docs/releases/v2.5.0.md` ("Where the model facts
7
+ * came from"), the context window OpenAI's published API docs advertise is
8
+ * for the API surface, not the ChatGPT Codex backend this wrapper actually
9
+ * talks to — and the docs pages don't even agree with each other. Treating a
10
+ * hardcoded number here as ground truth would repeat that exact mistake for
11
+ * a safety feature, which is worse than not shipping the feature at all.
12
+ *
13
+ * So this table is a fallback starting point ONLY. `getEffectiveContextWindow`
14
+ * always prefers a caller-supplied override (from
15
+ * `contextBudgetGuardModelWindowOverrides`, the setting a user fills in once
16
+ * they know their real ceiling) over anything listed here.
17
+ */
18
+ /**
19
+ * Best-effort estimates, in tokens. Deliberately conservative: an estimate
20
+ * that is too LOW makes the guard fire early (annoying, safe); an estimate
21
+ * that is too HIGH makes the guard fire late or never (silent, unsafe). When
22
+ * in doubt about a model's real ceiling, leave it out of this table and add
23
+ * it to UNESTIMATED_ROUTABLE_MODELS instead.
24
+ */
25
+ const ESTIMATED_MODEL_CONTEXT_WINDOWS = {
26
+ "gpt-5.1": 260_000,
27
+ "gpt-5.2": 260_000,
28
+ "gpt-5.2-pro": 260_000,
29
+ "gpt-5.3-codex": 260_000,
30
+ "gpt-5.4": 260_000,
31
+ "gpt-5.4-mini": 260_000,
32
+ "gpt-5.4-nano": 260_000,
33
+ "gpt-5.4-pro": 260_000,
34
+ "gpt-5.5": 260_000,
35
+ "gpt-5.5-pro": 260_000,
36
+ "gpt-5-mini": 260_000,
37
+ "gpt-5-nano": 260_000,
38
+ };
39
+ /**
40
+ * Routable models this guard consciously does not estimate a window for.
41
+ * `getEffectiveContextWindow` returns `null` for these absent an override,
42
+ * and the guard treats `null` as "cannot evaluate; skip" — never a guessed
43
+ * percentage. The 5.6 family ships with materially different per-tier
44
+ * behavior (see the v2.5.0 release notes) closely enough to launch that no
45
+ * estimate here has been reviewed for it yet.
46
+ */
47
+ export const UNESTIMATED_ROUTABLE_MODELS = [
48
+ "gpt-5.6-sol",
49
+ "gpt-5.6-terra",
50
+ "gpt-5.6-luna",
51
+ // GPT-6 Astra published two different numbers on day one: 1.05M for the API
52
+ // surface and 272K as the Codex context. This wrapper talks to the Codex
53
+ // backend, and the same split is what the v2.5.0 notes warn about — so no
54
+ // estimate is entered here. `gpt-daybreak-red-latest` is the one model whose
55
+ // upstream catalog entry pins `context_window` and `max_context_window` to
56
+ // the same 372000, but that is the Codex picker's number rather than a
57
+ // measured ceiling for this transport, so it stays unestimated too. Set
58
+ // `contextBudgetGuardModelWindowOverrides` once you know your real ceiling.
59
+ "gpt-6-astra",
60
+ "gpt-6-astra-aeon",
61
+ "gpt-daybreak-blue-latest",
62
+ "gpt-daybreak-red-latest",
63
+ ];
64
+ function normalizeModelName(model) {
65
+ const trimmed = model?.trim().toLowerCase();
66
+ return trimmed && trimmed.length > 0 ? trimmed : null;
67
+ }
68
+ /**
69
+ * Model ids to try, in order, against the override map and the estimate table.
70
+ *
71
+ * The guard is fed the model string exactly as the client sent it: the
72
+ * rotation proxy is a pass-through and `buildResponsesRequestContext` copies
73
+ * `body.model` verbatim. That raw string is very often NOT a key of this
74
+ * file's table — Codex CLI's own default is `gpt-5-codex`, and every
75
+ * reasoning-suffixed alias (`gpt-5.3-codex-high`, …) is an alias-map entry
76
+ * rather than a catalog model. Looking up only the raw string made the guard
77
+ * silently return "no window, skip" for the most common model in the product.
78
+ *
79
+ * So: try the raw (lowercased) string first, so a user override keyed exactly
80
+ * the way they type the model still wins, then the catalog's canonical id for
81
+ * it. `getNormalizedModel` is deliberately the exact/alias-only resolver —
82
+ * `resolveNormalizedModel` falls back to `DEFAULT_MODEL` for anything it does
83
+ * not recognize, which would hand an unknown model gpt-5.5's window and
84
+ * evaluate a real session against a fabricated number.
85
+ */
86
+ function windowLookupCandidates(model) {
87
+ const raw = normalizeModelName(model);
88
+ if (!raw)
89
+ return [];
90
+ const canonical = normalizeModelName(getNormalizedModel(raw));
91
+ return canonical && canonical !== raw ? [raw, canonical] : [raw];
92
+ }
93
+ /**
94
+ * Resolve the context-window size to evaluate a session's budget against.
95
+ *
96
+ * Precedence: an explicit override always wins, even for a model this file
97
+ * has never heard of — the whole point of the override setting is to let a
98
+ * user correct or extend past this file's guesses. Failing that, fall back
99
+ * to the estimate table. Returns `null` when neither source has a value, so
100
+ * the guard can no-op rather than evaluate against a fabricated number.
101
+ */
102
+ export function getEffectiveContextWindow(model, overrides) {
103
+ const candidates = windowLookupCandidates(model);
104
+ if (candidates.length === 0)
105
+ return null;
106
+ for (const candidate of candidates) {
107
+ const override = overrides?.[candidate];
108
+ if (typeof override !== "number" || !Number.isFinite(override))
109
+ continue;
110
+ // Floor BEFORE the positivity check, not after. Checking `override > 0`
111
+ // on the raw value admits anything in (0, 1), which then floors to 0 and
112
+ // returns a zero-token window -- breaking this function's contract that a
113
+ // window it cannot resolve comes back as null, and handing any caller
114
+ // that trusts it a division by zero.
115
+ const tokens = Math.floor(override);
116
+ if (tokens > 0) {
117
+ return { tokens, source: "override" };
118
+ }
119
+ }
120
+ for (const candidate of candidates) {
121
+ const estimate = ESTIMATED_MODEL_CONTEXT_WINDOWS[candidate];
122
+ if (typeof estimate === "number") {
123
+ return { tokens: estimate, source: "estimate" };
124
+ }
125
+ }
126
+ return null;
127
+ }
128
+ export function listEstimatedModelContextWindows() {
129
+ return { ...ESTIMATED_MODEL_CONTEXT_WINDOWS };
130
+ }
@@ -0,0 +1,100 @@
1
+ export interface ContextBudgetSnapshot {
2
+ model: string;
3
+ /**
4
+ * Tokens the NEXT turn on this session is expected to resend as context:
5
+ * this turn's `input_tokens` plus the part of its output that becomes
6
+ * conversation history. Deliberately NOT `total_tokens`, which also counts
7
+ * `reasoning_tokens` that the Responses API drops rather than resends —
8
+ * charging those against the window inflates every measurement by this
9
+ * turn's thinking budget and fires the guard early on long-reasoning turns.
10
+ */
11
+ contextTokens: number;
12
+ updatedAt: number;
13
+ }
14
+ export interface ContextBudgetOptions {
15
+ enabled?: boolean;
16
+ softPercent?: number;
17
+ hardPercent?: number;
18
+ modelWindowOverrides?: Record<string, number>;
19
+ }
20
+ interface ContextBudgetPressure {
21
+ percent: number;
22
+ contextTokens: number;
23
+ windowTokens: number;
24
+ windowSource: "override" | "estimate";
25
+ model: string;
26
+ }
27
+ export type ContextBudgetAdvisory = {
28
+ level: "ok";
29
+ } | ({
30
+ level: "soft";
31
+ } & ContextBudgetPressure) | ({
32
+ level: "hard";
33
+ } & ContextBudgetPressure);
34
+ /**
35
+ * Tracks how full each session's context window is and decides, before the
36
+ * NEXT request on that session goes out, whether to nudge (soft) or pause
37
+ * (hard) the caller.
38
+ *
39
+ * Deliberately shaped like `PreemptiveQuotaScheduler`
40
+ * (`lib/preemptive-quota-scheduler.ts`): a per-key `Map` snapshot, a
41
+ * `configure()`/decision-getter split, and a lazy `prune()` on the same
42
+ * cadence. Same reason in both places — the decision needs to survive
43
+ * across the request that observed the usage and the next request that
44
+ * asks "are we still OK," and a scheduled sweep keeps memory bounded
45
+ * without a dedicated timer.
46
+ */
47
+ export declare class ContextBudgetGuard {
48
+ private readonly snapshots;
49
+ private enabled;
50
+ private softPercent;
51
+ private hardPercent;
52
+ private modelWindowOverrides;
53
+ private lastPruneAt;
54
+ constructor(options?: ContextBudgetOptions);
55
+ configure(options?: ContextBudgetOptions): void;
56
+ private maybePrune;
57
+ /**
58
+ * Record the latest known context size for a session, from that turn's usage.
59
+ *
60
+ * No-ops while disabled. The call sites sit on the hot path of every
61
+ * forwarded Responses turn, so a default-off install must not pay for a
62
+ * per-session map it will never read.
63
+ */
64
+ update(key: string, snapshot: ContextBudgetSnapshot): void;
65
+ /**
66
+ * Evaluate before forwarding the NEXT request on this session key.
67
+ *
68
+ * `requestModel` is the model that request will use, and it is what the
69
+ * window is resolved from -- NOT the model of the last recorded turn. The
70
+ * two differ whenever a session switches models, and then the snapshot's
71
+ * model is the wrong denominator: a session carrying 205k tokens is 79% of
72
+ * a 260k window and a fifth of a 1M one. Using the stale model also let
73
+ * the guard pause a request for a model it deliberately refuses to
74
+ * estimate, and print that stale model's name in the notice. Falls back to
75
+ * the snapshot's model only when the request declares none.
76
+ */
77
+ getAdvisory(key: string, now?: number, requestModel?: string | null): ContextBudgetAdvisory;
78
+ /** Drop sessions untouched for a while so the map does not grow unbounded. */
79
+ prune(now?: number): number;
80
+ /** Forget a single session's tracked usage, e.g. once it has visibly compacted. */
81
+ forget(key: string): void;
82
+ /**
83
+ * Call immediately after emitting a hard pause for `key`.
84
+ *
85
+ * The pause is synthetic: it short-circuits before the request is forwarded,
86
+ * so `update()` never runs for it and the recorded usage can never fall on
87
+ * its own. Left in place, the first crossing of the hard threshold would
88
+ * block that session forever — including the `/compact` turn the pause
89
+ * message tells the user to run, which travels on the same session key.
90
+ *
91
+ * Dropping the snapshot makes the pause one-shot per measurement: the next
92
+ * request is forwarded and re-measures. A session that really did compact
93
+ * comes back under the threshold and stays quiet; one that did not gets
94
+ * paused again on the turn after, so the warning still repeats while the
95
+ * session is over budget, without ever becoming a dead end.
96
+ */
97
+ noteHardPauseEmitted(key: string): void;
98
+ }
99
+ export {};
100
+ //# sourceMappingURL=context-budget-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-budget-guard.d.ts","sourceRoot":"","sources":["../../lib/context-budget-guard.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAqB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;OAOG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9C;AAED,UAAU,qBAAqB;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,UAAU,GAAG,UAAU,CAAC;IACtC,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,qBAAqB,GAC9B;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GACf,CAAC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,qBAAqB,CAAC,GAC3C,CAAC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,qBAAqB,CAAC,CAAC;AAuB/C;;;;;;;;;;;;GAYG;AACH,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;IACtE,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAwB;IAC3C,OAAO,CAAC,WAAW,CAAwB;IAC3C,OAAO,CAAC,oBAAoB,CAAqC;IACjE,OAAO,CAAC,WAAW,CAAK;gBAEZ,OAAO,GAAE,oBAAyB;IAI9C,SAAS,CAAC,OAAO,GAAE,oBAAyB,GAAG,IAAI;IAgCnD,OAAO,CAAC,UAAU;IAMlB;;;;;;OAMG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,qBAAqB,GAAG,IAAI;IAmB1D;;;;;;;;;;;OAWG;IACH,WAAW,CACV,GAAG,EAAE,MAAM,EACX,GAAG,SAAa,EAChB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAC1B,qBAAqB;IAuCxB,8EAA8E;IAC9E,KAAK,CAAC,GAAG,SAAa,GAAG,MAAM;IAW/B,mFAAmF;IACnF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzB;;;;;;;;;;;;;;OAcG;IACH,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAGvC"}
@@ -0,0 +1,183 @@
1
+ import { getEffectiveContextWindow } from "./context-budget/model-context-windows.js";
2
+ const DEFAULT_SOFT_PERCENT = 65;
3
+ const DEFAULT_HARD_PERCENT = 69;
4
+ /**
5
+ * Lowest hard threshold that can describe a real budget.
6
+ *
7
+ * `getContextBudgetGuardHardPercent` clamps rather than rejects (that is what
8
+ * every other numeric setting does), so without a floor a configured `0` is a
9
+ * legal value that makes `percent >= hardPercent` true for every snapshot —
10
+ * every session pauses from its first recorded turn onward. Anything under
11
+ * 10% of a window is that same failure in slower motion, so clamp up to a
12
+ * value that at least can't fire on turn one of a normal session.
13
+ */
14
+ const MIN_HARD_PERCENT = 10;
15
+ /** Sessions idle longer than this are dropped on the next prune sweep. */
16
+ const SESSION_TTL_MS = 6 * 60 * 60_000;
17
+ const PRUNE_INTERVAL_MS = 60_000;
18
+ function clampInt(value, min, max) {
19
+ return Math.max(min, Math.min(max, Math.floor(value)));
20
+ }
21
+ /**
22
+ * Tracks how full each session's context window is and decides, before the
23
+ * NEXT request on that session goes out, whether to nudge (soft) or pause
24
+ * (hard) the caller.
25
+ *
26
+ * Deliberately shaped like `PreemptiveQuotaScheduler`
27
+ * (`lib/preemptive-quota-scheduler.ts`): a per-key `Map` snapshot, a
28
+ * `configure()`/decision-getter split, and a lazy `prune()` on the same
29
+ * cadence. Same reason in both places — the decision needs to survive
30
+ * across the request that observed the usage and the next request that
31
+ * asks "are we still OK," and a scheduled sweep keeps memory bounded
32
+ * without a dedicated timer.
33
+ */
34
+ export class ContextBudgetGuard {
35
+ snapshots = new Map();
36
+ enabled = false;
37
+ softPercent = DEFAULT_SOFT_PERCENT;
38
+ hardPercent = DEFAULT_HARD_PERCENT;
39
+ modelWindowOverrides;
40
+ lastPruneAt = 0;
41
+ constructor(options = {}) {
42
+ this.configure(options);
43
+ }
44
+ configure(options = {}) {
45
+ if (typeof options.enabled === "boolean") {
46
+ // Turning the guard off must also drop what it already tracked, or a
47
+ // disable/re-enable cycle re-evaluates against usage measured under
48
+ // the old settings and can pause a session on its first request back.
49
+ if (!options.enabled && this.enabled) {
50
+ this.snapshots.clear();
51
+ }
52
+ this.enabled = options.enabled;
53
+ }
54
+ if (typeof options.softPercent === "number" && Number.isFinite(options.softPercent)) {
55
+ this.softPercent = clampInt(options.softPercent, 0, 100);
56
+ }
57
+ if (typeof options.hardPercent === "number" && Number.isFinite(options.hardPercent)) {
58
+ this.hardPercent = clampInt(options.hardPercent, MIN_HARD_PERCENT, 100);
59
+ }
60
+ // A misconfigured soft >= hard must degrade safely (guard fires later
61
+ // than intended) rather than throw or produce a nonsensical "hard but
62
+ // not soft" state. Never silently widen hard to fix it — narrowing soft
63
+ // is the change least likely to surprise whoever set hard deliberately.
64
+ if (this.softPercent >= this.hardPercent) {
65
+ this.softPercent = Math.max(0, this.hardPercent - 1);
66
+ }
67
+ if (options.modelWindowOverrides) {
68
+ this.modelWindowOverrides = options.modelWindowOverrides;
69
+ }
70
+ }
71
+ maybePrune(now) {
72
+ if (now - this.lastPruneAt < PRUNE_INTERVAL_MS)
73
+ return;
74
+ this.prune(now);
75
+ this.lastPruneAt = now;
76
+ }
77
+ /**
78
+ * Record the latest known context size for a session, from that turn's usage.
79
+ *
80
+ * No-ops while disabled. The call sites sit on the hot path of every
81
+ * forwarded Responses turn, so a default-off install must not pay for a
82
+ * per-session map it will never read.
83
+ */
84
+ update(key, snapshot) {
85
+ if (!this.enabled || !key)
86
+ return;
87
+ // Both production call sites source contextTokens from
88
+ // lib/usage/usage-extraction.ts, whose nonNegativeInteger already returns
89
+ // 0 for anything non-finite, so this is a boundary guard rather than a
90
+ // reachable path today. It is here because percent is a division by the
91
+ // window: a non-finite count would put `Infinity%` in the pause notice a
92
+ // user reads, and every threshold comparison against NaN is false, which
93
+ // disables the guard silently.
94
+ if (!Number.isFinite(snapshot.contextTokens) ||
95
+ snapshot.contextTokens < 0) {
96
+ return;
97
+ }
98
+ this.maybePrune(snapshot.updatedAt || Date.now());
99
+ this.snapshots.set(key, snapshot);
100
+ }
101
+ /**
102
+ * Evaluate before forwarding the NEXT request on this session key.
103
+ *
104
+ * `requestModel` is the model that request will use, and it is what the
105
+ * window is resolved from -- NOT the model of the last recorded turn. The
106
+ * two differ whenever a session switches models, and then the snapshot's
107
+ * model is the wrong denominator: a session carrying 205k tokens is 79% of
108
+ * a 260k window and a fifth of a 1M one. Using the stale model also let
109
+ * the guard pause a request for a model it deliberately refuses to
110
+ * estimate, and print that stale model's name in the notice. Falls back to
111
+ * the snapshot's model only when the request declares none.
112
+ */
113
+ getAdvisory(key, now = Date.now(), requestModel) {
114
+ this.maybePrune(now);
115
+ if (!this.enabled || !key)
116
+ return { level: "ok" };
117
+ const snapshot = this.snapshots.get(key);
118
+ if (!snapshot)
119
+ return { level: "ok" };
120
+ const trimmedRequestModel = requestModel?.trim();
121
+ const evaluatedModel = trimmedRequestModel && trimmedRequestModel.length > 0
122
+ ? trimmedRequestModel
123
+ : snapshot.model;
124
+ const window = getEffectiveContextWindow(evaluatedModel, this.modelWindowOverrides);
125
+ if (!window || window.tokens <= 0)
126
+ return { level: "ok" };
127
+ const percent = (snapshot.contextTokens / window.tokens) * 100;
128
+ if (percent >= this.hardPercent) {
129
+ return {
130
+ level: "hard",
131
+ percent,
132
+ contextTokens: snapshot.contextTokens,
133
+ windowTokens: window.tokens,
134
+ windowSource: window.source,
135
+ model: evaluatedModel,
136
+ };
137
+ }
138
+ if (percent >= this.softPercent) {
139
+ return {
140
+ level: "soft",
141
+ percent,
142
+ contextTokens: snapshot.contextTokens,
143
+ windowTokens: window.tokens,
144
+ windowSource: window.source,
145
+ model: evaluatedModel,
146
+ };
147
+ }
148
+ return { level: "ok" };
149
+ }
150
+ /** Drop sessions untouched for a while so the map does not grow unbounded. */
151
+ prune(now = Date.now()) {
152
+ let removed = 0;
153
+ for (const [key, snapshot] of this.snapshots.entries()) {
154
+ if (now - snapshot.updatedAt > SESSION_TTL_MS) {
155
+ this.snapshots.delete(key);
156
+ removed += 1;
157
+ }
158
+ }
159
+ return removed;
160
+ }
161
+ /** Forget a single session's tracked usage, e.g. once it has visibly compacted. */
162
+ forget(key) {
163
+ this.snapshots.delete(key);
164
+ }
165
+ /**
166
+ * Call immediately after emitting a hard pause for `key`.
167
+ *
168
+ * The pause is synthetic: it short-circuits before the request is forwarded,
169
+ * so `update()` never runs for it and the recorded usage can never fall on
170
+ * its own. Left in place, the first crossing of the hard threshold would
171
+ * block that session forever — including the `/compact` turn the pause
172
+ * message tells the user to run, which travels on the same session key.
173
+ *
174
+ * Dropping the snapshot makes the pause one-shot per measurement: the next
175
+ * request is forwarded and re-measures. A session that really did compact
176
+ * comes back under the threshold and stays quiet; one that did not gets
177
+ * paused again on the turn after, so the warning still repeats while the
178
+ * session is over budget, without ever becoming a dead end.
179
+ */
180
+ noteHardPauseEmitted(key) {
181
+ this.snapshots.delete(key);
182
+ }
183
+ }
@@ -0,0 +1,25 @@
1
+ import type { ContextBudgetAdvisory } from "./context-budget-guard.js";
2
+ /** Response header carrying the soft-threshold advisory, non-blocking. */
3
+ export declare const CONTEXT_BUDGET_PERCENT_HEADER = "x-codex-context-budget-percent";
4
+ /**
5
+ * Build the synthetic response returned in place of forwarding to upstream
6
+ * when the context budget guard's hard threshold has been reached.
7
+ *
8
+ * Same technique as `createContextOverflowResponse`: a 200 OK synthetic SSE
9
+ * reply so the host session never locks on an error for a notice the plugin
10
+ * itself generated — except this fires pre-flight, before the request that
11
+ * would overflow is ever sent, instead of reacting to the 400 after the
12
+ * fact.
13
+ */
14
+ export declare function createContextBudgetPauseResponse(advisory: Extract<ContextBudgetAdvisory, {
15
+ level: "hard";
16
+ }>): Response;
17
+ /**
18
+ * Non-blocking header for the soft threshold, added to the real forwarded
19
+ * response next to the existing `x-codex-*-used-percent` quota headers.
20
+ * Consumed by `codex-multi-auth status` / the statusline, not by the model.
21
+ */
22
+ export declare function buildContextBudgetHeaders(advisory: Extract<ContextBudgetAdvisory, {
23
+ level: "soft" | "hard";
24
+ }>): Record<string, string>;
25
+ //# sourceMappingURL=context-budget-response.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-budget-response.d.ts","sourceRoot":"","sources":["../../lib/context-budget-response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAGvE,0EAA0E;AAC1E,eAAO,MAAM,6BAA6B,mCAAmC,CAAC;AAgC9E;;;;;;;;;GASG;AACH,wBAAgB,gCAAgC,CAC/C,QAAQ,EAAE,OAAO,CAAC,qBAAqB,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GACzD,QAAQ,CAOV;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACxC,QAAQ,EAAE,OAAO,CAAC,qBAAqB,EAAE;IAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAC,GAClE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIxB"}
@@ -0,0 +1,57 @@
1
+ import { createSyntheticSseResponse } from "./synthetic-response.js";
2
+ /** Response header carrying the soft-threshold advisory, non-blocking. */
3
+ export const CONTEXT_BUDGET_PERCENT_HEADER = "x-codex-context-budget-percent";
4
+ function formatPercent(percent) {
5
+ return percent.toFixed(1);
6
+ }
7
+ /**
8
+ * The message shown to users when the context budget guard pauses a session
9
+ * at the hard threshold, before the request that would have pushed it over
10
+ * the model's window is even sent upstream.
11
+ *
12
+ * Deliberately echoes `lib/context-overflow.ts`'s CONTEXT_OVERFLOW_MESSAGE
13
+ * copy so the two related notices read as one family in a transcript,
14
+ * rather than as two unexplained different warnings.
15
+ */
16
+ function buildPauseMessage(advisory) {
17
+ const windowNote = advisory.windowSource === "override"
18
+ ? "your configured window size"
19
+ : "an estimated window size (unverified — set `contextBudgetGuardModelWindowOverrides` if you know the real limit)";
20
+ return `[Plugin Notice] Context budget guard paused this session at ${formatPercent(advisory.percent)}% of ${windowNote} for \`${advisory.model}\`, before hitting the model's actual limit.
21
+
22
+ Please use one of these commands to reduce context size:
23
+
24
+ • **/compact** - Compress conversation history (recommended)
25
+ • **/clear** - Start fresh with empty context
26
+ • **/undo** - Remove recent messages
27
+
28
+ Then retry your request. This pause clears itself automatically once your context usage drops back below the threshold.`;
29
+ }
30
+ /**
31
+ * Build the synthetic response returned in place of forwarding to upstream
32
+ * when the context budget guard's hard threshold has been reached.
33
+ *
34
+ * Same technique as `createContextOverflowResponse`: a 200 OK synthetic SSE
35
+ * reply so the host session never locks on an error for a notice the plugin
36
+ * itself generated — except this fires pre-flight, before the request that
37
+ * would overflow is ever sent, instead of reacting to the 400 after the
38
+ * fact.
39
+ */
40
+ export function createContextBudgetPauseResponse(advisory) {
41
+ return createSyntheticSseResponse({
42
+ model: advisory.model,
43
+ message: buildPauseMessage(advisory),
44
+ idPrefix: "context_budget_pause",
45
+ errorType: "context_budget_pause",
46
+ });
47
+ }
48
+ /**
49
+ * Non-blocking header for the soft threshold, added to the real forwarded
50
+ * response next to the existing `x-codex-*-used-percent` quota headers.
51
+ * Consumed by `codex-multi-auth status` / the statusline, not by the model.
52
+ */
53
+ export function buildContextBudgetHeaders(advisory) {
54
+ return {
55
+ [CONTEXT_BUDGET_PERCENT_HEADER]: formatPercent(advisory.percent),
56
+ };
57
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"context-overflow.d.ts","sourceRoot":"","sources":["../../lib/context-overflow.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiBH;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAMhF;AAiBD;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,GAAE,MAAkB,GAAG,QAAQ,CAsEjF;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,QAAQ,EAClB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAmBrE"}
1
+ {"version":3,"file":"context-overflow.d.ts","sourceRoot":"","sources":["../../lib/context-overflow.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkBH;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAMhF;AAiBD;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,GAAE,MAAkB,GAAG,QAAQ,CAOjF;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,QAAQ,EAClB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAmBrE"}
@@ -6,6 +6,7 @@
6
6
  * This prevents the host session from getting locked on 400 errors.
7
7
  */
8
8
  import { logDebug } from "./logger.js";
9
+ import { createSyntheticSseResponse } from "./synthetic-response.js";
9
10
  /**
10
11
  * Error patterns that indicate context overflow
11
12
  */
@@ -54,67 +55,11 @@ Alternatively, you can switch to a model with a larger context window.`;
54
55
  * (recovery-01). Returns 200 OK so the host session does not lock on the 400.
55
56
  */
56
57
  export function createContextOverflowResponse(model = "unknown") {
57
- const messageId = `msg_synthetic_overflow_${Date.now()}_${Math.random()
58
- .toString(36)
59
- .slice(2, 8)}`;
60
- const responseId = `resp_synthetic_overflow_${Date.now()}_${Math.random()
61
- .toString(36)
62
- .slice(2, 8)}`;
63
- const events = [];
64
- const push = (type, payload) => {
65
- events.push(`event: ${type}\ndata: ${JSON.stringify({ type, ...payload })}\n\n`);
66
- };
67
- const baseResponse = {
68
- id: responseId,
69
- object: "response",
58
+ return createSyntheticSseResponse({
70
59
  model,
71
- };
72
- // response.created
73
- push("response.created", { response: { ...baseResponse, status: "in_progress" } });
74
- // output item (assistant message) added
75
- push("response.output_item.added", {
76
- output_index: 0,
77
- item: {
78
- id: messageId,
79
- type: "message",
80
- role: "assistant",
81
- content: [],
82
- },
83
- });
84
- // streamed text + its terminal "done" carrying the final canonical text
85
- push("response.output_text.delta", {
86
- output_index: 0,
87
- content_index: 0,
88
- delta: CONTEXT_OVERFLOW_MESSAGE,
89
- });
90
- push("response.output_text.done", {
91
- output_index: 0,
92
- content_index: 0,
93
- text: CONTEXT_OVERFLOW_MESSAGE,
94
- });
95
- // terminal response.completed with the full output array
96
- push("response.completed", {
97
- response: {
98
- ...baseResponse,
99
- status: "completed",
100
- output: [
101
- {
102
- id: messageId,
103
- type: "message",
104
- role: "assistant",
105
- content: [{ type: "output_text", text: CONTEXT_OVERFLOW_MESSAGE }],
106
- },
107
- ],
108
- usage: { input_tokens: 0, output_tokens: 0, total_tokens: 0 },
109
- },
110
- });
111
- return new Response(events.join(""), {
112
- status: 200,
113
- headers: {
114
- "Content-Type": "text/event-stream",
115
- "X-Codex-Plugin-Synthetic": "true",
116
- "X-Codex-Plugin-Error-Type": "context_overflow",
117
- },
60
+ message: CONTEXT_OVERFLOW_MESSAGE,
61
+ idPrefix: "synthetic_overflow",
62
+ errorType: "context_overflow",
118
63
  });
119
64
  }
120
65
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"model-capability-matrix.d.ts","sourceRoot":"","sources":["../../lib/model-capability-matrix.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAGN,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAEN,KAAK,wBAAwB,EAC7B,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EACX,wBAAwB,EACxB,qBAAqB,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxE,MAAM,WAAW,0BAA0B;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,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;IAChC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAClD,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,0BAA0B,EAAE,CAAC;CACtC;AAsBD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE;IACjD,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,CAAC,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAC/C,gBAAgB,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAChD,UAAU,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;CACb,GAAG,qBAAqB,CAiFxB"}
1
+ {"version":3,"file":"model-capability-matrix.d.ts","sourceRoot":"","sources":["../../lib/model-capability-matrix.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAGN,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAEN,KAAK,wBAAwB,EAC7B,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EACX,wBAAwB,EACxB,qBAAqB,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxE,MAAM,WAAW,0BAA0B;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,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;IAChC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAClD,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,0BAA0B,EAAE,CAAC;CACtC;AAsBD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE;IACjD,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,CAAC,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAC/C,gBAAgB,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAChD,UAAU,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;CACb,GAAG,qBAAqB,CAyFxB"}
@@ -35,7 +35,15 @@ export function buildModelCapabilityMatrix(input) {
35
35
  });
36
36
  const entitlementKeys = [accountKey, entitlementKey];
37
37
  for (const model of models) {
38
- const profile = MODEL_PROFILES[model] ?? MODEL_PROFILES[resolveNormalizedModel(model)];
38
+ // `Object.hasOwn` before the index: `models` comes from `--model` on
39
+ // the CLI, so `constructor` and friends reach this lookup and a bare
40
+ // index returns the matching `Object.prototype` member. It is truthy,
41
+ // so the `!profile` guard passes it through and the matrix emits a row
42
+ // whose normalizedModel, promptFamily and capabilities are all
43
+ // undefined.
44
+ const profile = Object.hasOwn(MODEL_PROFILES, model)
45
+ ? MODEL_PROFILES[model]
46
+ : MODEL_PROFILES[resolveNormalizedModel(model)];
39
47
  if (!profile)
40
48
  continue;
41
49
  const entitlement = getEntitlementBlock(input.entitlements, entitlementKeys, profile.normalizedModel, now);
@@ -1 +1 @@
1
- {"version":3,"file":"error-classification.d.ts","sourceRoot":"","sources":["../../../lib/request/error-classification.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,MAAM,WAAW,gBAAgB;IACzB,aAAa,EAAE,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACvB;AAED,sGAAsG;AACtG,eAAO,MAAM,oCAAoC,6CAA6C,CAAC;AAQ/F,eAAO,MAAM,wCAAwC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAoB7E,CAAC;AAEF,MAAM,WAAW,yBAAyB;IACzC,aAAa,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,sCAAsC;IACtD,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACnC,+BAA+B,EAAE,OAAO,CAAC;IACzC,iCAAiC,EAAE,OAAO,CAAC;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACvC;AA0CD,wBAAgB,oCAAoC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAgBzF;AAED,sGAAsG;AACtG,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQ3F;AAED,wBAAgB,4BAA4B,CAC3C,SAAS,EAAE,OAAO,GAChB,yBAAyB,CAqD3B;AAED,wBAAgB,oCAAoC,CACnD,OAAO,EAAE,sCAAsC,GAC7C,MAAM,GAAG,SAAS,CAgCpB;AAED;;GAEG;AACH,wBAAgB,uCAAuC,CACtD,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,SAAS,EAAE,OAAO,GAChB,OAAO,CAgBT;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAK1E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAChC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,MAAM,GACrB,OAAO,CAoDT;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,CAmB1E"}
1
+ {"version":3,"file":"error-classification.d.ts","sourceRoot":"","sources":["../../../lib/request/error-classification.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,MAAM,WAAW,gBAAgB;IACzB,aAAa,EAAE,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACvB;AAED,sGAAsG;AACtG,eAAO,MAAM,oCAAoC,6CAA6C,CAAC;AAQ/F,eAAO,MAAM,wCAAwC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAoD7E,CAAC;AAEF,MAAM,WAAW,yBAAyB;IACzC,aAAa,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,sCAAsC;IACtD,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACnC,+BAA+B,EAAE,OAAO,CAAC;IACzC,iCAAiC,EAAE,OAAO,CAAC;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACvC;AAiDD,wBAAgB,oCAAoC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAgBzF;AAED,sGAAsG;AACtG,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQ3F;AAED,wBAAgB,4BAA4B,CAC3C,SAAS,EAAE,OAAO,GAChB,yBAAyB,CAqD3B;AAED,wBAAgB,oCAAoC,CACnD,OAAO,EAAE,sCAAsC,GAC7C,MAAM,GAAG,SAAS,CAkCpB;AAED;;GAEG;AACH,wBAAgB,uCAAuC,CACtD,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,SAAS,EAAE,OAAO,GAChB,OAAO,CAgBT;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAK1E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAChC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,MAAM,GACrB,OAAO,CAoDT;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,CAmB1E"}