devday 0.1.0
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 +58 -0
- package/bin/devday.js +2 -0
- package/dist/config.d.ts +14 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +89 -0
- package/dist/config.js.map +1 -0
- package/dist/cost.d.ts +12 -0
- package/dist/cost.d.ts.map +1 -0
- package/dist/cost.js +47 -0
- package/dist/cost.js.map +1 -0
- package/dist/git.d.ts +6 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +95 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +231 -0
- package/dist/index.js.map +1 -0
- package/dist/merge.d.ts +6 -0
- package/dist/merge.d.ts.map +1 -0
- package/dist/merge.js +80 -0
- package/dist/merge.js.map +1 -0
- package/dist/parsers/claude-code.d.ts +18 -0
- package/dist/parsers/claude-code.d.ts.map +1 -0
- package/dist/parsers/claude-code.js +385 -0
- package/dist/parsers/claude-code.js.map +1 -0
- package/dist/parsers/cursor.d.ts +15 -0
- package/dist/parsers/cursor.d.ts.map +1 -0
- package/dist/parsers/cursor.js +302 -0
- package/dist/parsers/cursor.js.map +1 -0
- package/dist/parsers/opencode.d.ts +21 -0
- package/dist/parsers/opencode.d.ts.map +1 -0
- package/dist/parsers/opencode.js +301 -0
- package/dist/parsers/opencode.js.map +1 -0
- package/dist/render.d.ts +6 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +161 -0
- package/dist/render.js.map +1 -0
- package/dist/summarize.d.ts +8 -0
- package/dist/summarize.d.ts.map +1 -0
- package/dist/summarize.js +157 -0
- package/dist/summarize.js.map +1 -0
- package/dist/types.d.ts +100 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +23 -0
- package/dist/types.js.map +1 -0
- package/package.json +54 -0
package/dist/merge.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { basename } from 'node:path';
|
|
2
|
+
import { sumTokens } from './cost.js';
|
|
3
|
+
/**
|
|
4
|
+
* Merge sessions and git activity into a DayRecap.
|
|
5
|
+
*/
|
|
6
|
+
export function buildDayRecap(date, sessions, gitActivities) {
|
|
7
|
+
// Group sessions by project path
|
|
8
|
+
const sessionsByProject = new Map();
|
|
9
|
+
for (const session of sessions) {
|
|
10
|
+
const key = session.projectPath ?? '__unknown__';
|
|
11
|
+
if (!sessionsByProject.has(key)) {
|
|
12
|
+
sessionsByProject.set(key, []);
|
|
13
|
+
}
|
|
14
|
+
sessionsByProject.get(key).push(session);
|
|
15
|
+
}
|
|
16
|
+
// Build a map of git activities by project path
|
|
17
|
+
const gitByProject = new Map();
|
|
18
|
+
for (const git of gitActivities) {
|
|
19
|
+
gitByProject.set(git.projectPath, git);
|
|
20
|
+
}
|
|
21
|
+
// Collect all unique project paths (from sessions and git)
|
|
22
|
+
const allProjectPaths = new Set([
|
|
23
|
+
...sessionsByProject.keys(),
|
|
24
|
+
...gitByProject.keys(),
|
|
25
|
+
]);
|
|
26
|
+
const projects = [];
|
|
27
|
+
for (const projectPath of allProjectPaths) {
|
|
28
|
+
const projectSessions = sessionsByProject.get(projectPath) ?? [];
|
|
29
|
+
const git = gitByProject.get(projectPath) ?? null;
|
|
30
|
+
if (projectSessions.length === 0 && (!git || git.commits.length === 0)) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const totalTokens = sumTokens(...projectSessions.map((s) => s.tokens));
|
|
34
|
+
const totalCostUsd = projectSessions.reduce((sum, s) => sum + s.costUsd, 0);
|
|
35
|
+
const totalDurationMs = projectSessions.reduce((sum, s) => sum + s.durationMs, 0);
|
|
36
|
+
const totalMessages = projectSessions.reduce((sum, s) => sum + s.messageCount, 0);
|
|
37
|
+
const toolsUsed = [...new Set(projectSessions.map((s) => s.tool))];
|
|
38
|
+
const modelsUsed = [...new Set(projectSessions.flatMap((s) => s.models))];
|
|
39
|
+
const filesTouched = [...new Set(projectSessions.flatMap((s) => s.filesTouched))];
|
|
40
|
+
const projectName = projectSessions[0]?.projectName ??
|
|
41
|
+
git?.projectName ??
|
|
42
|
+
basename(projectPath);
|
|
43
|
+
projects.push({
|
|
44
|
+
projectPath,
|
|
45
|
+
projectName,
|
|
46
|
+
sessions: projectSessions,
|
|
47
|
+
git,
|
|
48
|
+
totalSessions: projectSessions.length,
|
|
49
|
+
totalMessages,
|
|
50
|
+
totalTokens: totalTokens.total,
|
|
51
|
+
totalCostUsd,
|
|
52
|
+
totalDurationMs,
|
|
53
|
+
toolsUsed,
|
|
54
|
+
modelsUsed,
|
|
55
|
+
filesTouched,
|
|
56
|
+
aiSummary: null, // filled by summarizer
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
// Sort projects by total cost (most expensive first)
|
|
60
|
+
projects.sort((a, b) => b.totalCostUsd - a.totalCostUsd);
|
|
61
|
+
// Global aggregates
|
|
62
|
+
const totalSessions = projects.reduce((sum, p) => sum + p.totalSessions, 0);
|
|
63
|
+
const totalMessages = projects.reduce((sum, p) => sum + p.totalMessages, 0);
|
|
64
|
+
const globalTokens = sumTokens(...sessions.map((s) => s.tokens));
|
|
65
|
+
const totalCostUsd = projects.reduce((sum, p) => sum + p.totalCostUsd, 0);
|
|
66
|
+
const totalDurationMs = projects.reduce((sum, p) => sum + p.totalDurationMs, 0);
|
|
67
|
+
const toolsUsed = [...new Set(projects.flatMap((p) => p.toolsUsed))];
|
|
68
|
+
return {
|
|
69
|
+
date,
|
|
70
|
+
projects,
|
|
71
|
+
totalSessions,
|
|
72
|
+
totalMessages,
|
|
73
|
+
totalTokens: globalTokens.total,
|
|
74
|
+
totalCostUsd,
|
|
75
|
+
totalDurationMs,
|
|
76
|
+
toolsUsed,
|
|
77
|
+
standupMessage: null, // filled by summarizer
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Parser, Session } from '../types.js';
|
|
2
|
+
export declare class ClaudeCodeParser implements Parser {
|
|
3
|
+
readonly name: "claude-code";
|
|
4
|
+
private claudeHome;
|
|
5
|
+
constructor(claudeHome: string);
|
|
6
|
+
isAvailable(): Promise<boolean>;
|
|
7
|
+
getSessions(date: string): Promise<Session[]>;
|
|
8
|
+
private buildSession;
|
|
9
|
+
private buildSessionFromDb;
|
|
10
|
+
private buildSessionFromJsonl;
|
|
11
|
+
private parseJsonlFile;
|
|
12
|
+
/** Deduplicate assistant messages: streaming chunks share the same message.id */
|
|
13
|
+
private deduplicateAssistant;
|
|
14
|
+
private extractContentFromJsonl;
|
|
15
|
+
private extractContentFromMessages;
|
|
16
|
+
private truncatePrompt;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=claude-code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/parsers/claude-code.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAc,MAAM,aAAa,CAAC;AAuF/D,qBAAa,gBAAiB,YAAW,MAAM;IAC7C,QAAQ,CAAC,IAAI,EAAG,aAAa,CAAU;IACvC,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,EAAE,MAAM;IAIxB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAO/B,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAgFnD,OAAO,CAAC,YAAY;IAoBpB,OAAO,CAAC,kBAAkB;IAyG1B,OAAO,CAAC,qBAAqB;IA+E7B,OAAO,CAAC,cAAc;IA0CtB,iFAAiF;IACjF,OAAO,CAAC,oBAAoB;IAY5B,OAAO,CAAC,uBAAuB;IAa/B,OAAO,CAAC,0BAA0B;IA4FlC,OAAO,CAAC,cAAc;CAMvB"}
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join, basename } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import Database from 'better-sqlite3';
|
|
5
|
+
import { estimateCost, emptyTokenUsage } from '../cost.js';
|
|
6
|
+
// ── Parser ───────────────────────────────────────────────────────
|
|
7
|
+
export class ClaudeCodeParser {
|
|
8
|
+
name = 'claude-code';
|
|
9
|
+
claudeHome;
|
|
10
|
+
constructor(claudeHome) {
|
|
11
|
+
this.claudeHome = claudeHome;
|
|
12
|
+
}
|
|
13
|
+
async isAvailable() {
|
|
14
|
+
return (existsSync(this.claudeHome) &&
|
|
15
|
+
existsSync(join(this.claudeHome, 'projects')));
|
|
16
|
+
}
|
|
17
|
+
async getSessions(date) {
|
|
18
|
+
// Build day boundaries in local time
|
|
19
|
+
const [year, month, day] = date.split('-').map(Number);
|
|
20
|
+
const dayStart = new Date(year, month - 1, day, 0, 0, 0, 0);
|
|
21
|
+
const dayEnd = new Date(year, month - 1, day, 23, 59, 59, 999);
|
|
22
|
+
const dayStartMs = dayStart.getTime();
|
|
23
|
+
const dayEndMs = dayEnd.getTime();
|
|
24
|
+
const projectsDir = join(this.claudeHome, 'projects');
|
|
25
|
+
if (!existsSync(projectsDir))
|
|
26
|
+
return [];
|
|
27
|
+
// Open SQLite for cost/duration data (optional — parser works without it)
|
|
28
|
+
const dbPath = join(this.claudeHome, '__store.db');
|
|
29
|
+
let db = null;
|
|
30
|
+
if (existsSync(dbPath)) {
|
|
31
|
+
try {
|
|
32
|
+
db = new Database(dbPath, { readonly: true });
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// Can't open DB — continue without it
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const sessions = [];
|
|
39
|
+
try {
|
|
40
|
+
const projectDirs = readdirSync(projectsDir, { withFileTypes: true })
|
|
41
|
+
.filter((d) => d.isDirectory());
|
|
42
|
+
for (const projDir of projectDirs) {
|
|
43
|
+
const projPath = join(projectsDir, projDir.name);
|
|
44
|
+
const indexPath = join(projPath, 'sessions-index.json');
|
|
45
|
+
if (!existsSync(indexPath))
|
|
46
|
+
continue;
|
|
47
|
+
let index;
|
|
48
|
+
try {
|
|
49
|
+
index = JSON.parse(readFileSync(indexPath, 'utf-8'));
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
// Get the real project path from the first session entry
|
|
55
|
+
// (directory name encoding is lossy — dashes in dir names become ambiguous)
|
|
56
|
+
const projectPath = index.entries[0]?.projectPath ?? projDir.name.replace(/^-/, '/').replace(/-/g, '/');
|
|
57
|
+
const projectName = basename(projectPath);
|
|
58
|
+
for (const entry of index.entries) {
|
|
59
|
+
if (entry.isSidechain)
|
|
60
|
+
continue;
|
|
61
|
+
// Filter by date: session must overlap with the target day
|
|
62
|
+
const createdMs = new Date(entry.created).getTime();
|
|
63
|
+
const modifiedMs = new Date(entry.modified).getTime();
|
|
64
|
+
const overlapsDay = (createdMs >= dayStartMs && createdMs <= dayEndMs) ||
|
|
65
|
+
(modifiedMs >= dayStartMs && modifiedMs <= dayEndMs) ||
|
|
66
|
+
(createdMs <= dayStartMs && modifiedMs >= dayEndMs);
|
|
67
|
+
if (!overlapsDay)
|
|
68
|
+
continue;
|
|
69
|
+
// Build session from JSONL + optional DB data
|
|
70
|
+
const session = this.buildSession(entry, projectPath, projectName, dayStartMs, dayEndMs, db);
|
|
71
|
+
if (session)
|
|
72
|
+
sessions.push(session);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
db?.close();
|
|
78
|
+
}
|
|
79
|
+
return sessions;
|
|
80
|
+
}
|
|
81
|
+
// ── Build a single session ──────────────────────────────────────
|
|
82
|
+
buildSession(entry, projectPath, projectName, dayStartMs, dayEndMs, db) {
|
|
83
|
+
// Try DB-based approach first (more structured)
|
|
84
|
+
if (db) {
|
|
85
|
+
const dbSession = this.buildSessionFromDb(entry, projectPath, projectName, dayStartMs, dayEndMs, db);
|
|
86
|
+
if (dbSession)
|
|
87
|
+
return dbSession;
|
|
88
|
+
}
|
|
89
|
+
// Fall back to JSONL parsing
|
|
90
|
+
return this.buildSessionFromJsonl(entry, projectPath, projectName, dayStartMs, dayEndMs);
|
|
91
|
+
}
|
|
92
|
+
// ── DB-based session building ───────────────────────────────────
|
|
93
|
+
buildSessionFromDb(entry, projectPath, projectName, dayStartMs, dayEndMs, db) {
|
|
94
|
+
try {
|
|
95
|
+
// Get assistant messages for this session within the target day
|
|
96
|
+
const assistantRows = db.prepare(`
|
|
97
|
+
SELECT b.uuid, b.session_id, b.timestamp, a.cost_usd, a.duration_ms, a.model, a.message
|
|
98
|
+
FROM base_messages b
|
|
99
|
+
JOIN assistant_messages a ON a.uuid = b.uuid
|
|
100
|
+
WHERE b.session_id = ? AND b.timestamp >= ? AND b.timestamp <= ?
|
|
101
|
+
ORDER BY b.timestamp
|
|
102
|
+
`).all(entry.sessionId, dayStartMs, dayEndMs);
|
|
103
|
+
const userRows = db.prepare(`
|
|
104
|
+
SELECT b.uuid, b.session_id, b.timestamp, u.message
|
|
105
|
+
FROM base_messages b
|
|
106
|
+
JOIN user_messages u ON u.uuid = b.uuid
|
|
107
|
+
WHERE b.session_id = ? AND b.timestamp >= ? AND b.timestamp <= ?
|
|
108
|
+
ORDER BY b.timestamp
|
|
109
|
+
`).all(entry.sessionId, dayStartMs, dayEndMs);
|
|
110
|
+
const totalMessages = assistantRows.length + userRows.length;
|
|
111
|
+
if (totalMessages === 0)
|
|
112
|
+
return null;
|
|
113
|
+
// Aggregate cost and duration
|
|
114
|
+
let totalCost = 0;
|
|
115
|
+
let totalDurationMs = 0;
|
|
116
|
+
const MAX_MSG_DURATION_MS = 5 * 60 * 1000;
|
|
117
|
+
const models = new Set();
|
|
118
|
+
const totalTokens = emptyTokenUsage();
|
|
119
|
+
for (const row of assistantRows) {
|
|
120
|
+
if (row.cost_usd)
|
|
121
|
+
totalCost += row.cost_usd;
|
|
122
|
+
if (row.duration_ms) {
|
|
123
|
+
totalDurationMs += Math.min(row.duration_ms, MAX_MSG_DURATION_MS);
|
|
124
|
+
}
|
|
125
|
+
if (row.model)
|
|
126
|
+
models.add(row.model);
|
|
127
|
+
// Parse usage from the full message JSON
|
|
128
|
+
try {
|
|
129
|
+
const msg = JSON.parse(row.message);
|
|
130
|
+
if (msg.usage) {
|
|
131
|
+
const u = msg.usage;
|
|
132
|
+
totalTokens.input += u.input_tokens ?? 0;
|
|
133
|
+
totalTokens.output += u.output_tokens ?? 0;
|
|
134
|
+
totalTokens.cacheRead += u.cache_read_input_tokens ?? 0;
|
|
135
|
+
totalTokens.cacheWrite += u.cache_creation_input_tokens ?? 0;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// skip
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
totalTokens.total = totalTokens.input + totalTokens.output + totalTokens.cacheRead + totalTokens.cacheWrite;
|
|
143
|
+
// If no cost from DB, estimate from tokens
|
|
144
|
+
if (totalCost === 0 && totalTokens.total > 0 && models.size > 0) {
|
|
145
|
+
const model = [...models][0];
|
|
146
|
+
totalCost = estimateCost(model, totalTokens);
|
|
147
|
+
}
|
|
148
|
+
// Extract content from JSONL for conversation digest
|
|
149
|
+
const contentExtraction = this.extractContentFromJsonl(entry.fullPath, dayStartMs, dayEndMs);
|
|
150
|
+
// Timestamps
|
|
151
|
+
const allTimestamps = [
|
|
152
|
+
...assistantRows.map((r) => r.timestamp),
|
|
153
|
+
...userRows.map((r) => r.timestamp),
|
|
154
|
+
];
|
|
155
|
+
const earliest = Math.max(dayStartMs, Math.min(...allTimestamps));
|
|
156
|
+
const latest = Math.min(dayEndMs, Math.max(...allTimestamps));
|
|
157
|
+
return {
|
|
158
|
+
id: entry.sessionId,
|
|
159
|
+
tool: 'claude-code',
|
|
160
|
+
projectPath,
|
|
161
|
+
projectName,
|
|
162
|
+
title: entry.summary ?? this.truncatePrompt(entry.firstPrompt) ?? null,
|
|
163
|
+
startedAt: new Date(earliest),
|
|
164
|
+
endedAt: new Date(latest),
|
|
165
|
+
durationMs: totalDurationMs,
|
|
166
|
+
messageCount: totalMessages,
|
|
167
|
+
userMessageCount: userRows.length,
|
|
168
|
+
assistantMessageCount: assistantRows.length,
|
|
169
|
+
summary: entry.summary ?? null,
|
|
170
|
+
topics: entry.summary ? [entry.summary] : [],
|
|
171
|
+
tokens: totalTokens,
|
|
172
|
+
costUsd: totalCost,
|
|
173
|
+
models: [...models],
|
|
174
|
+
filesTouched: contentExtraction.filesTouched,
|
|
175
|
+
conversationDigest: contentExtraction.conversationDigest,
|
|
176
|
+
toolCallSummaries: contentExtraction.toolCallSummaries,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// ── JSONL-based session building (fallback) ─────────────────────
|
|
184
|
+
buildSessionFromJsonl(entry, projectPath, projectName, dayStartMs, dayEndMs) {
|
|
185
|
+
if (!existsSync(entry.fullPath))
|
|
186
|
+
return null;
|
|
187
|
+
const messages = this.parseJsonlFile(entry.fullPath, dayStartMs, dayEndMs);
|
|
188
|
+
if (messages.user.length === 0 && messages.assistant.length === 0)
|
|
189
|
+
return null;
|
|
190
|
+
const MAX_MSG_DURATION_MS = 5 * 60 * 1000;
|
|
191
|
+
const models = new Set();
|
|
192
|
+
const totalTokens = emptyTokenUsage();
|
|
193
|
+
let totalCost = 0;
|
|
194
|
+
let totalDurationMs = 0;
|
|
195
|
+
// Deduplicate assistant messages by message.id (streaming chunks)
|
|
196
|
+
const dedupedAssistant = this.deduplicateAssistant(messages.assistant);
|
|
197
|
+
for (const msg of dedupedAssistant) {
|
|
198
|
+
if (msg.message.model)
|
|
199
|
+
models.add(msg.message.model);
|
|
200
|
+
if (msg.message.usage) {
|
|
201
|
+
const u = msg.message.usage;
|
|
202
|
+
totalTokens.input += u.input_tokens ?? 0;
|
|
203
|
+
totalTokens.output += u.output_tokens ?? 0;
|
|
204
|
+
totalTokens.cacheRead += u.cache_read_input_tokens ?? 0;
|
|
205
|
+
totalTokens.cacheWrite += u.cache_creation_input_tokens ?? 0;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
totalTokens.total = totalTokens.input + totalTokens.output + totalTokens.cacheRead + totalTokens.cacheWrite;
|
|
209
|
+
if (totalTokens.total > 0 && models.size > 0) {
|
|
210
|
+
totalCost = estimateCost([...models][0], totalTokens);
|
|
211
|
+
}
|
|
212
|
+
// Estimate duration from timestamp gaps between consecutive messages
|
|
213
|
+
const allTimestamps = [
|
|
214
|
+
...messages.user.map((m) => new Date(m.timestamp).getTime()),
|
|
215
|
+
...messages.assistant.map((m) => new Date(m.timestamp).getTime()),
|
|
216
|
+
].sort((a, b) => a - b);
|
|
217
|
+
for (let i = 1; i < allTimestamps.length; i++) {
|
|
218
|
+
const gap = allTimestamps[i] - allTimestamps[i - 1];
|
|
219
|
+
totalDurationMs += Math.min(gap, MAX_MSG_DURATION_MS);
|
|
220
|
+
}
|
|
221
|
+
const contentExtraction = this.extractContentFromMessages(messages, dayStartMs, dayEndMs);
|
|
222
|
+
const earliest = Math.max(dayStartMs, allTimestamps[0] ?? dayStartMs);
|
|
223
|
+
const latest = Math.min(dayEndMs, allTimestamps[allTimestamps.length - 1] ?? dayEndMs);
|
|
224
|
+
return {
|
|
225
|
+
id: entry.sessionId,
|
|
226
|
+
tool: 'claude-code',
|
|
227
|
+
projectPath,
|
|
228
|
+
projectName,
|
|
229
|
+
title: entry.summary ?? this.truncatePrompt(entry.firstPrompt) ?? null,
|
|
230
|
+
startedAt: new Date(earliest),
|
|
231
|
+
endedAt: new Date(latest),
|
|
232
|
+
durationMs: totalDurationMs,
|
|
233
|
+
messageCount: messages.user.length + dedupedAssistant.length,
|
|
234
|
+
userMessageCount: messages.user.length,
|
|
235
|
+
assistantMessageCount: dedupedAssistant.length,
|
|
236
|
+
summary: entry.summary ?? null,
|
|
237
|
+
topics: entry.summary ? [entry.summary] : [],
|
|
238
|
+
tokens: totalTokens,
|
|
239
|
+
costUsd: totalCost,
|
|
240
|
+
models: [...models],
|
|
241
|
+
filesTouched: contentExtraction.filesTouched,
|
|
242
|
+
conversationDigest: contentExtraction.conversationDigest,
|
|
243
|
+
toolCallSummaries: contentExtraction.toolCallSummaries,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
// ── JSONL parsing ───────────────────────────────────────────────
|
|
247
|
+
parseJsonlFile(filePath, dayStartMs, dayEndMs) {
|
|
248
|
+
const user = [];
|
|
249
|
+
const assistant = [];
|
|
250
|
+
let content;
|
|
251
|
+
try {
|
|
252
|
+
content = readFileSync(filePath, 'utf-8');
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
return { user, assistant };
|
|
256
|
+
}
|
|
257
|
+
for (const line of content.split('\n')) {
|
|
258
|
+
if (!line.trim())
|
|
259
|
+
continue;
|
|
260
|
+
try {
|
|
261
|
+
const obj = JSON.parse(line);
|
|
262
|
+
if (obj.type === 'user') {
|
|
263
|
+
const msg = obj;
|
|
264
|
+
const ts = new Date(msg.timestamp).getTime();
|
|
265
|
+
if (ts >= dayStartMs && ts <= dayEndMs) {
|
|
266
|
+
user.push(msg);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else if (obj.type === 'assistant') {
|
|
270
|
+
const msg = obj;
|
|
271
|
+
const ts = new Date(msg.timestamp).getTime();
|
|
272
|
+
if (ts >= dayStartMs && ts <= dayEndMs) {
|
|
273
|
+
assistant.push(msg);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// Skip file-history-snapshot, progress, system types
|
|
277
|
+
}
|
|
278
|
+
catch {
|
|
279
|
+
// skip malformed lines
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return { user, assistant };
|
|
283
|
+
}
|
|
284
|
+
/** Deduplicate assistant messages: streaming chunks share the same message.id */
|
|
285
|
+
deduplicateAssistant(msgs) {
|
|
286
|
+
const byMsgId = new Map();
|
|
287
|
+
for (const msg of msgs) {
|
|
288
|
+
const key = msg.message.id;
|
|
289
|
+
// Keep the last chunk (most complete content)
|
|
290
|
+
byMsgId.set(key, msg);
|
|
291
|
+
}
|
|
292
|
+
return [...byMsgId.values()];
|
|
293
|
+
}
|
|
294
|
+
// ── Content extraction from JSONL ───────────────────────────────
|
|
295
|
+
extractContentFromJsonl(filePath, dayStartMs, dayEndMs) {
|
|
296
|
+
if (!existsSync(filePath)) {
|
|
297
|
+
return { conversationDigest: '', toolCallSummaries: [], filesTouched: [] };
|
|
298
|
+
}
|
|
299
|
+
const messages = this.parseJsonlFile(filePath, dayStartMs, dayEndMs);
|
|
300
|
+
return this.extractContentFromMessages(messages, dayStartMs, dayEndMs);
|
|
301
|
+
}
|
|
302
|
+
extractContentFromMessages(messages, _dayStartMs, _dayEndMs) {
|
|
303
|
+
const digestParts = [];
|
|
304
|
+
const toolSummaries = [];
|
|
305
|
+
const files = new Set();
|
|
306
|
+
const home = homedir();
|
|
307
|
+
const all = [
|
|
308
|
+
...messages.user.map((m) => ({ ts: new Date(m.timestamp).getTime(), role: 'user', msg: m })),
|
|
309
|
+
...messages.assistant.map((m) => ({ ts: new Date(m.timestamp).getTime(), role: 'assistant', msg: m })),
|
|
310
|
+
].sort((a, b) => a.ts - b.ts);
|
|
311
|
+
// Deduplicate assistant messages
|
|
312
|
+
const seenMsgIds = new Set();
|
|
313
|
+
for (const { role, msg } of all) {
|
|
314
|
+
if (role === 'user') {
|
|
315
|
+
const userMsg = msg;
|
|
316
|
+
const content = userMsg.message.content;
|
|
317
|
+
// Only include human text, not tool results
|
|
318
|
+
if (typeof content === 'string') {
|
|
319
|
+
const truncated = content.length > 500 ? content.slice(0, 500) + '...' : content;
|
|
320
|
+
digestParts.push(`[User]: ${truncated}`);
|
|
321
|
+
}
|
|
322
|
+
// Array content with tool_result entries → skip for digest
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
const assistantMsg = msg;
|
|
326
|
+
const msgId = assistantMsg.message.id;
|
|
327
|
+
// Skip duplicate streaming chunks
|
|
328
|
+
if (seenMsgIds.has(msgId))
|
|
329
|
+
continue;
|
|
330
|
+
seenMsgIds.add(msgId);
|
|
331
|
+
const contentBlocks = assistantMsg.message.content ?? [];
|
|
332
|
+
const textParts = [];
|
|
333
|
+
for (const block of contentBlocks) {
|
|
334
|
+
if (block.type === 'text' && block.text) {
|
|
335
|
+
textParts.push(block.text);
|
|
336
|
+
}
|
|
337
|
+
if (block.type === 'tool_use' && block.name) {
|
|
338
|
+
const input = block.input ?? {};
|
|
339
|
+
let summary = block.name;
|
|
340
|
+
const filePath = (input.filePath ?? input.path ?? input.file);
|
|
341
|
+
const command = input.command;
|
|
342
|
+
const pattern = input.pattern;
|
|
343
|
+
if (filePath) {
|
|
344
|
+
const short = filePath.startsWith(home) ? '~' + filePath.slice(home.length) : filePath;
|
|
345
|
+
summary = `${block.name} ${short}`;
|
|
346
|
+
files.add(filePath);
|
|
347
|
+
}
|
|
348
|
+
else if (command) {
|
|
349
|
+
summary = `bash: ${String(command).slice(0, 80)}`;
|
|
350
|
+
}
|
|
351
|
+
else if (pattern) {
|
|
352
|
+
summary = `${block.name}: ${pattern}`;
|
|
353
|
+
}
|
|
354
|
+
toolSummaries.push(summary);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
if (textParts.length > 0) {
|
|
358
|
+
const text = textParts.join('\n');
|
|
359
|
+
const truncated = text.length > 500 ? text.slice(0, 500) + '...' : text;
|
|
360
|
+
digestParts.push(`[Assistant]: ${truncated}`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
// Cap total digest
|
|
365
|
+
let conversationDigest = digestParts.join('\n\n');
|
|
366
|
+
if (conversationDigest.length > 4000) {
|
|
367
|
+
conversationDigest = conversationDigest.slice(0, 4000) + '\n\n[...truncated]';
|
|
368
|
+
}
|
|
369
|
+
return {
|
|
370
|
+
conversationDigest,
|
|
371
|
+
toolCallSummaries: toolSummaries,
|
|
372
|
+
filesTouched: [...files],
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
// ── Helpers ─────────────────────────────────────────────────────
|
|
376
|
+
truncatePrompt(prompt) {
|
|
377
|
+
if (!prompt)
|
|
378
|
+
return null;
|
|
379
|
+
const clean = prompt.replace(/\n/g, ' ').trim();
|
|
380
|
+
if (clean.length <= 60)
|
|
381
|
+
return clean;
|
|
382
|
+
return clean.slice(0, 57) + '...';
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
//# sourceMappingURL=claude-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/parsers/claude-code.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Parser, Session } from '../types.js';
|
|
2
|
+
export declare class CursorParser implements Parser {
|
|
3
|
+
readonly name: "cursor";
|
|
4
|
+
private dbPath;
|
|
5
|
+
constructor(dbPath: string);
|
|
6
|
+
isAvailable(): Promise<boolean>;
|
|
7
|
+
getSessions(date: string): Promise<Session[]>;
|
|
8
|
+
private loadBubbles;
|
|
9
|
+
/** Check if a bubble's timestamp falls within the target day */
|
|
10
|
+
private bubbleInDay;
|
|
11
|
+
/** Extract the best available timestamp from a bubble (ms epoch) */
|
|
12
|
+
private getBubbleTimestamp;
|
|
13
|
+
private buildSession;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=cursor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/parsers/cursor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAc,MAAM,aAAa,CAAC;AAsE/D,qBAAa,YAAa,YAAW,MAAM;IACzC,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAClC,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM;IAIpB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/B,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IA8DnD,OAAO,CAAC,WAAW;IAkEnB,gEAAgE;IAChE,OAAO,CAAC,WAAW;IAWnB,oEAAoE;IACpE,OAAO,CAAC,kBAAkB;IAgB1B,OAAO,CAAC,YAAY;CAiKrB"}
|