retrace-sdk 0.15.0 → 0.16.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.
@@ -3,6 +3,7 @@ import { genId, nowIso, truncateJson, wasTruncated } from "../utils.js";
3
3
  import { isReplaying, consumeCassetteEntry } from "../replay.js";
4
4
  import { emitAnthropicToolCalls, emitAnthropicToolResults, parseToolArgs, resetToolResultDedup, extractToolSchemas, extractSamplingParams } from "./tool-spans.js";
5
5
  import { dispatchRegisterOpenSpan, dispatchUnregisterOpenSpan } from "./_dispatch.js";
6
+ import { UNKNOWN_MODEL_PRICING, costFromRate } from "../pricing.js";
6
7
  const PRICING = {
7
8
  "claude-opus-4.7": [5.0, 25.0],
8
9
  "claude-opus-4.6": [5.0, 25.0],
@@ -17,9 +18,10 @@ const PRICING = {
17
18
  function calcCost(model, inputTokens, outputTokens) {
18
19
  for (const [key, p] of Object.entries(PRICING)) {
19
20
  if (model.includes(key))
20
- return (inputTokens * p[0] + outputTokens * p[1]) / 1_000_000;
21
+ return costFromRate(p, inputTokens, outputTokens);
21
22
  }
22
- return 0;
23
+ // Unknown model — never cost $0 (that silently disarms USD budget ceilings). Conservative fallback.
24
+ return costFromRate(UNKNOWN_MODEL_PRICING, inputTokens, outputTokens);
23
25
  }
24
26
  let originalCreate = null;
25
27
  let installed = false;
@@ -2,6 +2,7 @@ import { SpanType } from "../trace.js";
2
2
  import { genId, nowIso, truncateJson } from "../utils.js";
3
3
  import { dispatchRegisterOpenSpan, dispatchUnregisterOpenSpan, captureActiveSpanEmit } from "./_dispatch.js";
4
4
  import { emitGeminiToolCalls, emitGeminiToolResults, resetToolResultDedup, extractToolSchemas, extractSamplingParams } from "./tool-spans.js";
5
+ import { UNKNOWN_MODEL_PRICING, costFromRate } from "../pricing.js";
5
6
  const PRICING = {
6
7
  "gemini-3.1-flash-lite": [0.10, 0.40],
7
8
  "gemini-3.1-flash": [0.50, 3.0],
@@ -15,8 +16,10 @@ const PRICING = {
15
16
  "gemini-2.0-flash-lite": [0.05, 0.20],
16
17
  };
17
18
  function calcCost(model, inputTokens, outputTokens) {
18
- const p = PRICING[model] || [0, 0];
19
- return (inputTokens * p[0] + outputTokens * p[1]) / 1_000_000;
19
+ // Exact-match table (substring matching would mis-rank "…-flash" vs "…-flash-lite"); an unknown
20
+ // model falls back to a conservative non-zero rate so USD budget ceilings still engage.
21
+ const p = PRICING[model] ?? UNKNOWN_MODEL_PRICING;
22
+ return costFromRate(p, inputTokens, outputTokens);
20
23
  }
21
24
  let onSpanCallback = null;
22
25
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -5,6 +5,7 @@ import { getConfig } from "../config.js";
5
5
  import { RetraceRateLimitError, RetraceAuthError, RetraceConnectionError } from "../errors.js";
6
6
  import { emitOpenAIToolCalls, emitOpenAIToolResults, parseToolArgs, resetToolResultDedup, extractToolSchemas, extractSamplingParams } from "./tool-spans.js";
7
7
  import { dispatchRegisterOpenSpan, dispatchUnregisterOpenSpan } from "./_dispatch.js";
8
+ import { UNKNOWN_MODEL_PRICING, costFromRate } from "../pricing.js";
8
9
  /** Hardcoded fallback pricing ($/1M tokens: [input, output]). Updated periodically. */
9
10
  const FALLBACK_PRICING = {
10
11
  "gpt-5.5-pro": [30.0, 180.0],
@@ -55,9 +56,10 @@ function calcCost(model, inputTokens, outputTokens) {
55
56
  const pricing = livePricing || FALLBACK_PRICING;
56
57
  for (const [key, p] of Object.entries(pricing)) {
57
58
  if (model.includes(key))
58
- return (inputTokens * p[0] + outputTokens * p[1]) / 1_000_000;
59
+ return costFromRate(p, inputTokens, outputTokens);
59
60
  }
60
- return 0;
61
+ // Unknown model — never cost $0 (that silently disarms USD budget ceilings). Conservative fallback.
62
+ return costFromRate(UNKNOWN_MODEL_PRICING, inputTokens, outputTokens);
61
63
  }
62
64
  let originalCreate = null;
63
65
  let installed = false;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Conservative fallback pricing for models not present in an interceptor's price table.
3
+ *
4
+ * A model that matches no key (a brand-new release, a fine-tune, an OpenRouter alias) would
5
+ * otherwise be costed at $0 — and a $0 cost silently disarms USD budget ceilings in the enforcement
6
+ * gate (the gate trips on estimated USD per run). We instead cost unknown models at a conservative
7
+ * mid/high frontier rate so a budget cap still engages; the value self-corrects the moment the
8
+ * server price table (synced via /api/v1/pricing/models) learns the model.
9
+ *
10
+ * $/1M tokens: [input, output].
11
+ */
12
+ export declare const UNKNOWN_MODEL_PRICING: readonly [number, number];
13
+ /** Cost in USD from an [input, output] $/1M-token rate. */
14
+ export declare function costFromRate(rate: readonly [number, number], inputTokens: number, outputTokens: number): number;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Conservative fallback pricing for models not present in an interceptor's price table.
3
+ *
4
+ * A model that matches no key (a brand-new release, a fine-tune, an OpenRouter alias) would
5
+ * otherwise be costed at $0 — and a $0 cost silently disarms USD budget ceilings in the enforcement
6
+ * gate (the gate trips on estimated USD per run). We instead cost unknown models at a conservative
7
+ * mid/high frontier rate so a budget cap still engages; the value self-corrects the moment the
8
+ * server price table (synced via /api/v1/pricing/models) learns the model.
9
+ *
10
+ * $/1M tokens: [input, output].
11
+ */
12
+ export const UNKNOWN_MODEL_PRICING = [5.0, 15.0];
13
+ /** Cost in USD from an [input, output] $/1M-token rate. */
14
+ export function costFromRate(rate, inputTokens, outputTokens) {
15
+ return (inputTokens * rate[0] + outputTokens * rate[1]) / 1_000_000;
16
+ }
package/dist/telemetry.js CHANGED
@@ -14,7 +14,7 @@ import { getConfig } from "./config.js";
14
14
  const ANON_ID = Math.random().toString(16).slice(2, 18);
15
15
  const DISABLED = new Set(["0", "false", "no", "off"]);
16
16
  // Keep in sync with package.json version.
17
- const SDK_VERSION = "0.15.0";
17
+ const SDK_VERSION = "0.16.0";
18
18
  function enabled() {
19
19
  return !DISABLED.has((process.env.RETRACE_TELEMETRY ?? "1").trim().toLowerCase());
20
20
  }
package/dist/transport.js CHANGED
@@ -2,7 +2,7 @@ import { getConfig } from "./config.js";
2
2
  import { classifyServerSignal } from "./errors.js";
3
3
  // Client identifier sent on every request so the backend can attribute SDK usage/version.
4
4
  // Keep in sync with package.json on release.
5
- const CLIENT_ID = "typescript-sdk/0.15.0";
5
+ const CLIENT_ID = "typescript-sdk/0.16.0";
6
6
  // ─── Runtime-agnostic WebSocket ──────────────────────────────────────────────
7
7
  // Prefer the global Web `WebSocket` (Node 20+, Bun, Deno, browsers, and every edge runtime); fall
8
8
  // back to the OPTIONAL `ws` package only on older Node that lacks a global. Both expose the standard
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "retrace-sdk",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "description": "The execution replay engine for AI agents. Record, replay, fork, and share agent executions.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",