@trazum/core 1.82.0 → 1.85.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 (58) hide show
  1. package/README.md +2 -2
  2. package/dist/advisories.d.ts.map +1 -1
  3. package/dist/advisories.js +27 -4
  4. package/dist/advisories.js.map +1 -1
  5. package/dist/band.d.ts.map +1 -1
  6. package/dist/band.js +12 -0
  7. package/dist/band.js.map +1 -1
  8. package/dist/i18n/en.d.ts.map +1 -1
  9. package/dist/i18n/en.js +7 -0
  10. package/dist/i18n/en.js.map +1 -1
  11. package/dist/i18n/es.d.ts.map +1 -1
  12. package/dist/i18n/es.js +8 -0
  13. package/dist/i18n/es.js.map +1 -1
  14. package/dist/i18n/types.d.ts +17 -0
  15. package/dist/i18n/types.d.ts.map +1 -1
  16. package/dist/index.d.ts +6 -2
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +4 -2
  19. package/dist/index.js.map +1 -1
  20. package/dist/langsmith.d.ts +104 -0
  21. package/dist/langsmith.d.ts.map +1 -0
  22. package/dist/langsmith.js +270 -0
  23. package/dist/langsmith.js.map +1 -0
  24. package/dist/levers.d.ts +1 -1
  25. package/dist/levers.js +2 -2
  26. package/dist/levers.js.map +1 -1
  27. package/dist/optimize.d.ts +2 -2
  28. package/dist/optimize.d.ts.map +1 -1
  29. package/dist/optimize.js +15 -1
  30. package/dist/optimize.js.map +1 -1
  31. package/dist/pricing.d.ts +98 -3
  32. package/dist/pricing.d.ts.map +1 -1
  33. package/dist/pricing.js +393 -35
  34. package/dist/pricing.js.map +1 -1
  35. package/dist/receipt.d.ts +253 -0
  36. package/dist/receipt.d.ts.map +1 -0
  37. package/dist/receipt.js +111 -0
  38. package/dist/receipt.js.map +1 -0
  39. package/dist/tokenizer.d.ts +4 -2
  40. package/dist/tokenizer.d.ts.map +1 -1
  41. package/dist/tokenizer.js +4 -2
  42. package/dist/tokenizer.js.map +1 -1
  43. package/dist/types.d.ts +148 -1
  44. package/dist/types.d.ts.map +1 -1
  45. package/package.json +1 -1
  46. package/src/advisories.ts +34 -4
  47. package/src/band.ts +12 -0
  48. package/src/i18n/en.ts +9 -0
  49. package/src/i18n/es.ts +10 -0
  50. package/src/i18n/types.ts +18 -0
  51. package/src/index.ts +14 -1
  52. package/src/langsmith.ts +315 -0
  53. package/src/levers.ts +3 -3
  54. package/src/optimize.ts +16 -0
  55. package/src/pricing.ts +430 -30
  56. package/src/receipt.ts +351 -0
  57. package/src/tokenizer.ts +4 -2
  58. package/src/types.ts +144 -0
