@deepstrike/sdk 0.2.60 → 0.2.61

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.
@@ -1575,6 +1575,8 @@ export class RuntimeRunner {
1575
1575
  let turnOutputTokens = 0;
1576
1576
  let turnCacheReadTokens = 0;
1577
1577
  let turnCacheCreationTokens = 0;
1578
+ let turnCacheTelemetryStatus = "unavailable";
1579
+ let turnCacheTelemetrySource;
1578
1580
  let turnCacheReadBySlot;
1579
1581
  let turnStopReason;
1580
1582
  const providerPlan = createProviderRequestPlanForProvider(this.opts.provider, context, tools, ext);
@@ -1640,9 +1642,36 @@ export class RuntimeRunner {
1640
1642
  // P0-C: capture the prompt-cache split for the tool-gating hit-rate baseline.
1641
1643
  turnCacheReadTokens = usageEvt.cacheReadInputTokens ?? 0;
1642
1644
  turnCacheCreationTokens = usageEvt.cacheCreationInputTokens ?? 0;
1645
+ turnCacheTelemetryStatus = usageEvt.cacheTelemetryStatus
1646
+ ?? usageEvt.providerUsage?.cacheTelemetryStatus
1647
+ ?? ((usageEvt.cacheReadInputTokens ?? 0) > 0 || (usageEvt.cacheCreationInputTokens ?? 0) > 0
1648
+ ? "measured"
1649
+ : "unavailable");
1650
+ turnCacheTelemetrySource = usageEvt.cacheTelemetrySource ?? usageEvt.providerUsage?.cacheTelemetrySource;
1643
1651
  // I1: per-slot attribution forwarded into TurnMetrics. Undefined when the provider
1644
1652
  // doesn't honor cache_control (OpenAI-family auto-cache).
1645
1653
  turnCacheReadBySlot = usageEvt.cacheReadInputTokensBySlot;
1654
+ // spc_024-06: postflight observed input is the authority (INV-024-08). Feed it back
1655
+ // as a durable measurement fact for this exact request fingerprint so replay reuses
1656
+ // the observed truth instead of re-counting (or trusting the preflight estimate).
1657
+ if (turnInputTokens > 0) {
1658
+ const postflight = recordPromptMeasurement(providerPlan, {
1659
+ inputTokens: turnInputTokens,
1660
+ source: { kind: "postflight" },
1661
+ confidence: "exact",
1662
+ });
1663
+ recordedMeasurements.set(providerPlan.fingerprint, postflight);
1664
+ await this.opts.sessionLog.append(sessionId, {
1665
+ kind: "prompt_measured",
1666
+ turn: runtime.turn(),
1667
+ measurement: {
1668
+ requestFingerprint: postflight.requestFingerprint,
1669
+ inputTokens: postflight.inputTokens,
1670
+ source: postflight.source,
1671
+ confidence: postflight.confidence,
1672
+ },
1673
+ });
1674
+ }
1646
1675
  // Phase 4: stop_reason drives the kernel's max-output-tokens recovery. The closing
1647
1676
  // usage frame carries it; keep the last non-empty value seen this turn.
1648
1677
  if (usageEvt.stopReason)
@@ -1782,6 +1811,10 @@ export class RuntimeRunner {
1782
1811
  inputTokens: turnInputTokens,
1783
1812
  cacheReadTokens: turnCacheReadTokens,
1784
1813
  cacheCreationTokens: turnCacheCreationTokens,
1814
+ cacheTelemetryStatus: turnCacheTelemetryStatus,
1815
+ ...(turnCacheTelemetrySource ? { cacheTelemetrySource: turnCacheTelemetrySource } : {}),
1816
+ requestFingerprint: providerPlan.fingerprint,
1817
+ stablePrefixFingerprint: providerPlan.stablePrefixFingerprint,
1785
1818
  ...(turnCacheReadBySlot ? { cacheReadTokensBySlot: turnCacheReadBySlot } : {}),
1786
1819
  });
1787
1820
  }
package/dist/types.d.ts CHANGED
@@ -151,10 +151,9 @@ export interface UsageEvent extends StreamEvent {
151
151
  cacheReadInputTokens?: number;
152
152
  /** Prompt tokens written to cache this request (billed ~1.25x). Subset of inputTokens. */
153
153
  cacheCreationInputTokens?: number;
154
- /** I1: per-slot pro-rata attribution of `cacheReadInputTokens`. Estimated, not authoritative —
155
- * Anthropic returns a single cache-read total, so the SDK divides it evenly across the slots
156
- * that carried a `cache_control` breakpoint on the request. Missing when the provider doesn't
157
- * honor `cache_control` (OpenAI-family auto-cache) or when no breakpoints were placed. */
154
+ cacheTelemetryStatus?: CacheTelemetryStatus;
155
+ cacheTelemetrySource?: CacheTelemetrySource;
156
+ /** Reserved for provider-authoritative per-slot data. DeepStrike does not estimate this field. */
158
157
  cacheReadInputTokensBySlot?: {
159
158
  system?: number;
160
159
  tools?: number;
@@ -339,12 +338,16 @@ export interface ProviderUsage {
339
338
  outputTokens: number;
340
339
  cacheReadInputTokens?: number;
341
340
  cacheCreationInputTokens?: number;
341
+ cacheTelemetryStatus?: CacheTelemetryStatus;
342
+ cacheTelemetrySource?: CacheTelemetrySource;
342
343
  /** Output tokens spent on hidden reasoning (OpenAI `completion_tokens_details.reasoning_tokens` /
343
344
  * Responses `output_tokens_details.reasoning_tokens`). A SUBSET of `outputTokens`, not additional
344
345
  * — vendors that don't report a separate count (Anthropic, Gemini via this SDK) leave this unset
345
346
  * rather than guessing. */
346
347
  reasoningTokens?: number;
347
348
  }
349
+ export type CacheTelemetryStatus = "measured" | "unavailable";
350
+ export type CacheTelemetrySource = "anthropic_usage" | "openai_prompt_details" | "deepseek_prompt_cache" | "gemini_usage";
348
351
  /** Node-side mirror of the reserved Rust `context::measurement` types — where a
349
352
  * preflight token count came from. Field names/shape intentionally match the Rust
350
353
  * `MeasurementSource` enum (`kind`-tagged, snake_case variant names) so the two sides can be
@@ -523,7 +526,7 @@ export interface LLMProvider {
523
526
  * capability remains directly callable, but no dispatch trigger is enabled until request
524
527
  * fingerprinting and durable measurement semantics are defined.
525
528
  */
526
- countTokens?(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): Promise<PromptMeasurement>;
529
+ countTokens?(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>, state?: ProviderRunState): Promise<PromptMeasurement>;
527
530
  complete(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): Promise<Message>;
528
531
  stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>, state?: ProviderRunState,
529
532
  /** #2-B-ii: when provided, a preempting `InterruptNow` (or `interrupt()`) aborts the in-flight
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepstrike/sdk",
3
- "version": "0.2.60",
3
+ "version": "0.2.61",
4
4
  "description": "DeepStrike Node.js SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -72,9 +72,9 @@
72
72
  },
73
73
  "dependencies": {
74
74
  "@anthropic-ai/sdk": "^0.99.0",
75
- "@deepstrike/core": "0.2.60",
75
+ "@deepstrike/core": "0.2.61",
76
76
  "@google/generative-ai": "^0.24.1",
77
- "openai": "^5.23.2"
77
+ "openai": "^7.5.0"
78
78
  },
79
79
  "devDependencies": {
80
80
  "@types/jest": "^30.0.0",