@roberttlange/agentlens 0.2.2 → 0.2.3

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 (42) hide show
  1. package/node_modules/@agentlens/contracts/dist/index.d.ts +11 -0
  2. package/node_modules/@agentlens/core/dist/__tests__/config.test.js +49 -2
  3. package/node_modules/@agentlens/core/dist/__tests__/config.test.js.map +1 -1
  4. package/node_modules/@agentlens/core/dist/__tests__/index.test.js +220 -0
  5. package/node_modules/@agentlens/core/dist/__tests__/index.test.js.map +1 -1
  6. package/node_modules/@agentlens/core/dist/config.js +62 -5
  7. package/node_modules/@agentlens/core/dist/config.js.map +1 -1
  8. package/node_modules/@agentlens/core/dist/generatedPricing.d.ts +3 -0
  9. package/node_modules/@agentlens/core/dist/generatedPricing.js +131 -0
  10. package/node_modules/@agentlens/core/dist/generatedPricing.js.map +1 -0
  11. package/node_modules/@agentlens/core/dist/metrics.js +131 -54
  12. package/node_modules/@agentlens/core/dist/metrics.js.map +1 -1
  13. package/node_modules/@agentlens/core/dist/pricing.d.ts +15 -0
  14. package/node_modules/@agentlens/core/dist/pricing.js +133 -0
  15. package/node_modules/@agentlens/core/dist/pricing.js.map +1 -0
  16. package/node_modules/@agentlens/core/dist/pricing.test.d.ts +1 -0
  17. package/node_modules/@agentlens/core/dist/pricing.test.js +109 -0
  18. package/node_modules/@agentlens/core/dist/pricing.test.js.map +1 -0
  19. package/node_modules/@agentlens/core/dist/sourceProfiles.js +3 -67
  20. package/node_modules/@agentlens/core/dist/sourceProfiles.js.map +1 -1
  21. package/node_modules/@agentlens/core/dist/traceIndex.d.ts +12 -0
  22. package/node_modules/@agentlens/core/dist/traceIndex.js +58 -0
  23. package/node_modules/@agentlens/core/dist/traceIndex.js.map +1 -1
  24. package/node_modules/@agentlens/server/dist/activity-cache.d.ts +29 -0
  25. package/node_modules/@agentlens/server/dist/activity-cache.js +57 -0
  26. package/node_modules/@agentlens/server/dist/activity-cache.js.map +1 -0
  27. package/node_modules/@agentlens/server/dist/activity-cache.test.d.ts +1 -0
  28. package/node_modules/@agentlens/server/dist/activity-cache.test.js +84 -0
  29. package/node_modules/@agentlens/server/dist/activity-cache.test.js.map +1 -0
  30. package/node_modules/@agentlens/server/dist/activity.d.ts +12 -1
  31. package/node_modules/@agentlens/server/dist/activity.js +56 -34
  32. package/node_modules/@agentlens/server/dist/activity.js.map +1 -1
  33. package/node_modules/@agentlens/server/dist/app.js +6 -0
  34. package/node_modules/@agentlens/server/dist/app.js.map +1 -1
  35. package/node_modules/@agentlens/server/dist/app.test.js +1 -1
  36. package/node_modules/@agentlens/server/dist/app.test.js.map +1 -1
  37. package/node_modules/@agentlens/server/dist/web/assets/index-DjwZvHl6.css +1 -0
  38. package/node_modules/@agentlens/server/dist/web/assets/index-Ei_qfgA9.js +52 -0
  39. package/node_modules/@agentlens/server/dist/web/index.html +2 -2
  40. package/package.json +1 -1
  41. package/node_modules/@agentlens/server/dist/web/assets/index-Ci8okH8M.js +0 -52
  42. package/node_modules/@agentlens/server/dist/web/assets/index-Cj3kmsFf.css +0 -1
