agent-recorder 2.0.12 → 2.0.14

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 (188) hide show
  1. package/dist/bundle.js +4 -0
  2. package/dist/bundle.js.map +1 -1
  3. package/dist/embed.d.ts +21 -0
  4. package/dist/embed.d.ts.map +1 -0
  5. package/dist/embed.js +22 -0
  6. package/dist/embed.js.map +1 -0
  7. package/package.json +8 -1
  8. package/vendor/node_modules/@agent-recorder/cli/analytics/session-analytics.test.js +3 -0
  9. package/vendor/node_modules/@agent-recorder/cli/analytics/session-analytics.test.js.map +1 -1
  10. package/vendor/node_modules/@agent-recorder/cli/commands/mcp-server.d.ts +11 -0
  11. package/vendor/node_modules/@agent-recorder/cli/commands/mcp-server.d.ts.map +1 -0
  12. package/vendor/node_modules/@agent-recorder/cli/commands/mcp-server.js +442 -0
  13. package/vendor/node_modules/@agent-recorder/cli/commands/mcp-server.js.map +1 -0
  14. package/vendor/node_modules/@agent-recorder/cli/commands/sessions.d.ts.map +1 -1
  15. package/vendor/node_modules/@agent-recorder/cli/commands/sessions.js +8 -5
  16. package/vendor/node_modules/@agent-recorder/cli/commands/sessions.js.map +1 -1
  17. package/vendor/node_modules/@agent-recorder/cli/config/claude-paths.d.ts +2 -51
  18. package/vendor/node_modules/@agent-recorder/cli/config/claude-paths.d.ts.map +1 -1
  19. package/vendor/node_modules/@agent-recorder/cli/config/claude-paths.js +2 -113
  20. package/vendor/node_modules/@agent-recorder/cli/config/claude-paths.js.map +1 -1
  21. package/vendor/node_modules/@agent-recorder/cli/config/claude-paths.test.js +1 -1
  22. package/vendor/node_modules/@agent-recorder/cli/config/claude-paths.test.js.map +1 -1
  23. package/vendor/node_modules/@agent-recorder/cli/index.js +10 -0
  24. package/vendor/node_modules/@agent-recorder/cli/index.js.map +1 -1
  25. package/vendor/node_modules/@agent-recorder/cli/package.json +1 -1
  26. package/vendor/node_modules/@agent-recorder/cli/tui/components/EventInspectPanel.d.ts.map +1 -1
  27. package/vendor/node_modules/@agent-recorder/cli/tui/components/EventInspectPanel.js +1 -1
  28. package/vendor/node_modules/@agent-recorder/cli/tui/components/EventInspectPanel.js.map +1 -1
  29. package/vendor/node_modules/@agent-recorder/core/claude-config.d.ts +23 -0
  30. package/vendor/node_modules/@agent-recorder/core/claude-config.d.ts.map +1 -1
  31. package/vendor/node_modules/@agent-recorder/core/claude-config.js +50 -0
  32. package/vendor/node_modules/@agent-recorder/core/claude-config.js.map +1 -1
  33. package/vendor/node_modules/@agent-recorder/core/config.d.ts +10 -1
  34. package/vendor/node_modules/@agent-recorder/core/config.d.ts.map +1 -1
  35. package/vendor/node_modules/@agent-recorder/core/config.js +11 -1
  36. package/vendor/node_modules/@agent-recorder/core/config.js.map +1 -1
  37. package/vendor/node_modules/@agent-recorder/core/db/events-complete.test.d.ts +5 -0
  38. package/vendor/node_modules/@agent-recorder/core/db/events-complete.test.d.ts.map +1 -0
  39. package/vendor/node_modules/@agent-recorder/core/db/events-complete.test.js +133 -0
  40. package/vendor/node_modules/@agent-recorder/core/db/events-complete.test.js.map +1 -0
  41. package/vendor/node_modules/@agent-recorder/core/db/events.d.ts +23 -36
  42. package/vendor/node_modules/@agent-recorder/core/db/events.d.ts.map +1 -1
  43. package/vendor/node_modules/@agent-recorder/core/db/events.js +74 -3
  44. package/vendor/node_modules/@agent-recorder/core/db/events.js.map +1 -1
  45. package/vendor/node_modules/@agent-recorder/core/db/events.test.js +62 -1
  46. package/vendor/node_modules/@agent-recorder/core/db/events.test.js.map +1 -1
  47. package/vendor/node_modules/@agent-recorder/core/db/index.d.ts +2 -1
  48. package/vendor/node_modules/@agent-recorder/core/db/index.d.ts.map +1 -1
  49. package/vendor/node_modules/@agent-recorder/core/db/index.js +2 -1
  50. package/vendor/node_modules/@agent-recorder/core/db/index.js.map +1 -1
  51. package/vendor/node_modules/@agent-recorder/core/db/sessions.d.ts +2 -5
  52. package/vendor/node_modules/@agent-recorder/core/db/sessions.d.ts.map +1 -1
  53. package/vendor/node_modules/@agent-recorder/core/db/sessions.js.map +1 -1
  54. package/vendor/node_modules/@agent-recorder/core/db/token-metrics.d.ts +33 -0
  55. package/vendor/node_modules/@agent-recorder/core/db/token-metrics.d.ts.map +1 -0
  56. package/vendor/node_modules/@agent-recorder/core/db/token-metrics.js +88 -0
  57. package/vendor/node_modules/@agent-recorder/core/db/token-metrics.js.map +1 -0
  58. package/vendor/node_modules/@agent-recorder/core/db/token-metrics.test.d.ts +5 -0
  59. package/vendor/node_modules/@agent-recorder/core/db/token-metrics.test.d.ts.map +1 -0
  60. package/vendor/node_modules/@agent-recorder/core/db/token-metrics.test.js +167 -0
  61. package/vendor/node_modules/@agent-recorder/core/db/token-metrics.test.js.map +1 -0
  62. package/vendor/node_modules/@agent-recorder/core/index.d.ts +1 -1
  63. package/vendor/node_modules/@agent-recorder/core/index.d.ts.map +1 -1
  64. package/vendor/node_modules/@agent-recorder/core/index.js +1 -1
  65. package/vendor/node_modules/@agent-recorder/core/index.js.map +1 -1
  66. package/vendor/node_modules/@agent-recorder/core/migrations/007_add_correlation_id.sql +11 -0
  67. package/vendor/node_modules/@agent-recorder/core/migrations/007_add_token_columns.sql +19 -0
  68. package/vendor/node_modules/@agent-recorder/core/package.json +1 -1
  69. package/vendor/node_modules/@agent-recorder/core/types/index.d.ts +4 -2
  70. package/vendor/node_modules/@agent-recorder/core/types/index.d.ts.map +1 -1
  71. package/vendor/node_modules/@agent-recorder/core/types/index.js +3 -0
  72. package/vendor/node_modules/@agent-recorder/core/types/index.js.map +1 -1
  73. package/vendor/node_modules/@agent-recorder/core/utils/index.d.ts +1 -0
  74. package/vendor/node_modules/@agent-recorder/core/utils/index.d.ts.map +1 -1
  75. package/vendor/node_modules/@agent-recorder/core/utils/index.js +1 -0
  76. package/vendor/node_modules/@agent-recorder/core/utils/index.js.map +1 -1
  77. package/vendor/node_modules/@agent-recorder/core/utils/redact.d.ts.map +1 -1
  78. package/vendor/node_modules/@agent-recorder/core/utils/redact.js +6 -3
  79. package/vendor/node_modules/@agent-recorder/core/utils/redact.js.map +1 -1
  80. package/vendor/node_modules/@agent-recorder/core/utils/redact.test.d.ts +6 -0
  81. package/vendor/node_modules/@agent-recorder/core/utils/redact.test.d.ts.map +1 -0
  82. package/vendor/node_modules/@agent-recorder/core/utils/redact.test.js +82 -0
  83. package/vendor/node_modules/@agent-recorder/core/utils/redact.test.js.map +1 -0
  84. package/vendor/node_modules/@agent-recorder/core/utils/tokens.d.ts +24 -0
  85. package/vendor/node_modules/@agent-recorder/core/utils/tokens.d.ts.map +1 -0
  86. package/vendor/node_modules/@agent-recorder/core/utils/tokens.js +31 -0
  87. package/vendor/node_modules/@agent-recorder/core/utils/tokens.js.map +1 -0
  88. package/vendor/node_modules/@agent-recorder/core/utils/tokens.test.d.ts +5 -0
  89. package/vendor/node_modules/@agent-recorder/core/utils/tokens.test.d.ts.map +1 -0
  90. package/vendor/node_modules/@agent-recorder/core/utils/tokens.test.js +80 -0
  91. package/vendor/node_modules/@agent-recorder/core/utils/tokens.test.js.map +1 -0
  92. package/vendor/node_modules/@agent-recorder/hooks/package.json +1 -1
  93. package/vendor/node_modules/@agent-recorder/service/daemon-context.d.ts +14 -0
  94. package/vendor/node_modules/@agent-recorder/service/daemon-context.d.ts.map +1 -0
  95. package/vendor/node_modules/@agent-recorder/service/daemon-context.js +15 -0
  96. package/vendor/node_modules/@agent-recorder/service/daemon-context.js.map +1 -0
  97. package/vendor/node_modules/@agent-recorder/service/index.d.ts +1 -8
  98. package/vendor/node_modules/@agent-recorder/service/index.d.ts.map +1 -1
  99. package/vendor/node_modules/@agent-recorder/service/index.js +15 -22
  100. package/vendor/node_modules/@agent-recorder/service/index.js.map +1 -1
  101. package/vendor/node_modules/@agent-recorder/service/mcp/proxy.d.ts +27 -0
  102. package/vendor/node_modules/@agent-recorder/service/mcp/proxy.d.ts.map +1 -1
  103. package/vendor/node_modules/@agent-recorder/service/mcp/proxy.js +141 -35
  104. package/vendor/node_modules/@agent-recorder/service/mcp/proxy.js.map +1 -1
  105. package/vendor/node_modules/@agent-recorder/service/mcp/recorder.d.ts +4 -0
  106. package/vendor/node_modules/@agent-recorder/service/mcp/recorder.d.ts.map +1 -1
  107. package/vendor/node_modules/@agent-recorder/service/mcp/recorder.js +56 -14
  108. package/vendor/node_modules/@agent-recorder/service/mcp/recorder.js.map +1 -1
  109. package/vendor/node_modules/@agent-recorder/service/mcp/recorder.test.d.ts +5 -0
  110. package/vendor/node_modules/@agent-recorder/service/mcp/recorder.test.d.ts.map +1 -0
  111. package/vendor/node_modules/@agent-recorder/service/mcp/recorder.test.js +143 -0
  112. package/vendor/node_modules/@agent-recorder/service/mcp/recorder.test.js.map +1 -0
  113. package/vendor/node_modules/@agent-recorder/service/mcp/types.d.ts +5 -31
  114. package/vendor/node_modules/@agent-recorder/service/mcp/types.d.ts.map +1 -1
  115. package/vendor/node_modules/@agent-recorder/service/mcp/types.js +3 -1
  116. package/vendor/node_modules/@agent-recorder/service/mcp/types.js.map +1 -1
  117. package/vendor/node_modules/@agent-recorder/service/mcp/upstreams-cache.test.d.ts +5 -0
  118. package/vendor/node_modules/@agent-recorder/service/mcp/upstreams-cache.test.d.ts.map +1 -0
  119. package/vendor/node_modules/@agent-recorder/service/mcp/upstreams-cache.test.js +66 -0
  120. package/vendor/node_modules/@agent-recorder/service/mcp/upstreams-cache.test.js.map +1 -0
  121. package/vendor/node_modules/@agent-recorder/service/package.json +1 -1
  122. package/vendor/node_modules/@agent-recorder/service/routes/events.d.ts.map +1 -1
  123. package/vendor/node_modules/@agent-recorder/service/routes/events.js +42 -1
  124. package/vendor/node_modules/@agent-recorder/service/routes/events.js.map +1 -1
  125. package/vendor/node_modules/@agent-recorder/service/routes/health.d.ts +6 -1
  126. package/vendor/node_modules/@agent-recorder/service/routes/health.d.ts.map +1 -1
  127. package/vendor/node_modules/@agent-recorder/service/routes/health.js +5 -6
  128. package/vendor/node_modules/@agent-recorder/service/routes/health.js.map +1 -1
  129. package/vendor/node_modules/@agent-recorder/service/routes/hooks.d.ts +20 -0
  130. package/vendor/node_modules/@agent-recorder/service/routes/hooks.d.ts.map +1 -1
  131. package/vendor/node_modules/@agent-recorder/service/routes/hooks.js +403 -49
  132. package/vendor/node_modules/@agent-recorder/service/routes/hooks.js.map +1 -1
  133. package/vendor/node_modules/@agent-recorder/service/routes/hooks.test.d.ts +9 -0
  134. package/vendor/node_modules/@agent-recorder/service/routes/hooks.test.d.ts.map +1 -0
  135. package/vendor/node_modules/@agent-recorder/service/routes/hooks.test.js +406 -0
  136. package/vendor/node_modules/@agent-recorder/service/routes/hooks.test.js.map +1 -0
  137. package/vendor/node_modules/@agent-recorder/service/routes/isToolResponseError.test.d.ts +8 -0
  138. package/vendor/node_modules/@agent-recorder/service/routes/isToolResponseError.test.d.ts.map +1 -0
  139. package/vendor/node_modules/@agent-recorder/service/routes/isToolResponseError.test.js +65 -0
  140. package/vendor/node_modules/@agent-recorder/service/routes/isToolResponseError.test.js.map +1 -0
  141. package/vendor/node_modules/@agent-recorder/service/routes/sessions.d.ts.map +1 -1
  142. package/vendor/node_modules/@agent-recorder/service/routes/sessions.js +19 -1
  143. package/vendor/node_modules/@agent-recorder/service/routes/sessions.js.map +1 -1
  144. package/vendor/node_modules/@agent-recorder/service/routes/stdio.d.ts.map +1 -1
  145. package/vendor/node_modules/@agent-recorder/service/routes/stdio.js +20 -1
  146. package/vendor/node_modules/@agent-recorder/service/routes/stdio.js.map +1 -1
  147. package/vendor/node_modules/@agent-recorder/service/routes/tokens.d.ts +12 -0
  148. package/vendor/node_modules/@agent-recorder/service/routes/tokens.d.ts.map +1 -0
  149. package/vendor/node_modules/@agent-recorder/service/routes/tokens.js +18 -0
  150. package/vendor/node_modules/@agent-recorder/service/routes/tokens.js.map +1 -0
  151. package/vendor/node_modules/@agent-recorder/service/routes/tokens.test.d.ts +5 -0
  152. package/vendor/node_modules/@agent-recorder/service/routes/tokens.test.d.ts.map +1 -0
  153. package/vendor/node_modules/@agent-recorder/service/routes/tokens.test.js +88 -0
  154. package/vendor/node_modules/@agent-recorder/service/routes/tokens.test.js.map +1 -0
  155. package/vendor/node_modules/@agent-recorder/service/server.d.ts +4 -0
  156. package/vendor/node_modules/@agent-recorder/service/server.d.ts.map +1 -1
  157. package/vendor/node_modules/@agent-recorder/service/server.js +33 -3
  158. package/vendor/node_modules/@agent-recorder/service/server.js.map +1 -1
  159. package/vendor/node_modules/@agent-recorder/stdio-proxy/package.json +1 -1
  160. package/vendor/node_modules/@agent-recorder/stdio-proxy/types.d.ts +3 -19
  161. package/vendor/node_modules/@agent-recorder/stdio-proxy/types.d.ts.map +1 -1
  162. package/vendor/node_modules/@agent-recorder/stdio-proxy/types.js +2 -1
  163. package/vendor/node_modules/@agent-recorder/stdio-proxy/types.js.map +1 -1
  164. package/vendor/node_modules/@agent-recorder/{core/types → types}/events.d.ts +9 -0
  165. package/vendor/node_modules/@agent-recorder/types/events.d.ts.map +1 -0
  166. package/vendor/node_modules/@agent-recorder/types/events.js +9 -0
  167. package/vendor/node_modules/@agent-recorder/types/events.js.map +1 -0
  168. package/vendor/node_modules/@agent-recorder/types/index.d.ts +12 -0
  169. package/vendor/node_modules/@agent-recorder/types/index.d.ts.map +1 -0
  170. package/vendor/node_modules/@agent-recorder/types/index.js +9 -0
  171. package/vendor/node_modules/@agent-recorder/types/index.js.map +1 -0
  172. package/vendor/node_modules/@agent-recorder/types/jsonrpc.d.ts +35 -0
  173. package/vendor/node_modules/@agent-recorder/types/jsonrpc.d.ts.map +1 -0
  174. package/vendor/node_modules/@agent-recorder/types/jsonrpc.js +6 -0
  175. package/vendor/node_modules/@agent-recorder/types/jsonrpc.js.map +1 -0
  176. package/vendor/node_modules/@agent-recorder/types/package.json +12 -0
  177. package/vendor/node_modules/@agent-recorder/{core/types → types}/session.d.ts +6 -0
  178. package/vendor/node_modules/@agent-recorder/types/session.d.ts.map +1 -0
  179. package/vendor/node_modules/@agent-recorder/{core/types → types}/session.js.map +1 -1
  180. package/vendor/node_modules/@agent-recorder/types/storage.d.ts +80 -0
  181. package/vendor/node_modules/@agent-recorder/types/storage.d.ts.map +1 -0
  182. package/vendor/node_modules/@agent-recorder/types/storage.js +9 -0
  183. package/vendor/node_modules/@agent-recorder/types/storage.js.map +1 -0
  184. package/vendor/node_modules/@agent-recorder/core/types/events.d.ts.map +0 -1
  185. package/vendor/node_modules/@agent-recorder/core/types/events.js +0 -6
  186. package/vendor/node_modules/@agent-recorder/core/types/events.js.map +0 -1
  187. package/vendor/node_modules/@agent-recorder/core/types/session.d.ts.map +0 -1
  188. /package/vendor/node_modules/@agent-recorder/{core/types → types}/session.js +0 -0
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Token metrics DB operations.
3
+ * Upserts tool schema metrics and queries token summaries per session.
4
+ */
5
+ import type Database from "better-sqlite3";
6
+ export interface UpsertToolSchemaMetricInput {
7
+ sessionId: string;
8
+ upstreamKey: string | null;
9
+ toolName: string;
10
+ schemaTokens: number;
11
+ }
12
+ /** Upsert a tool schema metric (one row per session+upstream+tool). */
13
+ export declare function upsertToolSchemaMetric(db: Database.Database, input: UpsertToolSchemaMetricInput): void;
14
+ export interface TokenSummary {
15
+ sessionId: string;
16
+ estimatedTotalTokens: number;
17
+ budgetTokens: number;
18
+ percentUsed: number;
19
+ budgetExceeded: boolean;
20
+ byUpstream: Record<string, {
21
+ callTokens: number;
22
+ schemaTokens: number;
23
+ }>;
24
+ byTool: Array<{
25
+ toolName: string;
26
+ calls: number;
27
+ totalInputTokens: number;
28
+ totalOutputTokens: number;
29
+ }>;
30
+ }
31
+ /** Build a full token summary for a session. */
32
+ export declare function getTokenSummary(db: Database.Database, sessionId: string, budgetTokens: number): TokenSummary;
33
+ //# sourceMappingURL=token-metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-metrics.d.ts","sourceRoot":"","sources":["../../src/db/token-metrics.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAG3C,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,uEAAuE;AACvE,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,2BAA2B,GACjC,IAAI,CAkBN;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzE,MAAM,EAAE,KAAK,CAAC;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,gBAAgB,EAAE,MAAM,CAAC;QACzB,iBAAiB,EAAE,MAAM,CAAC;KAC3B,CAAC,CAAC;CACJ;AAED,gDAAgD;AAChD,wBAAgB,eAAe,CAC7B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,YAAY,CAoGd"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Token metrics DB operations.
3
+ * Upserts tool schema metrics and queries token summaries per session.
4
+ */
5
+ import { randomUUID } from "node:crypto";
6
+ /** Upsert a tool schema metric (one row per session+upstream+tool). */
7
+ export function upsertToolSchemaMetric(db, input) {
8
+ // Use ON CONFLICT against the expression-based unique index
9
+ // (session_id, COALESCE(upstream_key, ''), tool_name) to handle NULL upstream_key.
10
+ db.prepare(`
11
+ INSERT INTO tool_schema_metrics (id, session_id, upstream_key, tool_name, schema_tokens)
12
+ VALUES (?, ?, ?, ?, ?)
13
+ ON CONFLICT(session_id, COALESCE(upstream_key, ''), tool_name) DO UPDATE SET
14
+ schema_tokens = excluded.schema_tokens,
15
+ recorded_at = datetime('now')
16
+ `).run(randomUUID(), input.sessionId, input.upstreamKey ?? null, input.toolName, input.schemaTokens);
17
+ }
18
+ /** Build a full token summary for a session. */
19
+ export function getTokenSummary(db, sessionId, budgetTokens) {
20
+ // Per-upstream call tokens.
21
+ // Intentionally filtered to tool_call only: agent_call/subagent_call events
22
+ // don't carry meaningful token payloads in the current schema.
23
+ const upstreamCallRows = db
24
+ .prepare(`
25
+ SELECT upstream_key, COALESCE(SUM(input_tokens), 0) + COALESCE(SUM(output_tokens), 0) AS call_tokens
26
+ FROM events
27
+ WHERE session_id = ? AND event_type = 'tool_call'
28
+ GROUP BY upstream_key
29
+ `)
30
+ .all(sessionId);
31
+ // Per-upstream schema tokens
32
+ const upstreamSchemaRows = db
33
+ .prepare(`
34
+ SELECT upstream_key, SUM(schema_tokens) AS schema_tokens
35
+ FROM tool_schema_metrics
36
+ WHERE session_id = ?
37
+ GROUP BY upstream_key
38
+ `)
39
+ .all(sessionId);
40
+ // Per-tool breakdown
41
+ const toolRows = db
42
+ .prepare(`
43
+ SELECT
44
+ tool_name,
45
+ COUNT(*) AS calls,
46
+ COALESCE(SUM(input_tokens), 0) AS total_input_tokens,
47
+ COALESCE(SUM(output_tokens), 0) AS total_output_tokens
48
+ FROM events
49
+ WHERE session_id = ? AND event_type = 'tool_call'
50
+ GROUP BY tool_name
51
+ ORDER BY (total_input_tokens + total_output_tokens) DESC
52
+ `)
53
+ .all(sessionId);
54
+ // Merge into byUpstream map
55
+ const byUpstream = {};
56
+ for (const row of upstreamCallRows) {
57
+ const key = row.upstream_key ?? "(built-in)";
58
+ byUpstream[key] = { callTokens: row.call_tokens, schemaTokens: 0 };
59
+ }
60
+ for (const row of upstreamSchemaRows) {
61
+ const key = row.upstream_key ?? "(built-in)";
62
+ if (!byUpstream[key])
63
+ byUpstream[key] = { callTokens: 0, schemaTokens: 0 };
64
+ byUpstream[key].schemaTokens = row.schema_tokens;
65
+ }
66
+ const totalCallTokens = Object.values(byUpstream).reduce((s, v) => s + v.callTokens, 0);
67
+ const totalSchemaTokens = Object.values(byUpstream).reduce((s, v) => s + v.schemaTokens, 0);
68
+ const estimatedTotalTokens = totalCallTokens + totalSchemaTokens;
69
+ // Guard against divide-by-zero when budget is 0 or not configured
70
+ const percentUsed = budgetTokens > 0
71
+ ? Math.round((estimatedTotalTokens / budgetTokens) * 100)
72
+ : 0;
73
+ return {
74
+ sessionId,
75
+ estimatedTotalTokens,
76
+ budgetTokens,
77
+ percentUsed,
78
+ budgetExceeded: budgetTokens > 0 && estimatedTotalTokens > budgetTokens,
79
+ byUpstream,
80
+ byTool: toolRows.map((r) => ({
81
+ toolName: r.tool_name ?? "",
82
+ calls: r.calls,
83
+ totalInputTokens: r.total_input_tokens,
84
+ totalOutputTokens: r.total_output_tokens,
85
+ })),
86
+ };
87
+ }
88
+ //# sourceMappingURL=token-metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-metrics.js","sourceRoot":"","sources":["../../src/db/token-metrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for token metrics DB operations.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=token-metrics.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-metrics.test.d.ts","sourceRoot":"","sources":["../../src/db/token-metrics.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Tests for token metrics DB operations.
3
+ */
4
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
5
+ import { randomUUID } from "node:crypto";
6
+ import { openMemoryDatabase, runMigrations, getDefaultMigrationsDir, createSession, insertEvent, upsertToolSchemaMetric, getTokenSummary, } from "../index.js";
7
+ describe("upsertToolSchemaMetric", () => {
8
+ let db;
9
+ let sessionId;
10
+ beforeEach(() => {
11
+ db = openMemoryDatabase();
12
+ runMigrations(db, getDefaultMigrationsDir());
13
+ sessionId = randomUUID();
14
+ createSession(db, sessionId, new Date().toISOString());
15
+ });
16
+ afterEach(() => {
17
+ db.close();
18
+ });
19
+ it("inserts a new row", () => {
20
+ upsertToolSchemaMetric(db, {
21
+ sessionId,
22
+ upstreamKey: "github",
23
+ toolName: "search_code",
24
+ schemaTokens: 120,
25
+ });
26
+ const rows = db
27
+ .prepare("SELECT * FROM tool_schema_metrics WHERE session_id = ?")
28
+ .all(sessionId);
29
+ expect(rows).toHaveLength(1);
30
+ expect(rows[0].tool_name).toBe("search_code");
31
+ expect(rows[0].schema_tokens).toBe(120);
32
+ });
33
+ it("updates schema_tokens on duplicate (session, upstream, tool)", () => {
34
+ upsertToolSchemaMetric(db, {
35
+ sessionId,
36
+ upstreamKey: "github",
37
+ toolName: "search_code",
38
+ schemaTokens: 120,
39
+ });
40
+ // Second call with updated count
41
+ upsertToolSchemaMetric(db, {
42
+ sessionId,
43
+ upstreamKey: "github",
44
+ toolName: "search_code",
45
+ schemaTokens: 200,
46
+ });
47
+ const rows = db
48
+ .prepare("SELECT * FROM tool_schema_metrics WHERE session_id = ?")
49
+ .all(sessionId);
50
+ // Must still be exactly one row, not two
51
+ expect(rows).toHaveLength(1);
52
+ expect(rows[0].schema_tokens).toBe(200);
53
+ });
54
+ it("treats null upstream_key correctly (no duplicate rows)", () => {
55
+ upsertToolSchemaMetric(db, {
56
+ sessionId,
57
+ upstreamKey: null,
58
+ toolName: "Glob",
59
+ schemaTokens: 50,
60
+ });
61
+ upsertToolSchemaMetric(db, {
62
+ sessionId,
63
+ upstreamKey: null,
64
+ toolName: "Glob",
65
+ schemaTokens: 60,
66
+ });
67
+ const rows = db
68
+ .prepare("SELECT * FROM tool_schema_metrics WHERE session_id = ? AND tool_name = 'Glob'")
69
+ .all(sessionId);
70
+ expect(rows).toHaveLength(1);
71
+ });
72
+ it("allows same tool name under different upstream keys", () => {
73
+ upsertToolSchemaMetric(db, {
74
+ sessionId,
75
+ upstreamKey: "github",
76
+ toolName: "search",
77
+ schemaTokens: 100,
78
+ });
79
+ upsertToolSchemaMetric(db, {
80
+ sessionId,
81
+ upstreamKey: "linear",
82
+ toolName: "search",
83
+ schemaTokens: 80,
84
+ });
85
+ const rows = db
86
+ .prepare("SELECT * FROM tool_schema_metrics WHERE session_id = ?")
87
+ .all(sessionId);
88
+ expect(rows).toHaveLength(2);
89
+ });
90
+ });
91
+ describe("getTokenSummary", () => {
92
+ let db;
93
+ let sessionId;
94
+ beforeEach(() => {
95
+ db = openMemoryDatabase();
96
+ runMigrations(db, getDefaultMigrationsDir());
97
+ sessionId = randomUUID();
98
+ createSession(db, sessionId, new Date().toISOString());
99
+ });
100
+ afterEach(() => {
101
+ db.close();
102
+ });
103
+ it("returns zero totals for empty session", () => {
104
+ const summary = getTokenSummary(db, sessionId, 150000);
105
+ expect(summary.estimatedTotalTokens).toBe(0);
106
+ expect(summary.percentUsed).toBe(0);
107
+ expect(summary.budgetExceeded).toBe(false);
108
+ expect(summary.byTool).toHaveLength(0);
109
+ });
110
+ it("does not divide by zero when budgetTokens is 0", () => {
111
+ const summary = getTokenSummary(db, sessionId, 0);
112
+ expect(summary.percentUsed).toBe(0);
113
+ expect(summary.budgetExceeded).toBe(false);
114
+ });
115
+ it("aggregates call tokens from events", () => {
116
+ insertEvent(db, {
117
+ id: randomUUID(),
118
+ sessionId,
119
+ sequence: 1,
120
+ eventType: "tool_call",
121
+ agentRole: "main",
122
+ agentName: "claude-code",
123
+ toolName: "execute_sql",
124
+ upstreamKey: "supabase",
125
+ startedAt: new Date().toISOString(),
126
+ status: "success",
127
+ inputTokens: 100,
128
+ outputTokens: 200,
129
+ });
130
+ const summary = getTokenSummary(db, sessionId, 150000);
131
+ expect(summary.estimatedTotalTokens).toBe(300);
132
+ expect(summary.byTool).toHaveLength(1);
133
+ expect(summary.byTool[0].toolName).toBe("execute_sql");
134
+ expect(summary.byTool[0].totalInputTokens).toBe(100);
135
+ expect(summary.byTool[0].totalOutputTokens).toBe(200);
136
+ });
137
+ it("includes schema tokens in total", () => {
138
+ upsertToolSchemaMetric(db, {
139
+ sessionId,
140
+ upstreamKey: "supabase",
141
+ toolName: "execute_sql",
142
+ schemaTokens: 50,
143
+ });
144
+ const summary = getTokenSummary(db, sessionId, 150000);
145
+ expect(summary.estimatedTotalTokens).toBe(50);
146
+ expect(summary.byUpstream["supabase"].schemaTokens).toBe(50);
147
+ });
148
+ it("flags budget exceeded when total exceeds budget", () => {
149
+ insertEvent(db, {
150
+ id: randomUUID(),
151
+ sessionId,
152
+ sequence: 1,
153
+ eventType: "tool_call",
154
+ agentRole: "main",
155
+ agentName: "claude-code",
156
+ toolName: "execute_sql",
157
+ startedAt: new Date().toISOString(),
158
+ status: "success",
159
+ inputTokens: 1000,
160
+ outputTokens: 500,
161
+ });
162
+ const summary = getTokenSummary(db, sessionId, 1000);
163
+ expect(summary.budgetExceeded).toBe(true);
164
+ expect(summary.percentUsed).toBeGreaterThan(100);
165
+ });
166
+ });
167
+ //# sourceMappingURL=token-metrics.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-metrics.test.js","sourceRoot":"","sources":["../../src/db/token-metrics.test.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@
7
7
  export * from "./types/index.js";
