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,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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"}
|