@stigg/agent-sdk-js 0.0.0-stage → 0.2.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 +1411 -2
- package/dist/bindings/client/core/registry.d.ts +12 -0
- package/dist/bindings/client/core/registry.js +22 -0
- package/dist/bindings/client/core/types.d.ts +126 -0
- package/dist/bindings/client/core/types.js +13 -0
- package/dist/bindings/client/core/wrap-client.d.ts +6 -0
- package/dist/bindings/client/core/wrap-client.js +261 -0
- package/dist/bindings/client/gateways/bedrock/bedrock-recipe.d.ts +17 -0
- package/dist/bindings/client/gateways/bedrock/bedrock-recipe.js +134 -0
- package/dist/bindings/client/gateways/bedrock/types.d.ts +13 -0
- package/dist/bindings/client/gateways/bedrock/types.js +2 -0
- package/dist/bindings/client/gateways/cloudflare/cloudflare-recipe.d.ts +10 -0
- package/dist/bindings/client/gateways/cloudflare/cloudflare-recipe.js +254 -0
- package/dist/bindings/client/gateways/cloudflare/types.d.ts +35 -0
- package/dist/bindings/client/gateways/cloudflare/types.js +2 -0
- package/dist/bindings/client/gateways/databricks/databricks-recipe.d.ts +32 -0
- package/dist/bindings/client/gateways/databricks/databricks-recipe.js +324 -0
- package/dist/bindings/client/gateways/databricks/types.d.ts +30 -0
- package/dist/bindings/client/gateways/databricks/types.js +2 -0
- package/dist/bindings/client/gateways/litellm/litellm-recipe.d.ts +17 -0
- package/dist/bindings/client/gateways/litellm/litellm-recipe.js +158 -0
- package/dist/bindings/client/gateways/litellm/types.d.ts +30 -0
- package/dist/bindings/client/gateways/litellm/types.js +2 -0
- package/dist/bindings/client/gateways/openrouter/openrouter-recipe.d.ts +20 -0
- package/dist/bindings/client/gateways/openrouter/openrouter-recipe.js +233 -0
- package/dist/bindings/client/gateways/openrouter/sdk-usage.d.ts +37 -0
- package/dist/bindings/client/gateways/openrouter/sdk-usage.js +63 -0
- package/dist/bindings/client/gateways/openrouter/types.d.ts +78 -0
- package/dist/bindings/client/gateways/openrouter/types.js +2 -0
- package/dist/bindings/client/providers/anthropic/anthropic-recipe.d.ts +34 -0
- package/dist/bindings/client/providers/anthropic/anthropic-recipe.js +169 -0
- package/dist/bindings/client/providers/gemini/gemini-recipe.d.ts +54 -0
- package/dist/bindings/client/providers/gemini/gemini-recipe.js +243 -0
- package/dist/bindings/client/providers/groq/groq-recipe.d.ts +20 -0
- package/dist/bindings/client/providers/groq/groq-recipe.js +84 -0
- package/dist/bindings/client/providers/mistral/mistral-recipe.d.ts +22 -0
- package/dist/bindings/client/providers/mistral/mistral-recipe.js +114 -0
- package/dist/bindings/client/providers/mistral/types.d.ts +38 -0
- package/dist/bindings/client/providers/mistral/types.js +2 -0
- package/dist/bindings/client/providers/ollama/ollama-recipe.d.ts +31 -0
- package/dist/bindings/client/providers/ollama/ollama-recipe.js +107 -0
- package/dist/bindings/client/providers/ollama/types.d.ts +24 -0
- package/dist/bindings/client/providers/ollama/types.js +2 -0
- package/dist/bindings/client/providers/openai/openai-recipe.d.ts +71 -0
- package/dist/bindings/client/providers/openai/openai-recipe.js +122 -0
- package/dist/bindings/client/providers/typesafe/typesafe-recipe.d.ts +44 -0
- package/dist/bindings/client/providers/typesafe/typesafe-recipe.js +83 -0
- package/dist/bindings/proxy/headers.d.ts +6 -0
- package/dist/bindings/proxy/headers.js +12 -0
- package/dist/bindings/proxy/index.d.ts +21 -0
- package/dist/bindings/proxy/index.js +18 -0
- package/dist/bindings/proxy/types.d.ts +8 -0
- package/dist/bindings/proxy/types.js +2 -0
- package/dist/bindings/shared/base-url.d.ts +44 -0
- package/dist/bindings/shared/base-url.js +90 -0
- package/dist/bindings/shared/estimate.d.ts +27 -0
- package/dist/bindings/shared/estimate.js +38 -0
- package/dist/bindings/shared/meter-stream.d.ts +18 -0
- package/dist/bindings/shared/meter-stream.js +151 -0
- package/dist/bindings/shared/token-usage.d.ts +345 -0
- package/dist/bindings/shared/token-usage.js +735 -0
- package/dist/bindings/shared/types.d.ts +170 -0
- package/dist/bindings/shared/types.js +2 -0
- package/dist/bindings/shared/weighted-metrics.d.ts +37 -0
- package/dist/bindings/shared/weighted-metrics.js +47 -0
- package/dist/config.d.ts +145 -0
- package/dist/config.js +99 -0
- package/dist/core/context.d.ts +160 -0
- package/dist/core/context.js +221 -0
- package/dist/core/dimensions.d.ts +22 -0
- package/dist/core/dimensions.js +47 -0
- package/dist/core/hooks.d.ts +21 -0
- package/dist/core/hooks.js +47 -0
- package/dist/core/session.d.ts +190 -0
- package/dist/core/session.js +448 -0
- package/dist/decision-text.d.ts +15 -0
- package/dist/decision-text.js +54 -0
- package/dist/engine/composite-engine.d.ts +72 -0
- package/dist/engine/composite-engine.js +135 -0
- package/dist/engine/create-engine.d.ts +16 -0
- package/dist/engine/create-engine.js +93 -0
- package/dist/engine/decision.d.ts +42 -0
- package/dist/engine/decision.js +135 -0
- package/dist/engine/engine.d.ts +166 -0
- package/dist/engine/engine.js +11 -0
- package/dist/engine/node-sdk-engine.d.ts +125 -0
- package/dist/engine/node-sdk-engine.js +262 -0
- package/dist/engine/report.d.ts +106 -0
- package/dist/engine/report.js +188 -0
- package/dist/engine/rest-governance-engine.d.ts +47 -0
- package/dist/engine/rest-governance-engine.js +220 -0
- package/dist/errors.d.ts +86 -0
- package/dist/errors.js +161 -0
- package/dist/headers.d.ts +40 -0
- package/dist/headers.js +82 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.js +124 -0
- package/dist/internal.d.ts +33 -0
- package/dist/internal.js +91 -0
- package/dist/logger.d.ts +15 -0
- package/dist/logger.js +20 -0
- package/dist/sdk-identity.d.ts +36 -0
- package/dist/sdk-identity.js +43 -0
- package/dist/stigg-agent-sdk.d.ts +300 -0
- package/dist/stigg-agent-sdk.js +669 -0
- package/dist/types.d.ts +676 -0
- package/dist/types.js +147 -0
- package/package.json +94 -3
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider usage objects -> the SDK's neutral `TokenUsage`.
|
|
3
|
+
*
|
|
4
|
+
* The inputs are typed structurally rather than against each vendor's SDK, so this handful of
|
|
5
|
+
* readers covers a direct client, a gateway response and an orchestrator callback - and adding a
|
|
6
|
+
* provider whose response happens to match costs nothing. Hence the shape-named reader below:
|
|
7
|
+
* `fromFlatTokenUsage` is read by every vendor that counts that way, not by one of them.
|
|
8
|
+
*/
|
|
9
|
+
import { type Measurement, type Metrics, type MetricsMapper, type TokenUsage } from '../../types';
|
|
10
|
+
import type { BedrockLikeUsage, FlatTokenUsage, GeminiLikeUsage, LangChainLikeUsage, MistralLikeUsage, DatabricksLikeUsage, DatabricksQueryLikeUsage, OllamaLikeUsage, OpenAILikeUsage, ResponsesLikeUsage } from './types';
|
|
11
|
+
export declare function fromFlatTokenUsage(usage: FlatTokenUsage | null | undefined): TokenUsage;
|
|
12
|
+
export declare function fromOpenAIUsage(usage: OpenAILikeUsage | null | undefined): TokenUsage;
|
|
13
|
+
/**
|
|
14
|
+
* OpenAI's Responses API, which counts the same tokens under different names - `input_tokens`
|
|
15
|
+
* rather than `prompt_tokens`, and the cache detail one level along. Reading it with the Chat
|
|
16
|
+
* Completions extractor finds none of them and meters the call at zero.
|
|
17
|
+
*/
|
|
18
|
+
export declare function fromResponsesUsage(usage: ResponsesLikeUsage | null | undefined): TokenUsage;
|
|
19
|
+
/**
|
|
20
|
+
* Bedrock's Converse usage, whose four counters are disjoint.
|
|
21
|
+
*
|
|
22
|
+
* Nothing is subtracted, unlike the OpenAI and Gemini readers: AWS states that `inputTokens`
|
|
23
|
+
* already excludes whatever was read from or written to the cache, so taking the cache back out
|
|
24
|
+
* would charge the call for less than it used.
|
|
25
|
+
*
|
|
26
|
+
* The total is read, not recomputed, like every other vendor that publishes one - but it is worth
|
|
27
|
+
* knowing what it covers. AWS documents `totalTokens` as the input and output of the call, and
|
|
28
|
+
* documents `inputTokens` as cache-exclusive, so on a cached call the stated total can be smaller
|
|
29
|
+
* than the four counters add up to. Both are reported: price the breakdown if the cache matters to
|
|
30
|
+
* you, the total if it does not, and see the README's overlap table before pricing both.
|
|
31
|
+
*/
|
|
32
|
+
export declare function fromBedrockUsage(usage: BedrockLikeUsage | null | undefined): TokenUsage;
|
|
33
|
+
export declare function fromLangChainUsage(usage: LangChainLikeUsage | null | undefined): TokenUsage;
|
|
34
|
+
/**
|
|
35
|
+
* Gemini's `usageMetadata`, whose two overlaps run in opposite directions - see `GeminiLikeUsage`
|
|
36
|
+
* for the vendor's own wording on each.
|
|
37
|
+
*
|
|
38
|
+
* The arithmetic is checked by the one invariant the vendor publishes: the four counters below
|
|
39
|
+
* add back up to `totalTokenCount`, which is why neither overlap may be read the other way.
|
|
40
|
+
*/
|
|
41
|
+
export declare function fromGeminiUsage(usage: GeminiLikeUsage | null | undefined): TokenUsage;
|
|
42
|
+
/**
|
|
43
|
+
* Mistral's `UsageInfo` - the OpenAI three, camelCased by a generated SDK.
|
|
44
|
+
*
|
|
45
|
+
* Counts the same way OpenAI's chat usage does, so the arithmetic is the same: the vendor states
|
|
46
|
+
* its own total and it is read rather than recomputed. There is no cache counter to subtract -
|
|
47
|
+
* `UsageInfo` carries none, so unlike `fromOpenAIUsage` nothing is nested inside the prompt count.
|
|
48
|
+
*/
|
|
49
|
+
export declare function fromMistralUsage(usage: MistralLikeUsage | null | undefined): TokenUsage;
|
|
50
|
+
/**
|
|
51
|
+
* Ollama's two counters, read off the response root rather than out of a `usage` block.
|
|
52
|
+
*
|
|
53
|
+
* Disjoint - the prompt evaluation and the generation are separate work - so their sum is the
|
|
54
|
+
* whole call and computing a total from them is the vendor's own arithmetic rather than ours.
|
|
55
|
+
* Ollama publishes no total of its own, which is why there is one to compute.
|
|
56
|
+
*/
|
|
57
|
+
export declare function fromOllamaUsage(usage: OllamaLikeUsage | null | undefined): TokenUsage;
|
|
58
|
+
/**
|
|
59
|
+
* Any of the three shapes above, recognised by its own fields. Vendors disagree on names but not
|
|
60
|
+
* enough to be ambiguous, so the caller can pass whatever the response carried.
|
|
61
|
+
*/
|
|
62
|
+
export declare function normalizeUsage(usage: unknown): TokenUsage;
|
|
63
|
+
export declare const addTokenUsage: (into: TokenUsage, add: TokenUsage) => TokenUsage;
|
|
64
|
+
/**
|
|
65
|
+
* The name a computed total is reported under, for the vendors that publish none of their own.
|
|
66
|
+
*
|
|
67
|
+
* `total_tokens` rather than a name of ours, because it is what OpenAI calls the same number and
|
|
68
|
+
* what a reader expects to find - but it is worth knowing which vendors state it and which get it
|
|
69
|
+
* from {@link COMPUTED_TOTALS}: Anthropic and TypeSafe publish no total at all, so theirs is the
|
|
70
|
+
* SDK's arithmetic over counters the vendor *did* state, not a figure off their dashboard.
|
|
71
|
+
*/
|
|
72
|
+
export declare const TOTAL_TOKENS = "total_tokens";
|
|
73
|
+
/** Anthropic's four counters. Disjoint - cache reads and writes are not inside `input_tokens`. */
|
|
74
|
+
export declare const ANTHROPIC_COMPONENT_METRICS: readonly ["input_tokens", "output_tokens", "cache_read_input_tokens", "cache_creation_input_tokens"];
|
|
75
|
+
/** Those four, plus the total this SDK adds up for them. */
|
|
76
|
+
export declare const ANTHROPIC_METRICS: readonly ["input_tokens", "output_tokens", "cache_read_input_tokens", "cache_creation_input_tokens", "total_tokens"];
|
|
77
|
+
/**
|
|
78
|
+
* Gemini's five. Two of them overlap in opposite directions and both are reported verbatim, the
|
|
79
|
+
* way every vendor's are, because a number published under a vendor's field name has to reconcile
|
|
80
|
+
* against that vendor's own dashboard: `cachedContentTokenCount` is already *inside*
|
|
81
|
+
* `promptTokenCount`, while `thoughtsTokenCount` and `toolUsePromptTokenCount` sit *outside* the
|
|
82
|
+
* two headline counters. Price accordingly - or price `normalizedMetrics` instead, which is
|
|
83
|
+
* disjoint by construction.
|
|
84
|
+
*/
|
|
85
|
+
export declare const GEMINI_METRICS: readonly ["promptTokenCount", "candidatesTokenCount", "cachedContentTokenCount", "thoughtsTokenCount", "toolUsePromptTokenCount", "totalTokenCount"];
|
|
86
|
+
/** What identifies a Gemini usage object: its breakdown, never its total. */
|
|
87
|
+
export declare const GEMINI_COMPONENT_METRICS: readonly ["promptTokenCount", "candidatesTokenCount", "cachedContentTokenCount", "thoughtsTokenCount", "toolUsePromptTokenCount"];
|
|
88
|
+
/**
|
|
89
|
+
* Chat Completions. `prompt_tokens` **includes** `cached_tokens`, so these two overlap - reported
|
|
90
|
+
* as the vendor states them, which is what reconciles against its invoice. Whoever prices
|
|
91
|
+
* `prompt_tokens` must know the cached ones are already inside it.
|
|
92
|
+
*/
|
|
93
|
+
export declare const OPENAI_CHAT_METRICS: readonly ["prompt_tokens", "completion_tokens", "cached_tokens", "total_tokens"];
|
|
94
|
+
/** The Responses API, which overlaps the same way under its own names. */
|
|
95
|
+
export declare const OPENAI_RESPONSES_METRICS: readonly ["input_tokens", "output_tokens", "cached_tokens", "total_tokens"];
|
|
96
|
+
/**
|
|
97
|
+
* Where Mistral's counters are **read** and what each is **reported** as - the only vocabulary
|
|
98
|
+
* here where those are different strings.
|
|
99
|
+
*
|
|
100
|
+
* Every other vendor is reported under the key it was read from, which is why `METRIC_PATHS` is a
|
|
101
|
+
* list and `metricName` just takes the last segment. Mistral's generated SDK renames the wire on
|
|
102
|
+
* the way in - the API sends `prompt_tokens`, the client hands you `promptTokens` - so following
|
|
103
|
+
* that convention would report a camelCase feature id that matches nothing on Mistral's own
|
|
104
|
+
* dashboard, and would differ from what the same account reports through an `OpenAI` client
|
|
105
|
+
* pointed at `api.mistral.ai/v1`. One account, one invoice, one vocabulary: the wire's.
|
|
106
|
+
*
|
|
107
|
+
* So the map runs read-key -> reported-name, and `pickRenamedMetrics` is what applies it.
|
|
108
|
+
*/
|
|
109
|
+
export declare const MISTRAL_METRIC_NAME_MAP: {
|
|
110
|
+
readonly promptTokens: "prompt_tokens";
|
|
111
|
+
readonly completionTokens: "completion_tokens";
|
|
112
|
+
readonly totalTokens: "total_tokens";
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Mistral's three, under the wire's own names.
|
|
116
|
+
*
|
|
117
|
+
* No cache counter: `UsageInfo` carries none. The cache and reasoning detail the v2 SDK models
|
|
118
|
+
* lives on a different type that chat responses do not use, so declaring it here would type a
|
|
119
|
+
* pricing table against a number that never arrives.
|
|
120
|
+
*/
|
|
121
|
+
export declare const MISTRAL_METRICS: readonly ["prompt_tokens", "completion_tokens", "total_tokens"];
|
|
122
|
+
/**
|
|
123
|
+
* TypeSafe's two. No cache counters and no cost: the API reports what it charged for and stops
|
|
124
|
+
* there, which was confirmed against the wire rather than inferred from the SDK's types.
|
|
125
|
+
*/
|
|
126
|
+
export declare const TYPESAFE_COMPONENT_METRICS: readonly ["input_tokens", "output_tokens"];
|
|
127
|
+
/** Those two, plus the total this SDK adds up for them. */
|
|
128
|
+
export declare const TYPESAFE_METRICS: readonly ["input_tokens", "output_tokens", "total_tokens"];
|
|
129
|
+
/**
|
|
130
|
+
* Ollama's two. Flat on the response root, so the paths are the names.
|
|
131
|
+
*
|
|
132
|
+
* No cache counter and no cost: Ollama is self-hosted, so there is no invoice behind these at all
|
|
133
|
+
* - they measure the customer's own capacity rather than a vendor's charge. The durations beside
|
|
134
|
+
* them on the response are nanoseconds, not tokens, and are deliberately absent from this list.
|
|
135
|
+
*/
|
|
136
|
+
export declare const OLLAMA_COMPONENT_METRICS: readonly ["prompt_eval_count", "eval_count"];
|
|
137
|
+
/** Those two, plus the total this SDK adds up for them. */
|
|
138
|
+
export declare const OLLAMA_METRICS: readonly ["prompt_eval_count", "eval_count", "total_tokens"];
|
|
139
|
+
/** Both OpenAI surfaces, which is what one client can report across its two APIs. */
|
|
140
|
+
export declare const OPENAI_METRICS: readonly ["prompt_tokens", "completion_tokens", "input_tokens", "output_tokens", "cached_tokens", "total_tokens"];
|
|
141
|
+
/** A gateway speaks the OpenAI shape and adds the price it charged, under its own field name. */
|
|
142
|
+
export declare const GATEWAY_METRICS: readonly ["prompt_tokens", "completion_tokens", "input_tokens", "output_tokens", "cached_tokens", "total_tokens", "cost"];
|
|
143
|
+
/**
|
|
144
|
+
* A gateway that forwards the upstream body untouched, and so reports in two vocabularies.
|
|
145
|
+
*
|
|
146
|
+
* Unlike LiteLLM, which normalises every upstream to the OpenAI wire, Cloudflare AI Gateway's
|
|
147
|
+
* provider-native routes pass the provider's own body straight through - so `/openai` returns
|
|
148
|
+
* OpenAI's counter names and `/anthropic` returns Anthropic's. One recipe serves both wires, so
|
|
149
|
+
* this is the union of what its surfaces can report, which is what `metrics` is defined to be.
|
|
150
|
+
*
|
|
151
|
+
* No `cost`, and that is the defining fact rather than an oversight. Cloudflare states no price on
|
|
152
|
+
* any response: its figure lives in the gateway's own log, is explicitly an estimate, and is zero
|
|
153
|
+
* on a cache hit. So the recipe carries the log id as a dimension and lets spend be reconciled out
|
|
154
|
+
* of band, exactly as the gateway reference prescribes for a price that is only available
|
|
155
|
+
* asynchronously.
|
|
156
|
+
*/
|
|
157
|
+
export declare const CLOUDFLARE_METRICS: readonly ["prompt_tokens", "completion_tokens", "input_tokens", "output_tokens", "cached_tokens", "total_tokens", "cache_read_input_tokens", "cache_creation_input_tokens"];
|
|
158
|
+
/**
|
|
159
|
+
* Bedrock's five, under its own names and with no price among them.
|
|
160
|
+
*
|
|
161
|
+
* Reported verbatim rather than translated into the OpenAI spelling, which is the rule everywhere
|
|
162
|
+
* except where one service is reachable through two different clients - see `sdk-usage.ts` for
|
|
163
|
+
* that exception. Bedrock is reached one way, so its own names are the honest ones, and a reader
|
|
164
|
+
* comparing a Stigg meter against an AWS bill is comparing like with like.
|
|
165
|
+
*
|
|
166
|
+
* No `cost`: Bedrock states no price on the response, which is the thing that most separates it
|
|
167
|
+
* from the other two gateways here. See the recipe for what that costs a run.
|
|
168
|
+
*/
|
|
169
|
+
export declare const BEDROCK_PATHS: readonly ["inputTokens", "outputTokens", "cacheReadInputTokens", "cacheWriteInputTokens", "totalTokens"];
|
|
170
|
+
/** Those five. Flat, so the paths are the names. */
|
|
171
|
+
export declare const BEDROCK_METRICS: readonly ["inputTokens", "outputTokens", "cacheReadInputTokens", "cacheWriteInputTokens", "totalTokens"];
|
|
172
|
+
/**
|
|
173
|
+
* Databricks' six, under its own names - and its own names are two vendors' names at once.
|
|
174
|
+
*
|
|
175
|
+
* The first three are OpenAI's spelling, because the serving endpoints speak the OpenAI wire. The
|
|
176
|
+
* two cache counters are *Anthropic's* spelling, flat on the usage block rather than nested under
|
|
177
|
+
* `prompt_tokens_details` where an OpenAI-shaped reader would look for them, and `reasoning_tokens`
|
|
178
|
+
* is Databricks' own. Reported exactly as Databricks spells them, per the rule that a number has to
|
|
179
|
+
* reconcile against the vendor's own dashboard - renaming the cache pair to `cached_tokens` would
|
|
180
|
+
* make one account read as two vocabularies and find nothing where it looked.
|
|
181
|
+
*
|
|
182
|
+
* No `cost`, and that is the fact that most shapes this binding: Databricks states no price on any
|
|
183
|
+
* response, on either route. See `databricks-recipe.ts` for what that costs a run.
|
|
184
|
+
*/
|
|
185
|
+
export declare const DATABRICKS_PATHS: readonly ["prompt_tokens", "completion_tokens", "total_tokens", "reasoning_tokens", "cache_read_input_tokens", "cache_creation_input_tokens"];
|
|
186
|
+
/**
|
|
187
|
+
* The same counters as the Responses API spells them.
|
|
188
|
+
*
|
|
189
|
+
* Databricks serves both OpenAI surfaces, and they do not share field names: Chat Completions
|
|
190
|
+
* sends `prompt_tokens`/`completion_tokens` and Responses sends `input_tokens`/`output_tokens`.
|
|
191
|
+
* Reading a Responses body with the list above finds neither, so the call would report its total
|
|
192
|
+
* and nothing else - a number with no breakdown under it, which prices wrongly rather than
|
|
193
|
+
* visibly. Each surface reads its own list.
|
|
194
|
+
*/
|
|
195
|
+
export declare const DATABRICKS_RESPONSES_PATHS: readonly ["input_tokens", "output_tokens", "total_tokens", "reasoning_tokens", "cache_read_input_tokens", "cache_creation_input_tokens"];
|
|
196
|
+
/** The union across both surfaces: what a Databricks call can report, which is what `metrics` is. */
|
|
197
|
+
export declare const DATABRICKS_METRICS: readonly ["prompt_tokens", "completion_tokens", "input_tokens", "output_tokens", "total_tokens", "reasoning_tokens", "cache_read_input_tokens", "cache_creation_input_tokens"];
|
|
198
|
+
/**
|
|
199
|
+
* Where the **first-party client's** counters are read and what each is reported as.
|
|
200
|
+
*
|
|
201
|
+
* The second map in this file, and it exists for precisely the reason the Mistral one does.
|
|
202
|
+
* `@databricks/sdk-modelservingquery` is generated, and its zod schema parses `prompt_tokens` off
|
|
203
|
+
* the wire and transforms it to `promptTokens` before the caller ever sees it - so following the
|
|
204
|
+
* key it was read from would report a camelCase feature id for a call that the *same workspace*
|
|
205
|
+
* reports in snake_case when the application holds an `OpenAI` client instead.
|
|
206
|
+
*
|
|
207
|
+
* That is not a cosmetic difference. It is one Databricks account producing two different feature
|
|
208
|
+
* ids depending on which package the application happened to import, splitting one bill across two
|
|
209
|
+
* meters - which is the failure `pickRenamedMetrics` was built to prevent. Three entries rather
|
|
210
|
+
* than six because `ExternalModelUsageElement` carries only three; the cache pair and
|
|
211
|
+
* `reasoning_tokens` have no field on it, and a counter with no field is absent rather than zero.
|
|
212
|
+
*/
|
|
213
|
+
export declare const DATABRICKS_QUERY_METRIC_NAME_MAP: {
|
|
214
|
+
readonly promptTokens: "prompt_tokens";
|
|
215
|
+
readonly completionTokens: "completion_tokens";
|
|
216
|
+
readonly totalTokens: "total_tokens";
|
|
217
|
+
};
|
|
218
|
+
/**
|
|
219
|
+
* Workers AI's three, and only three.
|
|
220
|
+
*
|
|
221
|
+
* OpenAI's spelling, flat, with no cache detail nested underneath - so this is a narrower list
|
|
222
|
+
* than `OPENAI_CHAT_METRICS` rather than a reuse of it. Declaring `cached_tokens` here would type
|
|
223
|
+
* a pricing table against a counter Workers AI never sends.
|
|
224
|
+
*
|
|
225
|
+
* No neurons either, which is the counter a reader might expect. Cloudflare bills Workers AI in
|
|
226
|
+
* Neurons, and publishes none of them on any response - binding or REST - so the conversion from
|
|
227
|
+
* tokens is a price list this SDK does not hold. Tokens are what the response states and tokens
|
|
228
|
+
* are what this reports.
|
|
229
|
+
*/
|
|
230
|
+
export declare const WORKERS_AI_PATHS: readonly ["prompt_tokens", "completion_tokens", "total_tokens"];
|
|
231
|
+
/** Those three. Flat, so the paths are the names. */
|
|
232
|
+
export declare const WORKERS_AI_METRICS: readonly ["prompt_tokens", "completion_tokens", "total_tokens"];
|
|
233
|
+
/**
|
|
234
|
+
* Databricks' usage block -> the neutral digest.
|
|
235
|
+
*
|
|
236
|
+
* `input` is `prompt_tokens` verbatim, *not* reduced by the cache reads the way `fromOpenAIUsage`
|
|
237
|
+
* reduces its own. OpenAI documents its cached tokens as counted inside `prompt_tokens`, so
|
|
238
|
+
* subtracting there is undoing a documented overlap. Databricks documents no such thing, and the
|
|
239
|
+
* spelling it chose for the pair is Anthropic's - whose cache counters sit *beside* the input
|
|
240
|
+
* count rather than inside it. So the Anthropic convention is the better guess and the overlap is
|
|
241
|
+
* left alone; the stated total is read rather than computed, which keeps the one number that gets
|
|
242
|
+
* invoiced right whichever way the overlap actually runs. The README's overlap table says the
|
|
243
|
+
* direction is unverified for Databricks, because it is.
|
|
244
|
+
*/
|
|
245
|
+
export declare function fromDatabricksUsage(usage: DatabricksLikeUsage | null | undefined): TokenUsage;
|
|
246
|
+
/**
|
|
247
|
+
* The same block as read through the first-party client -> the neutral digest.
|
|
248
|
+
*
|
|
249
|
+
* Its own reader rather than a call into `fromDatabricksUsage`, because the field names genuinely
|
|
250
|
+
* differ: the generated client camelCases the wire on the way in, so a snake_case reader finds
|
|
251
|
+
* none of these and returns an all-zero digest without throwing. That is the shape of failure the
|
|
252
|
+
* invariants call out - an extractor that meters every call at nothing and trips no test.
|
|
253
|
+
*
|
|
254
|
+
* No cache arithmetic to get wrong here, which is the one simplification over the wire-shaped
|
|
255
|
+
* reader: `ExternalModelUsageElement` declares no cache counters at all, so there is no overlap of
|
|
256
|
+
* unknown direction to leave alone. The stated total is still read rather than recomputed.
|
|
257
|
+
*/
|
|
258
|
+
export declare function fromDatabricksQueryUsage(usage: DatabricksQueryLikeUsage | null | undefined): TokenUsage;
|
|
259
|
+
/** The leaf a dotted path reports under - `prompt_tokens_details.cached_tokens` -> `cached_tokens`. */
|
|
260
|
+
export declare const metricName: (path: string) => string;
|
|
261
|
+
/**
|
|
262
|
+
* Which counters are summed to produce a vendor's total, for the vendors that publish none.
|
|
263
|
+
*
|
|
264
|
+
* Only ever disjoint sets: Anthropic's four do not overlap and neither do TypeSafe's two, so the
|
|
265
|
+
* sum is the whole call and nothing is counted twice. A vendor whose counters overlap - Gemini's
|
|
266
|
+
* cached tokens sit inside its prompt count, OpenAI's inside theirs - is not in this table,
|
|
267
|
+
* because adding those up would be arithmetic the vendor never agreed to. Those vendors state a
|
|
268
|
+
* total themselves and it is read, not computed.
|
|
269
|
+
*/
|
|
270
|
+
export declare const COMPUTED_TOTALS: Record<string, readonly string[]>;
|
|
271
|
+
/**
|
|
272
|
+
* Adds the computed total to a metrics object, for a vendor that states none of its own.
|
|
273
|
+
*
|
|
274
|
+
* Absent rather than zero when nothing was counted, like every other metric here: a call that
|
|
275
|
+
* measured nothing reports nothing, instead of a zero somebody has to interpret.
|
|
276
|
+
*/
|
|
277
|
+
export declare function withComputedTotal(metrics: Metrics, keys: readonly string[]): Metrics;
|
|
278
|
+
/**
|
|
279
|
+
* Whether a path list and a name list agree, for the test that keeps them from drifting.
|
|
280
|
+
*
|
|
281
|
+
* Two lists describing one thing is the cost of separating where a counter lives from what it is
|
|
282
|
+
* called. This is what makes that cost a compile-and-test problem rather than a billing one.
|
|
283
|
+
*/
|
|
284
|
+
export declare const metricNamesMatchPaths: (paths: readonly string[], names: readonly string[]) => boolean;
|
|
285
|
+
/** The read paths, for the tests that hold them in step with the names above. */
|
|
286
|
+
export declare const METRIC_PATHS: {
|
|
287
|
+
readonly anthropic: readonly ["input_tokens", "output_tokens", "cache_read_input_tokens", "cache_creation_input_tokens"];
|
|
288
|
+
readonly openaiChat: readonly ["prompt_tokens", "completion_tokens", "prompt_tokens_details.cached_tokens", "total_tokens"];
|
|
289
|
+
readonly openaiResponses: readonly ["input_tokens", "output_tokens", "input_tokens_details.cached_tokens", "total_tokens"];
|
|
290
|
+
readonly typesafe: readonly ["input_tokens", "output_tokens"];
|
|
291
|
+
readonly gemini: readonly ["promptTokenCount", "candidatesTokenCount", "cachedContentTokenCount", "thoughtsTokenCount", "toolUsePromptTokenCount", "totalTokenCount"];
|
|
292
|
+
readonly bedrock: readonly ["inputTokens", "outputTokens", "cacheReadInputTokens", "cacheWriteInputTokens", "totalTokens"];
|
|
293
|
+
readonly databricks: readonly ["prompt_tokens", "completion_tokens", "total_tokens", "reasoning_tokens", "cache_read_input_tokens", "cache_creation_input_tokens"];
|
|
294
|
+
readonly databricksResponses: readonly ["input_tokens", "output_tokens", "total_tokens", "reasoning_tokens", "cache_read_input_tokens", "cache_creation_input_tokens"];
|
|
295
|
+
readonly workersAi: readonly ["prompt_tokens", "completion_tokens", "total_tokens"];
|
|
296
|
+
readonly ollama: readonly ["prompt_eval_count", "eval_count"];
|
|
297
|
+
};
|
|
298
|
+
/**
|
|
299
|
+
* Reads the named keys off a vendor's usage object, dotted paths included.
|
|
300
|
+
*
|
|
301
|
+
* A nested key reports under its leaf - `prompt_tokens_details.cached_tokens` becomes
|
|
302
|
+
* `cached_tokens` - because the leaf is the vendor's own name for it and a feature id with a dot
|
|
303
|
+
* in it reads badly everywhere. Anything absent, fractional or not a number is skipped: a metric
|
|
304
|
+
* the vendor did not report is not a zero, and Stigg rejects fractions.
|
|
305
|
+
*/
|
|
306
|
+
export declare function pickMetrics(usage: unknown, keys: readonly string[]): Metrics;
|
|
307
|
+
/**
|
|
308
|
+
* Reads each key of a read -> reported map off a usage object, reporting under the mapped name.
|
|
309
|
+
*
|
|
310
|
+
* The counterpart to {@link pickMetrics} for a vendor whose SDK spells its counters differently
|
|
311
|
+
* from its own wire. Same guards, and for the same reasons: anything absent, fractional or not a
|
|
312
|
+
* number is skipped, because a metric the vendor did not report is not a zero and Stigg rejects
|
|
313
|
+
* fractions. Flat keys only - no vendor needing this nests its counters, and a dotted read here
|
|
314
|
+
* would make the map ambiguous about which half of the arrow the dot belongs to.
|
|
315
|
+
*/
|
|
316
|
+
export declare function pickRenamedMetrics(usage: unknown, map: Record<string, string>): Metrics;
|
|
317
|
+
/** Accumulates metrics across a stream, which reports its counters in more than one chunk. */
|
|
318
|
+
export declare const addMetrics: (into: Metrics, add: Metrics) => Metrics;
|
|
319
|
+
/**
|
|
320
|
+
* The SDK's own four counters, under SDK-owned names, from the normalized measurement.
|
|
321
|
+
*
|
|
322
|
+
* The opt-out from vendor names, for an application running more than one provider: these are
|
|
323
|
+
* disjoint and mean the same thing whoever served the call, so one set of Stigg features covers
|
|
324
|
+
* every vendor. Pass it as a run's `metrics`.
|
|
325
|
+
*/
|
|
326
|
+
export declare const normalizedMetrics: MetricsMapper;
|
|
327
|
+
/** The shapes a gateway can be told it observed, since guessing reports to the wrong features. */
|
|
328
|
+
/**
|
|
329
|
+
* The shapes a proxy can be told it observed.
|
|
330
|
+
*
|
|
331
|
+
* Named for the vendor rather than for the shape, because a proxy operator knows what is behind
|
|
332
|
+
* them and not what its usage object looks like - but it is the shape that is being selected,
|
|
333
|
+
* which is why OpenAI appears twice. Its two APIs spell the same counters differently, and
|
|
334
|
+
* `openai-responses` is that surface rather than a vendor of its own.
|
|
335
|
+
*/
|
|
336
|
+
export type ObservedVendor = 'anthropic' | 'typesafe' | 'openai' | 'openai-responses' | 'gemini';
|
|
337
|
+
/**
|
|
338
|
+
* Both views of a usage object a proxy observed, for the ingest path that has no recipe.
|
|
339
|
+
*
|
|
340
|
+
* The vendor is named rather than sniffed. `normalizeUsage` guesses from the object's own fields
|
|
341
|
+
* and says itself that Anthropic and the Responses API are ambiguous - both count `input_tokens`.
|
|
342
|
+
* A wrong guess would report to another meter entirely, which nothing downstream can undo - so
|
|
343
|
+
* an unnamed vendor reports nothing raw and leaves the normalized counters to a mapper.
|
|
344
|
+
*/
|
|
345
|
+
export declare function observedMeasurement(usage: unknown, vendor?: ObservedVendor): Measurement;
|