@trazum/core 1.81.0 → 1.82.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +34 -18
  2. package/dist/advisories.d.ts +33 -1
  3. package/dist/advisories.d.ts.map +1 -1
  4. package/dist/advisories.js +103 -16
  5. package/dist/advisories.js.map +1 -1
  6. package/dist/band.d.ts +131 -0
  7. package/dist/band.d.ts.map +1 -0
  8. package/dist/band.js +210 -0
  9. package/dist/band.js.map +1 -0
  10. package/dist/conform.d.ts +1 -1
  11. package/dist/conform.d.ts.map +1 -1
  12. package/dist/conform.js +84 -1
  13. package/dist/conform.js.map +1 -1
  14. package/dist/helicone.d.ts +92 -0
  15. package/dist/helicone.d.ts.map +1 -0
  16. package/dist/helicone.js +194 -0
  17. package/dist/helicone.js.map +1 -0
  18. package/dist/i18n/en.d.ts.map +1 -1
  19. package/dist/i18n/en.js +9 -3
  20. package/dist/i18n/en.js.map +1 -1
  21. package/dist/i18n/es.d.ts.map +1 -1
  22. package/dist/i18n/es.js +9 -3
  23. package/dist/i18n/es.js.map +1 -1
  24. package/dist/i18n/types.d.ts +43 -1
  25. package/dist/i18n/types.d.ts.map +1 -1
  26. package/dist/index.d.ts +10 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +5 -1
  29. package/dist/index.js.map +1 -1
  30. package/dist/litellm.d.ts +98 -0
  31. package/dist/litellm.d.ts.map +1 -0
  32. package/dist/litellm.js +207 -0
  33. package/dist/litellm.js.map +1 -0
  34. package/dist/measured-profile.d.ts +4 -0
  35. package/dist/measured-profile.d.ts.map +1 -1
  36. package/dist/measured-profile.js +22 -1
  37. package/dist/measured-profile.js.map +1 -1
  38. package/dist/schemas.d.ts.map +1 -1
  39. package/dist/schemas.js +36 -0
  40. package/dist/schemas.js.map +1 -1
  41. package/dist/tokenizer.d.ts +45 -49
  42. package/dist/tokenizer.d.ts.map +1 -1
  43. package/dist/tokenizer.js +100 -51
  44. package/dist/tokenizer.js.map +1 -1
  45. package/dist/types.d.ts +1 -1
  46. package/dist/types.d.ts.map +1 -1
  47. package/dist/verdict-bridge.d.ts +113 -0
  48. package/dist/verdict-bridge.d.ts.map +1 -0
  49. package/dist/verdict-bridge.js +127 -0
  50. package/dist/verdict-bridge.js.map +1 -0
  51. package/package.json +1 -1
  52. package/src/advisories.ts +132 -15
  53. package/src/band.ts +213 -0
  54. package/src/conform.ts +100 -1
  55. package/src/helicone.ts +227 -0
  56. package/src/i18n/en.ts +10 -3
  57. package/src/i18n/es.ts +10 -3
  58. package/src/i18n/types.ts +45 -1
  59. package/src/index.ts +17 -1
  60. package/src/litellm.ts +243 -0
  61. package/src/measured-profile.ts +26 -2
  62. package/src/schemas.ts +36 -0
  63. package/src/tokenizer.ts +101 -51
  64. package/src/types.ts +1 -0
  65. package/src/verdict-bridge.ts +200 -0