@@ -0,0 +1,133 @@
1
+ function normalizedLookupCandidates(model) {
2
+ const raw = String(model).trim();
3
+ if (!raw)
4
+ return [];
5
+ const normalized = normalizePricingModelId(raw);
6
+ return normalized === raw ? [raw] : [raw, normalized];
7
+ }
8
+ function findCostRate(model, costConfig) {
9
+ const candidates = normalizedLookupCandidates(model);
10
+ for (const candidate of candidates) {
11
+ const match = costConfig.modelRates.find((rate) => rate.model === candidate);
12
+ if (match)
13
+ return match;
14
+ }
15
+ return null;
16
+ }
17
+ function pickActiveRate(rate, promptTokens) {
18
+ const useLongContext = typeof rate.longContextThresholdTokens === "number" &&
19
+ Number.isFinite(rate.longContextThresholdTokens) &&
20
+ rate.longContextThresholdTokens > 0 &&
21
+ promptTokens > rate.longContextThresholdTokens;
22
+ if (!useLongContext) {
23
+ const activeRate = {
24
+ inputPer1MUsd: rate.inputPer1MUsd,
25
+ outputPer1MUsd: rate.outputPer1MUsd,
26
+ cachedReadPer1MUsd: rate.cachedReadPer1MUsd,
27
+ cachedCreatePer1MUsd: rate.cachedCreatePer1MUsd,
28
+ reasoningOutputPer1MUsd: rate.reasoningOutputPer1MUsd,
29
+ };
30
+ if (typeof rate.cachedCreate5mPer1MUsd === "number")
31
+ activeRate.cachedCreate5mPer1MUsd = rate.cachedCreate5mPer1MUsd;
32
+ if (typeof rate.cachedCreate1hPer1MUsd === "number")
33
+ activeRate.cachedCreate1hPer1MUsd = rate.cachedCreate1hPer1MUsd;
34
+ return activeRate;
35
+ }
36
+ const activeRate = {
37
+ inputPer1MUsd: rate.longContextInputPer1MUsd ?? rate.inputPer1MUsd,
38
+ outputPer1MUsd: rate.longContextOutputPer1MUsd ?? rate.outputPer1MUsd,
39
+ cachedReadPer1MUsd: rate.longContextCachedReadPer1MUsd ?? rate.cachedReadPer1MUsd,
40
+ cachedCreatePer1MUsd: rate.longContextCachedCreatePer1MUsd ?? rate.cachedCreatePer1MUsd,
41
+ reasoningOutputPer1MUsd: rate.longContextReasoningOutputPer1MUsd ?? rate.reasoningOutputPer1MUsd,
42
+ };
43
+ const cachedCreate5mPer1MUsd = rate.longContextCachedCreate5mPer1MUsd ?? rate.cachedCreate5mPer1MUsd;
44
+ if (typeof cachedCreate5mPer1MUsd === "number")
45
+ activeRate.cachedCreate5mPer1MUsd = cachedCreate5mPer1MUsd;
46
+ const cachedCreate1hPer1MUsd = rate.longContextCachedCreate1hPer1MUsd ?? rate.cachedCreate1hPer1MUsd;
47
+ if (typeof cachedCreate1hPer1MUsd === "number")
48
+ activeRate.cachedCreate1hPer1MUsd = cachedCreate1hPer1MUsd;
49
+ return activeRate;
50
+ }
51
+ function estimateCachedCreateCost(usage, rate) {
52
+ const cachedCreate5mTokens = usage.cachedCreate5mTokens ?? 0;
53
+ const cachedCreate1hTokens = usage.cachedCreate1hTokens ?? 0;
54
+ const splitKnownTokens = Math.max(0, cachedCreate5mTokens) + Math.max(0, cachedCreate1hTokens);
55
+ const aggregateTokens = Math.max(0, usage.cachedCreateTokens);
56
+ const remainingAggregateTokens = Math.max(0, aggregateTokens - splitKnownTokens);
57
+ let total = 0;
58
+ if (cachedCreate5mTokens > 0) {
59
+ total +=
60
+ (cachedCreate5mTokens / 1_000_000) * (rate.cachedCreate5mPer1MUsd ?? rate.cachedCreatePer1MUsd);
61
+ }
62
+ if (cachedCreate1hTokens > 0) {
63
+ total +=
64
+ (cachedCreate1hTokens / 1_000_000) * (rate.cachedCreate1hPer1MUsd ?? rate.cachedCreatePer1MUsd);
65
+ }
66
+ if (remainingAggregateTokens > 0) {
67
+ total += (remainingAggregateTokens / 1_000_000) * rate.cachedCreatePer1MUsd;
68
+ }
69
+ return total;
70
+ }
71
+ export function estimateUsageCost(usage, costConfig) {
72
+ if (!costConfig.enabled)
73
+ return null;
74
+ const rate = findCostRate(usage.model, costConfig);
75
+ if (!rate) {
76
+ return costConfig.unknownModelPolicy === "zero" ? 0 : null;
77
+ }
78
+ const activeRate = pickActiveRate(rate, usage.promptTokens);
79
+ const total = (Math.max(0, usage.inputTokens) / 1_000_000) * activeRate.inputPer1MUsd +
80
+ (Math.max(0, usage.cachedReadTokens) / 1_000_000) * activeRate.cachedReadPer1MUsd +
81
+ estimateCachedCreateCost(usage, activeRate) +
82
+ (Math.max(0, usage.outputTokens) / 1_000_000) * activeRate.outputPer1MUsd +
83
+ (Math.max(0, usage.reasoningOutputTokens) / 1_000_000) * activeRate.reasoningOutputPer1MUsd;
84
+ return Number(total.toFixed(6));
85
+ }
86
+ export function normalizePricingModelId(model) {
87
+ let normalized = String(model).trim().toLowerCase();
88
+ if (!normalized)
89
+ return "";
90
+ normalized = normalized.replace(/^global\.anthropic\./, "");
91
+ normalized = normalized.replace(/^anthropic\//, "");
92
+ normalized = normalized.replace(/^openai\//, "");
93
+ normalized = normalized.replace(/-v\d+(?::\d+)?$/, "");
94
+ if (normalized.includes("/")) {
95
+ const tail = normalized.split("/").at(-1)?.trim() ?? normalized;
96
+ if (tail.startsWith("claude-") || tail.startsWith("gpt-"))
97
+ normalized = tail;
98
+ }
99
+ const claudeMatch = normalized.match(/^claude-(haiku|sonnet|opus)-4-(5|6)(?:-\d{8})?$/);
100
+ if (claudeMatch)
101
+ return `claude-${claudeMatch[1]}-4.${claudeMatch[2]}`;
102
+ const gpt54Match = normalized.match(/^gpt-5\.4(?:-\d{4}-\d{2}-\d{2})?$/);
103
+ if (gpt54Match)
104
+ return "gpt-5.4";
105
+ const gpt53CodexMatch = normalized.match(/^gpt-5\.3-codex(?:-\d{4}-\d{2}-\d{2})?$/);
106
+ if (gpt53CodexMatch)
107
+ return "gpt-5.3-codex";
108
+ const gpt52CodexMatch = normalized.match(/^gpt-5\.2-codex(?:-\d{4}-\d{2}-\d{2})?$/);
109
+ if (gpt52CodexMatch)
110
+ return "gpt-5.2-codex";
111
+ const gpt52Match = normalized.match(/^gpt-5\.2(?:-\d{4}-\d{2}-\d{2})?$/);
112
+ if (gpt52Match)
113
+ return "gpt-5.2";
114
+ return normalized;
115
+ }
116
+ export function resolveContextWindowTokens(model, config) {
117
+ const rawModel = String(model).trim();
118
+ const normalizedModel = normalizePricingModelId(rawModel);
119
+ for (const candidate of [rawModel, normalizedModel]) {
120
+ if (!candidate)
121
+ continue;
122
+ const direct = config.models.contextWindows.find((entry) => entry.model === candidate);
123
+ if (direct && Number.isFinite(direct.contextWindowTokens) && direct.contextWindowTokens > 0) {
124
+ return direct.contextWindowTokens;
125
+ }
126
+ }
127
+ const rate = findCostRate(rawModel || normalizedModel, config.cost);
128
+ if (rate && Number.isFinite(rate.contextWindowTokens) && (rate.contextWindowTokens ?? 0) > 0) {
129
+ return rate.contextWindowTokens ?? 0;
130
+ }
131
+ return config.models.defaultContextWindowTokens > 0 ? config.models.defaultContextWindowTokens : 0;
132
+ }
133
+ //# sourceMappingURL=pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.js","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { mergeConfig } from "./config.js";
3
+ import { estimateUsageCost, normalizePricingModelId } from "./pricing.js";
4
+ describe("pricing", () => {
5
+ it("normalizes observed Anthropic and OpenAI model ids to canonical pricing keys", () => {
6
+ expect(normalizePricingModelId("global.anthropic.claude-opus-4-6-v1")).toBe("claude-opus-4.6");
7
+ expect(normalizePricingModelId("global.anthropic.claude-haiku-4-5-20251001-v1:0")).toBe("claude-haiku-4.5");
8
+ expect(normalizePricingModelId("claude-sonnet-4-6-20260219")).toBe("claude-sonnet-4.6");
9
+ expect(normalizePricingModelId("openai/gpt-5.4-2026-02-28")).toBe("gpt-5.4");
10
+ expect(normalizePricingModelId("gpt-5.3-codex")).toBe("gpt-5.3-codex");
11
+ });
12
+ it("uses Anthropic split cache write pricing and long-context premiums", () => {
13
+ const config = mergeConfig({
14
+ cost: {
15
+ enabled: true,
16
+ currency: "USD",
17
+ unknownModelPolicy: "n_a",
18
+ modelRates: [
19
+ {
20
+ model: "claude-sonnet-4.6",
21
+ inputPer1MUsd: 3,
22
+ outputPer1MUsd: 15,
23
+ cachedReadPer1MUsd: 0.3,
24
+ cachedCreatePer1MUsd: 3.75,
25
+ cachedCreate5mPer1MUsd: 3.75,
26
+ cachedCreate1hPer1MUsd: 6,
27
+ reasoningOutputPer1MUsd: 0,
28
+ longContextThresholdTokens: 200_000,
29
+ longContextInputPer1MUsd: 6,
30
+ longContextOutputPer1MUsd: 22.5,
31
+ longContextCachedReadPer1MUsd: 0.6,
32
+ longContextCachedCreatePer1MUsd: 7.5,
33
+ longContextCachedCreate5mPer1MUsd: 7.5,
34
+ longContextCachedCreate1hPer1MUsd: 12,
35
+ contextWindowTokens: 1_000_000,
36
+ },
37
+ ],
38
+ },
39
+ });
40
+ const baseCost = estimateUsageCost({
41
+ model: "claude-sonnet-4-6-20260219",
42
+ promptTokens: 150_000,
43
+ inputTokens: 100_000,
44
+ cachedReadTokens: 20_000,
45
+ cachedCreateTokens: 10_000,
46
+ cachedCreate5mTokens: 8_000,
47
+ cachedCreate1hTokens: 2_000,
48
+ outputTokens: 50_000,
49
+ reasoningOutputTokens: 0,
50
+ }, config.cost);
51
+ const longCost = estimateUsageCost({
52
+ model: "claude-sonnet-4-6-20260219",
53
+ promptTokens: 250_000,
54
+ inputTokens: 100_000,
55
+ cachedReadTokens: 20_000,
56
+ cachedCreateTokens: 10_000,
57
+ cachedCreate5mTokens: 8_000,
58
+ cachedCreate1hTokens: 2_000,
59
+ outputTokens: 50_000,
60
+ reasoningOutputTokens: 0,
61
+ }, config.cost);
62
+ expect(baseCost).toBe(1.098);
63
+ expect(longCost).toBe(1.821);
64
+ });
65
+ it("applies GPT-5.4 premium pricing only above the long-context threshold", () => {
66
+ const config = mergeConfig({
67
+ cost: {
68
+ enabled: true,
69
+ currency: "USD",
70
+ unknownModelPolicy: "n_a",
71
+ modelRates: [
72
+ {
73
+ model: "gpt-5.4",
74
+ inputPer1MUsd: 1.25,
75
+ outputPer1MUsd: 7.5,
76
+ cachedReadPer1MUsd: 0.125,
77
+ cachedCreatePer1MUsd: 0,
78
+ reasoningOutputPer1MUsd: 0,
79
+ longContextThresholdTokens: 272_000,
80
+ longContextInputPer1MUsd: 2.5,
81
+ longContextOutputPer1MUsd: 11.25,
82
+ contextWindowTokens: 1_050_000,
83
+ },
84
+ ],
85
+ },
86
+ });
87
+ const shortCost = estimateUsageCost({
88
+ model: "gpt-5.4-2026-02-28",
89
+ promptTokens: 200_000,
90
+ inputTokens: 180_000,
91
+ cachedReadTokens: 20_000,
92
+ cachedCreateTokens: 0,
93
+ outputTokens: 40_000,
94
+ reasoningOutputTokens: 0,
95
+ }, config.cost);
96
+ const longCost = estimateUsageCost({
97
+ model: "gpt-5.4-2026-02-28",
98
+ promptTokens: 300_000,
99
+ inputTokens: 180_000,
100
+ cachedReadTokens: 20_000,
101
+ cachedCreateTokens: 0,
102
+ outputTokens: 40_000,
103
+ reasoningOutputTokens: 0,
104
+ }, config.cost);
105
+ expect(shortCost).toBe(0.5275);
106
+ expect(longCost).toBe(0.9025);
107
+ });
108
+ });
109
+ //# sourceMappingURL=pricing.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.test.js","sourceRoot":"","sources":["../src/pricing.test.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { DEFAULT_CONTEXT_WINDOWS, DEFAULT_PRICING_MODEL_RATES } from "./generatedPricing.js";
1
2
  export const DEFAULT_SESSION_LOG_DIRECTORIES = [
2
3
  { directory: "~/.codex", logType: "codex" },
3
4
  { directory: "~/.claude", logType: "claude" },
@@ -111,76 +112,11 @@ export const DEFAULT_CONFIG = {
111
112
  enabled: true,
112
113
  currency: "USD",
113
114
  unknownModelPolicy: "n_a",
114
- modelRates: [
115
- {
116
- model: "gpt-5.2-codex",
117
- inputPer1MUsd: 1.5,
118
- outputPer1MUsd: 6,
119
- cachedReadPer1MUsd: 0.375,
120
- cachedCreatePer1MUsd: 0.375,
121
- reasoningOutputPer1MUsd: 0,
122
- },
123
- {
124
- model: "gpt-5.3-codex",
125
- inputPer1MUsd: 1.5,
126
- outputPer1MUsd: 6,
127
- cachedReadPer1MUsd: 0.375,
128
- cachedCreatePer1MUsd: 0.375,
129
- reasoningOutputPer1MUsd: 0,
130
- },
131
- {
132
- model: "gpt-5.2",
133
- inputPer1MUsd: 1.75,
134
- outputPer1MUsd: 14,
135
- cachedReadPer1MUsd: 0.175,
136
- cachedCreatePer1MUsd: 0.175,
137
- reasoningOutputPer1MUsd: 0,
138
- },
139
- {
140
- model: "claude-opus-4-5-20251101",
141
- inputPer1MUsd: 5,
142
- outputPer1MUsd: 25,
143
- cachedReadPer1MUsd: 0.5,
144
- cachedCreatePer1MUsd: 6.25,
145
- reasoningOutputPer1MUsd: 0,
146
- },
147
- {
148
- model: "claude-opus-4-6",
149
- inputPer1MUsd: 5,
150
- outputPer1MUsd: 25,
151
- cachedReadPer1MUsd: 0.5,
152
- cachedCreatePer1MUsd: 6.25,
153
- reasoningOutputPer1MUsd: 0,
154
- },
155
- {
156
- model: "claude-sonnet-4-5-20250929",
157
- inputPer1MUsd: 3,
158
- outputPer1MUsd: 15,
159
- cachedReadPer1MUsd: 0.3,
160
- cachedCreatePer1MUsd: 3.75,
161
- reasoningOutputPer1MUsd: 0,
162
- },
163
- {
164
- model: "claude-haiku-4-5-20251001",
165
- inputPer1MUsd: 1,
166
- outputPer1MUsd: 5,
167
- cachedReadPer1MUsd: 0.1,
168
- cachedCreatePer1MUsd: 1.25,
169
- reasoningOutputPer1MUsd: 0,
170
- },
171
- ],
115
+ modelRates: DEFAULT_PRICING_MODEL_RATES,
172
116
  },
173
117
  models: {
174
118
  defaultContextWindowTokens: 200_000,
175
- contextWindows: [
176
- { model: "gpt-5.2-codex", contextWindowTokens: 400_000 },
177
- { model: "gpt-5.3-codex", contextWindowTokens: 400_000 },
178
- { model: "gpt-5.2", contextWindowTokens: 400_000 },
179
- { model: "claude-opus-4-5-20251101", contextWindowTokens: 200_000 },
180
- { model: "claude-opus-4-6", contextWindowTokens: 200_000 },
181
- { model: "claude-sonnet-4-5-20250929", contextWindowTokens: 200_000 },
182
- { model: "claude-haiku-4-5-20251001", contextWindowTokens: 200_000 },
183
- ],
119
+ contextWindows: DEFAULT_CONTEXT_WINDOWS,
184
120
  },
185
121
  };
186
122
  //# sourceMappingURL=sourceProfiles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sourceProfiles.js","sourceRoot":"","sources":["../src/sourceProfiles.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sourceProfiles.js","sourceRoot":"","sources":["../src/sourceProfiles.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,15 @@ export interface TracePageOptions {
8
8
  export interface TraceIndexEvent {
9
9
  envelope: StreamEnvelope;
10
10
  }
11
+ interface SessionActivitySpan {
12
+ startMs: number;
13
+ endMs: number;
14
+ }
15
+ interface SessionActivityArtifacts {
16
+ eventCount: number;
17
+ eventTimestamps: number[];
18
+ activeSegments: SessionActivitySpan[];
19
+ }
11
20
  export declare class TraceIndex extends EventEmitter {
12
21
  private readonly parserRegistry;
13
22
  private config;
@@ -34,6 +43,7 @@ export declare class TraceIndex extends EventEmitter {
34
43
  stop(): void;
35
44
  refresh(): Promise<void>;
36
45
  getPerformanceStats(): IndexPerformanceStats;
46
+ getStreamVersion(): number;
37
47
  getTopTools(limit?: number): NamedCount[];
38
48
  private buildRetentionStats;
39
49
  private computeBaseIntervalMs;
@@ -61,6 +71,8 @@ export declare class TraceIndex extends EventEmitter {
61
71
  getOverview(): OverviewStats;
62
72
  private hydrateEventsForEntry;
63
73
  getSessionDetail(id: string): SessionDetail;
74
+ getSessionActivityArtifacts(id: string): Readonly<SessionActivityArtifacts>;
64
75
  getTracePage(id: string, options?: TracePageOptions): TracePage;
65
76
  resolveId(candidate: string): string;
66
77
  }
78
+ export {};
@@ -22,6 +22,7 @@ const EVENT_KIND_KEYS = [
22
22
  const WAITING_INPUT_PATTERN = /\b(?:await(?:ing)?\s+(?:user|input)|waiting\s+for\s+(?:user|input|approval)|user\s+input\s+required|needs?\s+user\s+input|permission\s+required|approval\s+required|confirm(?:ation)?\s+(?:required|needed)|press\s+enter\s+to\s+continue)\b/i;
23
23
  const WAITING_PROMPT_PATTERN = /\b(?:do\s+you\s+want(?:\s+me)?|would\s+you\s+like(?:\s+me)?|should\s+i\b|can\s+you\s+confirm|please\s+confirm|let\s+me\s+know\s+if\s+you(?:'d)?\s+like|which\s+(?:option|approach)|choose\s+(?:one|an?\s+option)|pick\s+(?:one|an?\s+option)|approve(?:\s+this)?|permission\s+to)\b/i;
24
24
  const ACTIVITY_BIN_COUNT = 12;
25
+ const ACTIVE_IDLE_GAP_MS = 20 * 60_000;
25
26
  const MATERIALIZED_TTL_MS = 5 * 60_000;
26
27
  const DIRTY_BATCH_LIMIT = 64;
27
28
  function emptyEventKindCounts() {
@@ -36,6 +37,43 @@ function emptyEventKindCounts() {
36
37
  meta: 0,
37
38
  };
38
39
  }
40
+ function collectTimestampMs(events) {
41
+ const timestamps = [];
42
+ for (const event of events) {
43
+ const timestampMs = event.timestampMs;
44
+ if (timestampMs === null || !Number.isFinite(timestampMs) || timestampMs <= 0)
45
+ continue;
46
+ timestamps.push(timestampMs);
47
+ }
48
+ timestamps.sort((left, right) => left - right);
49
+ return timestamps;
50
+ }
51
+ function buildActiveSegmentsFromEventTimestamps(eventTimestamps) {
52
+ if (eventTimestamps.length === 0)
53
+ return [];
54
+ const segments = [];
55
+ let segmentStartMs = eventTimestamps[0] ?? 0;
56
+ let previousTsMs = segmentStartMs;
57
+ for (let index = 1; index < eventTimestamps.length; index += 1) {
58
+ const nextTsMs = eventTimestamps[index] ?? previousTsMs;
59
+ const gapMs = Math.max(0, nextTsMs - previousTsMs);
60
+ if (gapMs > ACTIVE_IDLE_GAP_MS) {
61
+ segments.push({ startMs: segmentStartMs, endMs: previousTsMs });
62
+ segmentStartMs = nextTsMs;
63
+ }
64
+ previousTsMs = nextTsMs;
65
+ }
66
+ segments.push({ startMs: segmentStartMs, endMs: previousTsMs });
67
+ return segments;
68
+ }
69
+ function buildSessionActivityArtifacts(events) {
70
+ const eventTimestamps = collectTimestampMs(events);
71
+ return {
72
+ eventCount: events.length,
73
+ eventTimestamps,
74
+ activeSegments: buildActiveSegmentsFromEventTimestamps(eventTimestamps),
75
+ };
76
+ }
39
77
  function normalizeActivityCounts(counts) {
40
78
  let maxCount = 0;
41
79
  for (const count of counts) {
@@ -523,6 +561,9 @@ export class TraceIndex extends EventEmitter {
523
561
  ...stats,
524
562
  };
525
563
  }
564
+ getStreamVersion() {
565
+ return this.streamVersion;
566
+ }
526
567
  getTopTools(limit = 12) {
527
568
  const counts = new Map();
528
569
  for (const entry of this.entries.values()) {
@@ -1000,6 +1041,7 @@ export class TraceIndex extends EventEmitter {
1000
1041
  residentEvents: redactedEvents,
1001
1042
  cachedFullEvents: redactedEvents,
1002
1043
  cachedRawEvents: parsed.events,
1044
+ activityArtifacts: null,
1003
1045
  pinnedMaterializedAtMs: current?.pinnedMaterializedAtMs ?? 0,
1004
1046
  });
1005
1047
  this.cursorById.set(file.id, {
@@ -1028,6 +1070,7 @@ export class TraceIndex extends EventEmitter {
1028
1070
  residentEvents: [],
1029
1071
  cachedFullEvents: [],
1030
1072
  cachedRawEvents: [],
1073
+ activityArtifacts: null,
1031
1074
  pinnedMaterializedAtMs: 0,
1032
1075
  });
1033
1076
  this.cursorById.set(file.id, {
@@ -1111,6 +1154,7 @@ export class TraceIndex extends EventEmitter {
1111
1154
  residentEvents: mergedEvents,
1112
1155
  cachedFullEvents: mergedEvents,
1113
1156
  cachedRawEvents: mergedRawEvents,
1157
+ activityArtifacts: null,
1114
1158
  pinnedMaterializedAtMs: current.pinnedMaterializedAtMs,
1115
1159
  });
1116
1160
  this.cursorById.set(file.id, {
@@ -1255,6 +1299,7 @@ export class TraceIndex extends EventEmitter {
1255
1299
  const refreshedSummary = summarize(entry.file, parsed.agent, parsed.parser, parsed.sessionId, parsed.events, parsed.parseError, this.config, nowMs());
1256
1300
  entry.cachedFullEvents = redactedEvents;
1257
1301
  entry.cachedRawEvents = parsed.events;
1302
+ entry.activityArtifacts = null;
1258
1303
  entry.pinnedMaterializedAtMs = nowMs();
1259
1304
  entry.summary = {
1260
1305
  ...refreshedSummary,
@@ -1274,6 +1319,19 @@ export class TraceIndex extends EventEmitter {
1274
1319
  events,
1275
1320
  };
1276
1321
  }
1322
+ getSessionActivityArtifacts(id) {
1323
+ const found = this.entries.get(id);
1324
+ if (!found) {
1325
+ throw new Error(`unknown trace id: ${id}`);
1326
+ }
1327
+ if (found.activityArtifacts && found.activityArtifacts.eventCount === found.summary.eventCount) {
1328
+ return found.activityArtifacts;
1329
+ }
1330
+ const events = this.hydrateEventsForEntry(found);
1331
+ const artifacts = buildSessionActivityArtifacts(events);
1332
+ found.activityArtifacts = artifacts;
1333
+ return artifacts;
1334
+ }
1277
1335
  getTracePage(id, options = {}) {
1278
1336
  const detail = this.getSessionDetail(id);
1279
1337
  const includeMeta = options.includeMeta ?? this.config.scan.includeMetaDefault;