agent-trace 0.2.4 → 0.2.5

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 (2) hide show
  1. package/agent-trace.cjs +123 -87
  2. package/package.json +1 -1
package/agent-trace.cjs CHANGED
@@ -26019,6 +26019,109 @@ function toTimelineEventFromClickHouseRow(row) {
26019
26019
  };
26020
26020
  }
26021
26021
 
26022
+ // packages/schema/src/pricing.ts
26023
+ var MODEL_PRICING = [
26024
+ // ── Opus family ──────────────────────────────────────────
26025
+ // Opus 4.5 / 4.6 — $5 in, $25 out
26026
+ ["claude-opus-4-6", {
26027
+ inputPerToken: 5 / 1e6,
26028
+ outputPerToken: 25 / 1e6,
26029
+ cacheReadPerToken: 0.5 / 1e6,
26030
+ cacheWritePerToken: 6.25 / 1e6
26031
+ }],
26032
+ ["claude-opus-4-5", {
26033
+ inputPerToken: 5 / 1e6,
26034
+ outputPerToken: 25 / 1e6,
26035
+ cacheReadPerToken: 0.5 / 1e6,
26036
+ cacheWritePerToken: 6.25 / 1e6
26037
+ }],
26038
+ // Opus 4.1 / 4.0 — $15 in, $75 out
26039
+ ["claude-opus-4-1", {
26040
+ inputPerToken: 15 / 1e6,
26041
+ outputPerToken: 75 / 1e6,
26042
+ cacheReadPerToken: 1.5 / 1e6,
26043
+ cacheWritePerToken: 18.75 / 1e6
26044
+ }],
26045
+ ["claude-opus-4", {
26046
+ inputPerToken: 15 / 1e6,
26047
+ outputPerToken: 75 / 1e6,
26048
+ cacheReadPerToken: 1.5 / 1e6,
26049
+ cacheWritePerToken: 18.75 / 1e6
26050
+ }],
26051
+ // ── Sonnet family ────────────────────────────────────────
26052
+ // Sonnet 4.x — $3 in, $15 out
26053
+ ["claude-sonnet-4", {
26054
+ inputPerToken: 3 / 1e6,
26055
+ outputPerToken: 15 / 1e6,
26056
+ cacheReadPerToken: 0.3 / 1e6,
26057
+ cacheWritePerToken: 3.75 / 1e6
26058
+ }],
26059
+ // ── Haiku family ─────────────────────────────────────────
26060
+ // Haiku 4.5 — $1 in, $5 out
26061
+ ["claude-haiku-4", {
26062
+ inputPerToken: 1 / 1e6,
26063
+ outputPerToken: 5 / 1e6,
26064
+ cacheReadPerToken: 0.1 / 1e6,
26065
+ cacheWritePerToken: 1.25 / 1e6
26066
+ }],
26067
+ // ── Legacy 3.x models ───────────────────────────────────
26068
+ ["claude-3-5-sonnet", {
26069
+ inputPerToken: 3 / 1e6,
26070
+ outputPerToken: 15 / 1e6,
26071
+ cacheReadPerToken: 0.3 / 1e6,
26072
+ cacheWritePerToken: 3.75 / 1e6
26073
+ }],
26074
+ ["claude-3-5-haiku", {
26075
+ inputPerToken: 0.8 / 1e6,
26076
+ outputPerToken: 4 / 1e6,
26077
+ cacheReadPerToken: 0.08 / 1e6,
26078
+ cacheWritePerToken: 1 / 1e6
26079
+ }],
26080
+ ["claude-3-opus", {
26081
+ inputPerToken: 15 / 1e6,
26082
+ outputPerToken: 75 / 1e6,
26083
+ cacheReadPerToken: 1.5 / 1e6,
26084
+ cacheWritePerToken: 18.75 / 1e6
26085
+ }],
26086
+ ["claude-3-sonnet", {
26087
+ inputPerToken: 3 / 1e6,
26088
+ outputPerToken: 15 / 1e6,
26089
+ cacheReadPerToken: 0.3 / 1e6,
26090
+ cacheWritePerToken: 3.75 / 1e6
26091
+ }],
26092
+ ["claude-3-haiku", {
26093
+ inputPerToken: 0.25 / 1e6,
26094
+ outputPerToken: 1.25 / 1e6,
26095
+ cacheReadPerToken: 0.03 / 1e6,
26096
+ cacheWritePerToken: 0.3 / 1e6
26097
+ }]
26098
+ ];
26099
+ var SORTED_PRICING = [...MODEL_PRICING].sort((a, b) => b[0].length - a[0].length);
26100
+ function lookupModelPricing(model) {
26101
+ const normalized = model.toLowerCase();
26102
+ for (const [pattern, pricing] of SORTED_PRICING) {
26103
+ if (normalized.startsWith(pattern)) {
26104
+ return pricing;
26105
+ }
26106
+ }
26107
+ return void 0;
26108
+ }
26109
+ function calculateCostUsd(input) {
26110
+ if (input.model === void 0) {
26111
+ return 0;
26112
+ }
26113
+ const pricing = lookupModelPricing(input.model);
26114
+ if (pricing === void 0) {
26115
+ return 0;
26116
+ }
26117
+ const baseInput = Math.max(0, input.inputTokens);
26118
+ const output = Math.max(0, input.outputTokens);
26119
+ const cacheRead = Math.max(0, input.cacheReadTokens ?? 0);
26120
+ const cacheWrite = Math.max(0, input.cacheWriteTokens ?? 0);
26121
+ const cost = baseInput * pricing.inputPerToken + cacheRead * pricing.cacheReadPerToken + cacheWrite * pricing.cacheWritePerToken + output * pricing.outputPerToken;
26122
+ return Number(cost.toFixed(6));
26123
+ }
26124
+
26022
26125
  // packages/runtime/src/runtime.ts