8
8
  export * from "./db/index.js";
9
9
  export * from "./utils/index.js";
10
- export { loadConfig, getActualListenPort, getDefaultUpstreamsPath, type Config, } from "./config.js";
10
+ export { loadConfig, getActualListenPort, getDefaultUpstreamsPath, DEFAULT_CONTEXT_BUDGET_TOKENS, type Config, } from "./config.js";
11
11
  export * from "./daemon-paths.js";
12
12
  export * from "./lockfile.js";
13
13
  export * from "./wrap-utils.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,OAAO,EACL,UAAU,EACV,mBAAmB,EACnB,uBAAuB,EACvB,KAAK,MAAM,GACZ,MAAM,aAAa,CAAC;AACrB,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,OAAO,EACL,UAAU,EACV,mBAAmB,EACnB,uBAAuB,EACvB,6BAA6B,EAC7B,KAAK,MAAM,GACZ,MAAM,aAAa,CAAC;AACrB,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC"}
@@ -7,7 +7,7 @@
7
7
  export * from "./types/index.js";
8
8
  export * from "./db/index.js";
9
9
  export * from "./utils/index.js";
10
- export { loadConfig, getActualListenPort, getDefaultUpstreamsPath, } from "./config.js";
10
+ export { loadConfig, getActualListenPort, getDefaultUpstreamsPath, DEFAULT_CONTEXT_BUDGET_TOKENS, } from "./config.js";
11
11
  export * from "./daemon-paths.js";
