@equilateral_ai/mindmeld 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +300 -0
- package/hooks/README.md +494 -0
- package/hooks/pre-compact.js +392 -0
- package/hooks/session-start.js +264 -0
- package/package.json +90 -0
- package/scripts/harvest.js +561 -0
- package/scripts/init-project.js +437 -0
- package/scripts/inject.js +388 -0
- package/src/collaboration/CollaborationPrompt.js +460 -0
- package/src/core/AlertEngine.js +813 -0
- package/src/core/AlertNotifier.js +363 -0
- package/src/core/CorrelationAnalyzer.js +774 -0
- package/src/core/CurationEngine.js +688 -0
- package/src/core/LLMPatternDetector.js +508 -0
- package/src/core/LoadBearingDetector.js +242 -0
- package/src/core/NotificationService.js +1032 -0
- package/src/core/PatternValidator.js +355 -0
- package/src/core/README.md +160 -0
- package/src/core/RapportOrchestrator.js +446 -0
- package/src/core/RelevanceDetector.js +577 -0
- package/src/core/StandardsIngestion.js +575 -0
- package/src/core/TeamLoadBearingDetector.js +431 -0
- package/src/database/dbOperations.js +105 -0
- package/src/handlers/activity/activityGetMe.js +98 -0
- package/src/handlers/activity/activityGetTeam.js +130 -0
- package/src/handlers/alerts/alertsAcknowledge.js +91 -0
- package/src/handlers/alerts/alertsGet.js +250 -0
- package/src/handlers/collaborators/collaboratorAdd.js +201 -0
- package/src/handlers/collaborators/collaboratorInvite.js +218 -0
- package/src/handlers/collaborators/collaboratorList.js +88 -0
- package/src/handlers/collaborators/collaboratorRemove.js +127 -0
- package/src/handlers/collaborators/inviteAccept.js +122 -0
- package/src/handlers/context/contextGet.js +57 -0
- package/src/handlers/context/invariantsGet.js +74 -0
- package/src/handlers/context/loopsGet.js +82 -0
- package/src/handlers/context/notesCreate.js +74 -0
- package/src/handlers/context/purposeGet.js +78 -0
- package/src/handlers/correlations/correlationsDeveloperGet.js +226 -0
- package/src/handlers/correlations/correlationsGet.js +93 -0
- package/src/handlers/correlations/correlationsProjectGet.js +161 -0
- package/src/handlers/github/githubConnectionStatus.js +49 -0
- package/src/handlers/github/githubDiscoverPatterns.js +364 -0
- package/src/handlers/github/githubOAuthCallback.js +166 -0
- package/src/handlers/github/githubOAuthStart.js +59 -0
- package/src/handlers/github/githubPatternsReview.js +109 -0
- package/src/handlers/github/githubReposList.js +105 -0
- package/src/handlers/helpers/checkSuperAdmin.js +85 -0
- package/src/handlers/helpers/dbOperations.js +53 -0
- package/src/handlers/helpers/errorHandler.js +49 -0
- package/src/handlers/helpers/index.js +106 -0
- package/src/handlers/helpers/lambdaWrapper.js +60 -0
- package/src/handlers/helpers/responseUtil.js +55 -0
- package/src/handlers/helpers/subscriptionTiers.js +1168 -0
- package/src/handlers/notifications/getPreferences.js +84 -0
- package/src/handlers/notifications/sendNotification.js +170 -0
- package/src/handlers/notifications/updatePreferences.js +316 -0
- package/src/handlers/patterns/patternUsagePost.js +182 -0
- package/src/handlers/patterns/patternViolationPost.js +185 -0
- package/src/handlers/projects/projectCreate.js +107 -0
- package/src/handlers/projects/projectDelete.js +82 -0
- package/src/handlers/projects/projectGet.js +95 -0
- package/src/handlers/projects/projectUpdate.js +118 -0
- package/src/handlers/reports/aiLeverage.js +206 -0
- package/src/handlers/reports/engineeringInvestment.js +132 -0
- package/src/handlers/reports/riskForecast.js +186 -0
- package/src/handlers/reports/standardsRoi.js +162 -0
- package/src/handlers/scheduled/analyzeCorrelations.js +178 -0
- package/src/handlers/scheduled/analyzeGitHistory.js +510 -0
- package/src/handlers/scheduled/generateAlerts.js +135 -0
- package/src/handlers/scheduled/refreshActivity.js +21 -0
- package/src/handlers/scheduled/scanCompliance.js +334 -0
- package/src/handlers/sessions/sessionEndPost.js +180 -0
- package/src/handlers/sessions/sessionStandardsPost.js +135 -0
- package/src/handlers/stripe/addonManagePost.js +240 -0
- package/src/handlers/stripe/billingPortalPost.js +93 -0
- package/src/handlers/stripe/enterpriseCheckoutPost.js +272 -0
- package/src/handlers/stripe/seatsUpdatePost.js +185 -0
- package/src/handlers/stripe/subscriptionCancelDelete.js +169 -0
- package/src/handlers/stripe/subscriptionCreatePost.js +221 -0
- package/src/handlers/stripe/subscriptionUpdatePut.js +163 -0
- package/src/handlers/stripe/webhookPost.js +454 -0
- package/src/handlers/users/cognitoPostConfirmation.js +150 -0
- package/src/handlers/users/userEntitlementsGet.js +89 -0
- package/src/handlers/users/userGet.js +114 -0
- package/src/handlers/webhooks/githubWebhook.js +223 -0
- package/src/index.js +969 -0
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLMPatternDetector - LLM-powered pattern detection for Rapport v3
|
|
3
|
+
*
|
|
4
|
+
* Uses AWS Bedrock (Claude) to analyze session transcripts and detect:
|
|
5
|
+
* - Architectural decisions made during coding
|
|
6
|
+
* - Coding patterns and conventions applied
|
|
7
|
+
* - Anti-patterns or standards violations
|
|
8
|
+
* - Semantic intent behind code changes
|
|
9
|
+
*
|
|
10
|
+
* Replaces regex-based pattern detection with semantic understanding.
|
|
11
|
+
*
|
|
12
|
+
* @module LLMPatternDetector
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const { BedrockRuntimeClient, InvokeModelCommand } = require('@aws-sdk/client-bedrock-runtime');
|
|
16
|
+
const fs = require('fs').promises;
|
|
17
|
+
const path = require('path');
|
|
18
|
+
|
|
19
|
+
class LLMPatternDetector {
|
|
20
|
+
constructor(config = {}) {
|
|
21
|
+
this.config = {
|
|
22
|
+
// Bedrock model ID for Claude 3.5 Haiku (cross-region inference profile)
|
|
23
|
+
model: config.model || 'us.anthropic.claude-3-5-haiku-20241022-v1:0',
|
|
24
|
+
maxTokens: config.maxTokens || 2048,
|
|
25
|
+
enabled: config.enabled !== false,
|
|
26
|
+
cacheEnabled: config.cacheEnabled !== false,
|
|
27
|
+
cacheTTL: config.cacheTTL || 300000, // 5 minutes
|
|
28
|
+
region: config.region || 'us-east-2',
|
|
29
|
+
...config
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
this.client = null;
|
|
33
|
+
this.cache = new Map();
|
|
34
|
+
this.patternExamples = null;
|
|
35
|
+
|
|
36
|
+
// Initialize Bedrock client (uses default AWS credentials)
|
|
37
|
+
try {
|
|
38
|
+
this.client = new BedrockRuntimeClient({ region: this.config.region });
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error('[LLMPatternDetector] Failed to initialize Bedrock client:', error.message);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Check if LLM detection is available
|
|
46
|
+
* Uses AWS Bedrock - no API key needed, uses default AWS credentials
|
|
47
|
+
*/
|
|
48
|
+
isAvailable() {
|
|
49
|
+
return this.config.enabled && this.client !== null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Load pattern examples for LLM context
|
|
54
|
+
*/
|
|
55
|
+
async loadPatternExamples() {
|
|
56
|
+
if (this.patternExamples) return this.patternExamples;
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const examplesPath = path.join(__dirname, '../../docs/PATTERN_EXAMPLES.md');
|
|
60
|
+
this.patternExamples = await fs.readFile(examplesPath, 'utf-8');
|
|
61
|
+
} catch (error) {
|
|
62
|
+
this.patternExamples = '';
|
|
63
|
+
}
|
|
64
|
+
return this.patternExamples;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Analyze a Claude Code session transcript for patterns
|
|
69
|
+
*
|
|
70
|
+
* @param {string} transcript - Full session transcript text
|
|
71
|
+
* @param {Object} context - Additional context (project, files, etc.)
|
|
72
|
+
* @returns {Promise<Object>} Detected patterns and analysis
|
|
73
|
+
*/
|
|
74
|
+
async analyzeSessionTranscript(transcript, context = {}) {
|
|
75
|
+
if (!this.isAvailable()) {
|
|
76
|
+
return this.fallbackAnalysis(transcript, context);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Check cache
|
|
80
|
+
const cacheKey = this.getCacheKey(transcript);
|
|
81
|
+
if (this.config.cacheEnabled && this.cache.has(cacheKey)) {
|
|
82
|
+
const cached = this.cache.get(cacheKey);
|
|
83
|
+
if (Date.now() - cached.timestamp < this.config.cacheTTL) {
|
|
84
|
+
return cached.result;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
const result = await this.callLLM(transcript, context);
|
|
90
|
+
|
|
91
|
+
// Cache result
|
|
92
|
+
if (this.config.cacheEnabled) {
|
|
93
|
+
this.cache.set(cacheKey, {
|
|
94
|
+
result,
|
|
95
|
+
timestamp: Date.now()
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return result;
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error('[LLMPatternDetector] Analysis error:', error.message);
|
|
102
|
+
return this.fallbackAnalysis(transcript, context);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Call AWS Bedrock (Claude) for pattern analysis
|
|
108
|
+
*/
|
|
109
|
+
async callLLM(transcript, context) {
|
|
110
|
+
const systemPrompt = await this.buildSystemPrompt(context);
|
|
111
|
+
const userPrompt = this.buildUserPrompt(transcript, context);
|
|
112
|
+
|
|
113
|
+
// Bedrock request body for Claude Messages API
|
|
114
|
+
const requestBody = {
|
|
115
|
+
anthropic_version: 'bedrock-2023-05-31',
|
|
116
|
+
max_tokens: this.config.maxTokens,
|
|
117
|
+
system: systemPrompt,
|
|
118
|
+
messages: [
|
|
119
|
+
{ role: 'user', content: userPrompt }
|
|
120
|
+
]
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const command = new InvokeModelCommand({
|
|
124
|
+
modelId: this.config.model,
|
|
125
|
+
contentType: 'application/json',
|
|
126
|
+
accept: 'application/json',
|
|
127
|
+
body: JSON.stringify(requestBody)
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const response = await this.client.send(command);
|
|
131
|
+
const responseBody = JSON.parse(new TextDecoder().decode(response.body));
|
|
132
|
+
|
|
133
|
+
const content = responseBody.content?.[0]?.text || '';
|
|
134
|
+
return this.parseResponse(content);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Build system prompt for pattern detection
|
|
139
|
+
*/
|
|
140
|
+
async buildSystemPrompt(context) {
|
|
141
|
+
const examples = await this.loadPatternExamples();
|
|
142
|
+
const techStack = context.techStack || 'Node.js, AWS Lambda, PostgreSQL, React';
|
|
143
|
+
|
|
144
|
+
return `You are an expert software architecture analyst for MindMeld/Rapport, a team knowledge sharing platform.
|
|
145
|
+
|
|
146
|
+
Your task is to analyze Claude Code session transcripts and extract:
|
|
147
|
+
1. **Architectural Decisions**: Key decisions made about code structure, patterns, or approaches
|
|
148
|
+
2. **Coding Patterns**: Reusable patterns applied (e.g., error handling, database access, API design)
|
|
149
|
+
3. **Anti-Patterns**: Potential violations of best practices or standards
|
|
150
|
+
4. **Invariants**: Rules that should always be followed based on this session
|
|
151
|
+
|
|
152
|
+
Context about the codebase:
|
|
153
|
+
- Tech stack: ${techStack}
|
|
154
|
+
- Standards: .equilateral-standards/ (serverless-saas-aws, tim-combo pattern)
|
|
155
|
+
|
|
156
|
+
Key patterns to detect:
|
|
157
|
+
- Lambda database connections (MUST use cached single client, NEVER pools)
|
|
158
|
+
- API Gateway CORS (NEVER use DefaultAuthorizer)
|
|
159
|
+
- Handler pattern (wrapHandler, executeQuery, createSuccessResponse)
|
|
160
|
+
- Business-scoped IDs (NOT random UUIDs)
|
|
161
|
+
- SSM parameters (NEVER fetch at runtime, use env vars)
|
|
162
|
+
|
|
163
|
+
${examples ? `\n## Pattern Examples Reference:\n${examples.substring(0, 8000)}` : ''}
|
|
164
|
+
|
|
165
|
+
Respond ONLY with valid JSON in this exact format:
|
|
166
|
+
{
|
|
167
|
+
"patterns": [
|
|
168
|
+
{
|
|
169
|
+
"element": "Pattern name",
|
|
170
|
+
"type": "standard|anti_pattern|invariant|architectural_decision",
|
|
171
|
+
"intent": "What this pattern achieves",
|
|
172
|
+
"evidence": "Quote or reference from transcript",
|
|
173
|
+
"confidence": 0.95,
|
|
174
|
+
"severity": "info|warning|critical",
|
|
175
|
+
"category": "database|api|security|performance|architecture"
|
|
176
|
+
}
|
|
177
|
+
],
|
|
178
|
+
"summary": "Brief summary of key patterns detected",
|
|
179
|
+
"recommendations": ["Actionable recommendations"],
|
|
180
|
+
"violations": [
|
|
181
|
+
{
|
|
182
|
+
"standard": "Which standard was violated",
|
|
183
|
+
"description": "What the violation is",
|
|
184
|
+
"fix": "How to fix it"
|
|
185
|
+
}
|
|
186
|
+
]
|
|
187
|
+
}`;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Build user prompt with transcript
|
|
192
|
+
*/
|
|
193
|
+
buildUserPrompt(transcript, context) {
|
|
194
|
+
// Truncate very long transcripts to stay within token limits
|
|
195
|
+
const maxLength = 50000;
|
|
196
|
+
const truncated = transcript.length > maxLength
|
|
197
|
+
? transcript.substring(0, maxLength) + '\n\n[... transcript truncated ...]'
|
|
198
|
+
: transcript;
|
|
199
|
+
|
|
200
|
+
const projectName = context.projectName || 'Unknown';
|
|
201
|
+
const filesChanged = context.filesChanged?.join(', ') || 'Unknown';
|
|
202
|
+
|
|
203
|
+
return `Analyze this Claude Code session transcript for patterns, decisions, and potential violations:
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
PROJECT: ${projectName}
|
|
207
|
+
FILES CHANGED: ${filesChanged}
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
TRANSCRIPT:
|
|
211
|
+
${truncated}
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
Extract all architectural decisions, coding patterns, anti-patterns, and invariants from this session. Focus on:
|
|
216
|
+
1. Database connection patterns
|
|
217
|
+
2. Error handling approaches
|
|
218
|
+
3. API design decisions
|
|
219
|
+
4. Security considerations
|
|
220
|
+
5. Performance patterns
|
|
221
|
+
|
|
222
|
+
Respond with JSON only.`;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Parse LLM response into structured data
|
|
227
|
+
*/
|
|
228
|
+
parseResponse(content) {
|
|
229
|
+
try {
|
|
230
|
+
// Extract JSON from response (handle markdown code blocks)
|
|
231
|
+
let jsonStr = content;
|
|
232
|
+
const jsonMatch = content.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
233
|
+
if (jsonMatch) {
|
|
234
|
+
jsonStr = jsonMatch[1];
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const parsed = JSON.parse(jsonStr.trim());
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
success: true,
|
|
241
|
+
source: 'llm',
|
|
242
|
+
model: this.config.model,
|
|
243
|
+
timestamp: new Date().toISOString(),
|
|
244
|
+
...parsed
|
|
245
|
+
};
|
|
246
|
+
} catch (error) {
|
|
247
|
+
console.error('[LLMPatternDetector] Failed to parse response:', error.message);
|
|
248
|
+
return {
|
|
249
|
+
success: false,
|
|
250
|
+
source: 'llm',
|
|
251
|
+
error: 'Failed to parse LLM response',
|
|
252
|
+
rawContent: content.substring(0, 500),
|
|
253
|
+
patterns: [],
|
|
254
|
+
violations: []
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Fallback to regex-based analysis when LLM unavailable
|
|
261
|
+
*/
|
|
262
|
+
fallbackAnalysis(transcript, context) {
|
|
263
|
+
const patterns = [];
|
|
264
|
+
|
|
265
|
+
// Basic regex patterns (existing logic)
|
|
266
|
+
const patternMatchers = [
|
|
267
|
+
{
|
|
268
|
+
regex: /wrapHandler/g,
|
|
269
|
+
element: 'Lambda Handler Pattern',
|
|
270
|
+
type: 'standard',
|
|
271
|
+
category: 'api',
|
|
272
|
+
intent: 'Consistent error handling and logging for Lambda functions'
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
regex: /executeQuery/g,
|
|
276
|
+
element: 'Database Query Pattern',
|
|
277
|
+
type: 'standard',
|
|
278
|
+
category: 'database',
|
|
279
|
+
intent: 'Standardized database query execution with error handling'
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
regex: /createSuccessResponse/g,
|
|
283
|
+
element: 'API Response Pattern',
|
|
284
|
+
type: 'standard',
|
|
285
|
+
category: 'api',
|
|
286
|
+
intent: 'Consistent API response format'
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
regex: /new Pool\(|createPool/g,
|
|
290
|
+
element: 'Connection Pool in Lambda',
|
|
291
|
+
type: 'anti_pattern',
|
|
292
|
+
category: 'database',
|
|
293
|
+
severity: 'critical',
|
|
294
|
+
intent: 'Connection pools are wasteful in Lambda - use cached single client'
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
regex: /ssm\.getParameter|GetParameter/g,
|
|
298
|
+
element: 'SSM Runtime Fetch',
|
|
299
|
+
type: 'anti_pattern',
|
|
300
|
+
category: 'performance',
|
|
301
|
+
severity: 'critical',
|
|
302
|
+
intent: 'SSM at runtime costs $25/month per million - use env vars'
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
regex: /DefaultAuthorizer/g,
|
|
306
|
+
element: 'DefaultAuthorizer Usage',
|
|
307
|
+
type: 'anti_pattern',
|
|
308
|
+
category: 'api',
|
|
309
|
+
severity: 'critical',
|
|
310
|
+
intent: 'DefaultAuthorizer breaks CORS preflight'
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
regex: /uuid(?:v4)?|randomUUID/gi,
|
|
314
|
+
element: 'Random UUID for Business ID',
|
|
315
|
+
type: 'anti_pattern',
|
|
316
|
+
category: 'architecture',
|
|
317
|
+
severity: 'warning',
|
|
318
|
+
intent: 'Use business-scoped IDs, not random UUIDs'
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
regex: /console\.log\s*\(/g,
|
|
322
|
+
element: 'Console.log in Production',
|
|
323
|
+
type: 'anti_pattern',
|
|
324
|
+
category: 'performance',
|
|
325
|
+
severity: 'warning',
|
|
326
|
+
intent: 'Debug logging should be removed from production code'
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
regex: /(password|secret|key)\s*[:=]\s*['"][^'"]{8,}['"]/gi,
|
|
330
|
+
element: 'Hardcoded Secret',
|
|
331
|
+
type: 'anti_pattern',
|
|
332
|
+
category: 'security',
|
|
333
|
+
severity: 'critical',
|
|
334
|
+
intent: 'Secrets must come from environment variables, never hardcoded'
|
|
335
|
+
}
|
|
336
|
+
];
|
|
337
|
+
|
|
338
|
+
for (const matcher of patternMatchers) {
|
|
339
|
+
const matches = transcript.match(matcher.regex);
|
|
340
|
+
if (matches && matches.length > 0) {
|
|
341
|
+
patterns.push({
|
|
342
|
+
element: matcher.element,
|
|
343
|
+
type: matcher.type,
|
|
344
|
+
intent: matcher.intent,
|
|
345
|
+
category: matcher.category,
|
|
346
|
+
severity: matcher.severity || 'info',
|
|
347
|
+
confidence: 0.7, // Lower confidence for regex matches
|
|
348
|
+
evidence: `Found ${matches.length} occurrence(s)`,
|
|
349
|
+
matchCount: matches.length
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return {
|
|
355
|
+
success: true,
|
|
356
|
+
source: 'fallback_regex',
|
|
357
|
+
timestamp: new Date().toISOString(),
|
|
358
|
+
patterns,
|
|
359
|
+
summary: `Detected ${patterns.length} patterns using regex fallback`,
|
|
360
|
+
violations: patterns.filter(p => p.type === 'anti_pattern'),
|
|
361
|
+
recommendations: []
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Generate cache key from transcript
|
|
367
|
+
*/
|
|
368
|
+
getCacheKey(transcript) {
|
|
369
|
+
// Simple hash based on length and sample content
|
|
370
|
+
const sample = transcript.substring(0, 1000) + transcript.slice(-1000);
|
|
371
|
+
let hash = 0;
|
|
372
|
+
for (let i = 0; i < sample.length; i++) {
|
|
373
|
+
const char = sample.charCodeAt(i);
|
|
374
|
+
hash = ((hash << 5) - hash) + char;
|
|
375
|
+
hash = hash & hash;
|
|
376
|
+
}
|
|
377
|
+
return `session_${hash}_${transcript.length}`;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Analyze code content for patterns (standalone file analysis)
|
|
382
|
+
*/
|
|
383
|
+
async analyzeCode(code, filename, context = {}) {
|
|
384
|
+
if (!this.isAvailable()) {
|
|
385
|
+
return this.fallbackAnalysis(code, context);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
const codeSnippet = code.substring(0, 10000);
|
|
389
|
+
|
|
390
|
+
const prompt = `Analyze this code file for patterns and potential issues:
|
|
391
|
+
|
|
392
|
+
FILE: ${filename}
|
|
393
|
+
CONTEXT: ${context.projectName || 'Unknown project'}
|
|
394
|
+
|
|
395
|
+
\`\`\`
|
|
396
|
+
${codeSnippet}
|
|
397
|
+
\`\`\`
|
|
398
|
+
|
|
399
|
+
Focus on:
|
|
400
|
+
1. Adherence to Lambda database standards (no pools, cached client)
|
|
401
|
+
2. Error handling patterns
|
|
402
|
+
3. Security issues (hardcoded secrets, SQL injection)
|
|
403
|
+
4. Performance anti-patterns
|
|
404
|
+
|
|
405
|
+
Respond with JSON containing patterns and violations.`;
|
|
406
|
+
|
|
407
|
+
try {
|
|
408
|
+
const systemPrompt = await this.buildSystemPrompt(context);
|
|
409
|
+
|
|
410
|
+
const requestBody = {
|
|
411
|
+
anthropic_version: 'bedrock-2023-05-31',
|
|
412
|
+
max_tokens: 1024,
|
|
413
|
+
system: systemPrompt,
|
|
414
|
+
messages: [{ role: 'user', content: prompt }]
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
const command = new InvokeModelCommand({
|
|
418
|
+
modelId: this.config.model,
|
|
419
|
+
contentType: 'application/json',
|
|
420
|
+
accept: 'application/json',
|
|
421
|
+
body: JSON.stringify(requestBody)
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
const response = await this.client.send(command);
|
|
425
|
+
const responseBody = JSON.parse(new TextDecoder().decode(response.body));
|
|
426
|
+
|
|
427
|
+
return this.parseResponse(responseBody.content?.[0]?.text || '');
|
|
428
|
+
} catch (error) {
|
|
429
|
+
console.error('[LLMPatternDetector] Code analysis error:', error.message);
|
|
430
|
+
return this.fallbackAnalysis(code, context);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Extract invariants from session patterns
|
|
436
|
+
* Returns patterns that should become team invariants
|
|
437
|
+
*/
|
|
438
|
+
extractInvariants(analysisResult) {
|
|
439
|
+
if (!analysisResult.success || !analysisResult.patterns) {
|
|
440
|
+
return [];
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return analysisResult.patterns
|
|
444
|
+
.filter(p =>
|
|
445
|
+
p.type === 'invariant' ||
|
|
446
|
+
(p.type === 'anti_pattern' && p.severity === 'critical') ||
|
|
447
|
+
(p.confidence >= 0.9 && p.type === 'standard')
|
|
448
|
+
)
|
|
449
|
+
.map(p => ({
|
|
450
|
+
element: p.element,
|
|
451
|
+
rule: p.intent,
|
|
452
|
+
severity: p.severity || 'info',
|
|
453
|
+
source: 'llm_detected',
|
|
454
|
+
confidence: p.confidence,
|
|
455
|
+
evidence: p.evidence
|
|
456
|
+
}));
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Summarize session for team learning
|
|
461
|
+
*/
|
|
462
|
+
async summarizeSession(transcript, context = {}) {
|
|
463
|
+
if (!this.isAvailable()) {
|
|
464
|
+
return { summary: 'LLM not available for summarization' };
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
const prompt = `Summarize this Claude Code session in 2-3 sentences, focusing on:
|
|
468
|
+
1. What was accomplished
|
|
469
|
+
2. Key architectural decisions made
|
|
470
|
+
3. Any patterns or invariants established
|
|
471
|
+
|
|
472
|
+
TRANSCRIPT:
|
|
473
|
+
${transcript.substring(0, 20000)}
|
|
474
|
+
|
|
475
|
+
Respond with a JSON object: { "summary": "...", "keyDecisions": ["..."], "newPatterns": ["..."] }`;
|
|
476
|
+
|
|
477
|
+
try {
|
|
478
|
+
const requestBody = {
|
|
479
|
+
anthropic_version: 'bedrock-2023-05-31',
|
|
480
|
+
max_tokens: 512,
|
|
481
|
+
messages: [{ role: 'user', content: prompt }]
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
const command = new InvokeModelCommand({
|
|
485
|
+
modelId: this.config.model,
|
|
486
|
+
contentType: 'application/json',
|
|
487
|
+
accept: 'application/json',
|
|
488
|
+
body: JSON.stringify(requestBody)
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
const response = await this.client.send(command);
|
|
492
|
+
const responseBody = JSON.parse(new TextDecoder().decode(response.body));
|
|
493
|
+
|
|
494
|
+
return this.parseResponse(responseBody.content?.[0]?.text || '');
|
|
495
|
+
} catch (error) {
|
|
496
|
+
return { summary: 'Failed to summarize session', error: error.message };
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Clear cache (for testing or memory management)
|
|
502
|
+
*/
|
|
503
|
+
clearCache() {
|
|
504
|
+
this.cache.clear();
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
module.exports = { LLMPatternDetector };
|