@adaptic/utils 0.0.1014 → 0.0.1016
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/dist/index.cjs +2823 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +2783 -25
- package/dist/index.mjs.map +1 -1
- package/dist/types/__tests__/llm/client/support/rejections.d.ts +21 -0
- package/dist/types/__tests__/llm/client/support/rejections.d.ts.map +1 -0
- package/dist/types/__tests__/llm/client/support/routes.d.ts +67 -0
- package/dist/types/__tests__/llm/client/support/routes.d.ts.map +1 -0
- package/dist/types/__tests__/llm/client/support/streams.d.ts +74 -0
- package/dist/types/__tests__/llm/client/support/streams.d.ts.map +1 -0
- package/dist/types/__tests__/llm/client/support/transports.d.ts +105 -0
- package/dist/types/__tests__/llm/client/support/transports.d.ts.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/llm/alias-client.d.ts +64 -0
- package/dist/types/llm/alias-client.d.ts.map +1 -0
- package/dist/types/llm/circuit-breaker.d.ts +124 -0
- package/dist/types/llm/circuit-breaker.d.ts.map +1 -0
- package/dist/types/llm/eval/comparators.d.ts +127 -0
- package/dist/types/llm/eval/comparators.d.ts.map +1 -0
- package/dist/types/llm/eval/coverage.d.ts +44 -0
- package/dist/types/llm/eval/coverage.d.ts.map +1 -0
- package/dist/types/llm/eval/golden-set.d.ts +47 -0
- package/dist/types/llm/eval/golden-set.d.ts.map +1 -0
- package/dist/types/llm/eval/index.d.ts +25 -0
- package/dist/types/llm/eval/index.d.ts.map +1 -0
- package/dist/types/llm/eval/json-shape.d.ts +74 -0
- package/dist/types/llm/eval/json-shape.d.ts.map +1 -0
- package/dist/types/llm/eval/judge.d.ts +131 -0
- package/dist/types/llm/eval/judge.d.ts.map +1 -0
- package/dist/types/llm/eval/metrics.d.ts +51 -0
- package/dist/types/llm/eval/metrics.d.ts.map +1 -0
- package/dist/types/llm/eval/run.d.ts +97 -0
- package/dist/types/llm/eval/run.d.ts.map +1 -0
- package/dist/types/llm/eval/types.d.ts +242 -0
- package/dist/types/llm/eval/types.d.ts.map +1 -0
- package/dist/types/llm/fallback-chain.d.ts +97 -0
- package/dist/types/llm/fallback-chain.d.ts.map +1 -0
- package/dist/types/llm/index.d.ts +30 -0
- package/dist/types/llm/index.d.ts.map +1 -0
- package/dist/types/llm/param-matrix.d.ts +65 -0
- package/dist/types/llm/param-matrix.d.ts.map +1 -0
- package/dist/types/llm/rate-guard.d.ts +119 -0
- package/dist/types/llm/rate-guard.d.ts.map +1 -0
- package/dist/types/llm/route-table.d.ts +155 -0
- package/dist/types/llm/route-table.d.ts.map +1 -0
- package/dist/types/llm/schema-retry.d.ts +80 -0
- package/dist/types/llm/schema-retry.d.ts.map +1 -0
- package/dist/types/llm/streaming.d.ts +93 -0
- package/dist/types/llm/streaming.d.ts.map +1 -0
- package/dist/types/llm/transports/direct.d.ts +92 -0
- package/dist/types/llm/transports/direct.d.ts.map +1 -0
- package/dist/types/llm/transports/gateway.d.ts +73 -0
- package/dist/types/llm/transports/gateway.d.ts.map +1 -0
- package/dist/types/llm/types.d.ts +292 -0
- package/dist/types/llm/types.d.ts.map +1 -0
- package/dist/types/schemas/alpaca-schemas.d.ts +6 -6
- package/package.json +2 -2
- package/dist/types/__tests__/alpaca-broker-error-preservation.test.d.ts +0 -2
- package/dist/types/__tests__/alpaca-broker-error-preservation.test.d.ts.map +0 -1
- package/dist/types/__tests__/alpaca-client-order-id.test.d.ts +0 -2
- package/dist/types/__tests__/alpaca-client-order-id.test.d.ts.map +0 -1
- package/dist/types/__tests__/alpaca-functions.test.d.ts +0 -2
- package/dist/types/__tests__/alpaca-functions.test.d.ts.map +0 -1
- package/dist/types/__tests__/alpaca-market-data-retry.test.d.ts +0 -2
- package/dist/types/__tests__/alpaca-market-data-retry.test.d.ts.map +0 -1
- package/dist/types/__tests__/alpaca-order-idempotency.test.d.ts +0 -2
- package/dist/types/__tests__/alpaca-order-idempotency.test.d.ts.map +0 -1
- package/dist/types/__tests__/alpaca-trading-api.test.d.ts +0 -2
- package/dist/types/__tests__/alpaca-trading-api.test.d.ts.map +0 -1
- package/dist/types/__tests__/api-endpoints.test.d.ts +0 -2
- package/dist/types/__tests__/api-endpoints.test.d.ts.map +0 -1
- package/dist/types/__tests__/asset-allocation.test.d.ts +0 -2
- package/dist/types/__tests__/asset-allocation.test.d.ts.map +0 -1
- package/dist/types/__tests__/atr.test.d.ts +0 -2
- package/dist/types/__tests__/atr.test.d.ts.map +0 -1
- package/dist/types/__tests__/auth-validator.test.d.ts +0 -2
- package/dist/types/__tests__/auth-validator.test.d.ts.map +0 -1
- package/dist/types/__tests__/broker-factory.test.d.ts +0 -2
- package/dist/types/__tests__/broker-factory.test.d.ts.map +0 -1
- package/dist/types/__tests__/broker-types.test.d.ts +0 -2
- package/dist/types/__tests__/broker-types.test.d.ts.map +0 -1
- package/dist/types/__tests__/cache.test.d.ts +0 -2
- package/dist/types/__tests__/cache.test.d.ts.map +0 -1
- package/dist/types/__tests__/errors.test.d.ts +0 -2
- package/dist/types/__tests__/errors.test.d.ts.map +0 -1
- package/dist/types/__tests__/financial-regression.test.d.ts +0 -2
- package/dist/types/__tests__/financial-regression.test.d.ts.map +0 -1
- package/dist/types/__tests__/format-tools.test.d.ts +0 -2
- package/dist/types/__tests__/format-tools.test.d.ts.map +0 -1
- package/dist/types/__tests__/http-keep-alive.test.d.ts +0 -2
- package/dist/types/__tests__/http-keep-alive.test.d.ts.map +0 -1
- package/dist/types/__tests__/http-timeout.test.d.ts +0 -2
- package/dist/types/__tests__/http-timeout.test.d.ts.map +0 -1
- package/dist/types/__tests__/index.test.d.ts +0 -2
- package/dist/types/__tests__/index.test.d.ts.map +0 -1
- package/dist/types/__tests__/legacy-auth.test.d.ts +0 -2
- package/dist/types/__tests__/legacy-auth.test.d.ts.map +0 -1
- package/dist/types/__tests__/logger.test.d.ts +0 -2
- package/dist/types/__tests__/logger.test.d.ts.map +0 -1
- package/dist/types/__tests__/logging.test.d.ts +0 -2
- package/dist/types/__tests__/logging.test.d.ts.map +0 -1
- package/dist/types/__tests__/market-time.test.d.ts +0 -2
- package/dist/types/__tests__/market-time.test.d.ts.map +0 -1
- package/dist/types/__tests__/massive.test.d.ts +0 -2
- package/dist/types/__tests__/massive.test.d.ts.map +0 -1
- package/dist/types/__tests__/metrics-calcs-direction.test.d.ts +0 -2
- package/dist/types/__tests__/metrics-calcs-direction.test.d.ts.map +0 -1
- package/dist/types/__tests__/misc-utils.test.d.ts +0 -2
- package/dist/types/__tests__/misc-utils.test.d.ts.map +0 -1
- package/dist/types/__tests__/paginator.test.d.ts +0 -2
- package/dist/types/__tests__/paginator.test.d.ts.map +0 -1
- package/dist/types/__tests__/performance-metrics-fees.test.d.ts +0 -2
- package/dist/types/__tests__/performance-metrics-fees.test.d.ts.map +0 -1
- package/dist/types/__tests__/performance-metrics.test.d.ts +0 -2
- package/dist/types/__tests__/performance-metrics.test.d.ts.map +0 -1
- package/dist/types/__tests__/price-utils-fees.test.d.ts +0 -2
- package/dist/types/__tests__/price-utils-fees.test.d.ts.map +0 -1
- package/dist/types/__tests__/price-utils.test.d.ts +0 -2
- package/dist/types/__tests__/price-utils.test.d.ts.map +0 -1
- package/dist/types/__tests__/property-based-financial.test.d.ts +0 -2
- package/dist/types/__tests__/property-based-financial.test.d.ts.map +0 -1
- package/dist/types/__tests__/protective-order-sides.test.d.ts +0 -2
- package/dist/types/__tests__/protective-order-sides.test.d.ts.map +0 -1
- package/dist/types/__tests__/rate-limiter.test.d.ts +0 -2
- package/dist/types/__tests__/rate-limiter.test.d.ts.map +0 -1
- package/dist/types/__tests__/retry-classification.test.d.ts +0 -2
- package/dist/types/__tests__/retry-classification.test.d.ts.map +0 -1
- package/dist/types/__tests__/retry.test.d.ts +0 -2
- package/dist/types/__tests__/retry.test.d.ts.map +0 -1
- package/dist/types/__tests__/risk-free-rate.test.d.ts +0 -2
- package/dist/types/__tests__/risk-free-rate.test.d.ts.map +0 -1
- package/dist/types/__tests__/risk-metrics.test.d.ts +0 -2
- package/dist/types/__tests__/risk-metrics.test.d.ts.map +0 -1
- package/dist/types/__tests__/schema-validation.test.d.ts +0 -2
- package/dist/types/__tests__/schema-validation.test.d.ts.map +0 -1
- package/dist/types/__tests__/stampede-load-timeout.test.d.ts +0 -2
- package/dist/types/__tests__/stampede-load-timeout.test.d.ts.map +0 -1
- package/dist/types/__tests__/strategy-metrics.test.d.ts +0 -2
- package/dist/types/__tests__/strategy-metrics.test.d.ts.map +0 -1
- package/dist/types/__tests__/technical-analysis-totality.test.d.ts +0 -2
- package/dist/types/__tests__/technical-analysis-totality.test.d.ts.map +0 -1
- package/dist/types/__tests__/technical-analysis.test.d.ts +0 -2
- package/dist/types/__tests__/technical-analysis.test.d.ts.map +0 -1
- package/dist/types/__tests__/time-utils.test.d.ts +0 -2
- package/dist/types/__tests__/time-utils.test.d.ts.map +0 -1
- package/dist/types/__tests__/trading-policy-schemas.test.d.ts +0 -2
- package/dist/types/__tests__/trading-policy-schemas.test.d.ts.map +0 -1
- package/dist/types/__tests__/trailing-stops-portfolio.test.d.ts +0 -2
- package/dist/types/__tests__/trailing-stops-portfolio.test.d.ts.map +0 -1
- package/dist/types/__tests__/volatility.test.d.ts +0 -2
- package/dist/types/__tests__/volatility.test.d.ts.map +0 -1
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the LLM migration eval harness.
|
|
3
|
+
*
|
|
4
|
+
* Every gate in this harness is INCUMBENT-RELATIVE: the question is never "is
|
|
5
|
+
* the candidate good" but "is the candidate at least as good as the model it
|
|
6
|
+
* would replace". That framing is what makes a gate decidable by code from
|
|
7
|
+
* recorded data, which PD-6 requires — agent judgement never substitutes for a
|
|
8
|
+
* gate. It also fixes the shape of these types: a golden set that carries no
|
|
9
|
+
* recorded incumbent baseline has no comparison basis, so it can only render an
|
|
10
|
+
* `indeterminate` verdict. A gate that passed on missing data would certify
|
|
11
|
+
* nothing while looking green, which is strictly worse than having no gate.
|
|
12
|
+
*
|
|
13
|
+
* @module llm/eval/types
|
|
14
|
+
*/
|
|
15
|
+
import type { LlmAlias, LlmLatencyClass } from "../types";
|
|
16
|
+
/**
|
|
17
|
+
* The assertion types this harness implements, one per line of Section 6 of
|
|
18
|
+
* the migration backlog.
|
|
19
|
+
*
|
|
20
|
+
* `match` covers both exact-match and field-level F1 because the backlog treats
|
|
21
|
+
* them as one gate with two measurement choices — a set declares which of the
|
|
22
|
+
* two its category can be scored on, and the tolerance is the same.
|
|
23
|
+
*/
|
|
24
|
+
export type EvalAssertion = "schema-valid" | "match" | "judge" | "tool-call" | "latency";
|
|
25
|
+
/** The eval-gate categories the route table assigns to each alias. */
|
|
26
|
+
export type EvalGate = "structured-output" | "free-text-judge" | "tool-call" | "none-pinned-judge";
|
|
27
|
+
/** Which measurement a structured set is scored on for the `match` assertion. */
|
|
28
|
+
export type MatchMetric = "exact_match" | "field_f1";
|
|
29
|
+
/** Unit a verdict's numbers are expressed in, so a reader cannot misread a scale. */
|
|
30
|
+
export type MetricUnit = "rate" | "points" | "ms";
|
|
31
|
+
/** One tool call as a provider reported it. */
|
|
32
|
+
export interface RecordedToolCall {
|
|
33
|
+
/** The function the model asked to call. */
|
|
34
|
+
readonly name: string;
|
|
35
|
+
/** The raw argument JSON, kept unparsed because "did it parse" is part of the measurement. */
|
|
36
|
+
readonly arguments: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* One model answer as it was recorded.
|
|
40
|
+
*
|
|
41
|
+
* Recorded rather than re-derived: a gate that re-ran the incumbent to obtain
|
|
42
|
+
* its baseline would compare two different samples of a stochastic process and
|
|
43
|
+
* call the difference a regression.
|
|
44
|
+
*/
|
|
45
|
+
export interface RecordedResult {
|
|
46
|
+
/** The answer payload — a parsed object for structured sites, a string for free-text ones. */
|
|
47
|
+
readonly raw: unknown;
|
|
48
|
+
/** Wall-clock latency of the call that produced it. */
|
|
49
|
+
readonly latency_ms: number;
|
|
50
|
+
/** Tool calls the model asked for, where the site is a tool-call site. */
|
|
51
|
+
readonly tool_calls?: readonly RecordedToolCall[];
|
|
52
|
+
/** Pinned-judge score on a 0-100 scale, where the site is judged. */
|
|
53
|
+
readonly judge_score?: number;
|
|
54
|
+
/**
|
|
55
|
+
* Structured retries spent before this answer.
|
|
56
|
+
*
|
|
57
|
+
* Section 6 permits exactly one structured retry before the chain falls back,
|
|
58
|
+
* so the retry count is part of whether a tool call counts as valid — an
|
|
59
|
+
* answer that took three attempts did not meet the contract even if the third
|
|
60
|
+
* attempt parsed.
|
|
61
|
+
*/
|
|
62
|
+
readonly structured_retries?: number;
|
|
63
|
+
}
|
|
64
|
+
/** One graded example: an input, the answer it should produce, and what the incumbent produced. */
|
|
65
|
+
export interface GoldenCase {
|
|
66
|
+
/** Stable id, so a candidate run can be matched to the case it answered. */
|
|
67
|
+
readonly id: string;
|
|
68
|
+
/** The prompt exactly as the call site would send it, post-redaction. */
|
|
69
|
+
readonly input: string;
|
|
70
|
+
/** The reference answer the case is graded against. */
|
|
71
|
+
readonly expected: unknown;
|
|
72
|
+
/** What the incumbent model returned when the set was captured. */
|
|
73
|
+
readonly incumbent_result: RecordedResult;
|
|
74
|
+
}
|
|
75
|
+
/** Summary metrics attested for one side of a comparison. */
|
|
76
|
+
export interface BaselineMetrics {
|
|
77
|
+
/** Fraction of answers that parsed against the set's response shape. */
|
|
78
|
+
readonly schema_valid_rate?: number;
|
|
79
|
+
/** Fraction of answers deep-equal to `expected`. */
|
|
80
|
+
readonly exact_match_rate?: number;
|
|
81
|
+
/** Field-level F1 against `expected`, on a 0-100 point scale. */
|
|
82
|
+
readonly field_f1?: number;
|
|
83
|
+
/** Mean pinned-judge score, on a 0-100 point scale. */
|
|
84
|
+
readonly judge_score?: number;
|
|
85
|
+
/** Fraction of cases whose tool call was valid within the permitted retry budget. */
|
|
86
|
+
readonly valid_call_rate?: number;
|
|
87
|
+
/** p95 latency across the set. */
|
|
88
|
+
readonly latency_p95_ms?: number;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The attested incumbent baseline for a golden set.
|
|
92
|
+
*
|
|
93
|
+
* Attested AND recomputable: the harness recomputes every declared metric from
|
|
94
|
+
* the per-case `incumbent_result` records and refuses to render a verdict when
|
|
95
|
+
* the two disagree. A baseline that could be edited independently of the data
|
|
96
|
+
* it summarises would let a gate be passed by lowering the bar rather than by
|
|
97
|
+
* meeting it.
|
|
98
|
+
*/
|
|
99
|
+
export interface IncumbentBaseline {
|
|
100
|
+
/** When the incumbent run was captured. */
|
|
101
|
+
readonly recorded_at: string;
|
|
102
|
+
/** Where the traffic came from, so a reader can audit provenance. */
|
|
103
|
+
readonly source: string;
|
|
104
|
+
/** The incumbent's model family, recorded for attribution rather than for routing. */
|
|
105
|
+
readonly model_family: string;
|
|
106
|
+
/** Number of cases the baseline was computed over. */
|
|
107
|
+
readonly n: number;
|
|
108
|
+
/** The attested metrics. */
|
|
109
|
+
readonly metrics: BaselineMetrics;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The JSON-shape subset a structured set is validated against.
|
|
113
|
+
*
|
|
114
|
+
* A deliberate subset rather than full JSON Schema: the harness adds no
|
|
115
|
+
* dependency, and every keyword it does honour is one a captured call site
|
|
116
|
+
* actually uses. An unrecognised keyword is ignored rather than treated as
|
|
117
|
+
* satisfied, and that is stated here because silent leniency in a validator is
|
|
118
|
+
* how a schema gate stops separating anything.
|
|
119
|
+
*/
|
|
120
|
+
export interface JsonShape {
|
|
121
|
+
/** The JSON type this node must have. */
|
|
122
|
+
readonly type: "object" | "array" | "string" | "number" | "integer" | "boolean";
|
|
123
|
+
/** Property shapes, for an object node. */
|
|
124
|
+
readonly properties?: Readonly<Record<string, JsonShape>>;
|
|
125
|
+
/** Properties that must be present, for an object node. */
|
|
126
|
+
readonly required?: readonly string[];
|
|
127
|
+
/** Element shape, for an array node. */
|
|
128
|
+
readonly items?: JsonShape;
|
|
129
|
+
/** Permitted values, for a scalar node. */
|
|
130
|
+
readonly enum?: readonly (string | number | boolean)[];
|
|
131
|
+
}
|
|
132
|
+
/** What a tool-call site's answer must call, and with which arguments. */
|
|
133
|
+
export interface ToolExpectation {
|
|
134
|
+
/** The function name the model is expected to call. */
|
|
135
|
+
readonly tool: string;
|
|
136
|
+
/** Argument keys that must be present in the parsed argument object. */
|
|
137
|
+
readonly required_arguments: readonly string[];
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* A golden set: the durable, per-call-site-category evidence a gate runs on.
|
|
141
|
+
*
|
|
142
|
+
* Real sets are captured from PAPER traffic under a redaction profile (W5-01).
|
|
143
|
+
* The profile is recorded on the set rather than applied ad hoc, because a set
|
|
144
|
+
* whose redaction rules are not written down cannot be re-derived or audited.
|
|
145
|
+
*/
|
|
146
|
+
export interface GoldenSet {
|
|
147
|
+
/** Stable set id, unique across the golden-set directory. */
|
|
148
|
+
readonly id: string;
|
|
149
|
+
/** The call-site category this set stands for. */
|
|
150
|
+
readonly call_site_category: string;
|
|
151
|
+
/** The alias the category routes through. */
|
|
152
|
+
readonly alias: LlmAlias;
|
|
153
|
+
/** The eval gate this set enforces; must agree with the alias's route-table gate. */
|
|
154
|
+
readonly eval_gate: EvalGate;
|
|
155
|
+
/** Minimum cases below which no verdict is rendered. */
|
|
156
|
+
readonly min_n: number;
|
|
157
|
+
/** Named redaction profile applied when the set was captured. */
|
|
158
|
+
readonly redaction_profile: string;
|
|
159
|
+
/** The latency class the p95 comparison belongs to; must agree with the route table. */
|
|
160
|
+
readonly latency_class: LlmLatencyClass;
|
|
161
|
+
/** Which assertions this set is graded on. */
|
|
162
|
+
readonly assertions: readonly EvalAssertion[];
|
|
163
|
+
/** Which match measurement the set is scored on, where `match` is asserted. */
|
|
164
|
+
readonly match_metric?: MatchMetric;
|
|
165
|
+
/** The response shape, where `schema-valid` is asserted. */
|
|
166
|
+
readonly response_shape?: JsonShape;
|
|
167
|
+
/** The tool contract, where `tool-call` is asserted. */
|
|
168
|
+
readonly tool_expectation?: ToolExpectation;
|
|
169
|
+
/** The recorded incumbent baseline every assertion compares against. */
|
|
170
|
+
readonly incumbent_baseline: IncumbentBaseline;
|
|
171
|
+
/** The graded cases. */
|
|
172
|
+
readonly cases: readonly GoldenCase[];
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* A candidate model's answers to one golden set.
|
|
176
|
+
*
|
|
177
|
+
* Separate from the set because the set is durable and the candidate run is
|
|
178
|
+
* per-evaluation: swapping the candidate must not require re-capturing the
|
|
179
|
+
* evidence, or every model comparison would be against a different bar.
|
|
180
|
+
*/
|
|
181
|
+
export interface CandidateRun {
|
|
182
|
+
/** The golden set these answers belong to. */
|
|
183
|
+
readonly set_id: string;
|
|
184
|
+
/** Human-readable identity of the candidate, for the report. */
|
|
185
|
+
readonly candidate_label: string;
|
|
186
|
+
/** When the candidate run was produced. */
|
|
187
|
+
readonly recorded_at: string;
|
|
188
|
+
/** Answers keyed by golden-case id. */
|
|
189
|
+
readonly results: Readonly<Record<string, RecordedResult>>;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* The outcome of one assertion.
|
|
193
|
+
*
|
|
194
|
+
* A discriminated union with a first-class `indeterminate` arm. Collapsing
|
|
195
|
+
* "could not decide" into "pass" is the specific failure this shape forecloses:
|
|
196
|
+
* it is the difference between a gate that is silent about missing evidence and
|
|
197
|
+
* a gate that certifies its absence.
|
|
198
|
+
*/
|
|
199
|
+
export type Verdict = {
|
|
200
|
+
readonly kind: "pass";
|
|
201
|
+
readonly assertion: EvalAssertion;
|
|
202
|
+
readonly unit: MetricUnit;
|
|
203
|
+
readonly candidate: number;
|
|
204
|
+
readonly incumbent: number;
|
|
205
|
+
readonly n: number;
|
|
206
|
+
readonly detail: string;
|
|
207
|
+
} | {
|
|
208
|
+
readonly kind: "fail";
|
|
209
|
+
readonly assertion: EvalAssertion;
|
|
210
|
+
readonly unit: MetricUnit;
|
|
211
|
+
readonly candidate: number;
|
|
212
|
+
readonly incumbent: number;
|
|
213
|
+
readonly n: number;
|
|
214
|
+
readonly reason: string;
|
|
215
|
+
} | {
|
|
216
|
+
readonly kind: "indeterminate";
|
|
217
|
+
readonly assertion: EvalAssertion;
|
|
218
|
+
readonly reason: string;
|
|
219
|
+
};
|
|
220
|
+
/** Whether a set or a whole run cleared its gate. Only `PASSED` permits a merge. */
|
|
221
|
+
export type EvalStatus = "PASSED" | "FAILED";
|
|
222
|
+
/** The graded outcome of one golden set against one candidate run. */
|
|
223
|
+
export interface SetReport {
|
|
224
|
+
/** The set that was graded. */
|
|
225
|
+
readonly setId: string;
|
|
226
|
+
/** The candidate that was graded. */
|
|
227
|
+
readonly candidateLabel: string;
|
|
228
|
+
/** One verdict per asserted comparison, in assertion order. */
|
|
229
|
+
readonly verdicts: readonly Verdict[];
|
|
230
|
+
/** PASSED only when every verdict is `pass`. */
|
|
231
|
+
readonly status: EvalStatus;
|
|
232
|
+
}
|
|
233
|
+
/** The graded outcome of every set in one evaluation. */
|
|
234
|
+
export interface RunReport {
|
|
235
|
+
/** Per-set reports, in the order the sets were evaluated. */
|
|
236
|
+
readonly sets: readonly SetReport[];
|
|
237
|
+
/** PASSED only when every set passed and at least one set was graded. */
|
|
238
|
+
readonly status: EvalStatus;
|
|
239
|
+
/** Why the run reached its status, for the CI log. */
|
|
240
|
+
readonly summary: string;
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/llm/eval/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ordered execution of an alias's fallback chain (PD-3).
|
|
3
|
+
*
|
|
4
|
+
* Every call walks the chain primary -> secondary -> closed incumbent, and each
|
|
5
|
+
* leg runs under a hard timeout and a circuit breaker. Those three controls are
|
|
6
|
+
* one mechanism rather than three features: a chain without timeouts never
|
|
7
|
+
* reaches its second leg, a chain without a breaker pays a dead provider's full
|
|
8
|
+
* timeout on every call, and a timeout without a chain is just a slower
|
|
9
|
+
* failure. Timeout cascades are this system's known brown-out mode, which is
|
|
10
|
+
* why the budget is enforced here — at the only place that knows both the
|
|
11
|
+
* caller's deadline and how many legs are left to spend it on.
|
|
12
|
+
*
|
|
13
|
+
* Nothing here ever substitutes a value for an outcome. When every leg is
|
|
14
|
+
* exhausted the caller gets a typed error naming each leg and why it failed,
|
|
15
|
+
* because a default returned in place of an answer is a wrong answer that
|
|
16
|
+
* nobody is told about.
|
|
17
|
+
*
|
|
18
|
+
* @module llm/fallback-chain
|
|
19
|
+
*/
|
|
20
|
+
import type { CircuitBreakerRegistry } from "./circuit-breaker";
|
|
21
|
+
import { UnsupportedCapabilityError } from "./param-matrix";
|
|
22
|
+
import type { AliasAttemptRecord, LlmTransport, LlmTransportRequest, LlmTransportResponse, LlmUsageRecord, ResolvedRoute } from "./types";
|
|
23
|
+
/** What one leg of the chain needs in order to run. */
|
|
24
|
+
export interface ChainLeg {
|
|
25
|
+
readonly route: ResolvedRoute;
|
|
26
|
+
/** The transport that will carry this leg. */
|
|
27
|
+
readonly transport: LlmTransport;
|
|
28
|
+
/** Provider-normalised parameters, or the error that made this leg unusable. */
|
|
29
|
+
readonly params: Record<string, unknown> | UnsupportedCapabilityError;
|
|
30
|
+
}
|
|
31
|
+
/** Everything the executor needs for one call. */
|
|
32
|
+
export interface ChainExecution {
|
|
33
|
+
readonly legs: readonly ChainLeg[];
|
|
34
|
+
readonly content: string | readonly unknown[];
|
|
35
|
+
readonly responseFormat: LlmTransportRequest["responseFormat"];
|
|
36
|
+
readonly breakers: CircuitBreakerRegistry;
|
|
37
|
+
readonly correlationId?: string;
|
|
38
|
+
/** The caller's own cancellation, honoured ahead of any per-leg budget. */
|
|
39
|
+
readonly callerSignal?: AbortSignal;
|
|
40
|
+
/** Clock, injected so elapsed time is observable in tests without waiting. */
|
|
41
|
+
readonly now?: () => number;
|
|
42
|
+
/** Invoked once per leg after it settles, for metrics and shadow comparison. */
|
|
43
|
+
readonly onAttempt?: (record: AliasAttemptRecord) => void;
|
|
44
|
+
}
|
|
45
|
+
/** Result of walking a chain to a successful leg. */
|
|
46
|
+
export interface ChainOutcome<T> {
|
|
47
|
+
readonly response: LlmTransportResponse<T>;
|
|
48
|
+
readonly servedBy: ResolvedRoute;
|
|
49
|
+
readonly attempts: readonly AliasAttemptRecord[];
|
|
50
|
+
readonly totalUsage: LlmUsageRecord;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Thrown when every leg of a chain has been tried and none produced an answer.
|
|
54
|
+
*
|
|
55
|
+
* Carries the full attempt record rather than only the last error. The last
|
|
56
|
+
* error is usually the least informative one — the incumbent timing out says
|
|
57
|
+
* nothing about why the two legs before it were skipped — and an operator
|
|
58
|
+
* reading only that would go looking in the wrong place.
|
|
59
|
+
*/
|
|
60
|
+
export declare class ChainExhaustedError extends Error {
|
|
61
|
+
/** The alias whose chain was exhausted. */
|
|
62
|
+
readonly alias: string;
|
|
63
|
+
/** Every leg tried, in order, with its outcome. */
|
|
64
|
+
readonly attempts: readonly AliasAttemptRecord[];
|
|
65
|
+
/** Usage spent across the failed attempts, so the spend is still accounted for. */
|
|
66
|
+
readonly totalUsage: LlmUsageRecord;
|
|
67
|
+
/**
|
|
68
|
+
* @param alias The alias.
|
|
69
|
+
* @param attempts The attempt record.
|
|
70
|
+
* @param totalUsage Usage spent across all attempts.
|
|
71
|
+
*/
|
|
72
|
+
constructor(alias: string, attempts: readonly AliasAttemptRecord[], totalUsage: LlmUsageRecord);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Add two usage records.
|
|
76
|
+
*
|
|
77
|
+
* Attribution keeps the LAST attempt's provider and model, because that is the
|
|
78
|
+
* one that produced the answer the caller is holding, while the token counts
|
|
79
|
+
* accumulate across every attempt. Charging only the successful attempt would
|
|
80
|
+
* understate spend by exactly the amount the failures cost — which is the
|
|
81
|
+
* amount a fallback chain is most likely to run up.
|
|
82
|
+
*
|
|
83
|
+
* @param a The running total.
|
|
84
|
+
* @param b The attempt to add, if any.
|
|
85
|
+
* @returns The combined usage.
|
|
86
|
+
*/
|
|
87
|
+
export declare function sumUsage(a: LlmUsageRecord, b: LlmUsageRecord | undefined): LlmUsageRecord;
|
|
88
|
+
/**
|
|
89
|
+
* Walk a chain until a leg answers.
|
|
90
|
+
*
|
|
91
|
+
* @param alias The alias being served, for error attribution.
|
|
92
|
+
* @param execution The call context.
|
|
93
|
+
* @returns The first successful leg's answer, with the full attempt record.
|
|
94
|
+
* @throws {ChainExhaustedError} When no leg produced an answer.
|
|
95
|
+
*/
|
|
96
|
+
export declare function executeChain<T>(alias: string, execution: ChainExecution): Promise<ChainOutcome<T>>;
|
|
97
|
+
//# sourceMappingURL=fallback-chain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fallback-chain.d.ts","sourceRoot":"","sources":["../../../src/llm/fallback-chain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAE5D,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,aAAa,EACd,MAAM,SAAS,CAAC;AAWjB,uDAAuD;AACvD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,0BAA0B,CAAC;CACvE;AAED,kDAAkD;AAClD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,OAAO,EAAE,CAAC;IAC9C,QAAQ,CAAC,cAAc,EAAE,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;IAC/D,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC;IAC1C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,2EAA2E;IAC3E,QAAQ,CAAC,YAAY,CAAC,EAAE,WAAW,CAAC;IACpC,8EAA8E;IAC9E,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC3D;AAED,qDAAqD;AACrD,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC,CAAC,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACjD,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;CACrC;AAED;;;;;;;GAOG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,2CAA2C;IAC3C,SAAgB,KAAK,EAAE,MAAM,CAAC;IAE9B,mDAAmD;IACnD,SAAgB,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAExD,mFAAmF;IACnF,SAAgB,UAAU,EAAE,cAAc,CAAC;IAE3C;;;;OAIG;gBAED,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,SAAS,kBAAkB,EAAE,EACvC,UAAU,EAAE,cAAc;CAiB7B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CACtB,CAAC,EAAE,cAAc,EACjB,CAAC,EAAE,cAAc,GAAG,SAAS,GAC5B,cAAc,CAmBhB;AAuID;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAClC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,cAAc,GACxB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CA0F1B"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public surface of the alias-resolving LLM client.
|
|
3
|
+
*
|
|
4
|
+
* Everything a consumer needs to make an LLM call is here, and everything it
|
|
5
|
+
* needs to make one WITHOUT the timeout, breaker and fallback controls is
|
|
6
|
+
* deliberately not. The client is the only exported way to reach a model, so a
|
|
7
|
+
* call site cannot bypass the routing policy by importing something lower down.
|
|
8
|
+
*
|
|
9
|
+
* @module llm
|
|
10
|
+
*/
|
|
11
|
+
export { callLLMByAlias, configureLlmClient, llmAliases, llmBreakers } from "./alias-client";
|
|
12
|
+
export { ChainExhaustedError, sumUsage, } from "./fallback-chain";
|
|
13
|
+
export type { AliasAttemptRecord } from "./types";
|
|
14
|
+
export { NoServableRouteError, UnknownAliasError, closedIncumbentLeg, gatewayModelNameFor, listAliases, orderedRoutes, resolveChain, routeKeyFor, routeTable, } from "./route-table";
|
|
15
|
+
export type { ResolvedChain, RouteExclusion } from "./route-table";
|
|
16
|
+
export { UnsupportedCapabilityError, normaliseParams, routeSupports } from "./param-matrix";
|
|
17
|
+
export { RateGuardTimeoutError, guardSnapshots, limitsFor, limitsInventory, resetProviderGuards, withProviderGuards, } from "./rate-guard";
|
|
18
|
+
export type { GuardSnapshot, ProviderLimits } from "./rate-guard";
|
|
19
|
+
export { CircuitBreakerRegistry } from "./circuit-breaker";
|
|
20
|
+
export type { BreakerSnapshot, BreakerState } from "./circuit-breaker";
|
|
21
|
+
export { SchemaRetryExhaustedError, buildRetryPrompt, callWithValidation } from "./schema-retry";
|
|
22
|
+
export type { ValidatedOutcome } from "./schema-retry";
|
|
23
|
+
export { StreamProviderError, StreamTruncatedError, collectStream, normaliseAnthropicStream, normaliseOpenAiStream, normaliseStream, } from "./streaming";
|
|
24
|
+
export type { StreamChunk } from "./streaming";
|
|
25
|
+
export { GatewayResponseError, GatewayUnreachableError, createGatewayTransport, } from "./transports/gateway";
|
|
26
|
+
export type { GatewayTransportConfig } from "./transports/gateway";
|
|
27
|
+
export { DirectTransportRefusedError, createDirectTransport, resolveDefaultDirectCaller, } from "./transports/direct";
|
|
28
|
+
export type { DirectCaller, DirectCallerUsage, DirectTransportConfig, } from "./transports/direct";
|
|
29
|
+
export type { AliasCallOptions, AliasCallResult, LlmAlias, LlmAliasBudget, LlmAliasDefinition, LlmClientConfig, LlmCriticality, LlmLatencyClass, LlmModelIdStatus, LlmOpenItem, LlmPriceAnchor, LlmProvider, LlmProviderTier, LlmResponseFormat, LlmRoute, LlmRouteDefaults, LlmRouteParams, LlmRouteRole, LlmRouteTable, LlmToolCall, LlmTransport, LlmTransportRequest, LlmTransportResponse, LlmUsageRecord, LlmValidationOutcome, ResolvedRoute, } from "./types";
|
|
30
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/llm/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7F,OAAO,EACL,mBAAmB,EACnB,QAAQ,GACT,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,WAAW,EACX,aAAa,EACb,YAAY,EACZ,WAAW,EACX,UAAU,GACX,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEnE,OAAO,EAAE,0BAA0B,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE5F,OAAO,EACL,qBAAqB,EACrB,cAAc,EACd,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEvE,OAAO,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACjG,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACb,wBAAwB,EACxB,qBAAqB,EACrB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEnE,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,QAAQ,EACR,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,oBAAoB,EACpB,aAAa,GACd,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter normalisation across providers.
|
|
3
|
+
*
|
|
4
|
+
* A caller passes one option bag and the chain may serve it from any of three
|
|
5
|
+
* providers, so the same request has to be expressible to all of them. Vendors
|
|
6
|
+
* disagree about more than spelling: some reject a sampling parameter they do
|
|
7
|
+
* not support with a hard 400 rather than ignoring it, some name the output
|
|
8
|
+
* cap differently, and reasoning models take an effort knob that non-reasoning
|
|
9
|
+
* models refuse. Left unnormalised, a fallback would fail on the leg it fell
|
|
10
|
+
* back to — turning the mechanism that exists to survive an outage into a
|
|
11
|
+
* second way to fail.
|
|
12
|
+
*
|
|
13
|
+
* The rule throughout is that an unsupported parameter is OMITTED, never sent
|
|
14
|
+
* with a default. Sending a default asserts a value the caller did not choose;
|
|
15
|
+
* omitting it lets the provider apply its own, which is what "unsupported"
|
|
16
|
+
* actually means.
|
|
17
|
+
*
|
|
18
|
+
* @module llm/param-matrix
|
|
19
|
+
*/
|
|
20
|
+
import type { AliasCallOptions, LlmResponseFormat, ResolvedRoute } from "./types";
|
|
21
|
+
/**
|
|
22
|
+
* Normalise a caller's options into the exact parameter set one leg accepts.
|
|
23
|
+
*
|
|
24
|
+
* @param options The caller's options.
|
|
25
|
+
* @param route The leg the request is being prepared for.
|
|
26
|
+
* @param responseFormat The response shape the caller asked for.
|
|
27
|
+
* @returns Parameters ready to send verbatim.
|
|
28
|
+
*/
|
|
29
|
+
export declare function normaliseParams(options: AliasCallOptions, route: ResolvedRoute, responseFormat: LlmResponseFormat): Record<string, unknown>;
|
|
30
|
+
/**
|
|
31
|
+
* Thrown when a leg cannot honour a capability the caller requires.
|
|
32
|
+
*
|
|
33
|
+
* A distinct type rather than a generic error, because the chain treats it
|
|
34
|
+
* differently from a provider outage: the leg is not broken, it is simply the
|
|
35
|
+
* wrong leg for this request, and no retry against it will help.
|
|
36
|
+
*/
|
|
37
|
+
export declare class UnsupportedCapabilityError extends Error {
|
|
38
|
+
/** The leg that cannot serve the request. */
|
|
39
|
+
readonly routeKey: string;
|
|
40
|
+
/** The capability it lacks. */
|
|
41
|
+
readonly capability: string;
|
|
42
|
+
/**
|
|
43
|
+
* @param route The leg.
|
|
44
|
+
* @param capability The missing capability.
|
|
45
|
+
*/
|
|
46
|
+
constructor(route: ResolvedRoute, capability: string);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Whether a leg can serve a request needing the given capabilities at all.
|
|
50
|
+
*
|
|
51
|
+
* Used to skip a leg before spending a network round trip on it. Checking
|
|
52
|
+
* up front rather than reacting to the provider's rejection keeps a
|
|
53
|
+
* capability mismatch from consuming the caller's latency budget.
|
|
54
|
+
*
|
|
55
|
+
* @param route The leg.
|
|
56
|
+
* @param needs Capabilities the request requires.
|
|
57
|
+
* @returns Whether the leg is a candidate.
|
|
58
|
+
*/
|
|
59
|
+
export declare function routeSupports(route: ResolvedRoute, needs: {
|
|
60
|
+
readonly tools?: boolean;
|
|
61
|
+
readonly jsonSchema?: boolean;
|
|
62
|
+
readonly vision?: boolean;
|
|
63
|
+
readonly cacheControl?: boolean;
|
|
64
|
+
}): boolean;
|
|
65
|
+
//# sourceMappingURL=param-matrix.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"param-matrix.d.ts","sourceRoot":"","sources":["../../../src/llm/param-matrix.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACd,MAAM,SAAS,CAAC;AAkBjB;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,aAAa,EACpB,cAAc,EAAE,iBAAiB,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAmDzB;AAsCD;;;;;;GAMG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,6CAA6C;IAC7C,SAAgB,QAAQ,EAAE,MAAM,CAAC;IAEjC,+BAA+B;IAC/B,SAAgB,UAAU,EAAE,MAAM,CAAC;IAEnC;;;OAGG;gBACgB,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM;CAS5D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,aAAa,EACpB,KAAK,EAAE;IACL,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC,GACA,OAAO,CAcT"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side rate and concurrency guards, per provider (W4-04).
|
|
3
|
+
*
|
|
4
|
+
* A provider's rate limit is enforced at the provider whether or not the client
|
|
5
|
+
* respects it. The reason to respect it here is what a 429 means once it
|
|
6
|
+
* arrives: to the fallback chain it is indistinguishable from provider
|
|
7
|
+
* ill-health, so a client that over-drives a healthy provider will open that
|
|
8
|
+
* provider's circuit breaker, fail over to a more expensive leg, and keep doing
|
|
9
|
+
* so — converting a self-inflicted pacing problem into a permanent routing
|
|
10
|
+
* change nobody chose. Pacing at the client is what keeps the breaker measuring
|
|
11
|
+
* the provider rather than measuring us.
|
|
12
|
+
*
|
|
13
|
+
* Two distinct bounds are applied because they fail differently. The rate bound
|
|
14
|
+
* (requests per minute) protects the provider's published ceiling. The
|
|
15
|
+
* concurrency bound protects the caller: a hundred simultaneous in-flight
|
|
16
|
+
* requests will each wait behind the other ninety-nine at the provider, so
|
|
17
|
+
* every one of them blows its latency budget and the fan-out produces a hundred
|
|
18
|
+
* timeouts instead of a queue.
|
|
19
|
+
*
|
|
20
|
+
* Limits live in `provider-limits.json`, not here. A rate limit discovered
|
|
21
|
+
* during an incident should be correctable by config, not by a release.
|
|
22
|
+
*
|
|
23
|
+
* @module llm/rate-guard
|
|
24
|
+
*/
|
|
25
|
+
/** Limits for one provider. */
|
|
26
|
+
export interface ProviderLimits {
|
|
27
|
+
/** Whether these numbers were transcribed from a provider doc or chosen conservatively. */
|
|
28
|
+
readonly basis: "published" | "conservative-default";
|
|
29
|
+
readonly requests_per_minute: number;
|
|
30
|
+
readonly max_concurrent: number;
|
|
31
|
+
readonly acquire_timeout_ms: number;
|
|
32
|
+
/** Where a published limit was read from. Null while the basis is a conservative default. */
|
|
33
|
+
readonly source?: string | null;
|
|
34
|
+
readonly note?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Resolve the limits that apply to a provider.
|
|
38
|
+
*
|
|
39
|
+
* An unregistered provider falls back to the conservative defaults rather than
|
|
40
|
+
* to no limit at all. Treating "unknown" as "unlimited" would make every newly
|
|
41
|
+
* onboarded provider the one most likely to be over-driven, which is exactly
|
|
42
|
+
* backwards: a new provider is the one whose real ceiling is least understood.
|
|
43
|
+
*
|
|
44
|
+
* @param provider The provider key.
|
|
45
|
+
* @returns Its limits.
|
|
46
|
+
*/
|
|
47
|
+
export declare function limitsFor(provider: string): ProviderLimits;
|
|
48
|
+
/** Every provider with a recorded limit, plus whether it is published or a default. */
|
|
49
|
+
export declare function limitsInventory(): {
|
|
50
|
+
provider: string;
|
|
51
|
+
limits: ProviderLimits;
|
|
52
|
+
}[];
|
|
53
|
+
/**
|
|
54
|
+
* Thrown when a caller could not acquire a slot within its budget.
|
|
55
|
+
*
|
|
56
|
+
* Distinguished from a provider failure so the chain does not count it against
|
|
57
|
+
* route health: the provider was never asked, so nothing was learned about it.
|
|
58
|
+
*/
|
|
59
|
+
export declare class RateGuardTimeoutError extends Error {
|
|
60
|
+
/** The provider whose guard could not admit the call. */
|
|
61
|
+
readonly provider: string;
|
|
62
|
+
/** Which of the two bounds the caller waited on. */
|
|
63
|
+
readonly bound: "rate" | "concurrency";
|
|
64
|
+
/**
|
|
65
|
+
* @param provider The provider.
|
|
66
|
+
* @param bound Which bound was binding.
|
|
67
|
+
* @param waitedMs How long the caller waited.
|
|
68
|
+
*/
|
|
69
|
+
constructor(provider: string, bound: "rate" | "concurrency", waitedMs: number);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Run a call under a provider's rate and concurrency guards.
|
|
73
|
+
*
|
|
74
|
+
* The concurrency permit is taken AFTER the rate token. Taking it first would
|
|
75
|
+
* let callers hold scarce permits while idling in the rate queue, which
|
|
76
|
+
* throttles the provider twice over and turns a pacing bound into a deadlock
|
|
77
|
+
* shaped like slowness.
|
|
78
|
+
*
|
|
79
|
+
* `maxWaitMs` bounds how long a caller may queue. It exists because the queue
|
|
80
|
+
* spends the SAME budget the call itself does: a caller that waits out its whole
|
|
81
|
+
* deadline in a rate queue has failed just as completely as one that waited on
|
|
82
|
+
* the provider, and worse, it never reached the fallback chain that could have
|
|
83
|
+
* answered it. Passing the leg's own timeout keeps one clock governing the
|
|
84
|
+
* whole attempt.
|
|
85
|
+
*
|
|
86
|
+
* @param provider The provider key.
|
|
87
|
+
* @param call The work to run once admitted.
|
|
88
|
+
* @param maxWaitMs Ceiling on queue time; the configured guard timeout applies when lower.
|
|
89
|
+
* @returns The call's result.
|
|
90
|
+
* @throws {RateGuardTimeoutError} When neither bound admitted the call in time.
|
|
91
|
+
*/
|
|
92
|
+
export declare function withProviderGuards<T>(provider: string, call: () => Promise<T>, maxWaitMs?: number): Promise<T>;
|
|
93
|
+
/** Observable guard state, for dashboards and tests. */
|
|
94
|
+
export interface GuardSnapshot {
|
|
95
|
+
readonly provider: string;
|
|
96
|
+
readonly basis: ProviderLimits["basis"];
|
|
97
|
+
readonly requestsPerMinute: number;
|
|
98
|
+
readonly maxConcurrent: number;
|
|
99
|
+
readonly inFlight: number;
|
|
100
|
+
readonly rateQueueLength: number;
|
|
101
|
+
readonly concurrencyQueueLength: number;
|
|
102
|
+
readonly availableTokens: number;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Inspect the guards currently in use.
|
|
106
|
+
*
|
|
107
|
+
* @returns A snapshot per provider that has been used, sorted by provider.
|
|
108
|
+
*/
|
|
109
|
+
export declare function guardSnapshots(): GuardSnapshot[];
|
|
110
|
+
/**
|
|
111
|
+
* Discard all guard state.
|
|
112
|
+
*
|
|
113
|
+
* Exists so a test can start from a known position; a shared process-wide
|
|
114
|
+
* limiter is otherwise carried between tests and makes their order matter.
|
|
115
|
+
*
|
|
116
|
+
* @returns void
|
|
117
|
+
*/
|
|
118
|
+
export declare function resetProviderGuards(): void;
|
|
119
|
+
//# sourceMappingURL=rate-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-guard.d.ts","sourceRoot":"","sources":["../../../src/llm/rate-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAYH,+BAA+B;AAC/B,MAAM,WAAW,cAAc;IAC7B,2FAA2F;IAC3F,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,sBAAsB,CAAC;IACrD,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,6FAA6F;IAC7F,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAYD;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAE1D;AAED,uFAAuF;AACvF,wBAAgB,eAAe,IAAI;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,EAAE,CAIhF;AAED;;;;;GAKG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,yDAAyD;IACzD,SAAgB,QAAQ,EAAE,MAAM,CAAC;IAEjC,oDAAoD;IACpD,SAAgB,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC;IAE9C;;;;OAIG;gBACgB,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,EAAE,QAAQ,EAAE,MAAM;CASrF;AAgID;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,CAAC,CAAC,CAsBZ;AAED,wDAAwD;AACxD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;IACxC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,aAAa,EAAE,CAiBhD;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAM1C"}
|