@ccview/core 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/dist/analyzer/claude-md.d.ts +2 -0
- package/dist/analyzer/claude-md.d.ts.map +1 -0
- package/dist/analyzer/claude-md.js +3 -0
- package/dist/analyzer/claude-md.js.map +1 -0
- package/dist/analyzer/cost-calculator.d.ts +3 -0
- package/dist/analyzer/cost-calculator.d.ts.map +1 -0
- package/dist/analyzer/cost-calculator.js +8 -0
- package/dist/analyzer/cost-calculator.js.map +1 -0
- package/dist/analyzer/insights.d.ts +2 -0
- package/dist/analyzer/insights.d.ts.map +1 -0
- package/dist/analyzer/insights.js +3 -0
- package/dist/analyzer/insights.js.map +1 -0
- package/dist/analyzer/waste-detector.d.ts +2 -0
- package/dist/analyzer/waste-detector.d.ts.map +1 -0
- package/dist/analyzer/waste-detector.js +3 -0
- package/dist/analyzer/waste-detector.js.map +1 -0
- package/dist/db/index.d.ts +8 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +28 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/queries.d.ts +62 -0
- package/dist/db/queries.d.ts.map +1 -0
- package/dist/db/queries.js +404 -0
- package/dist/db/queries.js.map +1 -0
- package/dist/db/schema.d.ts +4 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +148 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/sync.d.ts +4 -0
- package/dist/db/sync.d.ts.map +1 -0
- package/dist/db/sync.js +63 -0
- package/dist/db/sync.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/file-impact.d.ts +5 -0
- package/dist/parser/file-impact.d.ts.map +1 -0
- package/dist/parser/file-impact.js +102 -0
- package/dist/parser/file-impact.js.map +1 -0
- package/dist/parser/index.d.ts +7 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +6 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/log-scanner.d.ts +24 -0
- package/dist/parser/log-scanner.d.ts.map +1 -0
- package/dist/parser/log-scanner.js +115 -0
- package/dist/parser/log-scanner.js.map +1 -0
- package/dist/parser/session-parser.d.ts +3 -0
- package/dist/parser/session-parser.d.ts.map +1 -0
- package/dist/parser/session-parser.js +131 -0
- package/dist/parser/session-parser.js.map +1 -0
- package/dist/parser/step-parser.d.ts +12 -0
- package/dist/parser/step-parser.d.ts.map +1 -0
- package/dist/parser/step-parser.js +242 -0
- package/dist/parser/step-parser.js.map +1 -0
- package/dist/parser/token-estimator.d.ts +11 -0
- package/dist/parser/token-estimator.d.ts.map +1 -0
- package/dist/parser/token-estimator.js +19 -0
- package/dist/parser/token-estimator.js.map +1 -0
- package/dist/types.d.ts +90 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/package.json +38 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { createReadStream } from 'node:fs';
|
|
2
|
+
import { createInterface } from 'node:readline';
|
|
3
|
+
import { parseStep, extractModel, extractUsage } from './step-parser.js';
|
|
4
|
+
import { extractFileImpacts } from './file-impact.js';
|
|
5
|
+
function resolveModelName(raw) {
|
|
6
|
+
const lower = raw.toLowerCase();
|
|
7
|
+
if (lower.includes('opus'))
|
|
8
|
+
return 'opus';
|
|
9
|
+
if (lower.includes('sonnet'))
|
|
10
|
+
return 'sonnet';
|
|
11
|
+
if (lower.includes('haiku'))
|
|
12
|
+
return 'haiku';
|
|
13
|
+
return 'unknown';
|
|
14
|
+
}
|
|
15
|
+
export async function parseSession(filePath) {
|
|
16
|
+
const steps = [];
|
|
17
|
+
let totalTokensIn = 0;
|
|
18
|
+
let totalTokensOut = 0;
|
|
19
|
+
let model = null;
|
|
20
|
+
let projectPath = null;
|
|
21
|
+
let startedAt = null;
|
|
22
|
+
let endedAt = null;
|
|
23
|
+
let errorCount = 0;
|
|
24
|
+
let toolCallCount = 0;
|
|
25
|
+
let lineIndex = 0;
|
|
26
|
+
const rl = createInterface({
|
|
27
|
+
input: createReadStream(filePath, { encoding: 'utf-8' }),
|
|
28
|
+
crlfDelay: Infinity,
|
|
29
|
+
});
|
|
30
|
+
for await (const line of rl) {
|
|
31
|
+
if (!line.trim()) {
|
|
32
|
+
lineIndex++;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
let entry;
|
|
36
|
+
try {
|
|
37
|
+
entry = JSON.parse(line);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
lineIndex++;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
// Extract project path from user entries
|
|
44
|
+
if (typeof entry === 'object' &&
|
|
45
|
+
entry !== null &&
|
|
46
|
+
entry['type'] === 'user' &&
|
|
47
|
+
!projectPath) {
|
|
48
|
+
const cwd = entry['cwd'];
|
|
49
|
+
if (typeof cwd === 'string') {
|
|
50
|
+
projectPath = cwd;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Extract model
|
|
54
|
+
const rawModel = extractModel(entry);
|
|
55
|
+
if (rawModel && !model) {
|
|
56
|
+
model = resolveModelName(rawModel);
|
|
57
|
+
}
|
|
58
|
+
// Extract usage from final assistant entries
|
|
59
|
+
const usage = extractUsage(entry);
|
|
60
|
+
if (usage) {
|
|
61
|
+
totalTokensIn += usage.tokensIn;
|
|
62
|
+
totalTokensOut += usage.tokensOut;
|
|
63
|
+
}
|
|
64
|
+
// Parse step
|
|
65
|
+
const result = parseStep(entry, lineIndex);
|
|
66
|
+
if (result) {
|
|
67
|
+
const parsed = Array.isArray(result) ? result : [result];
|
|
68
|
+
for (const step of parsed) {
|
|
69
|
+
steps.push(step);
|
|
70
|
+
// Track timestamps
|
|
71
|
+
if (step.createdAt.getTime() > 0) {
|
|
72
|
+
if (!startedAt || step.createdAt < startedAt) {
|
|
73
|
+
startedAt = step.createdAt;
|
|
74
|
+
}
|
|
75
|
+
if (!endedAt || step.createdAt > endedAt) {
|
|
76
|
+
endedAt = step.createdAt;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (step.type === 'tool_call')
|
|
80
|
+
toolCallCount++;
|
|
81
|
+
if (step.isError)
|
|
82
|
+
errorCount++;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
lineIndex++;
|
|
86
|
+
}
|
|
87
|
+
const now = new Date();
|
|
88
|
+
const sessionStart = startedAt ?? now;
|
|
89
|
+
const sessionEnd = endedAt ?? now;
|
|
90
|
+
const durationSeconds = startedAt && endedAt
|
|
91
|
+
? Math.round((endedAt.getTime() - startedAt.getTime()) / 1000)
|
|
92
|
+
: null;
|
|
93
|
+
// Build pseudo-steps with ids for file impact extraction
|
|
94
|
+
const stepsWithIds = steps.map((s, i) => ({
|
|
95
|
+
...s,
|
|
96
|
+
id: `step-${i}`,
|
|
97
|
+
sessionId: '',
|
|
98
|
+
}));
|
|
99
|
+
const fileImpacts = extractFileImpacts(stepsWithIds);
|
|
100
|
+
// Derive summary from first user prompt
|
|
101
|
+
let summary = null;
|
|
102
|
+
const firstPrompt = steps.find((s) => s.type === 'user_prompt');
|
|
103
|
+
if (firstPrompt?.content) {
|
|
104
|
+
summary =
|
|
105
|
+
firstPrompt.content.length > 200
|
|
106
|
+
? firstPrompt.content.slice(0, 200) + '…'
|
|
107
|
+
: firstPrompt.content;
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
session: {
|
|
111
|
+
projectPath,
|
|
112
|
+
projectName: projectPath ? projectPath.split('/').pop() ?? null : null,
|
|
113
|
+
startedAt: sessionStart,
|
|
114
|
+
endedAt: sessionEnd,
|
|
115
|
+
durationSeconds,
|
|
116
|
+
totalTokensIn,
|
|
117
|
+
totalTokensOut,
|
|
118
|
+
totalCostUsd: 0, // Calculated later with pricing
|
|
119
|
+
totalSteps: steps.length,
|
|
120
|
+
toolCallCount,
|
|
121
|
+
errorCount,
|
|
122
|
+
retryCount: 0,
|
|
123
|
+
model,
|
|
124
|
+
summary,
|
|
125
|
+
rawLogPath: filePath,
|
|
126
|
+
},
|
|
127
|
+
steps,
|
|
128
|
+
fileImpacts,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=session-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-parser.js","sourceRoot":"","sources":["../../src/parser/session-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Step } from '../types.js';
|
|
2
|
+
type PartialStep = Omit<Step, 'id' | 'sessionId'>;
|
|
3
|
+
export declare function parseStep(entry: unknown, index: number): PartialStep | PartialStep[] | null;
|
|
4
|
+
/** Extract model name string from an assistant entry */
|
|
5
|
+
export declare function extractModel(entry: unknown): string | null;
|
|
6
|
+
/** Extract usage from an assistant entry (only final entries) */
|
|
7
|
+
export declare function extractUsage(entry: unknown): {
|
|
8
|
+
tokensIn: number;
|
|
9
|
+
tokensOut: number;
|
|
10
|
+
} | null;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=step-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-parser.d.ts","sourceRoot":"","sources":["../../src/parser/step-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAyB,MAAM,aAAa,CAAA;AAE9D,KAAK,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,CAAC,CAAA;AAkDjD,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,WAAW,EAAE,GAAG,IAAI,CAkB3F;AAkLD,wDAAwD;AACxD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAM1D;AAED,iEAAiE;AACjE,wBAAgB,YAAY,CAC1B,KAAK,EAAE,OAAO,GACb;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAiBhD"}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
function extractText(content) {
|
|
2
|
+
if (typeof content === 'string')
|
|
3
|
+
return content;
|
|
4
|
+
if (!Array.isArray(content))
|
|
5
|
+
return null;
|
|
6
|
+
const texts = [];
|
|
7
|
+
for (const block of content) {
|
|
8
|
+
if (block.type === 'text' && typeof block.text === 'string') {
|
|
9
|
+
texts.push(block.text);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return texts.length > 0 ? texts.join('\n') : null;
|
|
13
|
+
}
|
|
14
|
+
function classifyTool(toolName) {
|
|
15
|
+
const name = toolName.toLowerCase();
|
|
16
|
+
if (name === 'edit' || name === 'write' || name === 'notebookedit')
|
|
17
|
+
return 'file_edit';
|
|
18
|
+
if (name === 'bash')
|
|
19
|
+
return 'bash';
|
|
20
|
+
if (name === 'read')
|
|
21
|
+
return 'read_file';
|
|
22
|
+
if (name === 'grep')
|
|
23
|
+
return 'search';
|
|
24
|
+
if (name === 'glob')
|
|
25
|
+
return 'glob';
|
|
26
|
+
return 'other';
|
|
27
|
+
}
|
|
28
|
+
function truncate(s, max) {
|
|
29
|
+
return s.length > max ? s.slice(0, max) + '…' : s;
|
|
30
|
+
}
|
|
31
|
+
export function parseStep(entry, index) {
|
|
32
|
+
if (typeof entry !== 'object' || entry === null)
|
|
33
|
+
return null;
|
|
34
|
+
const e = entry;
|
|
35
|
+
const type = e['type'];
|
|
36
|
+
const timestamp = e['timestamp'];
|
|
37
|
+
const createdAt = timestamp ? new Date(timestamp) : new Date(0);
|
|
38
|
+
if (type === 'user') {
|
|
39
|
+
return parseUserEntry(e, index, createdAt);
|
|
40
|
+
}
|
|
41
|
+
if (type === 'assistant') {
|
|
42
|
+
return parseAssistantEntry(e, index, createdAt);
|
|
43
|
+
}
|
|
44
|
+
// Ignore system, progress, permission-mode, file-history-snapshot, attachment, last-prompt
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
function parseUserEntry(e, index, createdAt) {
|
|
48
|
+
const message = e['message'];
|
|
49
|
+
if (!message)
|
|
50
|
+
return null;
|
|
51
|
+
const content = message['content'];
|
|
52
|
+
// Tool result entry: content is an array with tool_result blocks
|
|
53
|
+
if (Array.isArray(content)) {
|
|
54
|
+
const toolResult = e['toolUseResult'];
|
|
55
|
+
const blocks = content;
|
|
56
|
+
const firstBlock = blocks[0];
|
|
57
|
+
if (!firstBlock)
|
|
58
|
+
return null;
|
|
59
|
+
const isError = typeof toolResult === 'string' &&
|
|
60
|
+
(toolResult.startsWith('Error:') || toolResult.startsWith('error:'));
|
|
61
|
+
let outputText = null;
|
|
62
|
+
if (typeof toolResult === 'string') {
|
|
63
|
+
outputText = toolResult;
|
|
64
|
+
}
|
|
65
|
+
else if (typeof toolResult === 'object' && toolResult !== null) {
|
|
66
|
+
outputText = JSON.stringify(toolResult);
|
|
67
|
+
}
|
|
68
|
+
else if (typeof firstBlock.content === 'string') {
|
|
69
|
+
outputText = firstBlock.content;
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
stepIndex: index,
|
|
73
|
+
type: 'tool_result',
|
|
74
|
+
subtype: null,
|
|
75
|
+
content: null,
|
|
76
|
+
contentSummary: outputText ? truncate(outputText, 200) : null,
|
|
77
|
+
tokensIn: 0,
|
|
78
|
+
tokensOut: 0,
|
|
79
|
+
durationMs: null,
|
|
80
|
+
toolName: null,
|
|
81
|
+
toolInput: null,
|
|
82
|
+
toolOutput: outputText,
|
|
83
|
+
isError,
|
|
84
|
+
isRetry: false,
|
|
85
|
+
retryOfStepId: null,
|
|
86
|
+
createdAt,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// User prompt entry: content is a string
|
|
90
|
+
if (typeof content === 'string') {
|
|
91
|
+
return {
|
|
92
|
+
stepIndex: index,
|
|
93
|
+
type: 'user_prompt',
|
|
94
|
+
subtype: null,
|
|
95
|
+
content,
|
|
96
|
+
contentSummary: truncate(content, 200),
|
|
97
|
+
tokensIn: 0,
|
|
98
|
+
tokensOut: 0,
|
|
99
|
+
durationMs: null,
|
|
100
|
+
toolName: null,
|
|
101
|
+
toolInput: null,
|
|
102
|
+
toolOutput: null,
|
|
103
|
+
isError: false,
|
|
104
|
+
isRetry: false,
|
|
105
|
+
retryOfStepId: null,
|
|
106
|
+
createdAt,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
function parseAssistantEntry(e, index, createdAt) {
|
|
112
|
+
const message = e['message'];
|
|
113
|
+
if (!message)
|
|
114
|
+
return null;
|
|
115
|
+
const contentBlocks = message['content'];
|
|
116
|
+
if (!Array.isArray(contentBlocks))
|
|
117
|
+
return null;
|
|
118
|
+
const usage = message['usage'] ?? {};
|
|
119
|
+
const model = message['model'];
|
|
120
|
+
const stopReason = message['stop_reason'];
|
|
121
|
+
// Only take usage from final entry of a turn (stop_reason != null)
|
|
122
|
+
const isFinal = stopReason != null && stopReason !== '';
|
|
123
|
+
const tokensIn = isFinal
|
|
124
|
+
? (usage.input_tokens ?? 0) +
|
|
125
|
+
(usage.cache_creation_input_tokens ?? 0) +
|
|
126
|
+
(usage.cache_read_input_tokens ?? 0)
|
|
127
|
+
: 0;
|
|
128
|
+
const tokensOut = isFinal ? (usage.output_tokens ?? 0) : 0;
|
|
129
|
+
const steps = [];
|
|
130
|
+
const textParts = [];
|
|
131
|
+
for (const block of contentBlocks) {
|
|
132
|
+
if (block.type === 'text' && typeof block.text === 'string') {
|
|
133
|
+
textParts.push(block.text);
|
|
134
|
+
}
|
|
135
|
+
else if (block.type === 'tool_use' && typeof block.name === 'string') {
|
|
136
|
+
steps.push({
|
|
137
|
+
stepIndex: index,
|
|
138
|
+
type: 'tool_call',
|
|
139
|
+
subtype: classifyTool(block.name),
|
|
140
|
+
content: null,
|
|
141
|
+
contentSummary: `Tool call: ${block.name}`,
|
|
142
|
+
tokensIn: 0,
|
|
143
|
+
tokensOut: 0,
|
|
144
|
+
durationMs: null,
|
|
145
|
+
toolName: block.name,
|
|
146
|
+
toolInput: block.input ? JSON.stringify(block.input) : null,
|
|
147
|
+
toolOutput: null,
|
|
148
|
+
isError: false,
|
|
149
|
+
isRetry: false,
|
|
150
|
+
retryOfStepId: null,
|
|
151
|
+
createdAt,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
// thinking blocks are skipped
|
|
155
|
+
}
|
|
156
|
+
// Emit a text response step if there's text content
|
|
157
|
+
if (textParts.length > 0) {
|
|
158
|
+
const fullText = textParts.join('\n');
|
|
159
|
+
steps.unshift({
|
|
160
|
+
stepIndex: index,
|
|
161
|
+
type: 'assistant_response',
|
|
162
|
+
subtype: null,
|
|
163
|
+
content: fullText,
|
|
164
|
+
contentSummary: truncate(fullText, 200),
|
|
165
|
+
tokensIn,
|
|
166
|
+
tokensOut,
|
|
167
|
+
durationMs: null,
|
|
168
|
+
toolName: null,
|
|
169
|
+
toolInput: null,
|
|
170
|
+
toolOutput: null,
|
|
171
|
+
isError: false,
|
|
172
|
+
isRetry: false,
|
|
173
|
+
retryOfStepId: null,
|
|
174
|
+
createdAt,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
else if (steps.length > 0) {
|
|
178
|
+
// Attribute tokens to the first tool call step
|
|
179
|
+
const first = steps[0];
|
|
180
|
+
first.tokensIn = tokensIn;
|
|
181
|
+
first.tokensOut = tokensOut;
|
|
182
|
+
}
|
|
183
|
+
else if (isFinal) {
|
|
184
|
+
// Entry with no text and no tools but has usage (e.g. empty final streaming entry)
|
|
185
|
+
steps.push({
|
|
186
|
+
stepIndex: index,
|
|
187
|
+
type: 'assistant_response',
|
|
188
|
+
subtype: null,
|
|
189
|
+
content: null,
|
|
190
|
+
contentSummary: null,
|
|
191
|
+
tokensIn,
|
|
192
|
+
tokensOut,
|
|
193
|
+
durationMs: null,
|
|
194
|
+
toolName: null,
|
|
195
|
+
toolInput: null,
|
|
196
|
+
toolOutput: model ?? null,
|
|
197
|
+
isError: false,
|
|
198
|
+
isRetry: false,
|
|
199
|
+
retryOfStepId: null,
|
|
200
|
+
createdAt,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
if (steps.length === 0)
|
|
204
|
+
return null;
|
|
205
|
+
if (steps.length === 1)
|
|
206
|
+
return steps[0];
|
|
207
|
+
return steps;
|
|
208
|
+
}
|
|
209
|
+
/** Extract model name string from an assistant entry */
|
|
210
|
+
export function extractModel(entry) {
|
|
211
|
+
if (typeof entry !== 'object' || entry === null)
|
|
212
|
+
return null;
|
|
213
|
+
const e = entry;
|
|
214
|
+
if (e['type'] !== 'assistant')
|
|
215
|
+
return null;
|
|
216
|
+
const message = e['message'];
|
|
217
|
+
return message?.['model'] ?? null;
|
|
218
|
+
}
|
|
219
|
+
/** Extract usage from an assistant entry (only final entries) */
|
|
220
|
+
export function extractUsage(entry) {
|
|
221
|
+
if (typeof entry !== 'object' || entry === null)
|
|
222
|
+
return null;
|
|
223
|
+
const e = entry;
|
|
224
|
+
if (e['type'] !== 'assistant')
|
|
225
|
+
return null;
|
|
226
|
+
const message = e['message'];
|
|
227
|
+
if (!message)
|
|
228
|
+
return null;
|
|
229
|
+
const stopReason = message['stop_reason'];
|
|
230
|
+
if (stopReason == null || stopReason === '')
|
|
231
|
+
return null;
|
|
232
|
+
const usage = message['usage'];
|
|
233
|
+
if (!usage)
|
|
234
|
+
return null;
|
|
235
|
+
return {
|
|
236
|
+
tokensIn: (usage.input_tokens ?? 0) +
|
|
237
|
+
(usage.cache_creation_input_tokens ?? 0) +
|
|
238
|
+
(usage.cache_read_input_tokens ?? 0),
|
|
239
|
+
tokensOut: usage.output_tokens ?? 0,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=step-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-parser.js","sourceRoot":"","sources":["../../src/parser/step-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PricingModel } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Heuristic token estimation from text.
|
|
4
|
+
* ~4 chars/token for natural language, ~3 chars/token for code.
|
|
5
|
+
*/
|
|
6
|
+
export declare function estimateTokens(text: string, type: 'natural' | 'code'): number;
|
|
7
|
+
/**
|
|
8
|
+
* Estimate cost in USD from token counts and pricing model.
|
|
9
|
+
*/
|
|
10
|
+
export declare function estimateCost(tokensIn: number, tokensOut: number, pricing: PricingModel): number;
|
|
11
|
+
//# sourceMappingURL=token-estimator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-estimator.d.ts","sourceRoot":"","sources":["../../src/parser/token-estimator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,CAI7E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,YAAY,GACpB,MAAM,CAIR"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heuristic token estimation from text.
|
|
3
|
+
* ~4 chars/token for natural language, ~3 chars/token for code.
|
|
4
|
+
*/
|
|
5
|
+
export function estimateTokens(text, type) {
|
|
6
|
+
if (!text)
|
|
7
|
+
return 0;
|
|
8
|
+
const charsPerToken = type === 'code' ? 3 : 4;
|
|
9
|
+
return Math.ceil(text.length / charsPerToken);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Estimate cost in USD from token counts and pricing model.
|
|
13
|
+
*/
|
|
14
|
+
export function estimateCost(tokensIn, tokensOut, pricing) {
|
|
15
|
+
const inputCost = (tokensIn / 1_000_000) * pricing.inputPer1M;
|
|
16
|
+
const outputCost = (tokensOut / 1_000_000) * pricing.outputPer1M;
|
|
17
|
+
return inputCost + outputCost;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=token-estimator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-estimator.js","sourceRoot":"","sources":["../../src/parser/token-estimator.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,IAAwB;IACnE,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,CAAA;IACnB,MAAM,aAAa,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC,CAAA;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAgB,EAChB,SAAiB,EACjB,OAAqB;IAErB,MAAM,SAAS,GAAG,CAAC,QAAQ,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,UAAU,CAAA;IAC7D,MAAM,UAAU,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,WAAW,CAAA;IAChE,OAAO,SAAS,GAAG,UAAU,CAAA;AAC/B,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export type StepType = 'user_prompt' | 'assistant_response' | 'tool_call' | 'tool_result' | 'error';
|
|
2
|
+
export type ToolSubtype = 'file_edit' | 'bash' | 'read_file' | 'search' | 'glob' | 'other';
|
|
3
|
+
export type FileAction = 'create' | 'edit' | 'delete' | 'read' | 'rename';
|
|
4
|
+
export type ModelName = 'opus' | 'sonnet' | 'haiku' | 'unknown';
|
|
5
|
+
export interface Session {
|
|
6
|
+
id: string;
|
|
7
|
+
projectPath: string | null;
|
|
8
|
+
projectName: string | null;
|
|
9
|
+
startedAt: Date;
|
|
10
|
+
endedAt: Date | null;
|
|
11
|
+
durationSeconds: number | null;
|
|
12
|
+
totalTokensIn: number;
|
|
13
|
+
totalTokensOut: number;
|
|
14
|
+
totalCostUsd: number;
|
|
15
|
+
totalSteps: number;
|
|
16
|
+
toolCallCount: number;
|
|
17
|
+
errorCount: number;
|
|
18
|
+
retryCount: number;
|
|
19
|
+
model: ModelName | null;
|
|
20
|
+
summary: string | null;
|
|
21
|
+
rawLogPath: string;
|
|
22
|
+
}
|
|
23
|
+
export interface Step {
|
|
24
|
+
id: string;
|
|
25
|
+
sessionId: string;
|
|
26
|
+
stepIndex: number;
|
|
27
|
+
type: StepType;
|
|
28
|
+
subtype: ToolSubtype | null;
|
|
29
|
+
content: string | null;
|
|
30
|
+
contentSummary: string | null;
|
|
31
|
+
tokensIn: number;
|
|
32
|
+
tokensOut: number;
|
|
33
|
+
durationMs: number | null;
|
|
34
|
+
toolName: string | null;
|
|
35
|
+
toolInput: string | null;
|
|
36
|
+
toolOutput: string | null;
|
|
37
|
+
isError: boolean;
|
|
38
|
+
isRetry: boolean;
|
|
39
|
+
retryOfStepId: string | null;
|
|
40
|
+
createdAt: Date;
|
|
41
|
+
}
|
|
42
|
+
export interface FileImpact {
|
|
43
|
+
id: number;
|
|
44
|
+
sessionId: string;
|
|
45
|
+
stepId: string;
|
|
46
|
+
filePath: string;
|
|
47
|
+
action: FileAction;
|
|
48
|
+
linesAdded: number;
|
|
49
|
+
linesRemoved: number;
|
|
50
|
+
diffContent: string | null;
|
|
51
|
+
createdAt: Date;
|
|
52
|
+
}
|
|
53
|
+
export interface Project {
|
|
54
|
+
path: string;
|
|
55
|
+
name: string;
|
|
56
|
+
totalSessions: number;
|
|
57
|
+
totalTokens: number;
|
|
58
|
+
totalCostUsd: number;
|
|
59
|
+
firstSessionAt: Date | null;
|
|
60
|
+
lastSessionAt: Date | null;
|
|
61
|
+
claudeMdPath: string | null;
|
|
62
|
+
updatedAt: Date;
|
|
63
|
+
}
|
|
64
|
+
export interface ParsedLogEntry {
|
|
65
|
+
session: Omit<Session, 'id'>;
|
|
66
|
+
steps: Omit<Step, 'id' | 'sessionId'>[];
|
|
67
|
+
fileImpacts: Omit<FileImpact, 'id' | 'sessionId'>[];
|
|
68
|
+
}
|
|
69
|
+
export interface ScanOptions {
|
|
70
|
+
claudePath?: string;
|
|
71
|
+
forceRescan?: boolean;
|
|
72
|
+
onProgress?: (current: number, total: number) => void;
|
|
73
|
+
}
|
|
74
|
+
export interface ScanResult {
|
|
75
|
+
sessionsFound: number;
|
|
76
|
+
newSessions: number;
|
|
77
|
+
skippedSessions: number;
|
|
78
|
+
errors: ScanError[];
|
|
79
|
+
}
|
|
80
|
+
export interface ScanError {
|
|
81
|
+
filePath: string;
|
|
82
|
+
error: string;
|
|
83
|
+
}
|
|
84
|
+
export interface PricingModel {
|
|
85
|
+
model: ModelName;
|
|
86
|
+
inputPer1M: number;
|
|
87
|
+
outputPer1M: number;
|
|
88
|
+
}
|
|
89
|
+
export declare const DEFAULT_PRICING: Record<ModelName, PricingModel>;
|
|
90
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// ccview — Shared Types
|
|
3
|
+
// Core data model — allineato con lo schema SQLite in db/schema.ts
|
|
4
|
+
// ============================================================
|
|
5
|
+
export const DEFAULT_PRICING = {
|
|
6
|
+
opus: { model: 'opus', inputPer1M: 15, outputPer1M: 75 },
|
|
7
|
+
sonnet: { model: 'sonnet', inputPer1M: 3, outputPer1M: 15 },
|
|
8
|
+
haiku: { model: 'haiku', inputPer1M: 0.25, outputPer1M: 1.25 },
|
|
9
|
+
unknown: { model: 'unknown', inputPer1M: 3, outputPer1M: 15 },
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,wBAAwB;AACxB,mEAAmE;AACnE,+DAA+D;AAoG/D,MAAM,CAAC,MAAM,eAAe,GAAoC;IAC9D,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE;IACxD,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE;IAC3D,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE;IAC9D,OAAO,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE;CAC9D,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ccview/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Core parser and database for ccview — Claude Code session analytics",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"build:watch": "tsc --watch",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"clean": "rm -rf dist"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"better-sqlite3": "^12.8.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/better-sqlite3": "^7.6.10",
|
|
31
|
+
"@types/node": "^20.12.7",
|
|
32
|
+
"typescript": "^5.4.5",
|
|
33
|
+
"vitest": "^1.5.0"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18.0.0"
|
|
37
|
+
}
|
|
38
|
+
}
|