agent-trace 0.2.6 → 0.2.7

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 +66 -1
  2. package/package.json +1 -1
package/agent-trace.cjs CHANGED
@@ -25102,6 +25102,7 @@ var SqliteClient = class {
25102
25102
  this.db.pragma("synchronous = NORMAL");
25103
25103
  this.migrateDeduplicateEvents();
25104
25104
  this.db.exec(SCHEMA_SQL);
25105
+ this.migrateRebuildBrokenTraces();
25105
25106
  }
25106
25107
  async insertJsonEachRow(request) {
25107
25108
  if (request.rows.length === 0) return;
@@ -25395,6 +25396,32 @@ var SqliteClient = class {
25395
25396
  console.log(`[agent-trace] migration complete: ${afterCount.c} events after dedup (removed ${total - afterCount.c} duplicates)`);
25396
25397
  this.rebuildSessionTracesFromEvents();
25397
25398
  }
25399
+ /**
25400
+ * Migration v2: fix databases that ran v0.2.6's broken rebuild (models_used='[]' with data present).
25401
+ * Re-runs the rebuild if session_traces exist but have empty models_used while events have model data.
25402
+ */
25403
+ migrateRebuildBrokenTraces() {
25404
+ const tracesExist = this.db.prepare(
25405
+ "SELECT 1 FROM sqlite_master WHERE type='table' AND name='session_traces'"
25406
+ ).get();
25407
+ if (tracesExist === void 0) {
25408
+ return;
25409
+ }
25410
+ const broken = this.db.prepare(`
25411
+ SELECT 1 FROM session_traces st
25412
+ WHERE st.models_used = '[]'
25413
+ AND EXISTS (
25414
+ SELECT 1 FROM agent_events ae
25415
+ WHERE ae.session_id = st.session_id AND ae.model IS NOT NULL
25416
+ )
25417
+ LIMIT 1
25418
+ `).get();
25419
+ if (broken === void 0) {
25420
+ return;
25421
+ }
25422
+ console.log("[agent-trace] migrating: rebuilding session traces with correct models/tools");
25423
+ this.rebuildSessionTracesFromEvents();
25424
+ }
25398
25425
  /**
25399
25426
  * Rebuild session_traces by aggregating deduplicated agent_events.
25400
25427
  * Called after dedup migration so the dashboard has correct metrics immediately.
@@ -25437,6 +25464,32 @@ var SqliteClient = class {
25437
25464
  FROM agent_events
25438
25465
  GROUP BY session_id
25439
25466
  `);
25467
+ const sessionIds = this.db.prepare(
25468
+ "SELECT DISTINCT session_id FROM agent_events"
25469
+ ).all();
25470
+ const updateArrays = this.db.prepare(
25471
+ "UPDATE session_traces SET models_used = ?, tools_used = ?, files_touched = ? WHERE session_id = ?"
25472
+ );
25473
+ const transaction = this.db.transaction((ids) => {
25474
+ for (const { session_id } of ids) {
25475
+ const models = this.db.prepare(
25476
+ "SELECT DISTINCT model FROM agent_events WHERE session_id = ? AND model IS NOT NULL"
25477
+ ).all(session_id);
25478
+ const tools = this.db.prepare(
25479
+ "SELECT DISTINCT tool_name FROM agent_events WHERE session_id = ? AND tool_name IS NOT NULL"
25480
+ ).all(session_id);
25481
+ const files = this.db.prepare(
25482
+ "SELECT DISTINCT commit_sha FROM agent_events WHERE session_id = ? AND commit_sha IS NOT NULL"
25483
+ ).all(session_id);
25484
+ updateArrays.run(
25485
+ JSON.stringify(models.map((r) => r.model)),
25486
+ JSON.stringify(tools.map((r) => r.tool_name)),
25487
+ JSON.stringify(files.map((r) => r.commit_sha)),
25488
+ session_id
25489
+ );
25490
+ }
25491
+ });
25492
+ transaction(sessionIds);
25440
25493
  const rebuilt = this.db.prepare("SELECT COUNT(*) as c FROM session_traces").get();
25441
25494
  console.log(`[agent-trace] rebuilt ${rebuilt.c} session traces from deduplicated events`);
25442
25495
  }
@@ -28489,11 +28542,23 @@ async function close2(server) {
28489
28542
  });
28490
28543
  });
28491
28544
  }
28545
+ function enrichEnvelopeWithCost(event) {
28546
+ const payload = event.payload;
28547
+ if (typeof payload["cost_usd"] === "number" && payload["cost_usd"] > 0) {
28548
+ return event;
28549
+ }
28550
+ const cost = computeEventCost(payload);
28551
+ if (cost === void 0 || cost <= 0) {
28552
+ return event;
28553
+ }
28554
+ return { ...event, payload: { ...payload, cost_usd: cost } };
28555
+ }
28492
28556
  async function projectAndPersistEvent(event, sessionRepository, persistence) {
28493
28557
  const current = sessionRepository.getBySessionId(event.sessionId);
28494
28558
  const projected = projectEnvelopeToTrace(current, event);
28495
28559
  sessionRepository.upsert(projected);
28496
- await persistence.persistAcceptedEvent(event, projected);
28560
+ const enriched = enrichEnvelopeWithCost(event);
28561
+ await persistence.persistAcceptedEvent(enriched, projected);
28497
28562
  }
28498
28563
  function createRuntimeOtelSink(runtime) {
28499
28564
  return runtime.collectorService.otelSink;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-trace",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "description": "Self-hosted observability for AI coding agents. One command, zero config.",
5
5
  "license": "Apache-2.0",
6
6
  "bin": {