cccmemory 1.8.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/LICENSE +21 -0
- package/README.md +349 -0
- package/dist/ConversationMemory.d.ts +231 -0
- package/dist/ConversationMemory.d.ts.map +1 -0
- package/dist/ConversationMemory.js +357 -0
- package/dist/ConversationMemory.js.map +1 -0
- package/dist/cache/QueryCache.d.ts +215 -0
- package/dist/cache/QueryCache.d.ts.map +1 -0
- package/dist/cache/QueryCache.js +294 -0
- package/dist/cache/QueryCache.js.map +1 -0
- package/dist/cli/commands.d.ts +9 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +954 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/help.d.ts +16 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +361 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/index.d.ts +30 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +111 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/context/ContextInjector.d.ts +38 -0
- package/dist/context/ContextInjector.d.ts.map +1 -0
- package/dist/context/ContextInjector.js +235 -0
- package/dist/context/ContextInjector.js.map +1 -0
- package/dist/documentation/CodeAnalyzer.d.ts +29 -0
- package/dist/documentation/CodeAnalyzer.d.ts.map +1 -0
- package/dist/documentation/CodeAnalyzer.js +122 -0
- package/dist/documentation/CodeAnalyzer.js.map +1 -0
- package/dist/documentation/ConversationAnalyzer.d.ts +19 -0
- package/dist/documentation/ConversationAnalyzer.d.ts.map +1 -0
- package/dist/documentation/ConversationAnalyzer.js +157 -0
- package/dist/documentation/ConversationAnalyzer.js.map +1 -0
- package/dist/documentation/CrossReferencer.d.ts +67 -0
- package/dist/documentation/CrossReferencer.d.ts.map +1 -0
- package/dist/documentation/CrossReferencer.js +247 -0
- package/dist/documentation/CrossReferencer.js.map +1 -0
- package/dist/documentation/DocumentationGenerator.d.ts +22 -0
- package/dist/documentation/DocumentationGenerator.d.ts.map +1 -0
- package/dist/documentation/DocumentationGenerator.js +57 -0
- package/dist/documentation/DocumentationGenerator.js.map +1 -0
- package/dist/documentation/MarkdownFormatter.d.ts +26 -0
- package/dist/documentation/MarkdownFormatter.d.ts.map +1 -0
- package/dist/documentation/MarkdownFormatter.js +301 -0
- package/dist/documentation/MarkdownFormatter.js.map +1 -0
- package/dist/documentation/types.d.ts +176 -0
- package/dist/documentation/types.d.ts.map +1 -0
- package/dist/documentation/types.js +5 -0
- package/dist/documentation/types.js.map +1 -0
- package/dist/embeddings/ConfigManager.d.ts +46 -0
- package/dist/embeddings/ConfigManager.d.ts.map +1 -0
- package/dist/embeddings/ConfigManager.js +177 -0
- package/dist/embeddings/ConfigManager.js.map +1 -0
- package/dist/embeddings/EmbeddingConfig.d.ts +39 -0
- package/dist/embeddings/EmbeddingConfig.d.ts.map +1 -0
- package/dist/embeddings/EmbeddingConfig.js +132 -0
- package/dist/embeddings/EmbeddingConfig.js.map +1 -0
- package/dist/embeddings/EmbeddingGenerator.d.ts +51 -0
- package/dist/embeddings/EmbeddingGenerator.d.ts.map +1 -0
- package/dist/embeddings/EmbeddingGenerator.js +157 -0
- package/dist/embeddings/EmbeddingGenerator.js.map +1 -0
- package/dist/embeddings/EmbeddingProvider.d.ts +34 -0
- package/dist/embeddings/EmbeddingProvider.d.ts.map +1 -0
- package/dist/embeddings/EmbeddingProvider.js +6 -0
- package/dist/embeddings/EmbeddingProvider.js.map +1 -0
- package/dist/embeddings/ModelRegistry.d.ts +48 -0
- package/dist/embeddings/ModelRegistry.d.ts.map +1 -0
- package/dist/embeddings/ModelRegistry.js +170 -0
- package/dist/embeddings/ModelRegistry.js.map +1 -0
- package/dist/embeddings/VectorStore.d.ts +114 -0
- package/dist/embeddings/VectorStore.d.ts.map +1 -0
- package/dist/embeddings/VectorStore.js +393 -0
- package/dist/embeddings/VectorStore.js.map +1 -0
- package/dist/embeddings/providers/OllamaEmbeddings.d.ts +38 -0
- package/dist/embeddings/providers/OllamaEmbeddings.d.ts.map +1 -0
- package/dist/embeddings/providers/OllamaEmbeddings.js +125 -0
- package/dist/embeddings/providers/OllamaEmbeddings.js.map +1 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.d.ts +40 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.d.ts.map +1 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.js +129 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.js.map +1 -0
- package/dist/embeddings/providers/TransformersEmbeddings.d.ts +38 -0
- package/dist/embeddings/providers/TransformersEmbeddings.d.ts.map +1 -0
- package/dist/embeddings/providers/TransformersEmbeddings.js +115 -0
- package/dist/embeddings/providers/TransformersEmbeddings.js.map +1 -0
- package/dist/handoff/SessionHandoffStore.d.ts +80 -0
- package/dist/handoff/SessionHandoffStore.d.ts.map +1 -0
- package/dist/handoff/SessionHandoffStore.js +314 -0
- package/dist/handoff/SessionHandoffStore.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +115 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server.d.ts +27 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +157 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/memory/WorkingMemoryStore.d.ts +83 -0
- package/dist/memory/WorkingMemoryStore.d.ts.map +1 -0
- package/dist/memory/WorkingMemoryStore.js +318 -0
- package/dist/memory/WorkingMemoryStore.js.map +1 -0
- package/dist/memory/types.d.ts +192 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +8 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/parsers/CodexConversationParser.d.ts +51 -0
- package/dist/parsers/CodexConversationParser.d.ts.map +1 -0
- package/dist/parsers/CodexConversationParser.js +301 -0
- package/dist/parsers/CodexConversationParser.js.map +1 -0
- package/dist/parsers/ConversationParser.d.ts +286 -0
- package/dist/parsers/ConversationParser.d.ts.map +1 -0
- package/dist/parsers/ConversationParser.js +795 -0
- package/dist/parsers/ConversationParser.js.map +1 -0
- package/dist/parsers/DecisionExtractor.d.ts +144 -0
- package/dist/parsers/DecisionExtractor.d.ts.map +1 -0
- package/dist/parsers/DecisionExtractor.js +434 -0
- package/dist/parsers/DecisionExtractor.js.map +1 -0
- package/dist/parsers/GitIntegrator.d.ts +156 -0
- package/dist/parsers/GitIntegrator.d.ts.map +1 -0
- package/dist/parsers/GitIntegrator.js +348 -0
- package/dist/parsers/GitIntegrator.js.map +1 -0
- package/dist/parsers/MistakeExtractor.d.ts +151 -0
- package/dist/parsers/MistakeExtractor.d.ts.map +1 -0
- package/dist/parsers/MistakeExtractor.js +460 -0
- package/dist/parsers/MistakeExtractor.js.map +1 -0
- package/dist/parsers/RequirementsExtractor.d.ts +166 -0
- package/dist/parsers/RequirementsExtractor.d.ts.map +1 -0
- package/dist/parsers/RequirementsExtractor.js +338 -0
- package/dist/parsers/RequirementsExtractor.js.map +1 -0
- package/dist/realtime/ConversationWatcher.d.ts +87 -0
- package/dist/realtime/ConversationWatcher.d.ts.map +1 -0
- package/dist/realtime/ConversationWatcher.js +204 -0
- package/dist/realtime/ConversationWatcher.js.map +1 -0
- package/dist/realtime/IncrementalParser.d.ts +83 -0
- package/dist/realtime/IncrementalParser.d.ts.map +1 -0
- package/dist/realtime/IncrementalParser.js +232 -0
- package/dist/realtime/IncrementalParser.js.map +1 -0
- package/dist/realtime/LiveExtractor.d.ts +72 -0
- package/dist/realtime/LiveExtractor.d.ts.map +1 -0
- package/dist/realtime/LiveExtractor.js +288 -0
- package/dist/realtime/LiveExtractor.js.map +1 -0
- package/dist/search/SemanticSearch.d.ts +121 -0
- package/dist/search/SemanticSearch.d.ts.map +1 -0
- package/dist/search/SemanticSearch.js +823 -0
- package/dist/search/SemanticSearch.js.map +1 -0
- package/dist/storage/BackupManager.d.ts +58 -0
- package/dist/storage/BackupManager.d.ts.map +1 -0
- package/dist/storage/BackupManager.js +223 -0
- package/dist/storage/BackupManager.js.map +1 -0
- package/dist/storage/ConversationStorage.d.ts +341 -0
- package/dist/storage/ConversationStorage.d.ts.map +1 -0
- package/dist/storage/ConversationStorage.js +792 -0
- package/dist/storage/ConversationStorage.js.map +1 -0
- package/dist/storage/DeletionService.d.ts +70 -0
- package/dist/storage/DeletionService.d.ts.map +1 -0
- package/dist/storage/DeletionService.js +253 -0
- package/dist/storage/DeletionService.js.map +1 -0
- package/dist/storage/GlobalIndex.d.ts +133 -0
- package/dist/storage/GlobalIndex.d.ts.map +1 -0
- package/dist/storage/GlobalIndex.js +310 -0
- package/dist/storage/GlobalIndex.js.map +1 -0
- package/dist/storage/SQLiteManager.d.ts +114 -0
- package/dist/storage/SQLiteManager.d.ts.map +1 -0
- package/dist/storage/SQLiteManager.js +636 -0
- package/dist/storage/SQLiteManager.js.map +1 -0
- package/dist/storage/migrations.d.ts +54 -0
- package/dist/storage/migrations.d.ts.map +1 -0
- package/dist/storage/migrations.js +285 -0
- package/dist/storage/migrations.js.map +1 -0
- package/dist/storage/schema.sql +436 -0
- package/dist/tools/ToolDefinitions.d.ts +946 -0
- package/dist/tools/ToolDefinitions.d.ts.map +1 -0
- package/dist/tools/ToolDefinitions.js +937 -0
- package/dist/tools/ToolDefinitions.js.map +1 -0
- package/dist/tools/ToolHandlers.d.ts +791 -0
- package/dist/tools/ToolHandlers.d.ts.map +1 -0
- package/dist/tools/ToolHandlers.js +3262 -0
- package/dist/tools/ToolHandlers.js.map +1 -0
- package/dist/types/ToolTypes.d.ts +824 -0
- package/dist/types/ToolTypes.d.ts.map +1 -0
- package/dist/types/ToolTypes.js +6 -0
- package/dist/types/ToolTypes.js.map +1 -0
- package/dist/utils/Logger.d.ts +70 -0
- package/dist/utils/Logger.d.ts.map +1 -0
- package/dist/utils/Logger.js +131 -0
- package/dist/utils/Logger.js.map +1 -0
- package/dist/utils/McpConfig.d.ts +54 -0
- package/dist/utils/McpConfig.d.ts.map +1 -0
- package/dist/utils/McpConfig.js +136 -0
- package/dist/utils/McpConfig.js.map +1 -0
- package/dist/utils/ProjectMigration.d.ts +82 -0
- package/dist/utils/ProjectMigration.d.ts.map +1 -0
- package/dist/utils/ProjectMigration.js +416 -0
- package/dist/utils/ProjectMigration.js.map +1 -0
- package/dist/utils/constants.d.ts +75 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +105 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/safeJson.d.ts +37 -0
- package/dist/utils/safeJson.d.ts.map +1 -0
- package/dist/utils/safeJson.js +48 -0
- package/dist/utils/safeJson.js.map +1 -0
- package/dist/utils/sanitization.d.ts +45 -0
- package/dist/utils/sanitization.d.ts.map +1 -0
- package/dist/utils/sanitization.js +153 -0
- package/dist/utils/sanitization.js.map +1 -0
- package/dist/utils/worktree.d.ts +15 -0
- package/dist/utils/worktree.d.ts.map +1 -0
- package/dist/utils/worktree.js +86 -0
- package/dist/utils/worktree.js.map +1 -0
- package/package.json +98 -0
- package/scripts/changelog-check.sh +62 -0
- package/scripts/check-node.js +17 -0
- package/scripts/dev-config.js +56 -0
- package/scripts/postinstall.js +117 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex Conversation Parser for MCP integration.
|
|
3
|
+
*
|
|
4
|
+
* This parser reads conversation history from Codex's storage location
|
|
5
|
+
* (~/.codex/sessions) and converts it to the same format as ConversationParser.
|
|
6
|
+
*
|
|
7
|
+
* Codex stores conversations in a date-hierarchical structure:
|
|
8
|
+
* ~/.codex/sessions/YYYY/MM/DD/rollout-{timestamp}-{uuid}.jsonl
|
|
9
|
+
*
|
|
10
|
+
* Each line in a Codex session file has the structure:
|
|
11
|
+
* {
|
|
12
|
+
* timestamp: string,
|
|
13
|
+
* type: "session_meta" | "response_item" | "event_msg" | "turn_context",
|
|
14
|
+
* payload: { ... }
|
|
15
|
+
* }
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const parser = new CodexConversationParser();
|
|
20
|
+
* const result = parser.parseSessions('/Users/username/.codex');
|
|
21
|
+
* console.error(`Parsed ${result.conversations.length} Codex sessions`);
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
import { readFileSync, readdirSync, existsSync, statSync } from "fs";
|
|
25
|
+
import { join } from "path";
|
|
26
|
+
import { nanoid } from "nanoid";
|
|
27
|
+
/**
|
|
28
|
+
* Parser for Codex conversation history.
|
|
29
|
+
*
|
|
30
|
+
* Converts Codex session files into the same format as ConversationParser
|
|
31
|
+
* so they can be stored in the same database and searched together.
|
|
32
|
+
*/
|
|
33
|
+
export class CodexConversationParser {
|
|
34
|
+
/**
|
|
35
|
+
* Parse all Codex sessions.
|
|
36
|
+
*
|
|
37
|
+
* Recursively scans the sessions directory for JSONL files and parses them.
|
|
38
|
+
*
|
|
39
|
+
* @param codexPath - Path to Codex home directory (default: ~/.codex)
|
|
40
|
+
* @param sessionId - Optional specific session ID to parse
|
|
41
|
+
* @returns ParseResult with all extracted entities
|
|
42
|
+
*/
|
|
43
|
+
parseSession(codexPath, sessionId, lastIndexedMs) {
|
|
44
|
+
const sessionsDir = join(codexPath, "sessions");
|
|
45
|
+
if (!existsSync(sessionsDir)) {
|
|
46
|
+
throw new Error(`Codex sessions directory not found: ${sessionsDir}`);
|
|
47
|
+
}
|
|
48
|
+
const conversations = [];
|
|
49
|
+
const messages = [];
|
|
50
|
+
const tool_uses = [];
|
|
51
|
+
const tool_results = [];
|
|
52
|
+
const file_edits = [];
|
|
53
|
+
const thinking_blocks = [];
|
|
54
|
+
const indexed_folders = [];
|
|
55
|
+
let skippedCount = 0;
|
|
56
|
+
// Recursively find all .jsonl files in date-hierarchical structure
|
|
57
|
+
const sessionFiles = this.findSessionFiles(sessionsDir);
|
|
58
|
+
for (const sessionFile of sessionFiles) {
|
|
59
|
+
try {
|
|
60
|
+
// Skip unchanged files in incremental mode
|
|
61
|
+
if (lastIndexedMs) {
|
|
62
|
+
const stats = statSync(sessionFile);
|
|
63
|
+
if (stats.mtimeMs < lastIndexedMs) {
|
|
64
|
+
skippedCount++;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Extract session ID from filename: rollout-{timestamp}-{uuid}.jsonl
|
|
69
|
+
const filename = sessionFile.split("/").pop();
|
|
70
|
+
if (!filename) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
// Match rollout-{timestamp}-{uuid}.jsonl where timestamp is like 2025-11-03T20-35-04
|
|
74
|
+
// UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
75
|
+
const match = filename.match(/rollout-.+-([0-9a-f]+-[0-9a-f]+-[0-9a-f]+-[0-9a-f]+-[0-9a-f]+)\.jsonl$/i);
|
|
76
|
+
let extractedSessionId;
|
|
77
|
+
if (match) {
|
|
78
|
+
extractedSessionId = match[1];
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// Fallback: just strip "rollout-" prefix and ".jsonl" suffix
|
|
82
|
+
const fallbackId = filename.replace(/^rollout-/, "").replace(/\.jsonl$/, "");
|
|
83
|
+
if (!fallbackId) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
extractedSessionId = fallbackId;
|
|
87
|
+
}
|
|
88
|
+
// Skip if filtering by session ID
|
|
89
|
+
if (sessionId && extractedSessionId !== sessionId) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const result = this.parseSessionFile(sessionFile, codexPath);
|
|
93
|
+
conversations.push(...result.conversations);
|
|
94
|
+
messages.push(...result.messages);
|
|
95
|
+
tool_uses.push(...result.tool_uses);
|
|
96
|
+
tool_results.push(...result.tool_results);
|
|
97
|
+
file_edits.push(...result.file_edits);
|
|
98
|
+
thinking_blocks.push(...result.thinking_blocks);
|
|
99
|
+
// Track indexed folder
|
|
100
|
+
const sessionDir = sessionFile.substring(0, sessionFile.lastIndexOf("/"));
|
|
101
|
+
if (!indexed_folders.includes(sessionDir)) {
|
|
102
|
+
indexed_folders.push(sessionDir);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
console.error(`Failed to parse Codex session file ${sessionFile}:`, error);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (skippedCount > 0) {
|
|
110
|
+
console.error(`⏭ Skipped ${skippedCount} unchanged Codex session file(s)`);
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
conversations,
|
|
114
|
+
messages,
|
|
115
|
+
tool_uses,
|
|
116
|
+
tool_results,
|
|
117
|
+
file_edits,
|
|
118
|
+
thinking_blocks,
|
|
119
|
+
indexed_folders,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Recursively find all .jsonl session files.
|
|
124
|
+
*/
|
|
125
|
+
findSessionFiles(dir) {
|
|
126
|
+
const files = [];
|
|
127
|
+
if (!existsSync(dir)) {
|
|
128
|
+
return files;
|
|
129
|
+
}
|
|
130
|
+
const entries = readdirSync(dir);
|
|
131
|
+
for (const entry of entries) {
|
|
132
|
+
const fullPath = join(dir, entry);
|
|
133
|
+
const stat = statSync(fullPath);
|
|
134
|
+
if (stat.isDirectory()) {
|
|
135
|
+
files.push(...this.findSessionFiles(fullPath));
|
|
136
|
+
}
|
|
137
|
+
else if (entry.endsWith(".jsonl") && entry.startsWith("rollout-")) {
|
|
138
|
+
files.push(fullPath);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return files;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Parse a single Codex session file.
|
|
145
|
+
*/
|
|
146
|
+
parseSessionFile(filePath, codexPath) {
|
|
147
|
+
const conversations = [];
|
|
148
|
+
const messages = [];
|
|
149
|
+
const tool_uses = [];
|
|
150
|
+
const tool_results = [];
|
|
151
|
+
const file_edits = [];
|
|
152
|
+
const thinking_blocks = [];
|
|
153
|
+
const content = readFileSync(filePath, "utf-8");
|
|
154
|
+
const lines = content.trim().split("\n").filter((line) => line.trim());
|
|
155
|
+
if (lines.length === 0) {
|
|
156
|
+
return {
|
|
157
|
+
conversations,
|
|
158
|
+
messages,
|
|
159
|
+
tool_uses,
|
|
160
|
+
tool_results,
|
|
161
|
+
file_edits,
|
|
162
|
+
thinking_blocks,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
// Parse all entries
|
|
166
|
+
const entries = [];
|
|
167
|
+
for (const line of lines) {
|
|
168
|
+
try {
|
|
169
|
+
const entry = JSON.parse(line);
|
|
170
|
+
entries.push(entry);
|
|
171
|
+
}
|
|
172
|
+
catch (_error) {
|
|
173
|
+
// Skip malformed lines
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// Extract session metadata
|
|
178
|
+
const sessionMetaEntry = entries.find((e) => e.type === "session_meta");
|
|
179
|
+
if (!sessionMetaEntry) {
|
|
180
|
+
return {
|
|
181
|
+
conversations,
|
|
182
|
+
messages,
|
|
183
|
+
tool_uses,
|
|
184
|
+
tool_results,
|
|
185
|
+
file_edits,
|
|
186
|
+
thinking_blocks,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
const sessionMeta = sessionMetaEntry.payload;
|
|
190
|
+
const sessionId = sessionMeta.id;
|
|
191
|
+
const sessionTimestamp = new Date(sessionMeta.timestamp).getTime();
|
|
192
|
+
// Create conversation record
|
|
193
|
+
const conversation = {
|
|
194
|
+
id: sessionId,
|
|
195
|
+
project_path: sessionMeta.cwd || codexPath,
|
|
196
|
+
source_type: "codex",
|
|
197
|
+
first_message_at: sessionTimestamp,
|
|
198
|
+
last_message_at: sessionTimestamp,
|
|
199
|
+
message_count: 0,
|
|
200
|
+
git_branch: sessionMeta.git?.branch,
|
|
201
|
+
claude_version: sessionMeta.cli_version,
|
|
202
|
+
metadata: {
|
|
203
|
+
source: "codex",
|
|
204
|
+
originator: sessionMeta.originator,
|
|
205
|
+
model_provider: sessionMeta.model_provider,
|
|
206
|
+
git_commit: sessionMeta.git?.commit_hash,
|
|
207
|
+
git_repo: sessionMeta.git?.repository_url,
|
|
208
|
+
},
|
|
209
|
+
created_at: sessionTimestamp,
|
|
210
|
+
updated_at: sessionTimestamp,
|
|
211
|
+
};
|
|
212
|
+
// Process response_item entries (these contain user/assistant messages and tools)
|
|
213
|
+
const responseItems = entries.filter((e) => e.type === "response_item");
|
|
214
|
+
for (const entry of responseItems) {
|
|
215
|
+
const timestamp = new Date(entry.timestamp).getTime();
|
|
216
|
+
const payload = entry.payload;
|
|
217
|
+
// Update conversation timestamps
|
|
218
|
+
if (timestamp < conversation.first_message_at) {
|
|
219
|
+
conversation.first_message_at = timestamp;
|
|
220
|
+
}
|
|
221
|
+
if (timestamp > conversation.last_message_at) {
|
|
222
|
+
conversation.last_message_at = timestamp;
|
|
223
|
+
}
|
|
224
|
+
// Extract message role and content
|
|
225
|
+
const role = payload.role;
|
|
226
|
+
const content = payload.content;
|
|
227
|
+
if (!role || !content) {
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
// Create message record
|
|
231
|
+
const messageId = payload.id || `${sessionId}-${nanoid()}`;
|
|
232
|
+
const parentId = payload.parent_message_id;
|
|
233
|
+
const message = {
|
|
234
|
+
id: messageId,
|
|
235
|
+
conversation_id: sessionId,
|
|
236
|
+
parent_id: parentId,
|
|
237
|
+
message_type: role === "user" ? "user" : "assistant",
|
|
238
|
+
role,
|
|
239
|
+
content: typeof content === "string" ? content : JSON.stringify(content),
|
|
240
|
+
timestamp,
|
|
241
|
+
is_sidechain: false,
|
|
242
|
+
metadata: payload,
|
|
243
|
+
};
|
|
244
|
+
messages.push(message);
|
|
245
|
+
conversation.message_count++;
|
|
246
|
+
// Extract tool uses and results from content array
|
|
247
|
+
if (Array.isArray(content)) {
|
|
248
|
+
for (const item of content) {
|
|
249
|
+
const contentItem = item;
|
|
250
|
+
// Extract thinking blocks
|
|
251
|
+
if (contentItem.type === "thinking" && contentItem.thinking) {
|
|
252
|
+
const thinkingBlock = {
|
|
253
|
+
id: `${messageId}-thinking-${nanoid()}`,
|
|
254
|
+
message_id: messageId,
|
|
255
|
+
thinking_content: contentItem.thinking,
|
|
256
|
+
signature: contentItem.signature,
|
|
257
|
+
timestamp,
|
|
258
|
+
};
|
|
259
|
+
thinking_blocks.push(thinkingBlock);
|
|
260
|
+
}
|
|
261
|
+
// Extract tool uses
|
|
262
|
+
if (contentItem.type === "tool_use" && contentItem.name && contentItem.id) {
|
|
263
|
+
const toolUse = {
|
|
264
|
+
id: contentItem.id,
|
|
265
|
+
message_id: messageId,
|
|
266
|
+
tool_name: contentItem.name,
|
|
267
|
+
tool_input: (contentItem.input || {}),
|
|
268
|
+
timestamp,
|
|
269
|
+
};
|
|
270
|
+
tool_uses.push(toolUse);
|
|
271
|
+
}
|
|
272
|
+
// Extract tool results
|
|
273
|
+
if (contentItem.type === "tool_result" && contentItem.tool_use_id) {
|
|
274
|
+
const toolResult = {
|
|
275
|
+
id: `${contentItem.tool_use_id}-result`,
|
|
276
|
+
tool_use_id: contentItem.tool_use_id,
|
|
277
|
+
message_id: messageId,
|
|
278
|
+
content: typeof contentItem.content === "string" ? contentItem.content : JSON.stringify(contentItem.content),
|
|
279
|
+
is_error: Boolean(contentItem.is_error),
|
|
280
|
+
stdout: contentItem.stdout,
|
|
281
|
+
stderr: contentItem.stderr,
|
|
282
|
+
is_image: false,
|
|
283
|
+
timestamp,
|
|
284
|
+
};
|
|
285
|
+
tool_results.push(toolResult);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
conversations.push(conversation);
|
|
291
|
+
return {
|
|
292
|
+
conversations,
|
|
293
|
+
messages,
|
|
294
|
+
tool_uses,
|
|
295
|
+
tool_results,
|
|
296
|
+
file_edits,
|
|
297
|
+
thinking_blocks,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
//# sourceMappingURL=CodexConversationParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodexConversationParser.js","sourceRoot":"","sources":["../../src/parsers/CodexConversationParser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-pass JSONL Conversation Parser for Claude Code history.
|
|
3
|
+
*
|
|
4
|
+
* This parser reads conversation history from Claude Code's storage locations
|
|
5
|
+
* (~/.claude/projects) and extracts structured data including messages, tool uses,
|
|
6
|
+
* file edits, and thinking blocks.
|
|
7
|
+
*
|
|
8
|
+
* The parser handles two directory structures:
|
|
9
|
+
* - Modern: ~/.claude/projects/{sanitized-path}
|
|
10
|
+
* - Legacy: ~/.claude/projects/{original-project-name}
|
|
11
|
+
*
|
|
12
|
+
* It performs a multi-pass parsing approach:
|
|
13
|
+
* 1. First pass: Extract conversations and messages
|
|
14
|
+
* 2. Second pass: Link tool uses and results
|
|
15
|
+
* 3. Third pass: Extract file edits from snapshots
|
|
16
|
+
* 4. Fourth pass: Extract thinking blocks
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const parser = new ConversationParser();
|
|
21
|
+
* const result = parser.parseProject('/path/to/project');
|
|
22
|
+
* console.error(`Parsed ${result.conversations.length} conversations`);
|
|
23
|
+
* console.error(`Found ${result.messages.length} messages`);
|
|
24
|
+
* console.error(`Extracted ${result.tool_uses.length} tool uses`);
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export interface ConversationMessage {
|
|
28
|
+
type: string;
|
|
29
|
+
uuid?: string;
|
|
30
|
+
parentUuid?: string | null;
|
|
31
|
+
sessionId?: string;
|
|
32
|
+
timestamp?: string;
|
|
33
|
+
isSidechain?: boolean;
|
|
34
|
+
agentId?: string;
|
|
35
|
+
userType?: string;
|
|
36
|
+
cwd?: string;
|
|
37
|
+
version?: string;
|
|
38
|
+
gitBranch?: string;
|
|
39
|
+
message?: unknown;
|
|
40
|
+
requestId?: string;
|
|
41
|
+
messageId?: string;
|
|
42
|
+
snapshot?: unknown;
|
|
43
|
+
summary?: string;
|
|
44
|
+
leafUuid?: string;
|
|
45
|
+
subtype?: string;
|
|
46
|
+
level?: string;
|
|
47
|
+
content?: string | unknown[];
|
|
48
|
+
error?: unknown;
|
|
49
|
+
toolUseResult?: unknown;
|
|
50
|
+
[key: string]: unknown;
|
|
51
|
+
}
|
|
52
|
+
export interface Conversation {
|
|
53
|
+
id: string;
|
|
54
|
+
project_path: string;
|
|
55
|
+
source_type?: 'claude-code' | 'codex';
|
|
56
|
+
first_message_at: number;
|
|
57
|
+
last_message_at: number;
|
|
58
|
+
message_count: number;
|
|
59
|
+
git_branch?: string;
|
|
60
|
+
claude_version?: string;
|
|
61
|
+
metadata: Record<string, unknown>;
|
|
62
|
+
created_at: number;
|
|
63
|
+
updated_at: number;
|
|
64
|
+
}
|
|
65
|
+
export interface Message {
|
|
66
|
+
id: string;
|
|
67
|
+
conversation_id: string;
|
|
68
|
+
parent_id?: string;
|
|
69
|
+
message_type: string;
|
|
70
|
+
role?: string;
|
|
71
|
+
content?: string;
|
|
72
|
+
timestamp: number;
|
|
73
|
+
is_sidechain: boolean;
|
|
74
|
+
agent_id?: string;
|
|
75
|
+
request_id?: string;
|
|
76
|
+
git_branch?: string;
|
|
77
|
+
cwd?: string;
|
|
78
|
+
metadata: Record<string, unknown>;
|
|
79
|
+
}
|
|
80
|
+
export interface ToolUse {
|
|
81
|
+
id: string;
|
|
82
|
+
message_id: string;
|
|
83
|
+
tool_name: string;
|
|
84
|
+
tool_input: Record<string, unknown>;
|
|
85
|
+
timestamp: number;
|
|
86
|
+
}
|
|
87
|
+
export interface ToolResult {
|
|
88
|
+
id: string;
|
|
89
|
+
tool_use_id: string;
|
|
90
|
+
message_id: string;
|
|
91
|
+
content?: string;
|
|
92
|
+
is_error: boolean;
|
|
93
|
+
stdout?: string;
|
|
94
|
+
stderr?: string;
|
|
95
|
+
is_image: boolean;
|
|
96
|
+
timestamp: number;
|
|
97
|
+
}
|
|
98
|
+
export interface FileEdit {
|
|
99
|
+
id: string;
|
|
100
|
+
conversation_id: string;
|
|
101
|
+
file_path: string;
|
|
102
|
+
message_id: string;
|
|
103
|
+
backup_version?: number;
|
|
104
|
+
backup_time?: number;
|
|
105
|
+
snapshot_timestamp: number;
|
|
106
|
+
metadata: Record<string, unknown>;
|
|
107
|
+
}
|
|
108
|
+
export interface ThinkingBlock {
|
|
109
|
+
id: string;
|
|
110
|
+
message_id: string;
|
|
111
|
+
thinking_content: string;
|
|
112
|
+
signature?: string;
|
|
113
|
+
timestamp: number;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Information about a parsing error
|
|
117
|
+
*/
|
|
118
|
+
export interface ParseError {
|
|
119
|
+
/** File path where error occurred */
|
|
120
|
+
file: string;
|
|
121
|
+
/** Line number (1-based) */
|
|
122
|
+
line: number;
|
|
123
|
+
/** Error message */
|
|
124
|
+
error: string;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Result of parsing conversation history.
|
|
128
|
+
*
|
|
129
|
+
* Contains all extracted entities from conversation files.
|
|
130
|
+
*/
|
|
131
|
+
export interface ParseResult {
|
|
132
|
+
/** Parsed conversations with metadata */
|
|
133
|
+
conversations: Conversation[];
|
|
134
|
+
/** All messages from conversations */
|
|
135
|
+
messages: Message[];
|
|
136
|
+
/** Tool invocations extracted from assistant messages */
|
|
137
|
+
tool_uses: ToolUse[];
|
|
138
|
+
/** Results from tool executions */
|
|
139
|
+
tool_results: ToolResult[];
|
|
140
|
+
/** File edit records from snapshots */
|
|
141
|
+
file_edits: FileEdit[];
|
|
142
|
+
/** Thinking blocks (Claude's internal reasoning) */
|
|
143
|
+
thinking_blocks: ThinkingBlock[];
|
|
144
|
+
/** Folders that were actually indexed */
|
|
145
|
+
indexed_folders?: string[];
|
|
146
|
+
/** Parsing errors encountered (bad JSON lines, etc.) */
|
|
147
|
+
parse_errors?: ParseError[];
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Parser for Claude Code conversation history.
|
|
151
|
+
*
|
|
152
|
+
* Extracts structured data from JSONL conversation files stored in
|
|
153
|
+
* ~/.claude/projects. Handles both modern and legacy naming conventions.
|
|
154
|
+
*/
|
|
155
|
+
export declare class ConversationParser {
|
|
156
|
+
/**
|
|
157
|
+
* Parse all conversations for a project.
|
|
158
|
+
*
|
|
159
|
+
* Searches for conversation files in Claude's storage directories and
|
|
160
|
+
* parses them into structured entities. Supports filtering by session ID
|
|
161
|
+
* and handles both modern and legacy directory naming conventions.
|
|
162
|
+
*
|
|
163
|
+
* @param projectPath - Absolute path to the project (used for folder lookup)
|
|
164
|
+
* @param sessionId - Optional session ID to filter for a single conversation
|
|
165
|
+
* @param projectIdentifier - Optional identifier to store as project_path
|
|
166
|
+
* @param lastIndexedMs - Optional timestamp to skip unchanged files (mtime)
|
|
167
|
+
* @returns ParseResult containing all extracted entities
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* const parser = new ConversationParser();
|
|
172
|
+
*
|
|
173
|
+
* // Parse all conversations
|
|
174
|
+
* const allResults = parser.parseProject('/Users/me/my-project');
|
|
175
|
+
*
|
|
176
|
+
* // Parse specific session
|
|
177
|
+
* const sessionResults = parser.parseProject('/Users/me/my-project', 'session-123');
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
parseProject(projectPath: string, sessionId?: string, projectIdentifier?: string, lastIndexedMs?: number): ParseResult;
|
|
181
|
+
/**
|
|
182
|
+
* Parse conversations across multiple project paths and merge results.
|
|
183
|
+
*
|
|
184
|
+
* @param projectPaths - Project paths to scan for conversation folders
|
|
185
|
+
* @param sessionId - Optional session ID to filter for a single conversation
|
|
186
|
+
* @param projectIdentifier - Optional identifier to store as project_path
|
|
187
|
+
*/
|
|
188
|
+
parseProjects(projectPaths: string[], sessionId?: string, projectIdentifier?: string, lastIndexedMs?: number): ParseResult;
|
|
189
|
+
private mergeParseResults;
|
|
190
|
+
/**
|
|
191
|
+
* Parse conversations directly from a Claude projects folder.
|
|
192
|
+
*
|
|
193
|
+
* This method is used when you already have the path to the conversation
|
|
194
|
+
* folder (e.g., ~/.claude/projects/-Users-me-my-project) rather than
|
|
195
|
+
* a project path that needs to be converted.
|
|
196
|
+
*
|
|
197
|
+
* @param folderPath - Absolute path to the Claude projects folder
|
|
198
|
+
* @param projectIdentifier - Optional identifier to use as project_path in records (defaults to folder path)
|
|
199
|
+
* @returns ParseResult containing all extracted entities
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```typescript
|
|
203
|
+
* const parser = new ConversationParser();
|
|
204
|
+
* const result = parser.parseFromFolder('~/.claude/projects/-Users-me-my-project');
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
parseFromFolder(folderPath: string, projectIdentifier?: string, lastIndexedMs?: number): ParseResult;
|
|
208
|
+
/**
|
|
209
|
+
* Parse conversations from a Claude projects folder using streaming.
|
|
210
|
+
*
|
|
211
|
+
* This async method uses line-by-line streaming to efficiently handle
|
|
212
|
+
* large JSONL files without loading the entire file into memory.
|
|
213
|
+
* Use this method for large conversation histories.
|
|
214
|
+
*
|
|
215
|
+
* @param folderPath - Absolute path to the Claude projects folder
|
|
216
|
+
* @param projectIdentifier - Optional identifier to use as project_path in records
|
|
217
|
+
* @param lastIndexedMs - Optional timestamp for incremental indexing (skip unchanged files)
|
|
218
|
+
* @returns Promise<ParseResult> containing all extracted entities
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```typescript
|
|
222
|
+
* const parser = new ConversationParser();
|
|
223
|
+
* const result = await parser.parseFromFolderAsync('~/.claude/projects/-Users-me-my-project');
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
parseFromFolderAsync(folderPath: string, projectIdentifier?: string, lastIndexedMs?: number): Promise<ParseResult>;
|
|
227
|
+
/**
|
|
228
|
+
* Parse a single .jsonl file using streaming (async).
|
|
229
|
+
*
|
|
230
|
+
* Uses readline interface with createReadStream to read the file
|
|
231
|
+
* line by line, avoiding loading the entire file into memory.
|
|
232
|
+
*/
|
|
233
|
+
private parseFileAsync;
|
|
234
|
+
/**
|
|
235
|
+
* Parse a single .jsonl file
|
|
236
|
+
*/
|
|
237
|
+
private parseFile;
|
|
238
|
+
/**
|
|
239
|
+
* Pass 1: Extract conversation metadata
|
|
240
|
+
*/
|
|
241
|
+
private extractConversation;
|
|
242
|
+
/**
|
|
243
|
+
* Detect MCP tool usage in conversation messages
|
|
244
|
+
*/
|
|
245
|
+
private detectMcpUsage;
|
|
246
|
+
/**
|
|
247
|
+
* Pass 2: Extract individual messages
|
|
248
|
+
*/
|
|
249
|
+
private extractMessages;
|
|
250
|
+
/**
|
|
251
|
+
* Pass 3: Extract tool uses and results
|
|
252
|
+
*/
|
|
253
|
+
private extractToolCalls;
|
|
254
|
+
/**
|
|
255
|
+
* Pass 4: Extract file edits from snapshots
|
|
256
|
+
*/
|
|
257
|
+
private extractFileEdits;
|
|
258
|
+
/**
|
|
259
|
+
* Pass 5: Extract thinking blocks
|
|
260
|
+
*/
|
|
261
|
+
private extractThinkingBlocks;
|
|
262
|
+
/**
|
|
263
|
+
* Generate path variants to handle potential encoding differences.
|
|
264
|
+
*
|
|
265
|
+
* Claude Code may encode paths differently than expected:
|
|
266
|
+
* - Hyphens in path components might become underscores
|
|
267
|
+
* - Underscores might become hyphens
|
|
268
|
+
* - Dots might become hyphens (legacy)
|
|
269
|
+
*
|
|
270
|
+
* This method generates multiple variants to try when searching for directories.
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* Input: "-Users-myid-GIT-projects-myProject"
|
|
274
|
+
* Output: [
|
|
275
|
+
* "-Users-myid-GIT-projects-myProject", // Original
|
|
276
|
+
* "-Users-myid-GIT_projects-myProject", // Hyphens in components -> underscores
|
|
277
|
+
* "-Users-myid-GIT-projects-myProject", // Dots -> hyphens (legacy)
|
|
278
|
+
* ]
|
|
279
|
+
*/
|
|
280
|
+
private generatePathVariants;
|
|
281
|
+
/**
|
|
282
|
+
* Extract text content from message
|
|
283
|
+
*/
|
|
284
|
+
private extractContent;
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=ConversationParser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConversationParser.d.ts","sourceRoot":"","sources":["../../src/parsers/ConversationParser.ts"],"names":[],"mappings":"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"}
|