12
12
  export * from "./lockfile.js";
13
13
  export * from "./wrap-utils.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,OAAO,EACL,UAAU,EACV,mBAAmB,EACnB,uBAAuB,GAExB,MAAM,aAAa,CAAC;AACrB,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,OAAO,EACL,UAAU,EACV,mBAAmB,EACnB,uBAAuB,EACvB,6BAA6B,GAE9B,MAAM,aAAa,CAAC;AACrB,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC"}
@@ -0,0 +1,11 @@
1
+ -- Add correlation_id column for future parallel tool execution support.
2
+ -- Currently always NULL — no code path generates or assigns correlation IDs yet.
3
+ -- This column is scaffolding for when Claude Code's hook API exposes correlation
4
+ -- IDs. At that point, findRunningEvent() will prefer matching on this column
5
+ -- over the fallback tool-name-based lookup.
6
+ -- See also: findRunningEvent() in packages/core/src/db/events.ts
7
+
8
+ ALTER TABLE events ADD COLUMN correlation_id TEXT;
9
+
10
+ -- Index for correlation-based lookups (unused until IDs are generated)
11
+ CREATE INDEX IF NOT EXISTS idx_events_correlation_id ON events(correlation_id);
@@ -0,0 +1,19 @@
1
+ -- Add token tracking columns to events table
2
+ ALTER TABLE events ADD COLUMN input_tokens INTEGER;
3
+ ALTER TABLE events ADD COLUMN output_tokens INTEGER;
4
+
5
+ -- Tool schema metrics: one row per (session, upstream, tool) from tools/list responses
6
+ CREATE TABLE IF NOT EXISTS tool_schema_metrics (
7
+ id TEXT PRIMARY KEY,
8
+ session_id TEXT NOT NULL,
9
+ upstream_key TEXT,
10
+ tool_name TEXT NOT NULL,
11
+ schema_tokens INTEGER NOT NULL,
12
+ recorded_at TEXT NOT NULL DEFAULT (datetime('now'))
13
+ );
14
+ CREATE INDEX IF NOT EXISTS idx_tsm_session ON tool_schema_metrics(session_id);
15
+ CREATE INDEX IF NOT EXISTS idx_tsm_upstream ON tool_schema_metrics(upstream_key);
16
+ -- Expression-based unique index to handle NULL upstream_key correctly.
17
+ -- ON CONFLICT targeting this index requires SQLite >= 3.37.0 (2021-11-27).
18
+ -- better-sqlite3 bundles its own SQLite, so the version is always recent enough.
19
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_tsm_unique ON tool_schema_metrics(session_id, COALESCE(upstream_key, ''), tool_name);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-recorder/core",
3
- "version": "2.0.8",
3
+ "version": "2.0.14",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -1,3 +1,5 @@
1
- export type { EventType, EventStatus, ErrorCategory, BaseEvent, AgentCallEvent, SubagentCallEvent, SkillCallEvent, ToolCallEvent, RecordedEvent, } from "./events.js";
2
- export type { SessionStatus, Session } from "./session.js";
1
+ /**
2
+ * Type re-exports from @agent-recorder/types (the canonical zero-dep source).
3
+ */
4
+ export type { EventType, EventStatus, ErrorCategory, BaseEvent, AgentCallEvent, SubagentCallEvent, SkillCallEvent, ToolCallEvent, RecordedEvent, SessionStatus, Session, SessionWithActivity, StorageAdapter, } from "@agent-recorder/types";
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,SAAS,EACT,WAAW,EACX,aAAa,EACb,SAAS,EACT,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,aAAa,GACd,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EACV,SAAS,EACT,WAAW,EACX,aAAa,EACb,SAAS,EACT,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,aAAa,EACb,aAAa,EACb,OAAO,EACP,mBAAmB,EACnB,cAAc,GACf,MAAM,uBAAuB,CAAC"}
@@ -1,2 +1,5 @@
1
+ /**
2
+ * Type re-exports from @agent-recorder/types (the canonical zero-dep source).
3
+ */
1
4
  export {};
