margin-meter 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +292 -2
- package/dist/batching.d.ts +94 -0
- package/dist/batching.d.ts.map +1 -0
- package/dist/batching.js +181 -0
- package/dist/batching.js.map +1 -0
- package/dist/braintrust.d.ts +153 -0
- package/dist/braintrust.d.ts.map +1 -0
- package/dist/braintrust.js +424 -0
- package/dist/braintrust.js.map +1 -0
- package/dist/capture.d.ts +28 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/capture.js +177 -0
- package/dist/capture.js.map +1 -0
- package/dist/index.d.ts +334 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +697 -23
- package/dist/index.js.map +1 -1
- package/dist/instrument.d.ts +8 -7
- package/dist/instrument.d.ts.map +1 -1
- package/dist/instrument.js +8 -7
- package/dist/instrument.js.map +1 -1
- package/dist/langsmith.d.ts +150 -0
- package/dist/langsmith.d.ts.map +1 -0
- package/dist/langsmith.js +415 -0
- package/dist/langsmith.js.map +1 -0
- package/dist/promptfoo.d.ts +161 -0
- package/dist/promptfoo.d.ts.map +1 -0
- package/dist/promptfoo.js +446 -0
- package/dist/promptfoo.js.map +1 -0
- package/dist/providers.d.ts +36 -0
- package/dist/providers.d.ts.map +1 -1
- package/dist/providers.js +229 -3
- package/dist/providers.js.map +1 -1
- package/dist/vitest.d.ts +232 -0
- package/dist/vitest.d.ts.map +1 -0
- package/dist/vitest.js +502 -0
- package/dist/vitest.js.map +1 -0
- package/package.json +24 -6
package/dist/capture.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fields the SDK reads off the call itself, so a customer writes no code for them (MAR-2013).
|
|
3
|
+
* The TypeScript twin of `margin_meter/capture.py`: hashes, counts and short slugs only. Prompt
|
|
4
|
+
* and output text never leave the process.
|
|
5
|
+
*
|
|
6
|
+
* - `promptHash` sha256 of the canonical JSON of the request's prompt-bearing fields.
|
|
7
|
+
* - `prefixHash/prefixChars` the stable leading part: the system prompt alone, or everything up to
|
|
8
|
+
* and including the last block carrying `cache_control` when the request
|
|
9
|
+
* marks a cache breakpoint (tools, then system, then messages).
|
|
10
|
+
* - `servingHost` OpenRouter's response `provider`, else the vendor when the client is on
|
|
11
|
+
* the vendor's own API (substrate `direct`), else nothing.
|
|
12
|
+
* - `retryKind` `truncation` when the same request is re-sent after a call that stopped
|
|
13
|
+
* on a length limit, `transport` after a call that threw.
|
|
14
|
+
* - `verdict` the one thing a customer may add: the agent's own label for its output.
|
|
15
|
+
*/
|
|
16
|
+
import { createHash } from "node:crypto";
|
|
17
|
+
const PROMPT_FIELDS = ["messages", "input", "contents", "prompt", "system", "tools"];
|
|
18
|
+
const VERDICT_RE = /^[a-z0-9][a-z0-9_.:,-]{0,63}$/;
|
|
19
|
+
const LENGTH_STOPS = new Set(["length", "max_tokens", "max_output_tokens"]);
|
|
20
|
+
const RETRY_WINDOW_MS = 600_000;
|
|
21
|
+
const DIRECT_VENDORS = new Set(["openai", "anthropic", "google"]);
|
|
22
|
+
/** JSON with every object's keys sorted, so equal requests serialise equally. */
|
|
23
|
+
export function canonicalJson(v) {
|
|
24
|
+
return JSON.stringify(v, (_k, val) => {
|
|
25
|
+
if (val && typeof val === "object" && !Array.isArray(val)) {
|
|
26
|
+
return Object.fromEntries(Object.entries(val).sort(([a], [b]) => (a < b ? -1 : 1)));
|
|
27
|
+
}
|
|
28
|
+
return val;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
const sha = (s) => createHash("sha256").update(s).digest("hex");
|
|
32
|
+
function textChars(o) {
|
|
33
|
+
if (typeof o === "string")
|
|
34
|
+
return o.length;
|
|
35
|
+
if (Array.isArray(o))
|
|
36
|
+
return o.reduce((n, x) => n + textChars(x), 0);
|
|
37
|
+
if (o && typeof o === "object") {
|
|
38
|
+
const r = o;
|
|
39
|
+
if (typeof r.text === "string")
|
|
40
|
+
return r.text.length;
|
|
41
|
+
return r.content !== undefined ? textChars(r.content) : 0;
|
|
42
|
+
}
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
function hasBreakpoint(b) {
|
|
46
|
+
if (!b || typeof b !== "object" || Array.isArray(b))
|
|
47
|
+
return false;
|
|
48
|
+
const r = b;
|
|
49
|
+
if ("cache_control" in r)
|
|
50
|
+
return true;
|
|
51
|
+
return Array.isArray(r.content) && r.content.some(hasBreakpoint);
|
|
52
|
+
}
|
|
53
|
+
function units(req) {
|
|
54
|
+
const out = [];
|
|
55
|
+
for (const t of (Array.isArray(req.tools) ? req.tools : []))
|
|
56
|
+
out.push(["tools", t]);
|
|
57
|
+
if (typeof req.system === "string")
|
|
58
|
+
out.push(["system", req.system]);
|
|
59
|
+
else if (Array.isArray(req.system))
|
|
60
|
+
for (const b of req.system)
|
|
61
|
+
out.push(["system", b]);
|
|
62
|
+
const msgs = Array.isArray(req.messages) ? req.messages : Array.isArray(req.input) ? req.input : [];
|
|
63
|
+
for (const m of msgs) {
|
|
64
|
+
const system = m?.role === "system" || m?.role === "developer";
|
|
65
|
+
if (!system && Array.isArray(m?.content))
|
|
66
|
+
for (const b of m.content)
|
|
67
|
+
out.push(["message", b]);
|
|
68
|
+
else
|
|
69
|
+
out.push([system ? "system" : "message", m]);
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
/** `{prefixHash, prefixChars}`, or `{}` when there is no system prompt and no cache breakpoint. */
|
|
74
|
+
export function prefixFields(req) {
|
|
75
|
+
try {
|
|
76
|
+
if (!req || typeof req !== "object")
|
|
77
|
+
return {};
|
|
78
|
+
const us = units(req);
|
|
79
|
+
let last = -1;
|
|
80
|
+
us.forEach(([, b], i) => {
|
|
81
|
+
if (hasBreakpoint(b))
|
|
82
|
+
last = i;
|
|
83
|
+
});
|
|
84
|
+
const prefix = last >= 0 ? us.slice(0, last + 1) : us.filter(([k]) => k === "system");
|
|
85
|
+
if (prefix.length === 0)
|
|
86
|
+
return {};
|
|
87
|
+
return {
|
|
88
|
+
prefixHash: sha(canonicalJson(prefix.map(([, b]) => b))),
|
|
89
|
+
prefixChars: prefix.reduce((n, [, b]) => n + textChars(b), 0),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return {}; // capture never breaks the host call
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** Every request-side field, read from the first argument of a provider call. */
|
|
97
|
+
export function requestFields(req) {
|
|
98
|
+
try {
|
|
99
|
+
if (!req || typeof req !== "object")
|
|
100
|
+
return {};
|
|
101
|
+
let r = req;
|
|
102
|
+
// An AWS SDK v3 command (Bedrock) carries its request under `.input`.
|
|
103
|
+
const cmd = r.constructor?.name ?? "";
|
|
104
|
+
if (cmd.endsWith("Command") && r.input && typeof r.input === "object")
|
|
105
|
+
r = r.input;
|
|
106
|
+
const part = {};
|
|
107
|
+
for (const k of PROMPT_FIELDS)
|
|
108
|
+
if (r[k] !== undefined && r[k] !== null)
|
|
109
|
+
part[k] = r[k];
|
|
110
|
+
const out = { ...prefixFields(r) };
|
|
111
|
+
if (Object.keys(part).length > 0)
|
|
112
|
+
out.promptHash = sha(canonicalJson(part));
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return {};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** A host name as a short lowercase slug, or undefined when nothing usable is left. */
|
|
120
|
+
export function slug(v) {
|
|
121
|
+
if (typeof v !== "string")
|
|
122
|
+
return undefined;
|
|
123
|
+
const s = v
|
|
124
|
+
.trim()
|
|
125
|
+
.toLowerCase()
|
|
126
|
+
.replace(/[^a-z0-9_.:/-]+/g, "-")
|
|
127
|
+
.replace(/^-+|-+$/g, "")
|
|
128
|
+
.slice(0, 48);
|
|
129
|
+
return /^[a-z0-9]/.test(s) ? s : undefined;
|
|
130
|
+
}
|
|
131
|
+
/** OpenRouter's reported upstream if the response named one, else the vendor on a direct client. */
|
|
132
|
+
export function servingHost(responseProvider, vendor, substrate) {
|
|
133
|
+
const named = slug(responseProvider);
|
|
134
|
+
if (named)
|
|
135
|
+
return named;
|
|
136
|
+
return substrate === "direct" && vendor && DIRECT_VENDORS.has(vendor) ? vendor : undefined;
|
|
137
|
+
}
|
|
138
|
+
/** Same rule ingest applies to `output_class`: a short lowercase label, never text. Throws on text. */
|
|
139
|
+
export function checkVerdict(v) {
|
|
140
|
+
if (v === undefined || v === null)
|
|
141
|
+
return undefined;
|
|
142
|
+
if (typeof v !== "string")
|
|
143
|
+
throw new Error("verdict must be a string label");
|
|
144
|
+
const s = v.trim().toLowerCase();
|
|
145
|
+
if (s === "")
|
|
146
|
+
return undefined;
|
|
147
|
+
if (!VERDICT_RE.test(s)) {
|
|
148
|
+
throw new Error("verdict must be a short lowercase label (a-z 0-9 _ . : , -), never text");
|
|
149
|
+
}
|
|
150
|
+
return s;
|
|
151
|
+
}
|
|
152
|
+
/** Remembers the last failed call per request, to tell a re-send from a fresh call. */
|
|
153
|
+
export class RetryTracker {
|
|
154
|
+
last = new Map();
|
|
155
|
+
observe(workflowId, operation, promptHash, status, finishReason, at = Date.now()) {
|
|
156
|
+
if (!promptHash)
|
|
157
|
+
return undefined;
|
|
158
|
+
const key = JSON.stringify([workflowId, operation ?? null, promptHash]);
|
|
159
|
+
const prev = this.last.get(key);
|
|
160
|
+
if (status === "error")
|
|
161
|
+
this.last.set(key, { at, state: "error" });
|
|
162
|
+
else if (LENGTH_STOPS.has((finishReason ?? "").toLowerCase()))
|
|
163
|
+
this.last.set(key, { at, state: "length" });
|
|
164
|
+
else
|
|
165
|
+
this.last.delete(key);
|
|
166
|
+
if (this.last.size > 4096)
|
|
167
|
+
this.last.clear();
|
|
168
|
+
if (!prev || at - prev.at > RETRY_WINDOW_MS)
|
|
169
|
+
return undefined;
|
|
170
|
+
return prev.state === "error" ? "transport" : "truncation";
|
|
171
|
+
}
|
|
172
|
+
reset() {
|
|
173
|
+
this.last.clear();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
export const RETRIES = new RetryTracker();
|
|
177
|
+
//# sourceMappingURL=capture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.js","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -25,13 +25,118 @@ import { type ProviderName } from "./providers.ts";
|
|
|
25
25
|
import { type Substrate } from "./substrate.ts";
|
|
26
26
|
export * from "./providers.ts";
|
|
27
27
|
export * from "./instrument.ts";
|
|
28
|
+
export * from "./batching.ts";
|
|
28
29
|
export * as substrate from "./substrate.ts";
|
|
29
30
|
export type { Substrate } from "./substrate.ts";
|
|
31
|
+
export * as promptfoo from "./promptfoo.ts";
|
|
32
|
+
export * as braintrust from "./braintrust.ts";
|
|
33
|
+
export * as langsmith from "./langsmith.ts";
|
|
34
|
+
export * as vitest from "./vitest.ts";
|
|
30
35
|
export declare const CALLS_PATH = "/api/ingest/calls";
|
|
31
36
|
export declare const OUTCOMES_PATH = "/api/ingest/outcomes";
|
|
32
37
|
export declare const KEY_HEADER = "X-Margin-Key";
|
|
33
|
-
export declare const DEFAULT_INGEST_URL = "http://127.0.0.1:8000";
|
|
34
38
|
export declare const DEFAULT_TIMEOUT_MS = 10000;
|
|
39
|
+
/** One batched request's byte ceiling, and the retry policy behind it. Full
|
|
40
|
+
* reasoning in `docs/reference/SDK_BATCHING.md`; the short version:
|
|
41
|
+
*
|
|
42
|
+
* - 1 MB is ~7x headroom over a worst-case 1500-byte row at the default 100
|
|
43
|
+
* records, and far under any gateway limit. Vercel accepts 100 MB bodies;
|
|
44
|
+
* that is a ceiling, not a target.
|
|
45
|
+
* - 3 attempts with FULL jitter rather than plain exponential, because every
|
|
46
|
+
* buffered client backs off on the same schedule and un-jittered retries
|
|
47
|
+
* re-synchronise into a herd aimed at the endpoint that just failed.
|
|
48
|
+
* - Duplicates from an at-least-once retry are free: every record carries an
|
|
49
|
+
* `event_id` and the server is idempotent on `(source, event_id)`.
|
|
50
|
+
*/
|
|
51
|
+
export declare const MAX_BATCH_BYTES = 1000000;
|
|
52
|
+
export declare const RETRY_ATTEMPTS = 3;
|
|
53
|
+
export declare const RETRY_BASE_MS = 1000;
|
|
54
|
+
export declare const RETRY_CAP_MS = 30000;
|
|
55
|
+
/** The active step's re-label. Mirrors the Python `_STAGE_OVERRIDE` tuple. */
|
|
56
|
+
interface StageOverride {
|
|
57
|
+
operation?: string;
|
|
58
|
+
sessionId?: string;
|
|
59
|
+
taskClass?: string;
|
|
60
|
+
}
|
|
61
|
+
/** Options for {@link stage}. */
|
|
62
|
+
export interface StageOptions {
|
|
63
|
+
/** The run this step belongs to. Wins over a `sessionId` passed at the call —
|
|
64
|
+
* that is how the steps of one multi-agent run share an id. */
|
|
65
|
+
sessionId?: string;
|
|
66
|
+
/** WHAT KIND of work this step does, in the vocabulary the face-off ledger is
|
|
67
|
+
* keyed on (`signal-check`, `document-extraction`, …). DECLARED, never inferred
|
|
68
|
+
* from the step name (see `RecordCallInput.taskClass`). A call that names its
|
|
69
|
+
* own `taskClass` keeps it; this fills the ones that do not. */
|
|
70
|
+
taskClass?: string;
|
|
71
|
+
/** Attach this step under a parent the async context cannot see — a branch run
|
|
72
|
+
* on a worker (`AsyncLocalStorage` does not cross a worker boundary, exactly as
|
|
73
|
+
* a Python contextvar does not cross a bare thread). Without it such a branch
|
|
74
|
+
* records as a root, which reads as "no chain happened" rather than the missing
|
|
75
|
+
* edge it is, so pass it by hand there. */
|
|
76
|
+
parentSpanId?: string;
|
|
77
|
+
}
|
|
78
|
+
/** Options for {@link span}. */
|
|
79
|
+
export interface SpanOptions {
|
|
80
|
+
/** The orchestration shape THIS block performs. Rides only the calls emitted
|
|
81
|
+
* directly in it — a nested span opens its own node and inherits none of it, so
|
|
82
|
+
* `branchWidth` on a child cannot claim the child did the fanning out. */
|
|
83
|
+
pattern?: "pipeline" | "barrier" | "panel" | "loop_until_dry";
|
|
84
|
+
/** How many branches the orchestration opened. */
|
|
85
|
+
branchWidth?: number;
|
|
86
|
+
/** The rule that ended the orchestration, free text (e.g. "majority of 3"). */
|
|
87
|
+
stoppingRule?: string;
|
|
88
|
+
/** Force this node's id instead of generating one — for a branch resumed in
|
|
89
|
+
* another process that must reuse a known id. */
|
|
90
|
+
spanId?: string;
|
|
91
|
+
/** Attach this node under a parent the async context cannot see (worker/process
|
|
92
|
+
* boundary), the same case as {@link StageOptions.parentSpanId}. */
|
|
93
|
+
parentSpanId?: string;
|
|
94
|
+
}
|
|
95
|
+
/** Mark one STEP of a pipeline — its name, its identity in the chain, and its kind
|
|
96
|
+
* — for the length of `fn`. Every call `fn` makes, however many awaits deep,
|
|
97
|
+
* meters as this operation and records as one node of the chain, nested under any
|
|
98
|
+
* enclosing `stage`/`span`. Returns whatever `fn` returns (a value or a promise).
|
|
99
|
+
*
|
|
100
|
+
* ```ts
|
|
101
|
+
* import { MarginMeter, stage, instrumentGemini } from "margin-meter";
|
|
102
|
+
* await stage("classify", { taskClass: "signal-check", sessionId: runId }, () =>
|
|
103
|
+
* classifier.run(input), // meters as operation="classify"
|
|
104
|
+
* );
|
|
105
|
+
* await stage("implement", { taskClass: "algorithm", sessionId: runId }, () =>
|
|
106
|
+
* implementer.run(plan), // ... and these as operation="implement"
|
|
107
|
+
* );
|
|
108
|
+
* ```
|
|
109
|
+
*
|
|
110
|
+
* The two steps share `sessionId` but carry DISTINCT operations, so the run reads
|
|
111
|
+
* as a real >=2-step pipeline instead of collapsing onto one node — the exact bug
|
|
112
|
+
* the Python SDK hit before `stage()` opened a span. The step's span id is passed
|
|
113
|
+
* to `fn`, for the worker-boundary case where a child must be attached explicitly
|
|
114
|
+
* via {@link StageOptions.parentSpanId}. This is the TS twin of `margin_meter.stage`. */
|
|
115
|
+
export declare function stage<T>(operation: string, fn: (spanId: string) => T): T;
|
|
116
|
+
export declare function stage<T>(operation: string, opts: StageOptions, fn: (spanId: string) => T): T;
|
|
117
|
+
/** The active `(operation, sessionId, taskClass)` step override, or `undefined`
|
|
118
|
+
* outside any `stage`. */
|
|
119
|
+
export declare function currentStage(): StageOverride | undefined;
|
|
120
|
+
/** Mark every metered call inside `fn` as one node of an agent tree — the tree the
|
|
121
|
+
* Money Map decomposes to ask what a BRANCH cost, which a flat list of calls
|
|
122
|
+
* sharing a `sessionId` cannot answer. Nesting is what builds the tree; returns
|
|
123
|
+
* whatever `fn` returns.
|
|
124
|
+
*
|
|
125
|
+
* ```ts
|
|
126
|
+
* await span({ pattern: "panel", branchWidth: 3, stoppingRule: "majority of 3" }, () =>
|
|
127
|
+
* Promise.all(candidates.map((c) => judge(c))), // each judge nests its own node
|
|
128
|
+
* );
|
|
129
|
+
* ```
|
|
130
|
+
*
|
|
131
|
+
* `stage()` is the primitive to reach for on a plain pipeline step; `span()` adds
|
|
132
|
+
* the orchestration shape when a block fans out. This is the TS twin of
|
|
133
|
+
* `margin_meter.span`. */
|
|
134
|
+
export declare function span<T>(opts: SpanOptions, fn: (spanId: string) => T): T;
|
|
135
|
+
/** The active `(spanId, parentSpanId)`, or `undefined` outside any span/stage. */
|
|
136
|
+
export declare function currentSpan(): {
|
|
137
|
+
spanId: string;
|
|
138
|
+
parentSpanId?: string;
|
|
139
|
+
} | undefined;
|
|
35
140
|
/** The outcome of one emit. Returned by every record call. */
|
|
36
141
|
export interface IngestResult {
|
|
37
142
|
/** True only on an HTTP 200. */
|
|
@@ -42,6 +147,37 @@ export interface IngestResult {
|
|
|
42
147
|
body?: Record<string, unknown>;
|
|
43
148
|
/** The failure reason, when not ok. */
|
|
44
149
|
error?: string;
|
|
150
|
+
/** The same failure as a stable BUCKET (`no_key`, `transport`, `http_<status>`).
|
|
151
|
+
* `error` is a human sentence and its wording moves, so anything COUNTING
|
|
152
|
+
* failures reads this instead of parsing that. Absent when ok. */
|
|
153
|
+
reason?: string;
|
|
154
|
+
}
|
|
155
|
+
/** What a meter TRIED to deliver against what actually landed.
|
|
156
|
+
*
|
|
157
|
+
* A meter is fail-safe by contract: a dropped row never breaks the host app and
|
|
158
|
+
* never throws. That trade is right — telemetry must not take an agent down —
|
|
159
|
+
* but it makes the failure INVISIBLE, and an invisible loss reads downstream as
|
|
160
|
+
* traffic that never happened. Margin's own 2026-07-25 invoice reconcile found
|
|
161
|
+
* ~65 of ~200 `gpt-4o` calls missing from the ledger with nothing anywhere
|
|
162
|
+
* having recorded a single failure, so the rate could not be told from the cause.
|
|
163
|
+
*
|
|
164
|
+
* `dropRate` is the number that answers "is the ledger short because the agent
|
|
165
|
+
* made fewer calls, or because we failed to deliver them?" — the one question a
|
|
166
|
+
* coverage gap cannot answer about itself.
|
|
167
|
+
*
|
|
168
|
+
* Narrower than the Python SDK's `DeliveryStats` on purpose, not by omission:
|
|
169
|
+
* this client has no file sink and no cross-hook de-dup, so it has no
|
|
170
|
+
* `unmeasured` holes to name and no `deduped` suppressions to keep out of the
|
|
171
|
+
* loss count. Every emit it makes goes through one door and is counted there. */
|
|
172
|
+
export interface DeliveryStats {
|
|
173
|
+
attempted: number;
|
|
174
|
+
delivered: number;
|
|
175
|
+
dropped: number;
|
|
176
|
+
/** Share of attempted emits that never landed. 0 when nothing was tried. */
|
|
177
|
+
dropRate: number;
|
|
178
|
+
droppedByReason: Record<string, number>;
|
|
179
|
+
attemptedByPath: Record<string, number>;
|
|
180
|
+
droppedByPath: Record<string, number>;
|
|
45
181
|
}
|
|
46
182
|
/** The response shape a transport returns (a subset of the `fetch` Response). */
|
|
47
183
|
export interface TransportResponse {
|
|
@@ -109,6 +245,21 @@ export interface RecordCallInput {
|
|
|
109
245
|
* supply-chain node label the Money Map decomposes by, e.g. "extract"). Omit
|
|
110
246
|
* for a single-call workflow. */
|
|
111
247
|
operation?: string;
|
|
248
|
+
/** WHERE the agent lives — the org-chart rung ABOVE it (MAR-345). `environment`
|
|
249
|
+
* is prod/staging; `team` is who owns it. Two fields rather than one composite
|
|
250
|
+
* because they are two questions: "is this real traffic?" and "whose budget?".
|
|
251
|
+
*
|
|
252
|
+
* ⛔ These are LABELS. They group rows in the estate view and authorise nothing
|
|
253
|
+
* — ownership is still the ingest key's project, forced server-side, which is
|
|
254
|
+
* the part a caller cannot spoof. Omit both and the registry reports the agent
|
|
255
|
+
* under `(unlabelled)`, never a home it did not claim.
|
|
256
|
+
*
|
|
257
|
+
* ⚠️ Omitting them is not free, though: the estate tree collapses from four
|
|
258
|
+
* rungs to two, so "you are running 34 agents across 3 environments" degrades
|
|
259
|
+
* to a flat list. Measured 2026-08-08 — every production row was `(unlabelled)`
|
|
260
|
+
* because this SDK had no way to send them at all. */
|
|
261
|
+
environment?: string;
|
|
262
|
+
team?: string;
|
|
112
263
|
costUsd?: number;
|
|
113
264
|
isSimulated?: boolean;
|
|
114
265
|
/** Idempotency key baked into the emitted payload. Defaults to a fresh uuid
|
|
@@ -146,17 +297,93 @@ export interface RecordCallInput {
|
|
|
146
297
|
* the path is not actually known — an unmeasured dimension belongs empty, not
|
|
147
298
|
* defaulted to "direct". The set is closed server-side. */
|
|
148
299
|
substrate?: "direct" | "openrouter" | "litellm" | "azure" | "bedrock" | "vertex" | "gateway";
|
|
300
|
+
/** WHICH UNIT OF WORK this call served, in your own vocabulary — a ticket
|
|
301
|
+
* topic, an intent label, a corpus task id. Margin measures a route's parity
|
|
302
|
+
* on a sample and records what that sample was made of; this is what lets it
|
|
303
|
+
* then say whether the traffic arriving now is still that population, rather
|
|
304
|
+
* than only whether the route got worse. Omit it and that question reads
|
|
305
|
+
* `unknown`, which is the honest answer and a permanent one. Open-ended on
|
|
306
|
+
* purpose: a topic nobody has seen before is how a mix shift announces
|
|
307
|
+
* itself. Never priced. Truncated server-side at 128 characters rather than
|
|
308
|
+
* refused — a long ticket subject costs you the tail of the label, never the
|
|
309
|
+
* call's tokens or cost. */
|
|
310
|
+
taskKey?: string;
|
|
311
|
+
/** WHAT KIND of work this step does (MAR-898), in the vocabulary Margin's face-off
|
|
312
|
+
* ledger is keyed on: `signal-check`, `document-extraction`, `multi-hop-reasoning`,
|
|
313
|
+
* `algorithm`. `taskKey` is WHICH unit of work; this is WHAT KIND, and the
|
|
314
|
+
* difference matters because a hold-rate prior is earned per CLASS — so a step
|
|
315
|
+
* without one can be measured and still not be advisable.
|
|
316
|
+
*
|
|
317
|
+
* ⛔ DECLARE IT; never let it be inferred from a step name. An operation called
|
|
318
|
+
* `summarize` may or may not be the class the ledger calls document-extraction,
|
|
319
|
+
* and mapping by resemblance would attach a real model recommendation to work it
|
|
320
|
+
* may not describe. Omit it and the step reads `not_measured` in a per-stage plan,
|
|
321
|
+
* which is the honest answer. Never priced; truncated server-side at 128. */
|
|
322
|
+
taskClass?: string;
|
|
323
|
+
/** WHICH AGENT SCAFFOLD drove the call (MAR-371) — the orchestration around the
|
|
324
|
+
* model (Claude Code, a LangChain agent, a bespoke loop). The same model on the
|
|
325
|
+
* same tasks costs differently by which harness ran it (Composio measured a 4.7x
|
|
326
|
+
* spread across eight), independent of `model` and `substrate`. Open-ended, never
|
|
327
|
+
* priced, truncated server-side at 64 characters. Omit it when the scaffold is not
|
|
328
|
+
* known — an unmeasured dimension belongs empty. */
|
|
329
|
+
harness?: string;
|
|
330
|
+
/** WHY the provider ended the generation, read verbatim off the response
|
|
331
|
+
* (Anthropic `stop_reason`, OpenAI/Gemini `finish_reason`, Bedrock `stopReason`).
|
|
332
|
+
* A raw signal, NOT a billing verdict: a blocked-and-fell-back call (Fable 5's
|
|
333
|
+
* safety fallback) is often not billed, but that is settled by the invoice, never
|
|
334
|
+
* inferred from this reason alone (MAR-209). Rides only when the provider reported
|
|
335
|
+
* one; absent it stays `unknown`, first-class. Never priced. Truncated
|
|
336
|
+
* server-side (open vocabulary — a novel reason is never a dropped row). */
|
|
337
|
+
finishReason?: string;
|
|
338
|
+
/** sha256 of the request (see `capture.ts`), set automatically by the wrapped clients. */
|
|
339
|
+
promptHash?: string;
|
|
340
|
+
/** sha256 and text-character count of the stable leading part of the request. Hashes only. */
|
|
341
|
+
prefixHash?: string;
|
|
342
|
+
prefixChars?: number;
|
|
343
|
+
/** Who served the call (OpenRouter's `provider`, or the vendor on a direct client). */
|
|
344
|
+
servingHost?: string;
|
|
345
|
+
/** `truncation` or `transport`, when this call re-sends a request that just failed. Detected
|
|
346
|
+
* from this process's own calls; pass it to override. */
|
|
347
|
+
retryKind?: "truncation" | "transport";
|
|
348
|
+
/** The agent's own label for this call's output (`output_class`): a short lowercase label,
|
|
349
|
+
* never text. The one optional thing a customer may add; never inferred from output text. */
|
|
350
|
+
verdict?: string;
|
|
149
351
|
}
|
|
150
352
|
export interface RecordOutcomeInput {
|
|
151
353
|
workflowId: string;
|
|
152
354
|
passed: boolean;
|
|
153
355
|
qualityScore?: number;
|
|
154
356
|
qualityMethod?: string;
|
|
357
|
+
/** WHO/what graded the score: "code" | "judge" | "human". Recorded, never
|
|
358
|
+
* inferred — omit to leave the grader kind unknown on the server. */
|
|
359
|
+
graderKind?: string;
|
|
360
|
+
/** Model id that judged when graderKind is "judge". */
|
|
361
|
+
judgeModelId?: string;
|
|
362
|
+
/** How SURE the grader was of qualityScore, in [0, 1]. Recorded, never inferred —
|
|
363
|
+
* omit to leave it unknown on the server (a missing value is never read as
|
|
364
|
+
* "certain"). */
|
|
365
|
+
graderConfidence?: number;
|
|
155
366
|
link?: string;
|
|
156
367
|
isSimulated?: boolean;
|
|
157
368
|
/** Idempotency key (see RecordCallInput.eventId): a redelivered outcome does
|
|
158
369
|
* not double-count the cost-per-outcome denominator. Defaults to a fresh uuid. */
|
|
159
370
|
eventId?: string;
|
|
371
|
+
/** The WORTH of this outcome in USD — the value-per-outcome NUMERATOR
|
|
372
|
+
* (RA-31 / MAR-634). Supply it when the outcome has a known business value;
|
|
373
|
+
* omit it and the outcome is measured as cost-per-outcome, the honest default.
|
|
374
|
+
* Optional by construction — absent is the normal case, never defaulted to 0. */
|
|
375
|
+
valueUsd?: number;
|
|
376
|
+
/** WHERE this outcome was produced — the DENOMINATOR twin of RecordCallInput's
|
|
377
|
+
* `environment` (MAR-1562): "prod" for the work the customer sells, "dev"/"eval"
|
|
378
|
+
* for the work they did to decide what to sell. Omit it and the server stores
|
|
379
|
+
* NULL — an unlabelled outcome is UNKNOWN and is never assumed to be "prod". */
|
|
380
|
+
environment?: string;
|
|
381
|
+
/** WHICH JOB inside the workflow produced this outcome (MAR-1912) — the outcome
|
|
382
|
+
* twin of RecordCallInput's `operation`. `workflowId` names the pipeline (on
|
|
383
|
+
* customer zero, the FILE) and one file holds many jobs, so per-job value cannot
|
|
384
|
+
* be attached without it. Omit it and the server stores NULL (UNKNOWN) — never
|
|
385
|
+
* coerced to the workflow itself. Capped at 64 chars, like the call path. */
|
|
386
|
+
operation?: string;
|
|
160
387
|
}
|
|
161
388
|
/** A per-project client that emits measured economics to a Margin ingest API. */
|
|
162
389
|
export declare class MarginMeter {
|
|
@@ -164,8 +391,84 @@ export declare class MarginMeter {
|
|
|
164
391
|
apiKey?: string;
|
|
165
392
|
raiseOnError: boolean;
|
|
166
393
|
private transport;
|
|
394
|
+
private attempted;
|
|
395
|
+
private delivered;
|
|
396
|
+
private droppedByReason;
|
|
397
|
+
private attemptedByPath;
|
|
398
|
+
private droppedByPath;
|
|
399
|
+
private warnedOnDrop;
|
|
400
|
+
private noUrl;
|
|
401
|
+
private batcher;
|
|
402
|
+
private exitFlush;
|
|
403
|
+
private exitFlushArmed;
|
|
167
404
|
constructor(options?: MarginMeterOptions);
|
|
405
|
+
/** Attach the process-exit flush, once, on the first row that will need it. */
|
|
406
|
+
private armExitFlush;
|
|
407
|
+
/** Record one emit attempt. Called at every exit point that knows its own
|
|
408
|
+
* outcome, BEFORE any `raiseOnError` throw, so a strict-mode failure is
|
|
409
|
+
* counted exactly like the fail-safe one it would otherwise have been. */
|
|
410
|
+
private count;
|
|
411
|
+
/** A snapshot of what this meter delivered against what it tried to.
|
|
412
|
+
* See {@link DeliveryStats}. */
|
|
413
|
+
deliveryStats(): DeliveryStats;
|
|
414
|
+
/**
|
|
415
|
+
* Route one built payload to the wire or the buffer.
|
|
416
|
+
*
|
|
417
|
+
* Buffering is the default and the whole point (`docs/reference/SDK_BATCHING.md`).
|
|
418
|
+
* Two cases deliberately stay immediate, and neither is a knob:
|
|
419
|
+
*
|
|
420
|
+
* - **Strict mode** (`raiseOnError`) means "throw at MY call site when this row
|
|
421
|
+
* is rejected", and a buffered emit has no call site left to throw at by the
|
|
422
|
+
* time the POST happens. The two are incompatible, so strict posts now.
|
|
423
|
+
* - **No key**, because buffering rows that can never be sent would fill the
|
|
424
|
+
* queue and then report `queue_full` — a diagnosis that sends the reader
|
|
425
|
+
* hunting for a network problem when the answer is a missing variable.
|
|
426
|
+
* A missing URL is the same case and is named `no_url`.
|
|
427
|
+
*/
|
|
168
428
|
private emit;
|
|
429
|
+
/** Hand one record to the buffer. Never blocks, never throws.
|
|
430
|
+
*
|
|
431
|
+
* `ok: true` here means ACCEPTED INTO THE BUFFER, not written to the ledger —
|
|
432
|
+
* the body says `queued` so nothing mistakes the two. What actually landed is
|
|
433
|
+
* `deliveryStats()`, which exists for exactly this question. */
|
|
434
|
+
private enqueue;
|
|
435
|
+
/** Resolve once every buffered row has been delivered or counted as dropped.
|
|
436
|
+
*
|
|
437
|
+
* Call it before reading `deliveryStats()` if you need the counts to cover rows
|
|
438
|
+
* you have only just emitted — buffering separates an emit from its delivery
|
|
439
|
+
* in time by design. */
|
|
440
|
+
flush(): Promise<void>;
|
|
441
|
+
/** Drain the buffer and stop the timer. Registered on `beforeExit`.
|
|
442
|
+
*
|
|
443
|
+
* Anything the timeout strands is COUNTED as dropped rather than abandoned: the
|
|
444
|
+
* records are handed back by `Batcher.close` precisely so the number is
|
|
445
|
+
* knowable. */
|
|
446
|
+
close(timeoutMs?: number): Promise<void>;
|
|
447
|
+
private postNow;
|
|
448
|
+
/** POST one buffered batch. Never rejects: it owns its own accounting.
|
|
449
|
+
*
|
|
450
|
+
* ⛔ The blanket `catch` is load-bearing, not defensive habit. `Batcher.flush`
|
|
451
|
+
* swallows a rejection to keep the drain going, so anything escaping here would
|
|
452
|
+
* vanish with the counters reading a clean sheet — an uncounted loss, which
|
|
453
|
+
* makes measured spend read CHEAPER than the bill. Scoped per chunk so records
|
|
454
|
+
* already accounted for in an earlier chunk are not counted twice. */
|
|
455
|
+
private sendBatch;
|
|
456
|
+
/** Split a batch so no request exceeds {@link MAX_BATCH_BYTES}.
|
|
457
|
+
*
|
|
458
|
+
* ⛔ A single record over the cap on its own is DROPPED and counted as
|
|
459
|
+
* `oversize`. No split can send it, and keeping it would wedge the queue behind
|
|
460
|
+
* one poisoned row forever. It is a bug in the caller — every open-vocabulary
|
|
461
|
+
* field is already bounded server-side, so an honest row cannot come near a
|
|
462
|
+
* megabyte.
|
|
463
|
+
*
|
|
464
|
+
* ⛔ A payload that will not serialise is dropped and counted too, and that case
|
|
465
|
+
* is not exotic — a `BigInt` anywhere in the payload makes `JSON.stringify`
|
|
466
|
+
* throw. Unguarded, the throw escaped into the flush and the row vanished with
|
|
467
|
+
* the counters reading a clean sheet. */
|
|
468
|
+
private chunkByBytes;
|
|
469
|
+
private deliverChunk;
|
|
470
|
+
/** POST one batch, retrying the failures that clear with time. */
|
|
471
|
+
private postBatchWithRetry;
|
|
169
472
|
/** Emit one measured LLM call. Cost is computed server-side when `costUsd`
|
|
170
473
|
* is omitted. Never throws unless `raiseOnError`. */
|
|
171
474
|
recordCall(input: RecordCallInput): Promise<IngestResult>;
|
|
@@ -219,6 +522,14 @@ export interface RecordResponseInput {
|
|
|
219
522
|
isSimulated?: boolean;
|
|
220
523
|
/** The delivery path the call took (see `substrate.ts`); omit when unknown. */
|
|
221
524
|
substrate?: Substrate;
|
|
525
|
+
/** The unit of work this call served (see `RecordCallInput.taskKey`). */
|
|
526
|
+
taskKey?: string;
|
|
527
|
+
/** Request fingerprints (see `capture.ts`); the wrapped clients fill them from the request. */
|
|
528
|
+
promptHash?: string;
|
|
529
|
+
prefixHash?: string;
|
|
530
|
+
prefixChars?: number;
|
|
531
|
+
/** The agent's own label for this call's output (see `RecordCallInput.verdict`). */
|
|
532
|
+
verdict?: string;
|
|
222
533
|
}
|
|
223
534
|
/** Options for `wrap` — how to meter every call to the wrapped fn. */
|
|
224
535
|
export interface WrapOptions {
|
|
@@ -232,6 +543,14 @@ export interface WrapOptions {
|
|
|
232
543
|
/** Derive the model per call (e.g. off a bound Gemini model); a truthy return
|
|
233
544
|
* overrides the static `model`. Receives the wrapped call's args. */
|
|
234
545
|
resolveModel?: (args: unknown[]) => string | undefined;
|
|
546
|
+
/** Derive the unit of work (`task_key`) per call — the WHICH-work axis. Resolved
|
|
547
|
+
* AT CALL TIME on purpose: task identity is per-call, so this is a callable (read
|
|
548
|
+
* a request-scoped store, the current ticket, an async-local), never a constant.
|
|
549
|
+
* A single constant across a whole run would manufacture a one-class distribution
|
|
550
|
+
* the mix gate treats as no signal (the reason the instrument path takes a
|
|
551
|
+
* resolver, not a `taskKey` string — MAR-197 / MAR-46). Undefined return, or no
|
|
552
|
+
* resolver, leaves the row's task_key unset: UNKNOWN, never a fabricated bucket. */
|
|
553
|
+
resolveTaskKey?: () => string | undefined;
|
|
235
554
|
/** OpenAI omits usage from a stream unless asked; when set (only by the OpenAI
|
|
236
555
|
* chat instrumenter), a `stream: true` call gets `stream_options.include_usage`
|
|
237
556
|
* injected so its final chunk carries the count the accumulator meters. */
|
|
@@ -259,4 +578,18 @@ export declare class Measurement {
|
|
|
259
578
|
cacheCreation1hTokens?: number;
|
|
260
579
|
}): void;
|
|
261
580
|
}
|
|
581
|
+
/** The server's own `Retry-After`, in ms, when it sent one.
|
|
582
|
+
*
|
|
583
|
+
* The ingest API computes the real wait from its rolling window rather than
|
|
584
|
+
* sending a round number, so honouring it beats any backoff we could calculate
|
|
585
|
+
* blind — a client that guesses either hammers or overshoots, and overshooting
|
|
586
|
+
* drops exactly the calls the SDK was installed to record. */
|
|
587
|
+
export declare function retryAfterMs_(resp: TransportResponse): number | undefined;
|
|
588
|
+
/** FULL jitter — `random(0, base * 2**attempt)`, capped, or the server's wait.
|
|
589
|
+
*
|
|
590
|
+
* Jittered rather than plain exponential because every buffered client backs off
|
|
591
|
+
* on the same schedule: un-jittered retries re-synchronise into a thundering herd
|
|
592
|
+
* aimed at the endpoint that just failed, which is how a brief blip becomes an
|
|
593
|
+
* outage. */
|
|
594
|
+
export declare function backoffMs(attempt: number, retryAfter?: number): number;
|
|
262
595
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|