@@ -0,0 +1,98 @@
1
+ /**
2
+ * LiteLLM's spend log, read as a usage log.
3
+ *
4
+ * `from-claude-code` proved the pattern and `from-otel` generalised it: a pure
5
+ * converter turns one tool's export into Trazum's usage-log records, and every
6
+ * door prices it from there. LiteLLM is the gateway a great many teams already
7
+ * put in front of every provider, so its `LiteLLM_SpendLogs` table is the one
8
+ * export most likely to already exist on somebody's disk.
9
+ *
10
+ * **The format is derived, not guessed.** Every field below is read off
11
+ * `litellm/proxy/schema.prisma` in BerriAI/litellm, model `LiteLLM_SpendLogs`.
12
+ * A converter written from memory of an API is a converter that silently
13
+ * mis-reads somebody's bill, and this project has one rule above all others
14
+ * about numbers it cannot justify.
15
+ *
16
+ * ## What maps
17
+ *
18
+ * | LiteLLM | Trazum |
19
+ * | --- | --- |
20
+ * | `model` | `model` |
21
+ * | `prompt_tokens` | `usage.input_tokens` |
22
+ * | `completion_tokens` | `usage.output_tokens` |
23
+ * | `startTime` | `ts` |
24
+ * | `session_id` | `session` |
25
+ * | `request_tags[0]`, else `metadata.tags[0]`, else `model_group` | `label` |
26
+ *
27
+ * ## What deliberately does not cross
28
+ *
29
+ * The row carries `messages` and `response` — the prompt itself and the
30
+ * completion — plus `api_key` (hashed, still credential-shaped),
31
+ * `requester_ip_address`, `user` and `end_user`. **None of it is read.** The
32
+ * converter names the fields it takes and takes nothing else, and a fixture
33
+ * plants a marker in each of them and greps the whole output.
34
+ *
35
+ * ## What it refuses to invent
36
+ *
37
+ * `cache_hit` is a flag and `cache_key` an identifier; neither is a token
38
+ * count. A converted record therefore carries no cache split at all, and the
39
+ * caching questions come back `cannot-tell` rather than answered from a
40
+ * guess — the same refusal as inventing a price. `cacheFlagged` counts the
41
+ * rows that said "hit" so the operator can see the gap is real rather than
42
+ * empty.
43
+ *
44
+ * `spend` is LiteLLM's own priced figure and is **never** merged into
45
+ * Trazum's catalogue-priced total. It is a second measurement of the same
46
+ * calls, kept apart the way the store's provider-billed standing is kept
47
+ * apart from the log's, and returned on its own so a caller who wants to
48
+ * compare the two can, deliberately.
49
+ */
50
+ /** One converted record, shaped exactly as `parseUsageLine` reads it. */
51
+ export interface LiteLlmRecord {
52
+ model: string;
53
+ ts?: string;
54
+ label?: string;
55
+ session?: string;
56
+ usage: {
57
+ input_tokens: number;
58
+ output_tokens: number;
59
+ };
60
+ }
61
+ export interface LiteLlmConversion {
62
+ records: LiteLlmRecord[];
63
+ /** Rows that were spend logs and converted. */
64
+ rows: number;
65
+ /** Rows naming no model: counted, never guessed at, never dropped silently. */
66
+ unnamedModel: number;
67
+ /** Rows carrying no token counts at all — a logged call nobody can price. */
68
+ noTokens: number;
69
+ /** Rows LiteLLM marked as a cache hit, with no token split to act on. */
70
+ cacheFlagged: number;
71
+ /**
72
+ * LiteLLM's own total for the converted rows, in USD, or null when no row
73
+ * carried one. **Never** added to anything Trazum computes: it is the
74
+ * gateway's arithmetic over the gateway's price table, and merging two
75
+ * price tables into one figure is how a report becomes quietly wrong.
76
+ */
77
+ reportedSpendUsd: number | null;
78
+ /** Lines or documents that did not parse as JSON at all. */
79
+ unparseable: number;
80
+ }
81
+ /**
82
+ * Convert a LiteLLM spend-log export.
83
+ *
84
+ * Accepts a JSON array of rows, a single row, `{ data: [...] }` as the proxy's
85
+ * own endpoints return it, or newline-delimited rows — so a `psql --json`
86
+ * dump, an API response and a streamed capture all work. Pure over its input.
87
+ */
88
+ export declare function litellmRecords(text: string): LiteLlmConversion;
89
+ /**
90
+ * Whether a file looks like a LiteLLM spend log, by shape.
91
+ *
92
+ * Deliberately narrow: `request_id` beside one of the two token columns, and
93
+ * a field no other export in this project carries. A looser test would claim
94
+ * an OpenAI usage response, whose rows also have `prompt_tokens`, and refuse
95
+ * it in this file's words instead of letting the code that can read it try.
96
+ */
97
+ export declare function looksLikeLiteLlm(text: string, prefixBytes?: number): boolean;
98
+ //# sourceMappingURL=litellm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"litellm.d.ts","sourceRoot":"","sources":["../src/litellm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;CACrB;AAqDD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAmF9D;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,SAAO,GAAG,OAAO,CAQ1E"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * LiteLLM's spend log, read as a usage log.
3
+ *
4
+ * `from-claude-code` proved the pattern and `from-otel` generalised it: a pure
5
+ * converter turns one tool's export into Trazum's usage-log records, and every
6
+ * door prices it from there. LiteLLM is the gateway a great many teams already
7
+ * put in front of every provider, so its `LiteLLM_SpendLogs` table is the one
8
+ * export most likely to already exist on somebody's disk.
9
+ *
10
+ * **The format is derived, not guessed.** Every field below is read off
11
+ * `litellm/proxy/schema.prisma` in BerriAI/litellm, model `LiteLLM_SpendLogs`.
12
+ * A converter written from memory of an API is a converter that silently
13
+ * mis-reads somebody's bill, and this project has one rule above all others
14
+ * about numbers it cannot justify.
15
+ *
16
+ * ## What maps
17
+ *
18
+ * | LiteLLM | Trazum |
19
+ * | --- | --- |
20
+ * | `model` | `model` |
21
+ * | `prompt_tokens` | `usage.input_tokens` |
22
+ * | `completion_tokens` | `usage.output_tokens` |
23
+ * | `startTime` | `ts` |
24
+ * | `session_id` | `session` |
25
+ * | `request_tags[0]`, else `metadata.tags[0]`, else `model_group` | `label` |
26
+ *
27
+ * ## What deliberately does not cross
28
+ *
29
+ * The row carries `messages` and `response` — the prompt itself and the
30
+ * completion — plus `api_key` (hashed, still credential-shaped),
31
+ * `requester_ip_address`, `user` and `end_user`. **None of it is read.** The
32
+ * converter names the fields it takes and takes nothing else, and a fixture
33
+ * plants a marker in each of them and greps the whole output.
34
+ *
35
+ * ## What it refuses to invent
36
+ *
37
+ * `cache_hit` is a flag and `cache_key` an identifier; neither is a token
38
+ * count. A converted record therefore carries no cache split at all, and the
39
+ * caching questions come back `cannot-tell` rather than answered from a
40
+ * guess — the same refusal as inventing a price. `cacheFlagged` counts the
41
+ * rows that said "hit" so the operator can see the gap is real rather than
42
+ * empty.
43
+ *
44
+ * `spend` is LiteLLM's own priced figure and is **never** merged into
45
+ * Trazum's catalogue-priced total. It is a second measurement of the same
46
+ * calls, kept apart the way the store's provider-billed standing is kept
47
+ * apart from the log's, and returned on its own so a caller who wants to
48
+ * compare the two can, deliberately.
49
+ */
50
+ const asObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value)
51
+ ? value
52
+ : null;
53
+ const tryParse = (text) => {
54
+ try {
55
+ return JSON.parse(text);
56
+ }
57
+ catch {
58
+ return undefined;
59
+ }
60
+ };
61
+ const asCount = (value) => {
62
+ const n = typeof value === 'string' ? Number(value) : value;
63
+ return typeof n === 'number' && Number.isFinite(n) && n >= 0 ? n : undefined;
64
+ };
65
+ /**
66
+ * The first tag LiteLLM carries for a row, from the two places it puts them.
67
+ *
68
+ * `request_tags` is the documented column and `metadata.tags` is where the
69
+ * proxy writes them when the caller passes them in the request body. First
70
+ * only: a workload has one name in a bill, and joining several tags into one
71
+ * label would invent a workload that does not exist.
72
+ */
73
+ function labelOf(row) {
74
+ const fromColumn = Array.isArray(row.request_tags) ? row.request_tags : null;
75
+ if (fromColumn !== null && typeof fromColumn[0] === 'string' && fromColumn[0] !== '') {
76
+ return fromColumn[0];
77
+ }
78
+ const metadata = asObject(row.metadata);
79
+ const fromMetadata = metadata !== null && Array.isArray(metadata.tags) ? metadata.tags : null;
80
+ if (fromMetadata !== null && typeof fromMetadata[0] === 'string' && fromMetadata[0] !== '') {
81
+ return fromMetadata[0];
82
+ }
83
+ // The public model name a proxy route is known by. A weaker label than a
84
+ // tag — it groups by route rather than by workload — and better than none.
85
+ if (typeof row.model_group === 'string' && row.model_group !== '')
86
+ return row.model_group;
87
+ return undefined;
88
+ }
89
+ /** `startTime` as an ISO instant, or undefined when it is not a time. */
90
+ function timeOf(row) {
91
+ const raw = row.startTime ?? row.start_time;
92
+ if (typeof raw !== 'string' && typeof raw !== 'number')
93
+ return undefined;
94
+ const ms = typeof raw === 'number' ? raw : Date.parse(raw);
95
+ if (!Number.isFinite(ms))
96
+ return undefined;
97
+ return new Date(ms).toISOString();
98
+ }
99
+ /**
100
+ * Convert a LiteLLM spend-log export.
101
+ *
102
+ * Accepts a JSON array of rows, a single row, `{ data: [...] }` as the proxy's
103
+ * own endpoints return it, or newline-delimited rows — so a `psql --json`
104
+ * dump, an API response and a streamed capture all work. Pure over its input.
105
+ */
106
+ export function litellmRecords(text) {
107
+ const out = {
108
+ records: [],
109
+ rows: 0,
110
+ unnamedModel: 0,
111
+ noTokens: 0,
112
+ cacheFlagged: 0,
113
+ reportedSpendUsd: null,
114
+ unparseable: 0,
115
+ };
116
+ const rows = [];
117
+ const whole = tryParse(text);
118
+ if (whole !== undefined) {
119
+ if (Array.isArray(whole))
120
+ rows.push(...whole);
121
+ else {
122
+ const doc = asObject(whole);
123
+ // `{ data: [...] }` is what the proxy's spend endpoints return.
124
+ if (doc !== null && Array.isArray(doc.data))
125
+ rows.push(...doc.data);
126
+ else if (doc !== null)
127
+ rows.push(doc);
128
+ }
129
+ }
130
+ else {
131
+ for (const line of text.split('\n')) {
132
+ if (line.trim() === '')
133
+ continue;
134
+ const parsed = tryParse(line);
135
+ if (parsed === undefined)
136
+ out.unparseable += 1;
137
+ else if (Array.isArray(parsed))
138
+ rows.push(...parsed);
139
+ else
140
+ rows.push(parsed);
141
+ }
142
+ }
143
+ let spend = 0;
144
+ let sawSpend = false;
145
+ for (const raw of rows) {
146
+ const row = asObject(raw);
147
+ if (row === null)
148
+ continue;
149
+ // A spend log row is one that carries at least one of the two token
150
+ // columns. Anything else in the same file is not a call and is skipped
151
+ // rather than converted into a record of zero.
152
+ const input = asCount(row.prompt_tokens);
153
+ const output = asCount(row.completion_tokens);
154
+ if (input === undefined && output === undefined)
155
+ continue;
156
+ out.rows += 1;
157
+ if (input === 0 && output === 0)
158
+ out.noTokens += 1;
159
+ if (row.cache_hit === true || row.cache_hit === 'true' || row.cache_hit === 'True') {
160
+ out.cacheFlagged += 1;
161
+ }
162
+ const reported = asCount(row.spend);
163
+ if (reported !== undefined) {
164
+ spend += reported;
165
+ sawSpend = true;
166
+ }
167
+ const model = typeof row.model === 'string' ? row.model.trim() : '';
168
+ if (model === '') {
169
+ // Counted, never guessed at. `model_group` is a route name, not a model,
170
+ // and pricing a call by the route it took would be a figure attributed
171
+ // to something it does not describe.
172
+ out.unnamedModel += 1;
173
+ continue;
174
+ }
175
+ const ts = timeOf(row);
176
+ const label = labelOf(row);
177
+ const session = typeof row.session_id === 'string' && row.session_id !== ''
178
+ ? row.session_id
179
+ : undefined;
180
+ out.records.push({
181
+ model,
182
+ ...(ts !== undefined ? { ts } : {}),
183
+ ...(label !== undefined ? { label } : {}),
184
+ ...(session !== undefined ? { session } : {}),
185
+ usage: { input_tokens: input ?? 0, output_tokens: output ?? 0 },
186
+ });
187
+ }
188
+ out.reportedSpendUsd = sawSpend ? spend : null;
189
+ return out;
190
+ }
191
+ /**
192
+ * Whether a file looks like a LiteLLM spend log, by shape.
193
+ *
194
+ * Deliberately narrow: `request_id` beside one of the two token columns, and
195
+ * a field no other export in this project carries. A looser test would claim
196
+ * an OpenAI usage response, whose rows also have `prompt_tokens`, and refuse
197
+ * it in this file's words instead of letting the code that can read it try.
198
+ */
199
+ export function looksLikeLiteLlm(text, prefixBytes = 8192) {
200
+ const head = text.slice(0, prefixBytes);
201
+ if (!head.includes('prompt_tokens') && !head.includes('completion_tokens'))
202
+ return false;
203
+ return (head.includes('"request_id"') ||
204
+ head.includes('"custom_llm_provider"') ||
205
+ head.includes('"model_group"'));
206
+ }
207
+ //# sourceMappingURL=litellm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"litellm.js","sourceRoot":"","sources":["../src/litellm.ts"],"names":[],"mappings":"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"}
@@ -68,6 +68,10 @@ export interface MeasuredUsage {
68
68
  * call is the same size. It is handed over as the better of two
69
69
  * approximations — a measured token share beats a typed call share — and
70
70
  * named honestly here so no rendering can call it something it is not.
71
+ *
72
+ * The denominator is every input token, **writes included**. Leaving writes
73
+ * out made a constantly-rewritten cache report a high hit rate, which is the
74
+ * one workload that most needs to be told otherwise.
71
75
  */
72
76
  cacheReadShare: number;
73
77
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"measured-profile.d.ts","sourceRoot":"","sources":["../src/measured-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC,iFAAiF;AACjF,eAAO,MAAM,aAAa,KAAK,CAAC;AAEhC,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,OAAO,EAAE,YAAY,CAAC;IACtB,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;;OAKG;IACH,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACpD;;;;;;;;;OASG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE,iEAAiE;IACjE,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,kBAAkB,EAC1B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC,aAAa,GAAG,IAAI,CAuDtB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,yDAAyD;IACzD,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAClE,yEAAyE;IACzE,oBAAoB,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9D,2EAA2E;IAC3E,oBAAoB,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC7D;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,aAAa,CAsBf"}
1
+ {"version":3,"file":"measured-profile.d.ts","sourceRoot":"","sources":["../src/measured-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC,iFAAiF;AACjF,eAAO,MAAM,aAAa,KAAK,CAAC;AAEhC,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,OAAO,EAAE,YAAY,CAAC;IACtB,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;;OAKG;IACH,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACpD;;;;;;;;;;;;;OAaG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE,iEAAiE;IACjE,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,kBAAkB,EAC1B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC,aAAa,GAAG,IAAI,CA2EtB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,yDAAyD;IACzD,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAClE,yEAAyE;IACzE,oBAAoB,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9D,2EAA2E;IAC3E,oBAAoB,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC7D;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,aAAa,CAsBf"}
@@ -55,6 +55,7 @@ export function measuredUsage(report, label, options = {}) {
55
55
  const outputTokens = slices.reduce((sum, row) => sum + row.breakdown.outputTokens, 0);
56
56
  const inputTokens = slices.reduce((sum, row) => sum + row.breakdown.inputTokens, 0);
57
57
  const cacheReadTokens = slices.reduce((sum, row) => sum + row.breakdown.cacheReadTokens, 0);
58
+ const cacheWriteTokens = slices.reduce((sum, row) => sum + row.breakdown.cacheWriteTokens, 0);
58
59
  // The model carrying the most spend. Ties break on the larger call count, so
59
60
  // the answer is stable rather than dependent on map ordering.
60
61
  const ranked = [...slices].sort((a, b) => b.breakdown.totalUsd - a.breakdown.totalUsd || b.breakdown.calls - a.breakdown.calls);
@@ -69,7 +70,27 @@ export function measuredUsage(report, label, options = {}) {
69
70
  const scaled = spanDays !== null && spanDays >= MIN_SCALE_DAYS
70
71
  ? { fromDays: spanDays, factor: SCALE_TO_DAYS / spanDays }
71
72
  : null;
72
- const readShare = inputTokens + cacheReadTokens > 0 ? cacheReadTokens / (inputTokens + cacheReadTokens) : 0;
73
+ /**
74
+ * Every input token in the denominator, writes included.
75
+ *
76
+ * This was `reads / (input + reads)`, which leaves cache *writes* out of the
77
+ * total it is a share of. A workload that rewrites its prefix on every call
78
+ * and reads it back rarely then reports a **high** hit rate: with 100 read
79
+ * tokens, no plain input and 10,000 written, the old expression answers 100%
80
+ * where the truth is 1%.
81
+ *
82
+ * That is the worst direction for this number to be wrong in. It is handed
83
+ * to `optimize` as `cacheHitRate`, which decides whether caching is paying
84
+ * off — so the shape that is burning money on writes was the shape most
85
+ * likely to be told its cache was working perfectly.
86
+ *
87
+ * Writes are input tokens: they are billed at the input rate times the write
88
+ * multiplier, they arrive in the same `usage` block, and any accounting of
89
+ * "what share of the input came from cache" that omits them is answering a
90
+ * narrower question than the one it is named for.
91
+ */
92
+ const allInputTokens = inputTokens + cacheReadTokens + cacheWriteTokens;
93
+ const readShare = allInputTokens > 0 ? cacheReadTokens / allInputTokens : 0;
73
94
  return {
74
95
  profile: {
75
96
  model: chosen.model,
@@ -1 +1 @@
1
- {"version":3,"file":"measured-profile.js","sourceRoot":"","sources":["../src/measured-profile.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"measured-profile.js","sourceRoot":"","sources":["../src/measured-profile.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AA6CjD;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoG1E,CAAC;AAEF,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE1E"}
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AA6CjD;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwI1E,CAAC;AAEF,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE1E"}
package/dist/schemas.js CHANGED
@@ -145,6 +145,42 @@ export const CONTRACT_SCHEMAS = {
145
145
  cannotSay: array,
146
146
  unpricedRecords: number,
147
147
  }),
148
+ 'routing-measurement': doc('routing-measurement', {
149
+ slice: object,
150
+ evaluation: object,
151
+ }),
152
+ 'example-pruning': doc('example-pruning', {
153
+ provider: string,
154
+ model: string,
155
+ selfAgreement: number,
156
+ recoverableTokens: number,
157
+ callsMade: number,
158
+ contributions: array,
159
+ }),
160
+ 'store-inventory': doc('store-inventory', {
161
+ providers: array,
162
+ totalRecords: number,
163
+ span: objectOrNull,
164
+ possiblyDouble: number,
165
+ unknownVersion: number,
166
+ totalUsd: number,
167
+ unreadable: array,
168
+ }),
169
+ conformance: doc('conformance', {
170
+ contract: stringOrNull,
171
+ because: stringOrNull,
172
+ problems: array,
173
+ unavailable: array,
174
+ records: { type: ['number', 'null'] },
175
+ conforms: boolean,
176
+ }),
177
+ 'watch-cycle': doc('watch-cycle', {
178
+ firedAtMs: number,
179
+ crossings: array,
180
+ suppressed: array,
181
+ abstentions: array,
182
+ gap: objectOrNull,
183
+ }),
148
184
  };
149
185
  /** The schema for one named contract — the object `trazum schema` prints. */
150
186
  export function contractSchema(name) {
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"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"}
@@ -2,71 +2,67 @@
2
2
  * Dependency-free token estimator.
3
3
  *
4
4
  * This is NOT a real tokenizer: it is a heuristic calibrated per character
5
- * class. It is built to keep the typical error on ordinary text
6
- * (English/Spanish, markdown, code) inside ±10%, which is plenty for comparing
7
- * two versions of the same prompt — but do NOT bill anyone from it.
5
+ * class, built for comparing two versions of the same prompt — but do NOT bill
6
+ * anyone from it.
8
7
  *
9
- * **That band is a design target that has not been measured.** It is printed on
10
- * every report and every dollar figure descends from it, and until
11
- * `scripts/measure-token-band.mjs` has been run against the official counting
12
- * endpoint, nothing in this repository establishes that it holds. It is stated
13
- * as one number for all text, which is a further assumption: the branches below
14
- * treat CJK, digits and punctuation quite differently from words, and there is
15
- * no reason those should land on the same accuracy.
8
+ * **Its accuracy is not one number, and the years it was written as one were
9
+ * the mistake.** The branches below treat CJK, digits and punctuation quite
10
+ * differently from words, and there was never a reason those should land on the
11
+ * same accuracy. Measured over 47 samples against the official counting
12
+ * endpoint they do not: the worst error is 3.2% on CJK, 5.6% on Latin prose,
13
+ * 25.1% on code and quoting, and 32.5% on a digit-dominant table. `band.ts`
14
+ * holds the bands those measurements earn and `bandFor(text)` is what a caller
15
+ * should print; the constant below is only the widest of them, for callers that
16
+ * have no text in hand.
16
17
  *
17
- * `test/token-band.test.js` asserts the band per text type as soon as the ground
18
- * truth exists. Until then it says so rather than passing quietly.
18
+ * `test/token-band.test.js` holds every sample against the band `bandFor` gives
19
+ * it, and a sample edited since it was measured fails rather than passing
20
+ * quietly.
19
21
  *
20
22
  * For exact numbers use `countTokensAnthropic` (the official token-counting
21
23
  * endpoint, which is free) or pass your own `TokenCounter`.
22
24
  */
23
25
  /**
24
- * The error band this estimator is published under, as a percentage.
26
+ * The widest band this estimator is published under, as a percentage.
25
27
  *
26
- * **Measured, not chosen, and it has moved three times.** It was `15` for eight
27
- * releases as a design target nobody had checked; the first measurement found two
28
- * of eight samples outside it and it went to `25`; fixing the digit divisor and
29
- * calibrating per language brought it back to `15`. This is the fourth value and
30
- * the first one that is comfortably above what the corpus actually shows.
28
+ * **A history worth keeping, because each value was believed at the time.** It
29
+ * was `15` for eight releases as a design target nobody had checked; the first
30
+ * measurement found two of eight samples outside it and it went to `25`; fixing
31
+ * the digit divisor and calibrating per language brought it back to `15`, and
32
+ * splitting kana from han — Japanese had been +11.2% and Chinese −3.2% under one
33
+ * rule — brought it to `10`. Four values, each an improvement, and all four
34
+ * wrong in the same way.
31
35
  *
32
- * ```
33
- * worst measured error 6.4% (code-heavy, which nothing is fitted to)
34
- * published band 10%
35
- * ```
36
+ * **The corpus they were measured on was the corpus they were fitted to.**
37
+ * Twenty-one samples held thirteen files of Latin prose and exactly one each of
38
+ * code, numeric and punctuation, and those single files were where the constants
39
+ * came from. The worst error it could show was 6.4%, and 10 looked like a
40
+ * comfortable margin over it. Neither figure was about the estimator.
36
41
  *
37
- * **The margin is deliberate and it is not slack.** 6.4 rounded up is 7, and
38
- * publishing 7 would be a tighter claim than twenty-one samples across six text
39
- * types can support: the corpus has no Korean, no Arabic, no Cyrillic prose, no
40
- * mixed-script document, and a seventh text type could easily land at eight. A
41
- * band that becomes false the first time somebody measures something new is the
42
- * exact fault this whole exercise was fixing. Overstating the uncertainty is the
43
- * safe direction for a tool that reports money.
42
+ * **It is no longer one number, and this one is the widest.** A corpus of
43
+ * thirteen prose files and one each of code, numeric and punctuation put the
44
+ * band at 10, and those single files were the set the constants had been fitted
45
+ * to. Measured on forty-seven, the same estimator is 6% out on prose and 33%
46
+ * out on a CSV ledger. `bandFor` in `band.ts` is what a caller that has the
47
+ * text should use.
44
48
  *
45
- * What earned the drop from 15 was **splitting kana from han**. Every CJK
46
- * character was charged one token, which put Japanese at +11.2% — the worst error
47
- * anywhere in the corpus — while Chinese sat at −3.2% under the same rule. Kana
48
- * measure 0.75 tokens per character and han 1.05, and that pair takes the two
49
- * samples to −1.5% and +1.3%. See `KANA_TOKENS_PER_CHAR`.
50
- *
51
- * **Which samples the band rests on matters more than the number.** Eight of the
52
- * twenty-one had a constant fitted to them — seven Latin divisors and the digit
53
- * divisor — so their residuals are optimistic by construction. The two worst
54
- * errors in the corpus, `code-heavy` at 6.4% and `punctuation-heavy` at 5.7%, are
55
- * fitted to nothing at all, and they are what sets this figure.
56
- *
57
- * Exported so every report, README and tool description reads the same number. It
58
- * was a literal in twenty-four files before this, with the only machine-readable
59
- * copy in a test, and `token-band.test.js` now fails any file that states a
60
- * different one.
49
+ * This stays for the callers that do not have it — a figure covering the whole
50
+ * catalogue of text, which can only be the worst of them. Widening it from 10
51
+ * to 33 makes every claim that reads it true where it had been false, at the
52
+ * cost of understating the estimator on prose. That trade is deliberate: a
53
+ * caller with no text cannot know which it is holding, and there is only one
54
+ * safe direction to guess in.
61
55
  */
62
- export declare const ESTIMATE_ERROR_BAND_PCT = 10;
56
+ export declare const ESTIMATE_ERROR_BAND_PCT = 33;
63
57
  /**
64
58
  * Whose tokenizer that band was measured against.
65
59
  *
66
60
  * The number above is not a property of the estimator; it is a property of the
67
- * estimator **against Claude**. Twenty-one samples, one counting endpoint, one
68
- * family. Trazum prices seven, and until somebody runs the harness against the
69
- * others nobody knows what the error is on a GPT or a Gemini prompt.
61
+ * estimator **against Claude**. Forty-seven samples, one counting endpoint, one
62
+ * family. Trazum prices seven, and the two that have since been run are far
63
+ * outside anything published here: DeepSeek 94.5% at worst, Mistral 103.1%. On
64
+ * a GPT or a Gemini prompt nobody has measured it at all, and
65
+ * `measuredForeignError` answers null rather than the nearest number.
70
66
  *
71
67
  * Exported as a name rather than left implicit in a comment because the band
72
68
  * had already leaked out of its domain in three places: an advisory that told a
@@ -1 +1 @@
1
- {"version":3,"file":"tokenizer.d.ts","sourceRoot":"","sources":["../src/tokenizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAKH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,wBAAwB,cAAc,CAAC;AAEpD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAExE;AAmGD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAuHnD;AAED,sDAAsD;AACtD,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAElE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,uBAAuB,GAAG,iBAAiB,CA6BxF"}
1
+ {"version":3,"file":"tokenizer.d.ts","sourceRoot":"","sources":["../src/tokenizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAKH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,wBAAwB,cAAc,CAAC;AAEpD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAExE;AA+HD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAiJnD;AAED,sDAAsD;AACtD,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAElE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,uBAAuB,GAAG,iBAAiB,CA6BxF"}