package/dist/types.d.ts CHANGED
@@ -48,7 +48,7 @@ export interface RuleResult {
48
48
  /** Severity of an advisory: the higher it is, the more money is usually at stake. */
49
49
  export type AdvisorySeverity = 'info' | 'opportunity' | 'warning';
50
50
  /** Every advisory the core can emit. */
51
- export type AdvisoryId = 'context-overflow' | 'context-near-limit' | 'prompt-caching' | 'prompt-caching-not-worth-it' | 'below-cache-minimum' | 'cache-prefix-reorder' | 'batch-api' | 'model-downgrade' | 'tier-signals-conflict' | 'output-dominated' | 'promo-pricing' | 'contradictory-instructions' | 'redundant-examples' | 'restated-output-format' | 'movable-output-schema';
51
+ export type AdvisoryId = 'context-overflow' | 'context-near-limit' | 'prompt-caching' | 'prompt-caching-not-worth-it' | 'below-cache-minimum' | 'cache-prefix-reorder' | 'batch-api' | 'model-downgrade' | 'tier-signals-conflict' | 'output-dominated' | 'promo-pricing' | 'model-retired' | 'contradictory-instructions' | 'redundant-examples' | 'restated-output-format' | 'movable-output-schema';
52
52
  /** A recommendation that does NOT modify the prompt, only informs. */
53
53
  export interface Advisory {
54
54
  id: AdvisoryId;
@@ -125,6 +125,64 @@ export type CachingMode =
125
125
  * what it says.
126
126
  */
127
127
  export type Capability = 'small' | 'mid' | 'large' | 'frontier' | 'unknown';
128
+ /**
129
+ * What makes a conditional rate apply, as data a machine can evaluate.
130
+ *
131
+ * Deliberately a closed union rather than a predicate function. A catalogue
132
+ * entry is reviewed the way a price is reviewed, and a reviewer can check
133
+ * "peak is 01:00-04:00 and 06:00-10:00 UTC on weekdays" against a provider's
134
+ * page; nobody can review a closure. It also means the condition survives
135
+ * `JSON.stringify`, which matters because the catalogue can be overlaid from a
136
+ * file.
137
+ */
138
+ export type TierCondition =
139
+ /**
140
+ * The prompt is larger than `tokens` input tokens.
141
+ *
142
+ * Decidable only where the token count is known, which is most of the places
143
+ * that price a specific call and none of the places that merely rank models.
144
+ * `effectivePricing` says which happened rather than guessing.
145
+ */
146
+ {
147
+ kind: 'input-tokens-above';
148
+ tokens: number;
149
+ }
150
+ /**
151
+ * The call falls inside one of `hours` in UTC, optionally on weekdays only.
152
+ *
153
+ * Decidable everywhere, because every caller already passes the date it is
154
+ * pricing for. `hours` lists the hour each window *starts*, so 01:00-04:00
155
+ * is `[1, 2, 3]` and not `[1, 4]`: an endpoint convention is the kind of
156
+ * thing two readers disagree about silently.
157
+ */
158
+ | {
159
+ kind: 'utc-hours';
160
+ hours: number[];
161
+ weekdaysOnly: boolean;
162
+ };
163
+ /**
164
+ * A rate that applies when its condition holds.
165
+ *
166
+ * Deliberately carries no multipliers of its own, and the first draft did. The
167
+ * reasoning for adding them was that DeepSeek halves the cache-hit price at
168
+ * off-peak along with everything else, so a cache read priced off the base
169
+ * would be wrong about the money — which is true of the *price* and false of
170
+ * the *ratio*: $0.007 against $0.22 and $0.014 against $0.44 are the same
171
+ * 3.18% to the last digit, on both models. Multiplying a tier's own input rate
172
+ * by the model's multiplier already gives the right answer.
173
+ *
174
+ * It was removed because the guard written to prove it mattered could not: with
175
+ * the tier multiplier equal to the base one, dropping it changed nothing and
176
+ * the test passed either way. An option nothing can distinguish from its
177
+ * absence is a claim nobody checks, which is worse than not having it.
178
+ */
179
+ export interface PricingTier {
180
+ /** Short, stable, and printed: a reader has to be able to see which applied. */
181
+ id: string;
182
+ when: TierCondition;
183
+ inputPerMTok: number;
184
+ outputPerMTok: number;
185
+ }
128
186
  export interface ModelPricing {
129
187
  id: string;
130
188
  displayName: string;
@@ -156,6 +214,32 @@ export interface ModelPricing {
156
214
  * buy is advice that wastes their time.
157
215
  */
158
216
  recommendable?: boolean;
217
+ /**
218
+ * Set when the provider refused a real request for this id.
219
+ *
220
+ * A retired model keeps its price and loses its future. Both halves matter:
221
+ * a log full of `deepseek-v3` calls records money that was genuinely spent,
222
+ * so deleting the row would make somebody's own history unpriceable — and a
223
+ * *new* call on that id will not happen at all, so quoting it as an option is
224
+ * a number for a question nobody can ask.
225
+ *
226
+ * `on` is the day `scripts/check-model-availability.mjs` was refused, and
227
+ * `because` is the provider's own sentence, quoted rather than paraphrased.
228
+ * Neither is a judgement, and neither implies anything about what the
229
+ * replacement costs: that is a price, and a price comes off the provider's
230
+ * own page or not at all.
231
+ *
232
+ * A retired model is never recommended, never offered as a cheaper
233
+ * alternative and never chosen as a tier's representative, in the same places
234
+ * `recommendable: false` is honoured — this is a stronger statement than that
235
+ * one and must not be weaker in effect.
236
+ */
237
+ retired?: {
238
+ /** ISO date the refusal was recorded. */
239
+ on: string;
240
+ /** What the provider answered, in the provider's words. */
241
+ because: string;
242
+ };
159
243
  /** Capability, on a vendor-neutral scale. */
160
244
  capability: Capability;
161
245
  /**
@@ -171,6 +255,29 @@ export interface ModelPricing {
171
255
  /** ISO date (inclusive) the promotional price applies until. */
172
256
  until: string;
173
257
  };
258
+ /**
259
+ * Rates that apply only under a stated condition.
260
+ *
261
+ * The catalogue held one input price and one output price per model until a
262
+ * real credential was pointed at the providers and two of them turned out not
263
+ * to charge that way:
264
+ *
265
+ * - **DeepSeek V4 bills by the clock.** Peak is 01:00-04:00 and 06:00-10:00
266
+ * UTC, Monday to Friday, and off-peak is exactly half. That is 35 hours of
267
+ * 168, so the common case is the cheap one and a single number would have
268
+ * been wrong by 2x in whichever direction it was chosen.
269
+ * - **Gemini 3.1 Pro bills by prompt size**, $2/$12 up to 200k input tokens
270
+ * and $4/$18 above it.
271
+ *
272
+ * Both are *conditions*, so both are written as data rather than as prose in
273
+ * `notes`: a note is something a reader has to apply by hand, and this
274
+ * product exists to stop people doing arithmetic by hand.
275
+ *
276
+ * The base `inputPerMTok` and `outputPerMTok` stay the rate that applies when
277
+ * no condition matches, which keeps every model that has no tiers unchanged
278
+ * and keeps this field optional in effect as well as in the type.
279
+ */
280
+ tiers?: PricingTier[];
174
281
  /**
175
282
  * Other ids that bill at exactly this rate.
176
283
  *
@@ -260,6 +367,32 @@ export interface OptimizeOptions {
260
367
  /** Counts tokens in a text. Synchronous so it can run inside the rule loop. */
261
368
  export type TokenCounter = (text: string) => number;
262
369
  /** Full result of an optimisation. */
370
+ /** Which counter produced a figure, named rather than left as *external*. */
371
+ export interface TokenProvenance {
372
+ /**
373
+ * A stable identifier for the counter, not a sentence.
374
+ *
375
+ * `anthropic-count-tokens` for the official endpoint,
376
+ * `openai-tiktoken` for the local rank tables. A consumer branches on this;
377
+ * `detail` is what a person reads.
378
+ */
379
+ counter: string;
380
+ /** The model the count was made for, since an encoding is a property of one. */
381
+ model: string;
382
+ /**
383
+ * What a reader needs to know about this particular count -- the encoding, or
384
+ * the endpoint. Free text, and never the only place a fact lives.
385
+ */
386
+ detail: string;
387
+ /**
388
+ * Whether the count came from this machine or from a request.
389
+ *
390
+ * The one distinction a privacy-conscious reader actually cares about: a
391
+ * local counter read the prompt in this process, a remote one sent it
392
+ * somewhere. Both are `external` to the heuristic, and only one leaves.
393
+ */
394
+ where: 'local' | 'remote';
395
+ }
263
396
  export interface OptimizationResult {
264
397
  original: string;
265
398
  optimized: string;
@@ -276,6 +409,20 @@ export interface OptimizationResult {
276
409
  locale: Locale;
277
410
  /** How tokens were counted, so the caller knows the margin of error. */
278
411
  tokenSource: 'heuristic' | 'external';
412
+ /**
413
+ * Which counter produced the figures, when it was not the heuristic.
414
+ *
415
+ * `tokenSource` says *not the estimator*, which is the question a margin of
416
+ * error depends on. It does not say **whose** counter, and once more than one
417
+ * external counter exists that difference matters: a count from Anthropic's
418
+ * endpoint and a count from OpenAI's rank tables are both `external` and are
419
+ * not interchangeable, and a reader repricing one workload against another
420
+ * model needs to know which they are holding.
421
+ *
422
+ * `null` when `tokenSource` is `heuristic`, so the two fields cannot drift
423
+ * into disagreeing about whether anything external was used at all.
424
+ */
425
+ countedBy: TokenProvenance | null;
279
426
  /**
280
427
  * Where the prices came from.
281
428
  *
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trazum/core",
3
- "version": "1.82.0",
3
+ "version": "1.85.0",
4
4
  "description": "Trazum core: priced advisories for LLM prompts (caching, model tier, batching, schemas), plus deterministic trimming, token counting and pricing.",
5
5
  "license": "MIT",
6
6
  "author": "David Mu\u00f1oz Rey",
package/src/advisories.ts CHANGED
@@ -2,7 +2,13 @@ import { analyzeCachePrefix } from './cache.js';
2
2
  import { getMessages } from './i18n/index.js';
3
3
  import type { Locale } from './i18n/types.js';
4
4
  import { COMPLEX_SIGNALS, SIMPLE_SIGNALS } from './phrases.js';
5
- import { BUNDLED_CATALOGUE, effectivePricing, modelFrom, multipliersFor } from './pricing.js';
5
+ import {
6
+ BUNDLED_CATALOGUE,
7
+ effectivePricing,
8
+ isOffered,
9
+ modelFrom,
10
+ multipliersFor,
11
+ } from './pricing.js';
6
12
  import type { PricingCatalogue } from './pricing.js';
7
13
  import { formatUsd } from './savings.js';
8
14
  import { analyzeExamples, findContradictions, findMovableSchema,
@@ -124,9 +130,10 @@ function cheapestInTier(
124
130
  (m) =>
125
131
  m.tier === tier &&
126
132
  m.provider === provider &&
127
- // Not generally available: recommending a model the reader cannot call is
128
- // worse than recommending nothing.
129
- m.recommendable !== false,
133
+ // Not generally available, or refused outright by the provider:
134
+ // recommending a model the reader cannot call is worse than
135
+ // recommending nothing. Both halves live in `isOffered`.
136
+ isOffered(m),
130
137
  );
131
138
  if (candidates.length === 0) return undefined;
132
139
  return candidates.reduce((best, m) =>
@@ -639,6 +646,29 @@ export function buildAdvisories(
639
646
  });
640
647
  }
641
648
 
649
+ if (model.retired) {
650
+ /**
651
+ * The most severe thing this function can say about a model, and it is
652
+ * placed before the promotional note deliberately: a price that is about to
653
+ * change matters less than a model that cannot be called at all.
654
+ *
655
+ * Not suppressed when the reader asked for this model by name. They asked
656
+ * because something in their world still says this id, and the whole value
657
+ * of the answer is that it no longer works.
658
+ */
659
+ advisories.push({
660
+ id: 'model-retired',
661
+ severity: 'warning',
662
+ ...t.advisories.modelRetired({
663
+ modelName: model.displayName,
664
+ modelId: model.id,
665
+ on: model.retired.on,
666
+ because: model.retired.because,
667
+ }),
668
+ estimatedMonthlyUsd: null,
669
+ });
670
+ }
671
+
642
672
  if (promoApplied && model.promo) {
643
673
  advisories.push({
644
674
  id: 'promo-pricing',
package/src/band.ts CHANGED
@@ -198,6 +198,18 @@ export const MEASURED_FOREIGN_ERROR_PCT: Readonly<Record<string, number>> = {
198
198
  deepseek: 94.5,
199
199
  /** Worst on `german-technical`, where even Latin prose is more than twice out. */
200
200
  mistral: 103.1,
201
+ /**
202
+ * Worst on `german-prose`, and the worst of the four.
203
+ *
204
+ * The measurement sat in this repository unclaimed for a release: the
205
+ * fixture was written by a real key against `gpt-5`, and this file went on
206
+ * answering `null`, so every report told a GPT user nobody had looked. The
207
+ * figure is not a surprise -- `o200k_base` packs Latin prose far more densely
208
+ * than the estimator's Claude-calibrated divisors expect -- but a report
209
+ * saying *unmeasured* where the answer is *more than twice out* is the
210
+ * flattering direction, and this whole file exists to refuse that.
211
+ */
212
+ openai: 112.4,
201
213
  };
202
214
 
203
215
  /**
package/src/i18n/en.ts CHANGED
@@ -218,6 +218,15 @@ export const en: CoreMessages = {
218
218
  detail: `${modelName} has introductory pricing of ${promoInput}/${promoOutput} per million tokens until ${until}. After that date it moves to ${listInput}/${listOutput}: your bill goes up even if you change nothing.`,
219
219
  }),
220
220
 
221
+ modelRetired: ({ modelName, modelId, on, because }) => ({
222
+ title: `${modelName} is priced here and refused by its provider`,
223
+ detail:
224
+ `A real request for \`${modelId}\` was answered with an error on ${on}: "${because}" `
225
+ + 'The price above is still the right one for calls already in your log, because that '
226
+ + 'money was spent. A new call on this id will not run. Nothing here proposes what the '
227
+ + 'replacement costs: that figure comes off the provider\'s own pricing page or not at all.',
228
+ }),
229
+
221
230
  contradictoryInstructions: ({
222
231
  axis,
223
232
  firstValue,
package/src/i18n/es.ts CHANGED
@@ -202,6 +202,16 @@ export const es: CoreMessages = {
202
202
  detail: `${modelName} tiene precio de lanzamiento ${promoInput}/${promoOutput} por millón de tokens hasta el ${until}. A partir de esa fecha pasa a ${listInput}/${listOutput}: tu factura subirá aunque no cambies nada.`,
203
203
  }),
204
204
 
205
+ modelRetired: ({ modelName, modelId, on, because }) => ({
206
+ title: `${modelName} está tarifado aquí y su proveedor lo rechaza`,
207
+ detail:
208
+ `Una petición real a \`${modelId}\` se respondió con un error el ${on}: "${because}" `
209
+ + 'El precio de arriba sigue siendo el correcto para las llamadas que ya están en tu '
210
+ + 'registro, porque ese dinero se gastó. Una llamada nueva a este id no se ejecutará. '
211
+ + 'Aquí no se propone lo que cuesta el reemplazo: esa cifra sale de la página de precios '
212
+ + 'del proveedor o no sale.',
213
+ }),
214
+
205
215
  contradictoryInstructions: ({
206
216
  axis,
207
217
  firstValue,
package/src/i18n/types.ts CHANGED
@@ -160,6 +160,23 @@ export interface OutputDominatedParams {
160
160
  inputUsd: string;
161
161
  }
162
162
 
163
+ /**
164
+ * The provider's own refusal, carried through to the reader unchanged.
165
+ *
166
+ * `because` is quoted rather than summarised: it is the only part of this
167
+ * message that is evidence, it usually names the replacement, and a paraphrase
168
+ * of a provider's error is a sentence this repository would then be the author
169
+ * of.
170
+ */
171
+ export interface ModelRetiredParams {
172
+ modelName: string;
173
+ modelId: string;
174
+ /** ISO date the refusal was recorded. */
175
+ on: string;
176
+ /** The provider's own words. */
177
+ because: string;
178
+ }
179
+
163
180
  export interface PromoPricingParams {
164
181
  modelName: string;
165
182
  promoInput: number;
@@ -287,6 +304,7 @@ export interface CoreMessages {
287
304
  tierSignalsConflict(p: TierSignalsConflictParams): LocalizedMessage;
288
305
  outputDominated(p: OutputDominatedParams): LocalizedMessage;
289
306
  promoPricing(p: PromoPricingParams): LocalizedMessage;
307
+ modelRetired(p: ModelRetiredParams): LocalizedMessage;
290
308
  contradictoryInstructions(p: ContradictoryInstructionsParams): LocalizedMessage;
291
309
  redundantExamples(p: RedundantExamplesParams): LocalizedMessage;
292
310
  restatedOutputFormat(p: RestatedOutputFormatParams): LocalizedMessage;
package/src/index.ts CHANGED
@@ -52,6 +52,14 @@ export { explainGateFailure, gateMargin, GATE_MARGIN_TIGHT } from './gate-explai
52
52
  export { measuredUsage, labelCoverage, MIN_SCALE_DAYS, SCALE_TO_DAYS } from './measured-profile.js';
53
53
  export { assignSources, fleetRollup } from './fleet.js';
54
54
  export { rollUp } from './rollup.js';
55
+ export { receiptFrom, RECEIPT_LINE_FIELDS } from './receipt.js';
56
+ export type {
57
+ ReceiptDocument,
58
+ ReceiptGap,
59
+ ReceiptLine,
60
+ ReceiptOptions,
61
+ ReceiptPricing,
62
+ } from './receipt.js';
55
63
  export { heartbeats } from './heartbeat.js';
56
64
  export { ruleYield } from './rule-yield.js';
57
65
  export { buildPlan, planLabelName, parsePlanDocument, PLAN_ACTION_KINDS } from './plan.js';
@@ -218,6 +226,8 @@ export { litellmRecords, looksLikeLiteLlm } from './litellm.js';
218
226
  export type { LiteLlmConversion, LiteLlmRecord } from './litellm.js';
219
227
  export { heliconeRecords, looksLikeHelicone } from './helicone.js';
220
228
  export type { HeliconeConversion, HeliconeRecord } from './helicone.js';
229
+ export { langsmithRecords, looksLikeLangsmith } from './langsmith.js';
230
+ export type { LangsmithConversion, LangsmithRecord } from './langsmith.js';
221
231
  export type { ClaudeCodeConversion, ClaudeCodeRecord } from './claude-code.js';
222
232
  export { positionReport } from './position-report.js';
223
233
  export type {
@@ -383,6 +393,8 @@ export {
383
393
  DEFAULT_MODEL,
384
394
  COST_MULTIPLIERS,
385
395
  PRICING_LAST_REVIEWED,
396
+ STALE_PRICING_DAYS,
397
+ PROVIDER_REVIEWED,
386
398
  reviewAgeDays,
387
399
  BUNDLED_CATALOGUE,
388
400
  getModel,
@@ -392,6 +404,7 @@ export {
392
404
  modelFrom,
393
405
  cheapestOfTierIn,
394
406
  multipliersFor,
407
+ isOffered,
395
408
  } from './pricing.js';
396
409
  export type { PricingCatalogue } from './pricing.js';
397
410
  export type { CachingMode, Capability, CostMultipliers } from './types.js';
@@ -557,7 +570,7 @@ export { NothingToPrune, plannedCalls, pruneExamples, withoutExample } from './p
557
570
  export type { ExampleContribution, PruneOptions, PruneReport } from './prune.js';
558
571
 
559
572
  // Golden-set evaluation (optional, costs three LLM calls per case)
560
- export { evaluate, fillPrompt, verdictFor } from './evaluate.js';
573
+ export { agreement, evaluate, fillPrompt, pooled, verdictFor } from './evaluate.js';
561
574
  export type { EvalCase, EvalReport, EvalVerdict, EvaluateOptions } from './evaluate.js';
562
575
 
563
576
  // Comparing two prompt versions