2
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -3,4 +3,5 @@
3
3
  */
4
4
  export { redactJson, truncateJson, redactAndTruncate } from "./redact.js";
5
5
  export { deriveErrorCategory } from "./error-category.js";
6
+ export { estimateTokens, estimateSerializedTokens } from "./tokens.js";
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC"}
@@ -3,4 +3,5 @@
3
3
  */
4
4
  export { redactJson, truncateJson, redactAndTruncate } from "./redact.js";
5
5
  export { deriveErrorCategory } from "./error-category.js";
6
+ export { estimateTokens, estimateSerializedTokens } from "./tokens.js";
6
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/utils/redact.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAwBlE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,OAAO,EACd,SAAS,GAAE,MAA2B,GACrC,MAAM,CASR;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,EAAE,EACd,SAAS,GAAE,MAA2B,GACrC,MAAM,CAGR"}
1
+ {"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/utils/redact.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAGlE;AA2BD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,OAAO,EACd,SAAS,GAAE,MAA2B,GACrC,MAAM,CASR;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,EAAE,EACd,SAAS,GAAE,MAA2B,GACrC,MAAM,CAGR"}
@@ -8,21 +8,24 @@ const DEFAULT_MAX_LENGTH = 10240; // 10KB
8
8
  * Keys are matched case-insensitively.
