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.
Files changed (216) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +349 -0
  3. package/dist/ConversationMemory.d.ts +231 -0
  4. package/dist/ConversationMemory.d.ts.map +1 -0
  5. package/dist/ConversationMemory.js +357 -0
  6. package/dist/ConversationMemory.js.map +1 -0
  7. package/dist/cache/QueryCache.d.ts +215 -0
  8. package/dist/cache/QueryCache.d.ts.map +1 -0
  9. package/dist/cache/QueryCache.js +294 -0
  10. package/dist/cache/QueryCache.js.map +1 -0
  11. package/dist/cli/commands.d.ts +9 -0
  12. package/dist/cli/commands.d.ts.map +1 -0
  13. package/dist/cli/commands.js +954 -0
  14. package/dist/cli/commands.js.map +1 -0
  15. package/dist/cli/help.d.ts +16 -0
  16. package/dist/cli/help.d.ts.map +1 -0
  17. package/dist/cli/help.js +361 -0
  18. package/dist/cli/help.js.map +1 -0
  19. package/dist/cli/index.d.ts +30 -0
  20. package/dist/cli/index.d.ts.map +1 -0
  21. package/dist/cli/index.js +111 -0
  22. package/dist/cli/index.js.map +1 -0
  23. package/dist/context/ContextInjector.d.ts +38 -0
  24. package/dist/context/ContextInjector.d.ts.map +1 -0
  25. package/dist/context/ContextInjector.js +235 -0
  26. package/dist/context/ContextInjector.js.map +1 -0
  27. package/dist/documentation/CodeAnalyzer.d.ts +29 -0
  28. package/dist/documentation/CodeAnalyzer.d.ts.map +1 -0
  29. package/dist/documentation/CodeAnalyzer.js +122 -0
  30. package/dist/documentation/CodeAnalyzer.js.map +1 -0
  31. package/dist/documentation/ConversationAnalyzer.d.ts +19 -0
  32. package/dist/documentation/ConversationAnalyzer.d.ts.map +1 -0
  33. package/dist/documentation/ConversationAnalyzer.js +157 -0
  34. package/dist/documentation/ConversationAnalyzer.js.map +1 -0
  35. package/dist/documentation/CrossReferencer.d.ts +67 -0
  36. package/dist/documentation/CrossReferencer.d.ts.map +1 -0
  37. package/dist/documentation/CrossReferencer.js +247 -0
  38. package/dist/documentation/CrossReferencer.js.map +1 -0
  39. package/dist/documentation/DocumentationGenerator.d.ts +22 -0
  40. package/dist/documentation/DocumentationGenerator.d.ts.map +1 -0
  41. package/dist/documentation/DocumentationGenerator.js +57 -0
  42. package/dist/documentation/DocumentationGenerator.js.map +1 -0
  43. package/dist/documentation/MarkdownFormatter.d.ts +26 -0
  44. package/dist/documentation/MarkdownFormatter.d.ts.map +1 -0
  45. package/dist/documentation/MarkdownFormatter.js +301 -0
  46. package/dist/documentation/MarkdownFormatter.js.map +1 -0
  47. package/dist/documentation/types.d.ts +176 -0
  48. package/dist/documentation/types.d.ts.map +1 -0
  49. package/dist/documentation/types.js +5 -0
  50. package/dist/documentation/types.js.map +1 -0
  51. package/dist/embeddings/ConfigManager.d.ts +46 -0
  52. package/dist/embeddings/ConfigManager.d.ts.map +1 -0
  53. package/dist/embeddings/ConfigManager.js +177 -0
  54. package/dist/embeddings/ConfigManager.js.map +1 -0
  55. package/dist/embeddings/EmbeddingConfig.d.ts +39 -0
  56. package/dist/embeddings/EmbeddingConfig.d.ts.map +1 -0
  57. package/dist/embeddings/EmbeddingConfig.js +132 -0
  58. package/dist/embeddings/EmbeddingConfig.js.map +1 -0
  59. package/dist/embeddings/EmbeddingGenerator.d.ts +51 -0
  60. package/dist/embeddings/EmbeddingGenerator.d.ts.map +1 -0
  61. package/dist/embeddings/EmbeddingGenerator.js +157 -0
  62. package/dist/embeddings/EmbeddingGenerator.js.map +1 -0
  63. package/dist/embeddings/EmbeddingProvider.d.ts +34 -0
  64. package/dist/embeddings/EmbeddingProvider.d.ts.map +1 -0
  65. package/dist/embeddings/EmbeddingProvider.js +6 -0
  66. package/dist/embeddings/EmbeddingProvider.js.map +1 -0
  67. package/dist/embeddings/ModelRegistry.d.ts +48 -0
  68. package/dist/embeddings/ModelRegistry.d.ts.map +1 -0
  69. package/dist/embeddings/ModelRegistry.js +170 -0
  70. package/dist/embeddings/ModelRegistry.js.map +1 -0
  71. package/dist/embeddings/VectorStore.d.ts +114 -0
  72. package/dist/embeddings/VectorStore.d.ts.map +1 -0
  73. package/dist/embeddings/VectorStore.js +393 -0
  74. package/dist/embeddings/VectorStore.js.map +1 -0
  75. package/dist/embeddings/providers/OllamaEmbeddings.d.ts +38 -0
  76. package/dist/embeddings/providers/OllamaEmbeddings.d.ts.map +1 -0
  77. package/dist/embeddings/providers/OllamaEmbeddings.js +125 -0
  78. package/dist/embeddings/providers/OllamaEmbeddings.js.map +1 -0
  79. package/dist/embeddings/providers/OpenAIEmbeddings.d.ts +40 -0
  80. package/dist/embeddings/providers/OpenAIEmbeddings.d.ts.map +1 -0
  81. package/dist/embeddings/providers/OpenAIEmbeddings.js +129 -0
  82. package/dist/embeddings/providers/OpenAIEmbeddings.js.map +1 -0
  83. package/dist/embeddings/providers/TransformersEmbeddings.d.ts +38 -0
  84. package/dist/embeddings/providers/TransformersEmbeddings.d.ts.map +1 -0
  85. package/dist/embeddings/providers/TransformersEmbeddings.js +115 -0
  86. package/dist/embeddings/providers/TransformersEmbeddings.js.map +1 -0
  87. package/dist/handoff/SessionHandoffStore.d.ts +80 -0
  88. package/dist/handoff/SessionHandoffStore.d.ts.map +1 -0
  89. package/dist/handoff/SessionHandoffStore.js +314 -0
  90. package/dist/handoff/SessionHandoffStore.js.map +1 -0
  91. package/dist/index.d.ts +7 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +115 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/mcp-server.d.ts +27 -0
  96. package/dist/mcp-server.d.ts.map +1 -0
  97. package/dist/mcp-server.js +157 -0
  98. package/dist/mcp-server.js.map +1 -0
  99. package/dist/memory/WorkingMemoryStore.d.ts +83 -0
  100. package/dist/memory/WorkingMemoryStore.d.ts.map +1 -0
  101. package/dist/memory/WorkingMemoryStore.js +318 -0
  102. package/dist/memory/WorkingMemoryStore.js.map +1 -0
  103. package/dist/memory/types.d.ts +192 -0
  104. package/dist/memory/types.d.ts.map +1 -0
  105. package/dist/memory/types.js +8 -0
  106. package/dist/memory/types.js.map +1 -0
  107. package/dist/parsers/CodexConversationParser.d.ts +51 -0
  108. package/dist/parsers/CodexConversationParser.d.ts.map +1 -0
  109. package/dist/parsers/CodexConversationParser.js +301 -0
  110. package/dist/parsers/CodexConversationParser.js.map +1 -0
  111. package/dist/parsers/ConversationParser.d.ts +286 -0
  112. package/dist/parsers/ConversationParser.d.ts.map +1 -0
  113. package/dist/parsers/ConversationParser.js +795 -0
  114. package/dist/parsers/ConversationParser.js.map +1 -0
  115. package/dist/parsers/DecisionExtractor.d.ts +144 -0
  116. package/dist/parsers/DecisionExtractor.d.ts.map +1 -0
  117. package/dist/parsers/DecisionExtractor.js +434 -0
  118. package/dist/parsers/DecisionExtractor.js.map +1 -0
  119. package/dist/parsers/GitIntegrator.d.ts +156 -0
  120. package/dist/parsers/GitIntegrator.d.ts.map +1 -0
  121. package/dist/parsers/GitIntegrator.js +348 -0
  122. package/dist/parsers/GitIntegrator.js.map +1 -0
  123. package/dist/parsers/MistakeExtractor.d.ts +151 -0
  124. package/dist/parsers/MistakeExtractor.d.ts.map +1 -0
  125. package/dist/parsers/MistakeExtractor.js +460 -0
  126. package/dist/parsers/MistakeExtractor.js.map +1 -0
  127. package/dist/parsers/RequirementsExtractor.d.ts +166 -0
  128. package/dist/parsers/RequirementsExtractor.d.ts.map +1 -0
  129. package/dist/parsers/RequirementsExtractor.js +338 -0
  130. package/dist/parsers/RequirementsExtractor.js.map +1 -0
  131. package/dist/realtime/ConversationWatcher.d.ts +87 -0
  132. package/dist/realtime/ConversationWatcher.d.ts.map +1 -0
  133. package/dist/realtime/ConversationWatcher.js +204 -0
  134. package/dist/realtime/ConversationWatcher.js.map +1 -0
  135. package/dist/realtime/IncrementalParser.d.ts +83 -0
  136. package/dist/realtime/IncrementalParser.d.ts.map +1 -0
  137. package/dist/realtime/IncrementalParser.js +232 -0
  138. package/dist/realtime/IncrementalParser.js.map +1 -0
  139. package/dist/realtime/LiveExtractor.d.ts +72 -0
  140. package/dist/realtime/LiveExtractor.d.ts.map +1 -0
  141. package/dist/realtime/LiveExtractor.js +288 -0
  142. package/dist/realtime/LiveExtractor.js.map +1 -0
  143. package/dist/search/SemanticSearch.d.ts +121 -0
  144. package/dist/search/SemanticSearch.d.ts.map +1 -0
  145. package/dist/search/SemanticSearch.js +823 -0
  146. package/dist/search/SemanticSearch.js.map +1 -0
  147. package/dist/storage/BackupManager.d.ts +58 -0
  148. package/dist/storage/BackupManager.d.ts.map +1 -0
  149. package/dist/storage/BackupManager.js +223 -0
  150. package/dist/storage/BackupManager.js.map +1 -0
  151. package/dist/storage/ConversationStorage.d.ts +341 -0
  152. package/dist/storage/ConversationStorage.d.ts.map +1 -0
  153. package/dist/storage/ConversationStorage.js +792 -0
  154. package/dist/storage/ConversationStorage.js.map +1 -0
  155. package/dist/storage/DeletionService.d.ts +70 -0
  156. package/dist/storage/DeletionService.d.ts.map +1 -0
  157. package/dist/storage/DeletionService.js +253 -0
  158. package/dist/storage/DeletionService.js.map +1 -0
  159. package/dist/storage/GlobalIndex.d.ts +133 -0
  160. package/dist/storage/GlobalIndex.d.ts.map +1 -0
  161. package/dist/storage/GlobalIndex.js +310 -0
  162. package/dist/storage/GlobalIndex.js.map +1 -0
  163. package/dist/storage/SQLiteManager.d.ts +114 -0
  164. package/dist/storage/SQLiteManager.d.ts.map +1 -0
  165. package/dist/storage/SQLiteManager.js +636 -0
  166. package/dist/storage/SQLiteManager.js.map +1 -0
  167. package/dist/storage/migrations.d.ts +54 -0
  168. package/dist/storage/migrations.d.ts.map +1 -0
  169. package/dist/storage/migrations.js +285 -0
  170. package/dist/storage/migrations.js.map +1 -0
  171. package/dist/storage/schema.sql +436 -0
  172. package/dist/tools/ToolDefinitions.d.ts +946 -0
  173. package/dist/tools/ToolDefinitions.d.ts.map +1 -0
  174. package/dist/tools/ToolDefinitions.js +937 -0
  175. package/dist/tools/ToolDefinitions.js.map +1 -0
  176. package/dist/tools/ToolHandlers.d.ts +791 -0
  177. package/dist/tools/ToolHandlers.d.ts.map +1 -0
  178. package/dist/tools/ToolHandlers.js +3262 -0
  179. package/dist/tools/ToolHandlers.js.map +1 -0
  180. package/dist/types/ToolTypes.d.ts +824 -0
  181. package/dist/types/ToolTypes.d.ts.map +1 -0
  182. package/dist/types/ToolTypes.js +6 -0
  183. package/dist/types/ToolTypes.js.map +1 -0
  184. package/dist/utils/Logger.d.ts +70 -0
  185. package/dist/utils/Logger.d.ts.map +1 -0
  186. package/dist/utils/Logger.js +131 -0
  187. package/dist/utils/Logger.js.map +1 -0
  188. package/dist/utils/McpConfig.d.ts +54 -0
  189. package/dist/utils/McpConfig.d.ts.map +1 -0
  190. package/dist/utils/McpConfig.js +136 -0
  191. package/dist/utils/McpConfig.js.map +1 -0
  192. package/dist/utils/ProjectMigration.d.ts +82 -0
  193. package/dist/utils/ProjectMigration.d.ts.map +1 -0
  194. package/dist/utils/ProjectMigration.js +416 -0
  195. package/dist/utils/ProjectMigration.js.map +1 -0
  196. package/dist/utils/constants.d.ts +75 -0
  197. package/dist/utils/constants.d.ts.map +1 -0
  198. package/dist/utils/constants.js +105 -0
  199. package/dist/utils/constants.js.map +1 -0
  200. package/dist/utils/safeJson.d.ts +37 -0
  201. package/dist/utils/safeJson.d.ts.map +1 -0
  202. package/dist/utils/safeJson.js +48 -0
  203. package/dist/utils/safeJson.js.map +1 -0
  204. package/dist/utils/sanitization.d.ts +45 -0
  205. package/dist/utils/sanitization.d.ts.map +1 -0
  206. package/dist/utils/sanitization.js +153 -0
  207. package/dist/utils/sanitization.js.map +1 -0
  208. package/dist/utils/worktree.d.ts +15 -0
  209. package/dist/utils/worktree.d.ts.map +1 -0
  210. package/dist/utils/worktree.js +86 -0
  211. package/dist/utils/worktree.js.map +1 -0
  212. package/package.json +98 -0
  213. package/scripts/changelog-check.sh +62 -0
  214. package/scripts/check-node.js +17 -0
  215. package/scripts/dev-config.js +56 -0
  216. package/scripts/postinstall.js +117 -0