26023
26126
  var import_node_http2 = __toESM(require("node:http"));
26024
26127
 
@@ -26897,6 +27000,10 @@ function buildNormalizedPayload(record, message, eventType) {
26897
27000
  if (cacheReadTokens !== void 0) {
26898
27001
  payload["cache_read_tokens"] = cacheReadTokens;
26899
27002
  }
27003
+ const cacheWriteTokens = readNumber(usage, ["cache_creation_input_tokens", "cacheCreationInputTokens"]);
27004
+ if (cacheWriteTokens !== void 0) {
27005
+ payload["cache_write_tokens"] = cacheWriteTokens;
27006
+ }
26900
27007
  const promptText = readPromptText(message);
26901
27008
  if (promptText !== void 0) {
26902
27009
  payload["prompt_text"] = promptText;
@@ -27967,92 +28074,6 @@ var InMemoryRuntimePersistence = class extends WriterBackedRuntimePersistence {
27967
28074
  }
27968
28075
  };
27969
28076
 
27970
- // packages/schema/src/pricing.ts
27971
- var MODEL_PRICING = [
27972
- // Opus 4 / 4.6
27973
- ["claude-opus-4", {
27974
- inputPerToken: 15 / 1e6,
27975
- outputPerToken: 75 / 1e6,
27976
- cacheReadPerToken: 1.5 / 1e6,
27977
- cacheWritePerToken: 18.75 / 1e6
27978
- }],
27979
- // Sonnet 4 / 4.6
27980
- ["claude-sonnet-4", {
27981
- inputPerToken: 3 / 1e6,
27982
- outputPerToken: 15 / 1e6,
27983
- cacheReadPerToken: 0.3 / 1e6,
27984
- cacheWritePerToken: 3.75 / 1e6
27985
- }],
27986
- // Haiku 4.5
27987
- ["claude-haiku-4", {
27988
- inputPerToken: 0.8 / 1e6,
27989
- outputPerToken: 4 / 1e6,
27990
- cacheReadPerToken: 0.08 / 1e6,
27991
- cacheWritePerToken: 1 / 1e6
27992
- }],
27993
- // Claude 3.5 Sonnet
27994
- ["claude-3-5-sonnet", {
27995
- inputPerToken: 3 / 1e6,
27996
- outputPerToken: 15 / 1e6,
27997
- cacheReadPerToken: 0.3 / 1e6,
27998
- cacheWritePerToken: 3.75 / 1e6
27999
- }],
28000
- // Claude 3.5 Haiku
28001
- ["claude-3-5-haiku", {
28002
- inputPerToken: 0.8 / 1e6,
28003
- outputPerToken: 4 / 1e6,
28004
- cacheReadPerToken: 0.08 / 1e6,
28005
- cacheWritePerToken: 1 / 1e6
28006
- }],
28007
- // Claude 3 Opus
28008
- ["claude-3-opus", {
28009
- inputPerToken: 15 / 1e6,
28010
- outputPerToken: 75 / 1e6,
28011
- cacheReadPerToken: 1.5 / 1e6,
28012
- cacheWritePerToken: 18.75 / 1e6
28013
- }],
28014
- // Claude 3 Sonnet
28015
- ["claude-3-sonnet", {
28016
- inputPerToken: 3 / 1e6,
28017
- outputPerToken: 15 / 1e6,
28018
- cacheReadPerToken: 0.3 / 1e6,
28019
- cacheWritePerToken: 3.75 / 1e6
28020
- }],
28021
- // Claude 3 Haiku
28022
- ["claude-3-haiku", {
28023
- inputPerToken: 0.25 / 1e6,
28024
- outputPerToken: 1.25 / 1e6,
28025
- cacheReadPerToken: 0.03 / 1e6,
28026
- cacheWritePerToken: 0.3 / 1e6
28027
- }]
28028
- ];
28029
- var SORTED_PRICING = [...MODEL_PRICING].sort((a, b) => b[0].length - a[0].length);
28030
- function lookupModelPricing(model) {
28031
- const normalized = model.toLowerCase();
28032
- for (const [pattern, pricing] of SORTED_PRICING) {
28033
- if (normalized.startsWith(pattern)) {
28034
- return pricing;
28035
- }
28036
- }
28037
- return void 0;
28038
- }
28039
- function calculateCostUsd(input) {
28040
- if (input.model === void 0) {
28041
- return 0;
28042
- }
28043
- const pricing = lookupModelPricing(input.model);
28044
- if (pricing === void 0) {
28045
- return 0;
28046
- }
28047
- const totalInput = Math.max(0, input.inputTokens);
28048
- const output = Math.max(0, input.outputTokens);
28049
- const cacheRead = Math.max(0, input.cacheReadTokens ?? 0);
28050
- const cacheWrite = Math.max(0, input.cacheWriteTokens ?? 0);
28051
- const regularInput = Math.max(0, totalInput - cacheRead - cacheWrite);
28052
- const cost = regularInput * pricing.inputPerToken + cacheRead * pricing.cacheReadPerToken + cacheWrite * pricing.cacheWritePerToken + output * pricing.outputPerToken;
28053
- return Number(cost.toFixed(6));
28054
- }
28055
-
28056
28077
  // packages/runtime/src/projector.ts
28057
28078
  function asRecord5(value) {
28058
28079
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
@@ -28543,11 +28564,26 @@ function hydrateFromSqlite(runtime, sqlite, limit, eventLimit) {
28543
28564
  const extra = commits.filter((c) => !pgShas.has(c.sha));
28544
28565
  commits = [...mapped, ...extra];
28545
28566
  }
28546
- return {
28567
+ let hydratedTrace = {
28547
28568
  ...trace,
28548
28569
  timeline,
28549
28570
  git: { ...trace.git, commits }
28550
28571
  };
28572
+ if (hydratedTrace.metrics.totalCostUsd === 0 && (hydratedTrace.metrics.totalInputTokens > 0 || hydratedTrace.metrics.totalOutputTokens > 0) && hydratedTrace.metrics.modelsUsed.length > 0) {
28573
+ const model = String(hydratedTrace.metrics.modelsUsed[0]);
28574
+ const recalculated = calculateCostUsd({
28575
+ model,
28576
+ inputTokens: hydratedTrace.metrics.totalInputTokens,
28577
+ outputTokens: hydratedTrace.metrics.totalOutputTokens
28578
+ });
28579
+ if (recalculated > 0) {
28580
+ hydratedTrace = {
28581
+ ...hydratedTrace,
28582
+ metrics: { ...hydratedTrace.metrics, totalCostUsd: recalculated }
28583
+ };
28584
+ }
28585
+ }
28586
+ return hydratedTrace;
28551
28587
  });
28552
28588
  for (const trace of traces) {
28553
28589
  runtime.sessionRepository.upsert(trace);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-trace",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "Self-hosted observability for AI coding agents. One command, zero config.",
5
5
  "license": "Apache-2.0",
6
6
  "bin": {