@metrxbot/sdk 0.2.0 → 0.2.1
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/README.md +42 -1
- package/dist/client.d.ts +8 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +7 -0
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/otel.d.ts +37 -0
- package/dist/otel.d.ts.map +1 -1
- package/dist/otel.js +56 -0
- package/dist/otel.js.map +1 -1
- package/dist/routing-gate.d.ts +49 -0
- package/dist/routing-gate.d.ts.map +1 -0
- package/dist/routing-gate.js +118 -0
- package/dist/routing-gate.js.map +1 -0
- package/dist/routing-policy-cache.d.ts +77 -0
- package/dist/routing-policy-cache.d.ts.map +1 -0
- package/dist/routing-policy-cache.js +96 -0
- package/dist/routing-policy-cache.js.map +1 -0
- package/dist/routing.d.ts +156 -0
- package/dist/routing.d.ts.map +1 -0
- package/dist/routing.js +631 -0
- package/dist/routing.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy cache for the SDK cascade router (spec §5.6).
|
|
3
|
+
*
|
|
4
|
+
* - One fetch caches the whole org's policy set (GET /api/v1/routing/policies).
|
|
5
|
+
* - TTL 5 min (matches the server's max-age) with ETag revalidation.
|
|
6
|
+
* - Stale tolerance ≤ 60 min: a kill-switch flip must propagate; past the
|
|
7
|
+
* bound the cache reports "unknown" and every caller falls back to
|
|
8
|
+
* pass-through (seam F2).
|
|
9
|
+
* - Lazy + non-blocking: the first call triggers a background load and
|
|
10
|
+
* returns "unknown" — cold start is pass-through, never a blocked request
|
|
11
|
+
* (seam F1).
|
|
12
|
+
*
|
|
13
|
+
* NEVER throws. All fetch failures degrade to "unknown" → pass-through.
|
|
14
|
+
*/
|
|
15
|
+
const DEFAULT_TTL_MS = 5 * 60 * 1000;
|
|
16
|
+
const DEFAULT_STALE_MAX_MS = 60 * 60 * 1000;
|
|
17
|
+
export class PolicyCache {
|
|
18
|
+
byKey = new Map();
|
|
19
|
+
etag = null;
|
|
20
|
+
loaded = false;
|
|
21
|
+
loadedAt = 0;
|
|
22
|
+
loading = null;
|
|
23
|
+
fetcher;
|
|
24
|
+
ttlMs;
|
|
25
|
+
staleMaxMs;
|
|
26
|
+
now;
|
|
27
|
+
constructor(opts) {
|
|
28
|
+
this.fetcher = opts.fetcher;
|
|
29
|
+
this.ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;
|
|
30
|
+
this.staleMaxMs = opts.staleMaxMs ?? DEFAULT_STALE_MAX_MS;
|
|
31
|
+
this.now = opts.now ?? Date.now;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Non-blocking lookup.
|
|
35
|
+
* - `undefined` → policy state UNKNOWN (never loaded, or stale past the
|
|
36
|
+
* bound) — caller must pass through.
|
|
37
|
+
* - `null` → the org's policies ARE loaded and this agent has no row —
|
|
38
|
+
* pass-through by design (no row = not allow-listed).
|
|
39
|
+
* - a policy row otherwise.
|
|
40
|
+
*/
|
|
41
|
+
get(agentKey) {
|
|
42
|
+
if (!this.loaded) {
|
|
43
|
+
// Cold: kick off the first load, serve pass-through now (F1).
|
|
44
|
+
this.refresh();
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
const age = this.now() - this.loadedAt;
|
|
48
|
+
if (age > this.staleMaxMs) {
|
|
49
|
+
// Too stale to trust — a kill-switch flip may not have propagated (F2).
|
|
50
|
+
this.refresh();
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
if (age > this.ttlMs) {
|
|
54
|
+
// Stale-but-tolerable: serve, refresh in the background.
|
|
55
|
+
this.refresh();
|
|
56
|
+
}
|
|
57
|
+
return this.byKey.get(normalizeAgentKey(agentKey)) ?? null;
|
|
58
|
+
}
|
|
59
|
+
/** Await any in-flight load — for tests and graceful shutdown. */
|
|
60
|
+
async settle() {
|
|
61
|
+
if (this.loading)
|
|
62
|
+
await this.loading.catch(() => undefined);
|
|
63
|
+
}
|
|
64
|
+
refresh() {
|
|
65
|
+
if (this.loading)
|
|
66
|
+
return; // single-flight
|
|
67
|
+
this.loading = this.fetcher(this.etag)
|
|
68
|
+
.then((result) => {
|
|
69
|
+
if (result.notModified) {
|
|
70
|
+
this.loadedAt = this.now();
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const next = new Map();
|
|
74
|
+
for (const p of result.policies) {
|
|
75
|
+
if (p && typeof p.agent_key === 'string') {
|
|
76
|
+
next.set(normalizeAgentKey(p.agent_key), p);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
this.byKey = next;
|
|
80
|
+
this.etag = result.etag ?? null;
|
|
81
|
+
this.loaded = true;
|
|
82
|
+
this.loadedAt = this.now();
|
|
83
|
+
})
|
|
84
|
+
.catch(() => {
|
|
85
|
+
// F1: fetch failure never surfaces; state stays as-is (or unknown).
|
|
86
|
+
})
|
|
87
|
+
.finally(() => {
|
|
88
|
+
this.loading = null;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/** Normalization rule shared with policy writes (spec §5.1 M8). */
|
|
93
|
+
export function normalizeAgentKey(key) {
|
|
94
|
+
return key.trim().toLowerCase();
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=routing-policy-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routing-policy-cache.js","sourceRoot":"","sources":["../src/routing-policy-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK cascade routing module — `runWithPolicy()` (spec
|
|
3
|
+
* docs/roi-engine-cascade-sdk-phase1-spec.md §5, Phase 1 S2).
|
|
4
|
+
*
|
|
5
|
+
* Bring-your-own-caller: the customer supplies the function that calls their
|
|
6
|
+
* provider with THEIR keys; this module supplies policy consultation, the
|
|
7
|
+
* confidence gate, escalation, holdout randomization, and evidence emission.
|
|
8
|
+
*
|
|
9
|
+
* THE INVARIANT (throw-parity, §5.7): no code path in runWithPolicy throws an
|
|
10
|
+
* error that the customer's own `callModel(prodModel)` would not have thrown.
|
|
11
|
+
* Policy fetch, gate, candidate calls, and every emit fail OPEN; only the
|
|
12
|
+
* production-model call's own errors propagate.
|
|
13
|
+
*
|
|
14
|
+
* Streaming is OUT OF SCOPE for v1 (§5.1 H7): this contract handles complete
|
|
15
|
+
* responses only — keep streaming call sites on their original path.
|
|
16
|
+
*/
|
|
17
|
+
import type { MetrxbotClient } from './client';
|
|
18
|
+
/** Bump with package.json (atomic-version rule). Server can force pass-through
|
|
19
|
+
* for known-bad versions via routing_policies.min_sdk_version (F10). */
|
|
20
|
+
export declare const SDK_VERSION = "0.2.1";
|
|
21
|
+
export interface ModelCallResult {
|
|
22
|
+
output: string;
|
|
23
|
+
costMicrocents?: number;
|
|
24
|
+
/** Server-side cost fallback via model_registry pricing when cost is absent. */
|
|
25
|
+
usage?: {
|
|
26
|
+
inputTokens: number;
|
|
27
|
+
outputTokens: number;
|
|
28
|
+
};
|
|
29
|
+
raw?: unknown;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Call-context handed to the customer's `ModelCaller`/`checkerCaller` on every
|
|
33
|
+
* provider call (v0.2.1, additive). Lets caller-side instrumentation (a) stamp
|
|
34
|
+
* `requestId`/`experimentId`/`arm` on the provider call so cascade cost SUMs
|
|
35
|
+
* join across `llm_events ↔ optimization_decisions ↔ quality`, and (b) detect
|
|
36
|
+
* the background shadow candidate (`phase === 'shadow_candidate'`) and suppress
|
|
37
|
+
* it from a cost dashboard.
|
|
38
|
+
*
|
|
39
|
+
* `phase` marks which leg of routing is making the call:
|
|
40
|
+
* - `primary` served production call (pass-through, shadow served,
|
|
41
|
+
* cascade control arm)
|
|
42
|
+
* - `candidate` cascade treatment candidate (the cheaper model)
|
|
43
|
+
* - `escalation` cascade treatment fell back to the production model
|
|
44
|
+
* - `shadow_candidate` background dual-call in shadow_sample (never served)
|
|
45
|
+
* - `checker` any `checkerCaller` invocation (gate + post-response judging)
|
|
46
|
+
*/
|
|
47
|
+
export interface ModelCallContext {
|
|
48
|
+
requestId: string;
|
|
49
|
+
experimentId?: string;
|
|
50
|
+
arm?: 'control' | 'treatment';
|
|
51
|
+
phase: 'primary' | 'candidate' | 'escalation' | 'shadow_candidate' | 'checker';
|
|
52
|
+
}
|
|
53
|
+
export interface ModelCaller {
|
|
54
|
+
/**
|
|
55
|
+
* `model === undefined` ⇒ "call your own default" — the day-0 pass-through
|
|
56
|
+
* contract (§5.1 M2). The input is passed through verbatim and is never
|
|
57
|
+
* serialized to Metrx.
|
|
58
|
+
*
|
|
59
|
+
* `ctx` (v0.2.1) is an OPTIONAL third argument — existing two-arg callers
|
|
60
|
+
* keep working unchanged. It is purely informational: it never changes what
|
|
61
|
+
* the router serves and passing it introduces no new throw path (§5.7).
|
|
62
|
+
*/
|
|
63
|
+
(model: string | undefined, input: unknown, ctx?: ModelCallContext): Promise<ModelCallResult>;
|
|
64
|
+
}
|
|
65
|
+
export interface ClientJudge {
|
|
66
|
+
(args: {
|
|
67
|
+
input: unknown;
|
|
68
|
+
output: string;
|
|
69
|
+
model: string;
|
|
70
|
+
}): Promise<{
|
|
71
|
+
score: number;
|
|
72
|
+
judgeModel: string;
|
|
73
|
+
}>;
|
|
74
|
+
}
|
|
75
|
+
export interface RunWithPolicyOptions {
|
|
76
|
+
agentKey: string;
|
|
77
|
+
/** The customer's own provider call — their client, their keys. */
|
|
78
|
+
callModel: ModelCaller;
|
|
79
|
+
/**
|
|
80
|
+
* Caller for the cross-family checker model. REQUIRED for shadow/cascade
|
|
81
|
+
* when the checker family is one the primary caller can't reach (e.g. an
|
|
82
|
+
* all-Anthropic customer with a non-Anthropic checker — §5.3 C3).
|
|
83
|
+
*/
|
|
84
|
+
checkerCaller?: ModelCaller;
|
|
85
|
+
input: unknown;
|
|
86
|
+
/** Optional custom scorer; default = the G4 checker via checkerCaller. */
|
|
87
|
+
judge?: ClientJudge;
|
|
88
|
+
requestId?: string;
|
|
89
|
+
}
|
|
90
|
+
export interface RunWithPolicyResult {
|
|
91
|
+
output: string;
|
|
92
|
+
/** undefined on no-policy pass-through (the customer's own default ran). */
|
|
93
|
+
servedModel: string | undefined;
|
|
94
|
+
escalated: boolean;
|
|
95
|
+
arm?: 'control' | 'treatment';
|
|
96
|
+
/** Cascade experiment id — attach to telemetry events (with the arm) so the
|
|
97
|
+
* contamination guard can exclude routed calls from baselines. */
|
|
98
|
+
experimentId?: string;
|
|
99
|
+
requestId: string;
|
|
100
|
+
/** What the policy said: pass_through | shadow_sample | cascade | disabled. */
|
|
101
|
+
mode: string;
|
|
102
|
+
}
|
|
103
|
+
export interface RouterConfig {
|
|
104
|
+
apiKey: string;
|
|
105
|
+
apiUrl: string;
|
|
106
|
+
/** Injectable for tests. */
|
|
107
|
+
fetchImpl?: typeof fetch;
|
|
108
|
+
now?: () => number;
|
|
109
|
+
random?: () => number;
|
|
110
|
+
/** Hard local kill switch (F10); also honors METRX_ROUTING_DISABLED=true. */
|
|
111
|
+
disabled?: boolean;
|
|
112
|
+
policyTtlMs?: number;
|
|
113
|
+
policyStaleMaxMs?: number;
|
|
114
|
+
}
|
|
115
|
+
export declare class MetrxRouter {
|
|
116
|
+
private readonly cfg;
|
|
117
|
+
private readonly cache;
|
|
118
|
+
private readonly now;
|
|
119
|
+
private readonly random;
|
|
120
|
+
private readonly fetchImpl;
|
|
121
|
+
private readonly breakers;
|
|
122
|
+
private readonly background;
|
|
123
|
+
constructor(cfg: RouterConfig);
|
|
124
|
+
/** Await all in-flight background work (emits, shadow calls, judging).
|
|
125
|
+
* For tests and graceful shutdown — never required for correctness. */
|
|
126
|
+
flush(): Promise<void>;
|
|
127
|
+
run(opts: RunWithPolicyOptions): Promise<RunWithPolicyResult>;
|
|
128
|
+
private passThrough;
|
|
129
|
+
private runShadowSample;
|
|
130
|
+
private runCascade;
|
|
131
|
+
private judgeOutput;
|
|
132
|
+
private emitDecision;
|
|
133
|
+
private emitPair;
|
|
134
|
+
private emitQuality;
|
|
135
|
+
private fireAndForget;
|
|
136
|
+
/** F8/F9: background work never throws into the request path. */
|
|
137
|
+
private spawnBackground;
|
|
138
|
+
private breakerFor;
|
|
139
|
+
private breakerOpen;
|
|
140
|
+
private recordCandidateError;
|
|
141
|
+
private recordEscalation;
|
|
142
|
+
private makePolicyFetcher;
|
|
143
|
+
}
|
|
144
|
+
export declare function routerFor(client: MetrxbotClient, overrides?: Partial<RouterConfig>): MetrxRouter;
|
|
145
|
+
/**
|
|
146
|
+
* Run one request under the agent's routing policy. Day 0 (no policy rows):
|
|
147
|
+
* behaves exactly like `opts.callModel(undefined, opts.input)`.
|
|
148
|
+
*/
|
|
149
|
+
export declare function runWithPolicy(client: MetrxbotClient, opts: RunWithPolicyOptions): Promise<RunWithPolicyResult>;
|
|
150
|
+
/**
|
|
151
|
+
* Loose semver-ish comparison. Returns true when a < b, false when a >= b,
|
|
152
|
+
* and `undefined` when either side is unparseable — the caller treats
|
|
153
|
+
* "unknown" as pass-through (fail toward doing nothing).
|
|
154
|
+
*/
|
|
155
|
+
export declare function semverLt(a: string, b: string): boolean | undefined;
|
|
156
|
+
//# sourceMappingURL=routing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../src/routing.ts"],"names":[],"mappings":"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"}
|