@@ -0,0 +1,338 @@
1
+ /**
2
+ * Requirements and Validations Extractor - Tracks constraints, dependencies, and testing context.
3
+ *
4
+ * This extractor analyzes conversation messages and tool executions to identify:
5
+ * - Requirements (dependencies, performance, compatibility, business constraints)
6
+ * - Validations (test runs, results, and performance data)
7
+ *
8
+ * Helps document:
9
+ * - What dependencies are required and why
10
+ * - Performance requirements and constraints
11
+ * - Compatibility requirements (versions, platforms)
12
+ * - Business rules and limitations
13
+ * - Test executions and their results
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const extractor = new RequirementsExtractor();
18
+ * const requirements = extractor.extractRequirements(messages);
19
+ * const validations = extractor.extractValidations(toolUses, toolResults, messages);
20
+ *
21
+ * console.log(`Found ${requirements.length} requirements`);
22
+ * console.log(`Found ${validations.length} test validations`);
23
+ * ```
24
+ */
25
+ import { nanoid } from "nanoid";
26
+ /**
27
+ * Extracts requirements and validations from conversation history.
28
+ *
29
+ * Analyzes messages for requirement patterns and tool executions for test results.
30
+ */
31
+ export class RequirementsExtractor {
32
+ // Requirement indicators
33
+ REQUIREMENT_PATTERNS = {
34
+ dependency: [
35
+ /(?:need|require|must use|depends on)\s+(.+?)\s+(?:library|package|module|dependency)/gi,
36
+ /(?:install|add)\s+(.+?)\s+(?:for|to)/gi,
37
+ ],
38
+ performance: [
39
+ /(?:must|should|need to)\s+(?:be|run)\s+(?:faster|slower|within|under)\s+(.+)/gi,
40
+ /response time\s+(?:must|should)\s+(?:be\s+)?(?:under|less than|within)\s+(.+)/gi,
41
+ /(?:latency|throughput|performance)\s+requirement:\s*(.+)/gi,
42
+ ],
43
+ compatibility: [
44
+ /(?:must|should|need to)\s+(?:support|work with|be compatible with)\s+(.+)/gi,
45
+ /(?:requires?|needs?)\s+(.+?)\s+(?:version|or higher|or later)/gi,
46
+ ],
47
+ business: [
48
+ /business requirement:\s*(.+)/gi,
49
+ /(?:must|cannot|can't)\s+(?:exceed|violate|break)\s+(.+)/gi,
50
+ /(?:constraint|limitation):\s*(.+)/gi,
51
+ ],
52
+ };
53
+ // Test/validation indicators
54
+ TEST_PATTERNS = [
55
+ /(?:npm|yarn|pnpm)\s+test/,
56
+ /(?:npm|yarn|pnpm)\s+run\s+test/,
57
+ /pytest/,
58
+ /jest/,
59
+ /mocha/,
60
+ /cargo\s+test/,
61
+ /go\s+test/,
62
+ ];
63
+ /**
64
+ * Get combined output from tool result (stdout + stderr + content)
65
+ * Test output may go to either stdout or stderr depending on the tool
66
+ */
67
+ getToolOutput(result) {
68
+ const parts = [];
69
+ if (result.stdout) {
70
+ parts.push(result.stdout);
71
+ }
72
+ if (result.stderr) {
73
+ parts.push(result.stderr);
74
+ }
75
+ if (result.content) {
76
+ parts.push(result.content);
77
+ }
78
+ return parts.join("\n");
79
+ }
80
+ /**
81
+ * Extract requirements from conversation messages.
82
+ *
83
+ * Analyzes messages using pattern matching to identify four types of requirements:
84
+ * - Dependency: Required libraries, packages, modules
85
+ * - Performance: Speed, latency, throughput constraints
86
+ * - Compatibility: Version requirements, platform support
87
+ * - Business: Business rules, limitations, constraints
88
+ *
89
+ * @param messages - Array of conversation messages to analyze
90
+ * @returns Array of extracted Requirement objects
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * const extractor = new RequirementsExtractor();
95
+ * const requirements = extractor.extractRequirements(messages);
96
+ *
97
+ * // Find all dependency requirements
98
+ * const deps = requirements.filter(r => r.type === 'dependency');
99
+ * deps.forEach(d => console.log(`${d.description} - ${d.rationale}`));
100
+ * ```
101
+ */
102
+ extractRequirements(messages) {
103
+ const requirements = [];
104
+ for (const message of messages) {
105
+ if (!message.content) {
106
+ continue;
107
+ }
108
+ // Check each requirement type
109
+ for (const [type, patterns] of Object.entries(this.REQUIREMENT_PATTERNS)) {
110
+ for (const pattern of patterns) {
111
+ const matches = Array.from(message.content.matchAll(pattern));
112
+ for (const match of matches) {
113
+ const requirement = this.parseRequirement(type, match, message);
114
+ if (requirement) {
115
+ requirements.push(requirement);
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
121
+ return this.deduplicateRequirements(requirements);
122
+ }
123
+ /**
124
+ * Extract validations from tool executions.
125
+ *
126
+ * Analyzes Bash tool uses to identify test command executions and their results.
127
+ * Captures test runs including pass/fail status, performance data, and files tested.
128
+ *
129
+ * Recognized test commands:
130
+ * - npm/yarn/pnpm test
131
+ * - pytest
132
+ * - jest/mocha
133
+ * - cargo test (Rust)
134
+ * - go test (Go)
135
+ *
136
+ * @param toolUses - Array of tool invocations
137
+ * @param toolResults - Array of tool execution results
138
+ * @param messages - Array of conversation messages for context
139
+ * @returns Array of extracted Validation objects
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * const extractor = new RequirementsExtractor();
144
+ * const validations = extractor.extractValidations(toolUses, toolResults, messages);
145
+ *
146
+ * // Find failed tests
147
+ * const failures = validations.filter(v => v.result === 'failed');
148
+ * console.log(`${failures.length} test failures found`);
149
+ * ```
150
+ */
151
+ extractValidations(toolUses, toolResults, messages) {
152
+ const validations = [];
153
+ for (const toolUse of toolUses) {
154
+ // Check if this is a test command
155
+ if (toolUse.tool_name === "Bash") {
156
+ const command = toolUse.tool_input.command;
157
+ if (!command || typeof command !== "string") {
158
+ continue;
159
+ }
160
+ const isTest = this.TEST_PATTERNS.some((pattern) => pattern.test(command));
161
+ if (isTest) {
162
+ // Find corresponding result
163
+ const result = toolResults.find((r) => r.tool_use_id === toolUse.id);
164
+ const message = messages.find((m) => m.id === toolUse.message_id);
165
+ if (result && message) {
166
+ validations.push({
167
+ id: nanoid(),
168
+ conversation_id: message.conversation_id,
169
+ what_was_tested: this.extractWhatWasTested(command, result),
170
+ test_command: command,
171
+ result: this.determineTestResult(result),
172
+ performance_data: this.extractPerformanceData(result),
173
+ files_tested: this.extractTestedFiles(result),
174
+ timestamp: toolUse.timestamp,
175
+ });
176
+ }
177
+ }
178
+ }
179
+ }
180
+ return validations;
181
+ }
182
+ /**
183
+ * Parse a requirement from pattern match
184
+ */
185
+ parseRequirement(type, match, message) {
186
+ const description = match[1]?.trim();
187
+ if (!description) {
188
+ return null;
189
+ }
190
+ if (!message.content) {
191
+ return null;
192
+ }
193
+ // Extract rationale from message context
194
+ const rationale = this.extractRationale(match[0], message.content);
195
+ // Extract affected components
196
+ const components = this.extractAffectedComponents(message);
197
+ return {
198
+ id: nanoid(),
199
+ type,
200
+ description,
201
+ rationale,
202
+ affects_components: components,
203
+ conversation_id: message.conversation_id,
204
+ message_id: message.id,
205
+ timestamp: message.timestamp,
206
+ };
207
+ }
208
+ /**
209
+ * Extract rationale from requirement text
210
+ */
211
+ extractRationale(requirementText, fullContent) {
212
+ // Look for "because", "since", "for" explanations
213
+ const rationaleMatch = requirementText.match(/(?:because|since|for|due to)\s+(.+?)(?:\.|$)/i);
214
+ if (rationaleMatch) {
215
+ return rationaleMatch[1].trim();
216
+ }
217
+ // Look in surrounding context
218
+ const contextMatch = fullContent.match(new RegExp(`${requirementText.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[^.]*?(?:because|since|for|due to)\\s+(.+?)(?:\\.|$)`, "i"));
219
+ return contextMatch?.[1]?.trim();
220
+ }
221
+ /**
222
+ * Extract affected components from message metadata
223
+ */
224
+ extractAffectedComponents(message) {
225
+ const components = [];
226
+ // Common component keywords
227
+ const componentKeywords = [
228
+ "frontend",
229
+ "backend",
230
+ "api",
231
+ "database",
232
+ "auth",
233
+ "ui",
234
+ "server",
235
+ "client",
236
+ ];
237
+ const content = message.content?.toLowerCase() || "";
238
+ for (const keyword of componentKeywords) {
239
+ if (content.includes(keyword)) {
240
+ components.push(keyword);
241
+ }
242
+ }
243
+ return [...new Set(components)];
244
+ }
245
+ /**
246
+ * Extract what was tested from command and result
247
+ */
248
+ extractWhatWasTested(command, result) {
249
+ // Try to extract test file/suite name
250
+ const fileMatch = command.match(/test[/\\](.+?)(?:\s|$)/);
251
+ if (fileMatch) {
252
+ return fileMatch[1];
253
+ }
254
+ // Try to extract from result (check all output sources)
255
+ const resultContent = this.getToolOutput(result);
256
+ const suiteMatch = resultContent.match(/(?:Test Suite|Describe):\s*(.+)/i);
257
+ if (suiteMatch) {
258
+ return suiteMatch[1].trim();
259
+ }
260
+ // Fallback to command
261
+ return command;
262
+ }
263
+ /**
264
+ * Determine test result from tool result
265
+ */
266
+ determineTestResult(result) {
267
+ if (result.is_error) {
268
+ return "error";
269
+ }
270
+ const output = this.getToolOutput(result).toLowerCase();
271
+ // Check for pass indicators
272
+ if (/(?:all tests? passed|✓|✔|success)/i.test(output) ||
273
+ /(?:\d+\s+passed,\s+0\s+failed)/i.test(output)) {
274
+ return "passed";
275
+ }
276
+ // Check for fail indicators
277
+ if (/(?:test failed|✗|✘|failure|failed)/i.test(output) ||
278
+ /(?:\d+\s+failed)/i.test(output)) {
279
+ return "failed";
280
+ }
281
+ // Default to passed if no errors
282
+ return result.is_error ? "error" : "passed";
283
+ }
284
+ /**
285
+ * Extract performance data from test results
286
+ */
287
+ extractPerformanceData(result) {
288
+ const output = this.getToolOutput(result);
289
+ const data = {};
290
+ // Extract timing information
291
+ const timeMatch = output.match(/(\d+(?:\.\d+)?)\s*(ms|s|seconds?|milliseconds?)/i);
292
+ if (timeMatch) {
293
+ const value = parseFloat(timeMatch[1]);
294
+ const unit = timeMatch[2].toLowerCase();
295
+ data.duration_ms = unit.startsWith("s") ? value * 1000 : value;
296
+ }
297
+ // Extract test counts
298
+ const passedMatch = output.match(/(\d+)\s+passed/i);
299
+ if (passedMatch) {
300
+ data.tests_passed = parseInt(passedMatch[1]);
301
+ }
302
+ const failedMatch = output.match(/(\d+)\s+failed/i);
303
+ if (failedMatch) {
304
+ data.tests_failed = parseInt(failedMatch[1]);
305
+ }
306
+ return Object.keys(data).length > 0 ? data : undefined;
307
+ }
308
+ /**
309
+ * Extract files that were tested
310
+ */
311
+ extractTestedFiles(result) {
312
+ const output = this.getToolOutput(result);
313
+ const files = [];
314
+ // Look for file paths
315
+ const filePattern = /(?:PASS|FAIL|ERROR)\s+([\w/.-]+\.(?:test|spec)\.[\w]+)/gi;
316
+ const matches = Array.from(output.matchAll(filePattern));
317
+ for (const match of matches) {
318
+ files.push(match[1]);
319
+ }
320
+ return [...new Set(files)];
321
+ }
322
+ /**
323
+ * Deduplicate similar requirements
324
+ */
325
+ deduplicateRequirements(requirements) {
326
+ const unique = [];
327
+ const seen = new Set();
328
+ for (const req of requirements) {
329
+ const signature = `${req.type}_${req.description.substring(0, 50)}`;
330
+ if (!seen.has(signature)) {
331
+ seen.add(signature);
332
+ unique.push(req);
333
+ }
334
+ }
335
+ return unique;
336
+ }
337
+ }
338
+ //# sourceMappingURL=RequirementsExtractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RequirementsExtractor.js","sourceRoot":"","sources":["../../src/parsers/RequirementsExtractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Conversation Watcher
3
+ *
4
+ * Watches Claude conversation JSONL files for changes using chokidar.
5
+ * Triggers incremental parsing and extraction when files are modified.
6
+ */
7
+ import { EventEmitter } from "events";
8
+ import { IncrementalParser, type ParsedMessage } from "./IncrementalParser.js";
9
+ import { LiveExtractor, type ExtractionResult } from "./LiveExtractor.js";
10
+ import type { Database } from "better-sqlite3";
11
+ import type { RealtimeConfig } from "../memory/types.js";
12
+ /**
13
+ * Events emitted by the watcher
14
+ */
15
+ export interface WatcherEvents {
16
+ message: (filePath: string, message: ParsedMessage) => void;
17
+ extraction: (filePath: string, result: ExtractionResult) => void;
18
+ error: (error: Error) => void;
19
+ started: () => void;
20
+ stopped: () => void;
21
+ }
22
+ /**
23
+ * Watcher status
24
+ */
25
+ export interface WatcherStatus {
26
+ isRunning: boolean;
27
+ watchedPaths: string[];
28
+ trackedFiles: number;
29
+ extractionsPending: number;
30
+ lastExtraction?: number;
31
+ }
32
+ export declare class ConversationWatcher extends EventEmitter {
33
+ private watcher;
34
+ private parser;
35
+ private extractor;
36
+ private config;
37
+ private isRunning;
38
+ private extractionQueue;
39
+ private pendingExtractions;
40
+ private lastExtractionTime?;
41
+ constructor(db: Database, config?: Partial<RealtimeConfig>);
42
+ /**
43
+ * Get default watch paths for Claude conversations
44
+ */
45
+ private getDefaultWatchPaths;
46
+ /**
47
+ * Start watching for conversation changes
48
+ */
49
+ start(): void;
50
+ /**
51
+ * Stop watching
52
+ */
53
+ stop(): Promise<void>;
54
+ /**
55
+ * Handle file change event
56
+ */
57
+ private handleFileChange;
58
+ /**
59
+ * Process file change after debounce
60
+ */
61
+ private processFileChange;
62
+ /**
63
+ * Get current watcher status
64
+ */
65
+ getStatus(): WatcherStatus;
66
+ /**
67
+ * Add a path to watch
68
+ */
69
+ addPath(path: string): void;
70
+ /**
71
+ * Remove a path from watching
72
+ */
73
+ removePath(path: string): void;
74
+ /**
75
+ * Force re-process a specific file
76
+ */
77
+ reprocessFile(filePath: string): Promise<ExtractionResult>;
78
+ /**
79
+ * Get parser for testing
80
+ */
81
+ getParser(): IncrementalParser;
82
+ /**
83
+ * Get extractor for testing
84
+ */
85
+ getExtractor(): LiveExtractor;
86
+ }
87
+ //# sourceMappingURL=ConversationWatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConversationWatcher.d.ts","sourceRoot":"","sources":["../../src/realtime/ConversationWatcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAC5D,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACjE,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,mBAAoB,SAAQ,YAAY;IACnD,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAAyD;IAChF,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,kBAAkB,CAAC,CAAS;gBAExB,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC;IAoB1D;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAK5B;;OAEG;IACH,KAAK,IAAI,IAAI;IAuCb;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAexB;;OAEG;YACW,iBAAiB;IAkC/B;;OAEG;IACH,SAAS,IAAI,aAAa;IAU1B;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAS3B;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAU9B;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAWhE;;OAEG;IACH,SAAS,IAAI,iBAAiB;IAI9B;;OAEG;IACH,YAAY,IAAI,aAAa;CAG9B"}
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Conversation Watcher
3
+ *
4
+ * Watches Claude conversation JSONL files for changes using chokidar.
5
+ * Triggers incremental parsing and extraction when files are modified.
6
+ */
7
+ import { watch } from "chokidar";
8
+ import { join } from "path";
9
+ import { homedir } from "os";
10
+ import { EventEmitter } from "events";
11
+ import { IncrementalParser } from "./IncrementalParser.js";
12
+ import { LiveExtractor } from "./LiveExtractor.js";
13
+ export class ConversationWatcher extends EventEmitter {
14
+ watcher = null;
15
+ parser;
16
+ extractor;
17
+ config;
18
+ isRunning = false;
19
+ extractionQueue = new Map();
20
+ pendingExtractions = 0;
21
+ lastExtractionTime;
22
+ constructor(db, config) {
23
+ super();
24
+ this.config = {
25
+ enabled: true,
26
+ watchPaths: this.getDefaultWatchPaths(),
27
+ extractionInterval: 1000, // Debounce interval
28
+ checkpointInterval: 60000,
29
+ autoRemember: {
30
+ decisions: true,
31
+ fileEdits: true,
32
+ errors: true,
33
+ },
34
+ ...config,
35
+ };
36
+ this.parser = new IncrementalParser();
37
+ this.extractor = new LiveExtractor(db, this.config);
38
+ }
39
+ /**
40
+ * Get default watch paths for Claude conversations
41
+ */
42
+ getDefaultWatchPaths() {
43
+ const claudeProjectsPath = join(homedir(), ".claude", "projects");
44
+ return [claudeProjectsPath];
45
+ }
46
+ /**
47
+ * Start watching for conversation changes
48
+ */
49
+ start() {
50
+ if (this.isRunning) {
51
+ return;
52
+ }
53
+ // Initialize chokidar watcher
54
+ this.watcher = watch(this.config.watchPaths, {
55
+ persistent: true,
56
+ ignoreInitial: true, // Don't process existing files on start
57
+ followSymlinks: false,
58
+ depth: 10, // Limit depth for performance
59
+ awaitWriteFinish: {
60
+ stabilityThreshold: 500,
61
+ pollInterval: 100,
62
+ },
63
+ // Only watch JSONL files
64
+ ignored: (path) => {
65
+ // Only watch .jsonl files in expected locations
66
+ if (path.endsWith(".jsonl")) {
67
+ return false;
68
+ }
69
+ // Allow directories to be traversed
70
+ return !path.includes("projects");
71
+ },
72
+ });
73
+ // Set up event handlers
74
+ this.watcher.on("change", (path) => this.handleFileChange(path));
75
+ this.watcher.on("add", (path) => this.handleFileChange(path));
76
+ this.watcher.on("error", (error) => this.emit("error", error));
77
+ this.isRunning = true;
78
+ this.emit("started");
79
+ console.error(`[Watcher] Started watching ${this.config.watchPaths.length} path(s)`);
80
+ }
81
+ /**
82
+ * Stop watching
83
+ */
84
+ async stop() {
85
+ if (!this.isRunning || !this.watcher) {
86
+ return;
87
+ }
88
+ // Clear pending extractions
89
+ for (const timeout of this.extractionQueue.values()) {
90
+ clearTimeout(timeout);
91
+ }
92
+ this.extractionQueue.clear();
93
+ await this.watcher.close();
94
+ this.watcher = null;
95
+ this.isRunning = false;
96
+ this.emit("stopped");
97
+ console.error("[Watcher] Stopped");
98
+ }
99
+ /**
100
+ * Handle file change event
101
+ */
102
+ handleFileChange(filePath) {
103
+ // Debounce extraction for the same file
104
+ const existingTimeout = this.extractionQueue.get(filePath);
105
+ if (existingTimeout) {
106
+ clearTimeout(existingTimeout);
107
+ }
108
+ const timeout = setTimeout(() => {
109
+ this.processFileChange(filePath);
110
+ this.extractionQueue.delete(filePath);
111
+ }, this.config.extractionInterval);
112
+ this.extractionQueue.set(filePath, timeout);
113
+ }
114
+ /**
115
+ * Process file change after debounce
116
+ */
117
+ async processFileChange(filePath) {
118
+ try {
119
+ // Parse new messages
120
+ const messages = this.parser.parseNewContent(filePath);
121
+ if (messages.length === 0) {
122
+ return;
123
+ }
124
+ // Emit message events
125
+ for (const message of messages) {
126
+ this.emit("message", filePath, message);
127
+ }
128
+ // Extract decisions, file edits, etc.
129
+ this.pendingExtractions++;
130
+ const result = await this.extractor.processMessages(filePath, messages);
131
+ this.pendingExtractions--;
132
+ this.lastExtractionTime = Date.now();
133
+ if (result.decisionsExtracted > 0 || result.filesTracked > 0 || result.errorsDetected > 0) {
134
+ this.emit("extraction", filePath, result);
135
+ console.error(`[Watcher] Extracted from ${filePath}: ` +
136
+ `${result.decisionsExtracted} decisions, ` +
137
+ `${result.filesTracked} files, ` +
138
+ `${result.errorsDetected} errors`);
139
+ }
140
+ }
141
+ catch (error) {
142
+ this.emit("error", error instanceof Error ? error : new Error(String(error)));
143
+ }
144
+ }
145
+ /**
146
+ * Get current watcher status
147
+ */
148
+ getStatus() {
149
+ return {
150
+ isRunning: this.isRunning,
151
+ watchedPaths: this.config.watchPaths,
152
+ trackedFiles: this.parser.getTrackedFiles().length,
153
+ extractionsPending: this.pendingExtractions,
154
+ lastExtraction: this.lastExtractionTime,
155
+ };
156
+ }
157
+ /**
158
+ * Add a path to watch
159
+ */
160
+ addPath(path) {
161
+ if (!this.config.watchPaths.includes(path)) {
162
+ this.config.watchPaths.push(path);
163
+ if (this.watcher) {
164
+ this.watcher.add(path);
165
+ }
166
+ }
167
+ }
168
+ /**
169
+ * Remove a path from watching
170
+ */
171
+ removePath(path) {
172
+ const index = this.config.watchPaths.indexOf(path);
173
+ if (index !== -1) {
174
+ this.config.watchPaths.splice(index, 1);
175
+ if (this.watcher) {
176
+ this.watcher.unwatch(path);
177
+ }
178
+ }
179
+ }
180
+ /**
181
+ * Force re-process a specific file
182
+ */
183
+ async reprocessFile(filePath) {
184
+ // Reset parser tracking for this file
185
+ this.parser.resetFile(filePath);
186
+ // Parse all content
187
+ const messages = this.parser.parseNewContent(filePath);
188
+ // Extract
189
+ return this.extractor.processMessages(filePath, messages);
190
+ }
191
+ /**
192
+ * Get parser for testing
193
+ */
194
+ getParser() {
195
+ return this.parser;
196
+ }
197
+ /**
198
+ * Get extractor for testing
199
+ */
200
+ getExtractor() {
201
+ return this.extractor;
202
+ }
203
+ }
204
+ //# sourceMappingURL=ConversationWatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConversationWatcher.js","sourceRoot":"","sources":["../../src/realtime/ConversationWatcher.ts"],"names":[],"mappings":"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"}