9
9
  */
10
10
  export function redactJson(value, keys) {
11
+ const lowerKeys = new Set(keys.map((k) => k.toLowerCase()));
12
+ return redactJsonInternal(value, lowerKeys);
13
+ }
14
+ function redactJsonInternal(value, lowerKeys) {
11
15
  if (value === null || value === undefined) {
12
16
  return value;
13
17
  }
14
18
  if (Array.isArray(value)) {
15
- return value.map((item) => redactJson(item, keys));
19
+ return value.map((item) => redactJsonInternal(item, lowerKeys));
16
20
  }
17
21
  if (typeof value === "object") {
18
22
  const result = {};
19
- const lowerKeys = new Set(keys.map((k) => k.toLowerCase()));
20
23
  for (const [k, v] of Object.entries(value)) {
21
24
  if (lowerKeys.has(k.toLowerCase())) {
22
25
  result[k] = REDACTED_VALUE;
23
26
  }
24
27
  else {
25
- result[k] = redactJson(v, keys);
28
+ result[k] = redactJsonInternal(v, lowerKeys);
26
29
  }
27
30
  }
28
31
  return result;
@@ -1 +1 @@
1
- {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/utils/redact.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,cAAc,GAAG,YAAY,CAAC;AACpC,MAAM,kBAAkB,GAAG,KAAK,CAAC,CAAC,OAAO;AAEzC;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,KAAc,EAAE,IAAc;IACvD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAE5D,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;YACtE,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBACnC,MAAM,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAc,EACd,YAAoB,kBAAkB;IAEtC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,eAAe,GAAG,SAAS,GAAG,EAAE,CAAC,CAAC,6BAA6B;IACrE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,GAAG,gBAAgB,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAc,EACd,IAAc,EACd,YAAoB,kBAAkB;IAEtC,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACzC,OAAO,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAC3C,CAAC"}
1
+ {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/utils/redact.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,cAAc,GAAG,YAAY,CAAC;AACpC,MAAM,kBAAkB,GAAG,KAAK,CAAC,CAAC,OAAO;AAEzC;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,KAAc,EAAE,IAAc;IACvD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAC5D,OAAO,kBAAkB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAc,EAAE,SAAsB;IAChE,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,MAAM,GAA4B,EAAE,CAAC;QAE3C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;YACtE,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBACnC,MAAM,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAc,EACd,YAAoB,kBAAkB;IAEtC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,eAAe,GAAG,SAAS,GAAG,EAAE,CAAC,CAAC,6BAA6B;IACrE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,GAAG,gBAAgB,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAc,EACd,IAAc,EACd,YAAoB,kBAAkB;IAEtC,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACzC,OAAO,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Tests for redaction and truncation utilities,
3
+ * including non-serializable edge cases.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=redact.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.test.d.ts","sourceRoot":"","sources":["../../src/utils/redact.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Tests for redaction and truncation utilities,
3
+ * including non-serializable edge cases.
4
+ */
5
+ import { describe, it, expect } from "vitest";
6
+ import { redactJson, truncateJson, redactAndTruncate } from "./redact.js";
7
+ describe("redactJson", () => {
8
+ it("redacts matching keys case-insensitively", () => {
9
+ const result = redactJson({ token: "secret", Token: "also-secret", safe: "ok" }, ["token"]);
10
+ expect(result).toEqual({
11
+ token: "[REDACTED]",
12
+ Token: "[REDACTED]",
13
+ safe: "ok",
14
+ });
15
+ });
16
+ it("handles null and undefined", () => {
17
+ expect(redactJson(null, ["key"])).toBeNull();
18
+ expect(redactJson(undefined, ["key"])).toBeUndefined();
19
+ });
20
+ it("handles arrays", () => {
21
+ const result = redactJson([{ password: "x" }, { safe: "y" }], ["password"]);
22
+ expect(result).toEqual([{ password: "[REDACTED]" }, { safe: "y" }]);
23
+ });
24
+ it("handles primitive values", () => {
25
+ expect(redactJson("hello", ["key"])).toBe("hello");
26
+ expect(redactJson(42, ["key"])).toBe(42);
27
+ expect(redactJson(true, ["key"])).toBe(true);
28
+ });
29
+ });
30
+ describe("truncateJson", () => {
31
+ it("does not truncate short values", () => {
32
+ const result = truncateJson({ a: 1 });
33
+ expect(result).toBe('{"a":1}');
34
+ });
35
+ it("truncates long values with indicator", () => {
36
+ const long = { data: "x".repeat(20000) };
37
+ const result = truncateJson(long, 100);
38
+ expect(result.length).toBe(100);
39
+ expect(result).toMatch(/\.\.\.\[TRUNCATED\]$/);
40
+ });
41
+ });
42
+ describe("redactAndTruncate", () => {
43
+ it("returns a string", () => {
44
+ const result = redactAndTruncate({ key: "value" }, []);
45
+ expect(typeof result).toBe("string");
46
+ });
47
+ it("redacts and truncates in one step", () => {
48
+ const result = redactAndTruncate({ password: "secret", data: "ok" }, [
49
+ "password",
50
+ ]);
51
+ const parsed = JSON.parse(result);
52
+ expect(parsed.password).toBe("[REDACTED]");
53
+ expect(parsed.data).toBe("ok");
54
+ });
55
+ it("handles circular references by throwing", () => {
56
+ const circular = { a: 1 };
57
+ circular.self = circular;
58
+ // JSON.stringify throws on circular refs; redactAndTruncate should propagate
59
+ expect(() => redactAndTruncate(circular, [])).toThrow();
60
+ });
61
+ it("handles BigInt by throwing", () => {
62
+ const withBigInt = { value: BigInt(123) };
63
+ // JSON.stringify throws on BigInt; redactAndTruncate should propagate
64
+ expect(() => redactAndTruncate(withBigInt, [])).toThrow();
65
+ });
66
+ it("handles Symbol values (dropped by JSON.stringify)", () => {
67
+ const withSymbol = { sym: Symbol("test"), safe: "ok" };
68
+ const result = redactAndTruncate(withSymbol, []);
69
+ const parsed = JSON.parse(result);
70
+ // Symbols are dropped by JSON.stringify
71
+ expect(parsed.sym).toBeUndefined();
72
+ expect(parsed.safe).toBe("ok");
73
+ });
74
+ it("handles undefined values (dropped by JSON.stringify)", () => {
75
+ const withUndefined = { undef: undefined, safe: "ok" };
76
+ const result = redactAndTruncate(withUndefined, []);
77
+ const parsed = JSON.parse(result);
78
+ expect("undef" in parsed).toBe(false);
79
+ expect(parsed.safe).toBe("ok");
80
+ });
81
+ });
82
+ //# sourceMappingURL=redact.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.test.js","sourceRoot":"","sources":["../../src/utils/redact.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Token estimation utility.
3
+ * Uses UTF-8 byte length / 4 approximation — no external dependencies.
4
+ */
5
+ /**
6
+ * Estimate token count for any value.
7
+ * Rough approximation: ~4 UTF-8 bytes per token.
8
+ * Uses TextEncoder for byte-accurate counting (handles non-ASCII correctly).
9
+ * Accurate enough for context-budget alerting; not suitable for exact billing.
10
+ *
11
+ * Pass raw values/objects only. For pre-serialized strings use
12
+ * `estimateSerializedTokens` directly — passing a string here will
13
+ * double-serialize it (JSON.stringify wraps strings in quotes), inflating
14
+ * the estimate.
15
+ */
16
+ export declare function estimateTokens(value: unknown): number;
17
+ /**
18
+ * Estimate token count for an already-serialized JSON string.
19
+ * Uses byte-accurate UTF-8 counting, consistent with estimateTokens.
20
+ * Use this when the value has already been passed through redactAndTruncate
21
+ * (which returns a string) to avoid double-serialization.
22
+ */
23
+ export declare function estimateSerializedTokens(json: string): number;
24
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/utils/tokens.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGrD;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7D"}