copilot-lens 1.0.11 → 1.0.13
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.
- package/README.md +17 -10
- package/dist/__tests__/claude-code-sessions.test.d.ts +1 -0
- package/dist/__tests__/claude-code-sessions.test.js +284 -0
- package/dist/__tests__/claude-code-sessions.test.js.map +1 -0
- package/dist/claude-code-sessions.d.ts +56 -0
- package/dist/claude-code-sessions.js +430 -0
- package/dist/claude-code-sessions.js.map +1 -0
- package/dist/cli.js +0 -0
- package/dist/search.d.ts +2 -2
- package/dist/server.js +5 -2
- package/dist/server.js.map +1 -1
- package/dist/sessions.d.ts +3 -2
- package/dist/sessions.js +57 -24
- package/dist/sessions.js.map +1 -1
- package/package.json +1 -1
- package/public/app.js +42 -8
- package/public/index.html +9 -0
- package/public/style.css +39 -0
package/README.md
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
**Your Copilot history has answers. Now you can actually find them.**
|
|
4
4
|
|
|
5
|
-
Copilot Lens is a local memory layer for
|
|
5
|
+
Copilot Lens is a local memory layer for AI coding assistants — search and browse everything you've ever discussed with Copilot or Claude, across Copilot CLI terminal sessions, VS Code Copilot Chat, and Claude Code. All on your machine. No cloud. No sign-in.
|
|
6
6
|
|
|
7
7
|
## Why
|
|
8
8
|
|
|
9
|
-
Copilot sessions are ephemeral by default. You solve a problem, close the terminal, and it's gone. Days later you need that same approach, that regex, that architecture decision — and you have nothing to reference.
|
|
9
|
+
Copilot and Claude sessions are ephemeral by default. You solve a problem, close the terminal, and it's gone. Days later you need that same approach, that regex, that architecture decision — and you have nothing to reference.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
These tools store all of this locally. Copilot Lens makes it accessible.
|
|
12
12
|
|
|
13
13
|
## Install
|
|
14
14
|
|
|
@@ -45,7 +45,7 @@ Search across every conversation you've ever had with Copilot — CLI and VS Cod
|
|
|
45
45
|
|
|
46
46
|
- Full-text search over all session content
|
|
47
47
|
- Ranked results with inline highlights showing context around each match
|
|
48
|
-
- Filter results by source (CLI
|
|
48
|
+
- Filter results by source (Copilot CLI, VS Code, or Claude Code), date range, or working directory
|
|
49
49
|
- Results update as you type (debounced)
|
|
50
50
|
- Works offline, entirely on your machine
|
|
51
51
|
|
|
@@ -55,8 +55,8 @@ Search across every conversation you've ever had with Copilot — CLI and VS Cod
|
|
|
55
55
|
|
|
56
56
|
Browse the full history of your Copilot sessions in a searchable, filterable list.
|
|
57
57
|
|
|
58
|
-
- **Unified view** — CLI
|
|
59
|
-
- **Source badges** — see at a glance whether a session came from CLI or
|
|
58
|
+
- **Unified view** — Copilot CLI, VS Code Copilot Chat, and Claude Code sessions side by side
|
|
59
|
+
- **Source badges** — see at a glance whether a session came from Copilot CLI, VS Code, or Claude Code
|
|
60
60
|
- **Color-coded by directory** — each project gets a distinct accent color
|
|
61
61
|
- **Status detection** — Running, Completed, or Error
|
|
62
62
|
- **Filter by** time range, status, and working directory
|
|
@@ -72,7 +72,7 @@ Browse the full history of your Copilot sessions in a searchable, filterable lis
|
|
|
72
72
|
|
|
73
73
|
### 📊 Analytics — Understand your usage patterns
|
|
74
74
|
|
|
75
|
-
Eight interactive charts that show how and when you use Copilot.
|
|
75
|
+
Eight interactive charts that show how and when you use Copilot and Claude. Filter by source (All / Copilot CLI / VS Code / Claude Code) to see per-tool breakdowns.
|
|
76
76
|
|
|
77
77
|
| Chart | What It Shows |
|
|
78
78
|
|-------|---------------|
|
|
@@ -107,9 +107,9 @@ A 0–100 score per repository (CLI) and globally (VS Code) with actionable impr
|
|
|
107
107
|
|
|
108
108
|
## How It Works
|
|
109
109
|
|
|
110
|
-
Copilot Lens reads session data from
|
|
110
|
+
Copilot Lens reads session data from three local sources — no network requests, no external APIs.
|
|
111
111
|
|
|
112
|
-
###
|
|
112
|
+
### Copilot CLI Sessions
|
|
113
113
|
- **Location**: `~/.copilot/session-state/`
|
|
114
114
|
- `workspace.yaml` — session metadata (directory, git branch, timestamps)
|
|
115
115
|
- `events.jsonl` — full event log (messages, tool calls, errors)
|
|
@@ -128,6 +128,13 @@ Supported platforms and paths:
|
|
|
128
128
|
|
|
129
129
|
VS Code Insiders is also supported. Sessions with pasted images (which can exceed 100MB) are automatically stripped of image data. Files over 200MB are skipped.
|
|
130
130
|
|
|
131
|
+
### Claude Code Sessions
|
|
132
|
+
- **Location**: `~/.claude/projects/{sanitized-project-path}/{sessionId}.jsonl`
|
|
133
|
+
- Each file is a JSONL stream of events with types `user`, `assistant`, `progress`, and others
|
|
134
|
+
- `user` events contain the prompt; `assistant` events contain model responses and tool calls
|
|
135
|
+
- Sidechain events (warmup/internal) are filtered out automatically
|
|
136
|
+
- Session title comes from the `slug` field (e.g. `happy-seeking-whistle`)
|
|
137
|
+
|
|
131
138
|
### Duration Calculation
|
|
132
139
|
|
|
133
140
|
Durations are calculated from actual event activity, not wall-clock time. Gaps longer than 5 minutes between events are excluded — so a session you paused and resumed doesn't show an inflated duration.
|
|
@@ -142,7 +149,7 @@ Durations are calculated from actual event activity, not wall-clock time. Gaps l
|
|
|
142
149
|
| Frontend | Vanilla HTML/CSS/JavaScript |
|
|
143
150
|
| Charts | Chart.js |
|
|
144
151
|
| Data | YAML, JSONL, SQLite (`better-sqlite3`) |
|
|
145
|
-
| Testing | Vitest (
|
|
152
|
+
| Testing | Vitest (97 tests) |
|
|
146
153
|
|
|
147
154
|
---
|
|
148
155
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const vitest_1 = require("vitest");
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const os = __importStar(require("os"));
|
|
40
|
+
const claude_code_sessions_1 = require("../claude-code-sessions");
|
|
41
|
+
const cache_1 = require("../cache");
|
|
42
|
+
const { extractTextContent, extractToolUseBlocks, deriveStatus, readAllLines } = claude_code_sessions_1._testing;
|
|
43
|
+
// ============ Unit tests for pure helpers ============
|
|
44
|
+
(0, vitest_1.describe)("extractTextContent", () => {
|
|
45
|
+
(0, vitest_1.it)("returns empty string for undefined", () => {
|
|
46
|
+
(0, vitest_1.expect)(extractTextContent(undefined)).toBe("");
|
|
47
|
+
});
|
|
48
|
+
(0, vitest_1.it)("returns string as-is", () => {
|
|
49
|
+
(0, vitest_1.expect)(extractTextContent("hello world")).toBe("hello world");
|
|
50
|
+
});
|
|
51
|
+
(0, vitest_1.it)("joins text blocks from array", () => {
|
|
52
|
+
const blocks = [
|
|
53
|
+
{ type: "text", text: "Hello " },
|
|
54
|
+
{ type: "thinking", thinking: "thinking..." },
|
|
55
|
+
{ type: "text", text: "world" },
|
|
56
|
+
];
|
|
57
|
+
(0, vitest_1.expect)(extractTextContent(blocks)).toBe("Hello world");
|
|
58
|
+
});
|
|
59
|
+
(0, vitest_1.it)("skips non-text blocks", () => {
|
|
60
|
+
const blocks = [
|
|
61
|
+
{ type: "tool_use", id: "t1", name: "bash", input: {} },
|
|
62
|
+
{ type: "text", text: "Done" },
|
|
63
|
+
];
|
|
64
|
+
(0, vitest_1.expect)(extractTextContent(blocks)).toBe("Done");
|
|
65
|
+
});
|
|
66
|
+
(0, vitest_1.it)("returns empty string for array with no text blocks", () => {
|
|
67
|
+
const blocks = [{ type: "thinking", thinking: "hmm" }];
|
|
68
|
+
(0, vitest_1.expect)(extractTextContent(blocks)).toBe("");
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
(0, vitest_1.describe)("extractToolUseBlocks", () => {
|
|
72
|
+
(0, vitest_1.it)("returns empty array for undefined", () => {
|
|
73
|
+
(0, vitest_1.expect)(extractToolUseBlocks(undefined)).toEqual([]);
|
|
74
|
+
});
|
|
75
|
+
(0, vitest_1.it)("returns empty array for string content", () => {
|
|
76
|
+
(0, vitest_1.expect)(extractToolUseBlocks("some string")).toEqual([]);
|
|
77
|
+
});
|
|
78
|
+
(0, vitest_1.it)("extracts only tool_use blocks", () => {
|
|
79
|
+
const blocks = [
|
|
80
|
+
{ type: "thinking", thinking: "hmm" },
|
|
81
|
+
{ type: "tool_use", id: "t1", name: "bash", input: { cmd: "ls" } },
|
|
82
|
+
{ type: "text", text: "result" },
|
|
83
|
+
{ type: "tool_use", id: "t2", name: "read", input: { path: "/foo" } },
|
|
84
|
+
];
|
|
85
|
+
const result = extractToolUseBlocks(blocks);
|
|
86
|
+
(0, vitest_1.expect)(result).toHaveLength(2);
|
|
87
|
+
(0, vitest_1.expect)(result[0].name).toBe("bash");
|
|
88
|
+
(0, vitest_1.expect)(result[1].name).toBe("read");
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
(0, vitest_1.describe)("deriveStatus", () => {
|
|
92
|
+
(0, vitest_1.it)("returns completed for undefined timestamp", () => {
|
|
93
|
+
(0, vitest_1.expect)(deriveStatus(undefined)).toBe("completed");
|
|
94
|
+
});
|
|
95
|
+
(0, vitest_1.it)("returns completed for old timestamp", () => {
|
|
96
|
+
const old = new Date(Date.now() - 600000).toISOString();
|
|
97
|
+
(0, vitest_1.expect)(deriveStatus(old)).toBe("completed");
|
|
98
|
+
});
|
|
99
|
+
(0, vitest_1.it)("returns running for recent timestamp", () => {
|
|
100
|
+
const recent = new Date(Date.now() - 60000).toISOString();
|
|
101
|
+
(0, vitest_1.expect)(deriveStatus(recent)).toBe("running");
|
|
102
|
+
});
|
|
103
|
+
(0, vitest_1.it)("returns completed for timestamp exactly at 5-min boundary", () => {
|
|
104
|
+
const boundary = new Date(Date.now() - 300001).toISOString();
|
|
105
|
+
(0, vitest_1.expect)(deriveStatus(boundary)).toBe("completed");
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
// ============ Integration tests with temp filesystem ============
|
|
109
|
+
function makeEvent(overrides) {
|
|
110
|
+
return JSON.stringify({ timestamp: "2024-01-15T10:00:00Z", ...overrides });
|
|
111
|
+
}
|
|
112
|
+
(0, vitest_1.describe)("listClaudeCodeSessions / getClaudeCodeSession / isClaudeCodeSession", () => {
|
|
113
|
+
let tmpDir;
|
|
114
|
+
let projectsDir;
|
|
115
|
+
let projectDir;
|
|
116
|
+
(0, vitest_1.beforeEach)(() => {
|
|
117
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "claude-lens-test-"));
|
|
118
|
+
projectsDir = path.join(tmpDir, ".claude", "projects");
|
|
119
|
+
projectDir = path.join(projectsDir, "-Users-test-myproject");
|
|
120
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
121
|
+
// Override home dir so getClaudeCodeProjectsDir() points to tmpDir
|
|
122
|
+
process.env.HOME = tmpDir;
|
|
123
|
+
});
|
|
124
|
+
(0, vitest_1.afterEach)(() => {
|
|
125
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
126
|
+
delete process.env.HOME;
|
|
127
|
+
});
|
|
128
|
+
function writeSession(sessionId, lines) {
|
|
129
|
+
fs.writeFileSync(path.join(projectDir, `${sessionId}.jsonl`), lines.join("\n") + "\n");
|
|
130
|
+
}
|
|
131
|
+
(0, vitest_1.it)("returns empty array when projects dir does not exist", () => {
|
|
132
|
+
fs.rmSync(projectsDir, { recursive: true, force: true });
|
|
133
|
+
const sessions = (0, claude_code_sessions_1.listClaudeCodeSessions)();
|
|
134
|
+
(0, vitest_1.expect)(sessions).toEqual([]);
|
|
135
|
+
});
|
|
136
|
+
(0, vitest_1.it)("skips sessions with no user events", () => {
|
|
137
|
+
writeSession("sess-no-user", [
|
|
138
|
+
makeEvent({ type: "assistant", sessionId: "sess-no-user", cwd: "/foo", gitBranch: "main", slug: "my-slug", message: { model: "claude-sonnet-4-6", content: [{ type: "text", text: "hi" }] } }),
|
|
139
|
+
]);
|
|
140
|
+
(0, vitest_1.expect)((0, claude_code_sessions_1.listClaudeCodeSessions)()).toHaveLength(0);
|
|
141
|
+
});
|
|
142
|
+
(0, vitest_1.it)("skips isSidechain user events when checking for user presence", () => {
|
|
143
|
+
writeSession("sess-sidechain", [
|
|
144
|
+
makeEvent({ type: "user", isSidechain: true, sessionId: "sess-sidechain", cwd: "/foo", gitBranch: "main", slug: "slug", message: { content: "warmup" } }),
|
|
145
|
+
]);
|
|
146
|
+
(0, vitest_1.expect)((0, claude_code_sessions_1.listClaudeCodeSessions)()).toHaveLength(0);
|
|
147
|
+
});
|
|
148
|
+
(0, vitest_1.it)("lists a valid session with correct metadata", () => {
|
|
149
|
+
writeSession("abc-123", [
|
|
150
|
+
makeEvent({ type: "user", isSidechain: false, sessionId: "abc-123", cwd: "/Users/test/myproject", gitBranch: "main", slug: "happy-slug", timestamp: "2024-01-15T10:00:00Z", message: { content: "Hello" } }),
|
|
151
|
+
makeEvent({ type: "assistant", isSidechain: false, sessionId: "abc-123", timestamp: "2024-01-15T10:01:00Z", message: { model: "claude-sonnet-4-6", content: [{ type: "text", text: "Hi there" }] } }),
|
|
152
|
+
]);
|
|
153
|
+
const sessions = (0, claude_code_sessions_1.listClaudeCodeSessions)();
|
|
154
|
+
(0, vitest_1.expect)(sessions).toHaveLength(1);
|
|
155
|
+
(0, vitest_1.expect)(sessions[0].id).toBe("abc-123");
|
|
156
|
+
(0, vitest_1.expect)(sessions[0].cwd).toBe("/Users/test/myproject");
|
|
157
|
+
(0, vitest_1.expect)(sessions[0].branch).toBe("main");
|
|
158
|
+
(0, vitest_1.expect)(sessions[0].title).toBe("happy-slug");
|
|
159
|
+
(0, vitest_1.expect)(sessions[0].source).toBe("claude-code");
|
|
160
|
+
(0, vitest_1.expect)(sessions[0].createdAt).toBe("2024-01-15T10:00:00Z");
|
|
161
|
+
(0, vitest_1.expect)(sessions[0].updatedAt).toBe("2024-01-15T10:01:00Z");
|
|
162
|
+
});
|
|
163
|
+
(0, vitest_1.it)("skips files inside subagents subdirectory", () => {
|
|
164
|
+
const subagentsDir = path.join(projectDir, "subagents");
|
|
165
|
+
fs.mkdirSync(subagentsDir, { recursive: true });
|
|
166
|
+
fs.writeFileSync(path.join(subagentsDir, "agent-abc.jsonl"), makeEvent({ type: "user", sessionId: "agent-abc", cwd: "/foo", slug: "s", message: { content: "hi" } }) + "\n");
|
|
167
|
+
// subagentsDir is a subdir of projectDir, not a .jsonl at top level — should be ignored
|
|
168
|
+
(0, vitest_1.expect)((0, claude_code_sessions_1.listClaudeCodeSessions)()).toHaveLength(0);
|
|
169
|
+
});
|
|
170
|
+
(0, vitest_1.it)("isClaudeCodeSession returns true for existing session", () => {
|
|
171
|
+
writeSession("my-session-id", [
|
|
172
|
+
makeEvent({ type: "user", sessionId: "my-session-id", cwd: "/foo", slug: "s", message: { content: "hi" } }),
|
|
173
|
+
]);
|
|
174
|
+
(0, vitest_1.expect)((0, claude_code_sessions_1.isClaudeCodeSession)("my-session-id")).toBe(true);
|
|
175
|
+
});
|
|
176
|
+
(0, vitest_1.it)("isClaudeCodeSession returns false for unknown id", () => {
|
|
177
|
+
(0, vitest_1.expect)((0, claude_code_sessions_1.isClaudeCodeSession)("does-not-exist")).toBe(false);
|
|
178
|
+
});
|
|
179
|
+
(0, vitest_1.it)("getClaudeCodeSession returns null for unknown session", () => {
|
|
180
|
+
(0, vitest_1.expect)((0, claude_code_sessions_1.getClaudeCodeSession)("does-not-exist")).toBeNull();
|
|
181
|
+
});
|
|
182
|
+
(0, vitest_1.it)("getClaudeCodeSession converts user events to user.message", () => {
|
|
183
|
+
writeSession("sess-1", [
|
|
184
|
+
makeEvent({ type: "user", isSidechain: false, sessionId: "sess-1", cwd: "/proj", gitBranch: "main", slug: "test-slug", timestamp: "2024-01-15T10:00:00Z", message: { content: "What is 2+2?" } }),
|
|
185
|
+
]);
|
|
186
|
+
const detail = (0, claude_code_sessions_1.getClaudeCodeSession)("sess-1");
|
|
187
|
+
(0, vitest_1.expect)(detail).not.toBeNull();
|
|
188
|
+
const userEvents = detail.events.filter((e) => e.type === "user.message");
|
|
189
|
+
(0, vitest_1.expect)(userEvents).toHaveLength(1);
|
|
190
|
+
(0, vitest_1.expect)(userEvents[0].data.content).toBe("What is 2+2?");
|
|
191
|
+
(0, vitest_1.expect)(detail.source).toBe("claude-code");
|
|
192
|
+
(0, vitest_1.expect)(detail.title).toBe("test-slug");
|
|
193
|
+
});
|
|
194
|
+
(0, vitest_1.it)("getClaudeCodeSession converts assistant text to assistant.message", () => {
|
|
195
|
+
writeSession("sess-2", [
|
|
196
|
+
makeEvent({ type: "user", isSidechain: false, sessionId: "sess-2", cwd: "/proj", slug: "s", timestamp: "2024-01-15T10:00:00Z", message: { content: "Hello" } }),
|
|
197
|
+
makeEvent({ type: "assistant", isSidechain: false, sessionId: "sess-2", timestamp: "2024-01-15T10:00:05Z", message: { model: "claude-sonnet-4-6", content: [{ type: "thinking", thinking: "let me think" }, { type: "text", text: "World" }] } }),
|
|
198
|
+
]);
|
|
199
|
+
const detail = (0, claude_code_sessions_1.getClaudeCodeSession)("sess-2");
|
|
200
|
+
const assistantEvents = detail.events.filter((e) => e.type === "assistant.message");
|
|
201
|
+
(0, vitest_1.expect)(assistantEvents).toHaveLength(1);
|
|
202
|
+
(0, vitest_1.expect)(assistantEvents[0].data.content).toBe("World");
|
|
203
|
+
(0, vitest_1.expect)(assistantEvents[0].data.model).toBe("claude-sonnet-4-6");
|
|
204
|
+
});
|
|
205
|
+
(0, vitest_1.it)("getClaudeCodeSession emits tool.execution_start for each tool_use block", () => {
|
|
206
|
+
writeSession("sess-3", [
|
|
207
|
+
makeEvent({ type: "user", isSidechain: false, sessionId: "sess-3", cwd: "/proj", slug: "s", timestamp: "2024-01-15T10:00:00Z", message: { content: "run something" } }),
|
|
208
|
+
makeEvent({ type: "assistant", isSidechain: false, sessionId: "sess-3", timestamp: "2024-01-15T10:00:05Z", message: { model: "claude-sonnet-4-6", content: [
|
|
209
|
+
{ type: "tool_use", id: "tool-1", name: "bash", input: { cmd: "ls" } },
|
|
210
|
+
{ type: "tool_use", id: "tool-2", name: "read", input: { path: "/foo" } },
|
|
211
|
+
{ type: "text", text: "Done" },
|
|
212
|
+
] } }),
|
|
213
|
+
]);
|
|
214
|
+
const detail = (0, claude_code_sessions_1.getClaudeCodeSession)("sess-3");
|
|
215
|
+
const toolEvents = detail.events.filter((e) => e.type === "tool.execution_start");
|
|
216
|
+
(0, vitest_1.expect)(toolEvents).toHaveLength(2);
|
|
217
|
+
(0, vitest_1.expect)(toolEvents[0].data.tool).toBe("bash");
|
|
218
|
+
(0, vitest_1.expect)(toolEvents[1].data.tool).toBe("read");
|
|
219
|
+
});
|
|
220
|
+
(0, vitest_1.it)("getClaudeCodeSession skips isSidechain events", () => {
|
|
221
|
+
writeSession("sess-4", [
|
|
222
|
+
makeEvent({ type: "user", isSidechain: false, sessionId: "sess-4", cwd: "/proj", slug: "s", timestamp: "2024-01-15T10:00:00Z", message: { content: "real message" } }),
|
|
223
|
+
makeEvent({ type: "user", isSidechain: true, sessionId: "sess-4", timestamp: "2024-01-15T10:00:01Z", message: { content: "warmup noise" } }),
|
|
224
|
+
]);
|
|
225
|
+
const detail = (0, claude_code_sessions_1.getClaudeCodeSession)("sess-4");
|
|
226
|
+
const userEvents = detail.events.filter((e) => e.type === "user.message");
|
|
227
|
+
(0, vitest_1.expect)(userEvents).toHaveLength(1);
|
|
228
|
+
(0, vitest_1.expect)(userEvents[0].data.content).toBe("real message");
|
|
229
|
+
});
|
|
230
|
+
(0, vitest_1.it)("getClaudeCodeSession computes gap-capped duration", () => {
|
|
231
|
+
writeSession("sess-5", [
|
|
232
|
+
makeEvent({ type: "user", isSidechain: false, sessionId: "sess-5", cwd: "/proj", slug: "s", timestamp: "2024-01-15T10:00:00Z", message: { content: "start" } }),
|
|
233
|
+
makeEvent({ type: "assistant", isSidechain: false, sessionId: "sess-5", timestamp: "2024-01-15T10:01:00Z", message: { model: "m", content: [{ type: "text", text: "ok" }] } }),
|
|
234
|
+
// 2-hour gap — should be capped at 5 min
|
|
235
|
+
makeEvent({ type: "user", isSidechain: false, sessionId: "sess-5", timestamp: "2024-01-15T12:01:00Z", message: { content: "later" } }),
|
|
236
|
+
]);
|
|
237
|
+
const detail = (0, claude_code_sessions_1.getClaudeCodeSession)("sess-5");
|
|
238
|
+
// 1 min gap + capped 5 min gap = 6 min = 360_000ms
|
|
239
|
+
(0, vitest_1.expect)(detail.duration).toBe(360000);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
// ============ Analytics ============
|
|
243
|
+
(0, vitest_1.describe)("getClaudeCodeAnalytics", () => {
|
|
244
|
+
let tmpDir;
|
|
245
|
+
let projectDir;
|
|
246
|
+
(0, vitest_1.beforeEach)(() => {
|
|
247
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "claude-lens-analytics-"));
|
|
248
|
+
projectDir = path.join(tmpDir, ".claude", "projects", "-Users-test-proj");
|
|
249
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
250
|
+
process.env.HOME = tmpDir;
|
|
251
|
+
(0, cache_1.clearCache)();
|
|
252
|
+
});
|
|
253
|
+
(0, vitest_1.afterEach)(() => {
|
|
254
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
255
|
+
delete process.env.HOME;
|
|
256
|
+
(0, cache_1.clearCache)();
|
|
257
|
+
});
|
|
258
|
+
function writeSession(sessionId, lines) {
|
|
259
|
+
fs.writeFileSync(path.join(projectDir, `${sessionId}.jsonl`), lines.join("\n") + "\n");
|
|
260
|
+
}
|
|
261
|
+
(0, vitest_1.it)("returns empty array when no sessions", () => {
|
|
262
|
+
(0, vitest_1.expect)((0, claude_code_sessions_1.getClaudeCodeAnalytics)()).toEqual([]);
|
|
263
|
+
});
|
|
264
|
+
(0, vitest_1.it)("aggregates tool and model usage per session", () => {
|
|
265
|
+
writeSession("a1", [
|
|
266
|
+
makeEvent({ type: "user", isSidechain: false, sessionId: "a1", cwd: "/x", slug: "test-slug", timestamp: "2024-01-15T10:00:00Z", message: { content: "go" } }),
|
|
267
|
+
makeEvent({ type: "assistant", isSidechain: false, sessionId: "a1", timestamp: "2024-01-15T10:00:05Z", message: { model: "claude-sonnet-4-6", content: [
|
|
268
|
+
{ type: "tool_use", id: "t1", name: "bash", input: {} },
|
|
269
|
+
{ type: "tool_use", id: "t2", name: "bash", input: {} },
|
|
270
|
+
{ type: "tool_use", id: "t3", name: "read", input: {} },
|
|
271
|
+
{ type: "text", text: "done" },
|
|
272
|
+
] } }),
|
|
273
|
+
]);
|
|
274
|
+
const entries = (0, claude_code_sessions_1.getClaudeCodeAnalytics)();
|
|
275
|
+
(0, vitest_1.expect)(entries).toHaveLength(1);
|
|
276
|
+
(0, vitest_1.expect)(entries[0].sessionId).toBe("a1");
|
|
277
|
+
(0, vitest_1.expect)(entries[0].title).toBe("test-slug");
|
|
278
|
+
(0, vitest_1.expect)(entries[0].toolUsage).toEqual({ bash: 2, read: 1 });
|
|
279
|
+
(0, vitest_1.expect)(entries[0].modelUsage).toEqual({ "claude-sonnet-4-6": 1 });
|
|
280
|
+
(0, vitest_1.expect)(entries[0].turnCount).toBe(1);
|
|
281
|
+
(0, vitest_1.expect)(entries[0].msgLengths).toEqual([2]); // "go".length
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
//# sourceMappingURL=claude-code-sessions.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code-sessions.test.js","sourceRoot":"","sources":["../../src/__tests__/claude-code-sessions.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mCAAqE;AACrE,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AAEzB,kEAA8I;AAC9I,oCAAsC;AACtC,MAAM,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,+BAAQ,CAAC;AAE1F,wDAAwD;AAExD,IAAA,iBAAQ,EAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,IAAA,WAAE,EAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,IAAA,eAAM,EAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,IAAA,eAAM,EAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,MAAM,GAAG;YACb,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE;YAChC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE;YAC7C,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE;SAChC,CAAC;QACF,IAAA,eAAM,EAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,MAAM,GAAG;YACb,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;YACvD,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;SAC/B,CAAC;QACF,IAAA,eAAM,EAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QACvD,IAAA,eAAM,EAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,IAAA,iBAAQ,EAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,IAAA,WAAE,EAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,IAAA,eAAM,EAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,IAAA,eAAM,EAAC,oBAAoB,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,MAAM,GAAG;YACb,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE;YACrC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;YAClE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE;YAChC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;SACtE,CAAC;QACF,MAAM,MAAM,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAC5C,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpC,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,IAAA,iBAAQ,EAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,IAAA,WAAE,EAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,IAAA,eAAM,EAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAO,CAAC,CAAC,WAAW,EAAE,CAAC;QACzD,IAAA,eAAM,EAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAC3D,IAAA,eAAM,EAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAO,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9D,IAAA,eAAM,EAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,mEAAmE;AAEnE,SAAS,SAAS,CAAC,SAAkC;IACnD,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,sBAAsB,EAAE,GAAG,SAAS,EAAE,CAAC,CAAC;AAC7E,CAAC;AAED,IAAA,iBAAQ,EAAC,qEAAqE,EAAE,GAAG,EAAE;IACnF,IAAI,MAAc,CAAC;IACnB,IAAI,WAAmB,CAAC;IACxB,IAAI,UAAkB,CAAC;IAEvB,IAAA,mBAAU,EAAC,GAAG,EAAE;QACd,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;QACrE,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACvD,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC;QAC7D,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE9C,mEAAmE;QACnE,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,IAAA,kBAAS,EAAC,GAAG,EAAE;QACb,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,SAAS,YAAY,CAAC,SAAiB,EAAE,KAAe;QACtD,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,SAAS,QAAQ,CAAC,EAC3C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CACxB,CAAC;IACJ,CAAC;IAED,IAAA,WAAE,EAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,IAAA,6CAAsB,GAAE,CAAC;QAC1C,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,YAAY,CAAC,cAAc,EAAE;YAC3B,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;SAC/L,CAAC,CAAC;QACH,IAAA,eAAM,EAAC,IAAA,6CAAsB,GAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,YAAY,CAAC,gBAAgB,EAAE;YAC7B,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC;SAC1J,CAAC,CAAC;QACH,IAAA,eAAM,EAAC,IAAA,6CAAsB,GAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,YAAY,CAAC,SAAS,EAAE;YACtB,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,sBAAsB,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;YAC5M,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,sBAAsB,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;SACtM,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,IAAA,6CAAsB,GAAE,CAAC;QAC1C,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACjC,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACvC,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACtD,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7C,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC/C,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAC3D,IAAA,eAAM,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QACxD,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,iBAAiB,CAAC,EAC1C,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAC/G,CAAC;QACF,wFAAwF;QACxF,IAAA,eAAM,EAAC,IAAA,6CAAsB,GAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,YAAY,CAAC,eAAe,EAAE;YAC5B,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;SAC5G,CAAC,CAAC;QACH,IAAA,eAAM,EAAC,IAAA,0CAAmB,EAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,IAAA,eAAM,EAAC,IAAA,0CAAmB,EAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,IAAA,eAAM,EAAC,IAAA,2CAAoB,EAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,YAAY,CAAC,QAAQ,EAAE;YACrB,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,sBAAsB,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,CAAC;SAClM,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAA,2CAAoB,EAAC,QAAQ,CAAC,CAAC;QAC9C,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,MAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;QAC3E,IAAA,eAAM,EAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACnC,IAAA,eAAM,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACxD,IAAA,eAAM,EAAC,MAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC3C,IAAA,eAAM,EAAC,MAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,mEAAmE,EAAE,GAAG,EAAE;QAC3E,YAAY,CAAC,QAAQ,EAAE;YACrB,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,sBAAsB,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;YAC/J,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,sBAAsB,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC;SAClP,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAA,2CAAoB,EAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,eAAe,GAAG,MAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,mBAAmB,CAAC,CAAC;QACrF,IAAA,eAAM,EAAC,eAAe,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACxC,IAAA,eAAM,EAAC,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtD,IAAA,eAAM,EAAC,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,YAAY,CAAC,QAAQ,EAAE;YACrB,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,sBAAsB,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,EAAE,CAAC;YACvK,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,sBAAsB,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE;wBACzJ,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;wBACtE,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;wBACzE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;qBAC/B,EAAE,EAAE,CAAC;SACP,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAA,2CAAoB,EAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,UAAU,GAAG,MAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,sBAAsB,CAAC,CAAC;QACnF,IAAA,eAAM,EAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACnC,IAAA,eAAM,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAA,eAAM,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,YAAY,CAAC,QAAQ,EAAE;YACrB,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,sBAAsB,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,CAAC;YACtK,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,sBAAsB,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,CAAC;SAC7I,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAA,2CAAoB,EAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,UAAU,GAAG,MAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;QAC3E,IAAA,eAAM,EAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACnC,IAAA,eAAM,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,YAAY,CAAC,QAAQ,EAAE;YACrB,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,sBAAsB,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;YAC/J,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,sBAAsB,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9K,yCAAyC;YACzC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,sBAAsB,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;SACvI,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAA,2CAAoB,EAAC,QAAQ,CAAC,CAAC;QAC9C,mDAAmD;QACnD,IAAA,eAAM,EAAC,MAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAO,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,sCAAsC;AAEtC,IAAA,iBAAQ,EAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,IAAI,MAAc,CAAC;IACnB,IAAI,UAAkB,CAAC;IAEvB,IAAA,mBAAU,EAAC,GAAG,EAAE;QACd,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;QAC1E,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAC;QAC1E,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC;QAC1B,IAAA,kBAAU,GAAE,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,IAAA,kBAAS,EAAC,GAAG,EAAE;QACb,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;QACxB,IAAA,kBAAU,GAAE,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,SAAS,YAAY,CAAC,SAAiB,EAAE,KAAe;QACtD,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,SAAS,QAAQ,CAAC,EAC3C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CACxB,CAAC;IACJ,CAAC;IAED,IAAA,WAAE,EAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,IAAA,eAAM,EAAC,IAAA,6CAAsB,GAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,YAAY,CAAC,IAAI,EAAE;YACjB,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,sBAAsB,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;YAC7J,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,sBAAsB,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE;wBACrJ,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;wBACvD,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;wBACvD,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;wBACvD,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;qBAC/B,EAAE,EAAE,CAAC;SACP,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,IAAA,6CAAsB,GAAE,CAAC;QACzC,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;QAC3D,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAC,EAAE,CAAC,CAAC;QAClE,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrC,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { SessionMeta, SessionDetail, SessionStatus } from "./sessions";
|
|
2
|
+
export declare function getClaudeCodeProjectsDir(): string;
|
|
3
|
+
interface ClaudeCodeEvent {
|
|
4
|
+
type: string;
|
|
5
|
+
uuid?: string;
|
|
6
|
+
sessionId?: string;
|
|
7
|
+
cwd?: string;
|
|
8
|
+
gitBranch?: string;
|
|
9
|
+
slug?: string;
|
|
10
|
+
version?: string;
|
|
11
|
+
timestamp?: string;
|
|
12
|
+
isSidechain?: boolean;
|
|
13
|
+
message?: {
|
|
14
|
+
role?: string;
|
|
15
|
+
content?: string | ContentBlock[];
|
|
16
|
+
model?: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
interface ContentBlock {
|
|
20
|
+
type: string;
|
|
21
|
+
text?: string;
|
|
22
|
+
thinking?: string;
|
|
23
|
+
id?: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
input?: Record<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
/** Parse all lines from a JSONL file */
|
|
28
|
+
declare function readAllLines(filePath: string): ClaudeCodeEvent[];
|
|
29
|
+
declare function extractTextContent(content: string | ContentBlock[] | undefined): string;
|
|
30
|
+
declare function extractToolUseBlocks(content: string | ContentBlock[] | undefined): ContentBlock[];
|
|
31
|
+
declare function deriveStatus(lastTimestamp: string | undefined): SessionStatus;
|
|
32
|
+
export declare function listClaudeCodeSessions(): SessionMeta[];
|
|
33
|
+
/** Find the JSONL file for a given session ID by scanning projects dir */
|
|
34
|
+
declare function findSessionFile(sessionId: string): string | null;
|
|
35
|
+
export declare function getClaudeCodeSession(sessionId: string): SessionDetail | null;
|
|
36
|
+
export declare function isClaudeCodeSession(sessionId: string): boolean;
|
|
37
|
+
export interface ClaudeCodeAnalyticsEntry {
|
|
38
|
+
sessionId: string;
|
|
39
|
+
title: string;
|
|
40
|
+
createdAt: string;
|
|
41
|
+
duration: number;
|
|
42
|
+
toolUsage: Record<string, number>;
|
|
43
|
+
modelUsage: Record<string, number>;
|
|
44
|
+
turnCount: number;
|
|
45
|
+
msgLengths: number[];
|
|
46
|
+
}
|
|
47
|
+
export declare function getClaudeCodeAnalytics(): ClaudeCodeAnalyticsEntry[];
|
|
48
|
+
export declare const _testing: {
|
|
49
|
+
getClaudeCodeProjectsDir: typeof getClaudeCodeProjectsDir;
|
|
50
|
+
findSessionFile: typeof findSessionFile;
|
|
51
|
+
extractTextContent: typeof extractTextContent;
|
|
52
|
+
extractToolUseBlocks: typeof extractToolUseBlocks;
|
|
53
|
+
deriveStatus: typeof deriveStatus;
|
|
54
|
+
readAllLines: typeof readAllLines;
|
|
55
|
+
};
|
|
56
|
+
export {};
|