@tonycasey/lisa 0.5.13
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 +42 -0
- package/dist/cli.js +390 -0
- package/dist/lib/interfaces/IDockerClient.js +2 -0
- package/dist/lib/interfaces/IMcpClient.js +2 -0
- package/dist/lib/interfaces/IServices.js +2 -0
- package/dist/lib/interfaces/ITemplateCopier.js +2 -0
- package/dist/lib/mcp.js +35 -0
- package/dist/lib/services.js +57 -0
- package/dist/package.json +36 -0
- package/dist/templates/agents/.sample.env +12 -0
- package/dist/templates/agents/docs/STORAGE_SETUP.md +161 -0
- package/dist/templates/agents/skills/common/group-id.js +193 -0
- package/dist/templates/agents/skills/init-review/SKILL.md +119 -0
- package/dist/templates/agents/skills/init-review/scripts/ai-enrich.js +258 -0
- package/dist/templates/agents/skills/init-review/scripts/init-review.js +769 -0
- package/dist/templates/agents/skills/lisa/SKILL.md +92 -0
- package/dist/templates/agents/skills/lisa/cache/.gitkeep +0 -0
- package/dist/templates/agents/skills/lisa/scripts/storage.js +374 -0
- package/dist/templates/agents/skills/memory/SKILL.md +31 -0
- package/dist/templates/agents/skills/memory/scripts/memory.js +533 -0
- package/dist/templates/agents/skills/prompt/SKILL.md +19 -0
- package/dist/templates/agents/skills/prompt/scripts/prompt.js +184 -0
- package/dist/templates/agents/skills/tasks/SKILL.md +31 -0
- package/dist/templates/agents/skills/tasks/scripts/tasks.js +489 -0
- package/dist/templates/claude/config.js +40 -0
- package/dist/templates/claude/hooks/README.md +158 -0
- package/dist/templates/claude/hooks/common/complexity-rater.js +290 -0
- package/dist/templates/claude/hooks/common/context.js +263 -0
- package/dist/templates/claude/hooks/common/group-id.js +188 -0
- package/dist/templates/claude/hooks/common/mcp-client.js +131 -0
- package/dist/templates/claude/hooks/common/transcript-parser.js +256 -0
- package/dist/templates/claude/hooks/common/zep-client.js +175 -0
- package/dist/templates/claude/hooks/session-start.js +401 -0
- package/dist/templates/claude/hooks/session-stop-worker.js +341 -0
- package/dist/templates/claude/hooks/session-stop.js +122 -0
- package/dist/templates/claude/hooks/user-prompt-submit.js +256 -0
- package/dist/templates/claude/settings.json +46 -0
- package/dist/templates/docker/.env.lisa.example +17 -0
- package/dist/templates/docker/docker-compose.graphiti.yml +45 -0
- package/dist/templates/rules/shared/clean-architecture.md +333 -0
- package/dist/templates/rules/shared/code-quality-rules.md +469 -0
- package/dist/templates/rules/shared/git-rules.md +64 -0
- package/dist/templates/rules/shared/testing-principles.md +469 -0
- package/dist/templates/rules/typescript/coding-standards.md +751 -0
- package/dist/templates/rules/typescript/testing.md +629 -0
- package/dist/templates/rules/typescript/typescript-config-guide.md +465 -0
- package/package.json +64 -0
- package/scripts/postinstall.js +710 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* ai-enrich.ts - Background AI enrichment worker for init-review
|
|
5
|
+
*
|
|
6
|
+
* This script runs in the background after static analysis completes.
|
|
7
|
+
* It submits the codebase summary to Graphiti MCP for AI-powered entity extraction,
|
|
8
|
+
* generating richer context about the project architecture and patterns.
|
|
9
|
+
*
|
|
10
|
+
* Usage (spawned by init-review.ts or postinstall.js):
|
|
11
|
+
* node ai-enrich.js <projectRoot> <agentsDir>
|
|
12
|
+
*
|
|
13
|
+
* The worker:
|
|
14
|
+
* 1. Reads static analysis from .agents/.init-review-static.json
|
|
15
|
+
* 2. Submits to Graphiti MCP for enrichment
|
|
16
|
+
* 3. Updates memory with enriched summary
|
|
17
|
+
* 4. Updates marker file with enriched: true
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
const fs = require('fs');
|
|
21
|
+
const path = require('path');
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// Configuration
|
|
24
|
+
// ============================================================================
|
|
25
|
+
const args = process.argv.slice(2);
|
|
26
|
+
const projectRoot = args[0] || process.cwd();
|
|
27
|
+
const agentsDir = args[1] || path.join(projectRoot, '.agents');
|
|
28
|
+
const STATIC_ANALYSIS_FILE = path.join(agentsDir, '.init-review-static.json');
|
|
29
|
+
const MARKER_FILE = path.join(agentsDir, '.init-review-done');
|
|
30
|
+
const LOG_FILE = path.join(agentsDir, '.init-review-enrich.log');
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Logging
|
|
33
|
+
// ============================================================================
|
|
34
|
+
function log(message) {
|
|
35
|
+
const timestamp = new Date().toISOString();
|
|
36
|
+
const line = `[${timestamp}] ${message}\n`;
|
|
37
|
+
fs.appendFileSync(LOG_FILE, line);
|
|
38
|
+
}
|
|
39
|
+
function loadConfig() {
|
|
40
|
+
const envPath = path.join(agentsDir, 'skills', '.env');
|
|
41
|
+
const config = {
|
|
42
|
+
endpoint: 'http://localhost:8010/mcp/',
|
|
43
|
+
groupId: path.basename(projectRoot).toLowerCase().replace(/[^a-z0-9-]/g, '-'),
|
|
44
|
+
zepApiKey: '',
|
|
45
|
+
};
|
|
46
|
+
try {
|
|
47
|
+
if (fs.existsSync(envPath)) {
|
|
48
|
+
const content = fs.readFileSync(envPath, 'utf8');
|
|
49
|
+
const lines = content.split('\n');
|
|
50
|
+
for (const line of lines) {
|
|
51
|
+
const [key, value] = line.split('=').map((s) => s.trim());
|
|
52
|
+
if (key === 'GRAPHITI_ENDPOINT')
|
|
53
|
+
config.endpoint = value;
|
|
54
|
+
if (key === 'GRAPHITI_GROUP_ID')
|
|
55
|
+
config.groupId = value;
|
|
56
|
+
if (key === 'ZEP_API_KEY')
|
|
57
|
+
config.zepApiKey = value;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (_) {
|
|
62
|
+
// Use defaults
|
|
63
|
+
}
|
|
64
|
+
// Also check environment variable
|
|
65
|
+
if (!config.zepApiKey) {
|
|
66
|
+
config.zepApiKey = process.env.ZEP_API_KEY || '';
|
|
67
|
+
}
|
|
68
|
+
return config;
|
|
69
|
+
}
|
|
70
|
+
async function initializeMCP(endpoint, apiKey) {
|
|
71
|
+
try {
|
|
72
|
+
const body = {
|
|
73
|
+
jsonrpc: '2.0',
|
|
74
|
+
id: 'init',
|
|
75
|
+
method: 'initialize',
|
|
76
|
+
params: {
|
|
77
|
+
protocolVersion: '2024-11-05',
|
|
78
|
+
capabilities: {},
|
|
79
|
+
clientInfo: { name: 'init-review-enrich', version: '1.0.0' },
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
const headers = {
|
|
83
|
+
'Content-Type': 'application/json',
|
|
84
|
+
Accept: 'application/json, text/event-stream',
|
|
85
|
+
};
|
|
86
|
+
// Add Authorization header for Zep Cloud endpoints
|
|
87
|
+
if (apiKey && endpoint.includes('getzep.com')) {
|
|
88
|
+
headers['Authorization'] = `Api-Key ${apiKey}`;
|
|
89
|
+
}
|
|
90
|
+
const resp = await fetch(endpoint, {
|
|
91
|
+
method: 'POST',
|
|
92
|
+
headers,
|
|
93
|
+
body: JSON.stringify(body),
|
|
94
|
+
signal: AbortSignal.timeout(10000),
|
|
95
|
+
});
|
|
96
|
+
if (!resp.ok) {
|
|
97
|
+
log(`MCP init failed: HTTP ${resp.status}`);
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const sessionId = resp.headers.get('mcp-session-id');
|
|
101
|
+
return sessionId;
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
log(`MCP init error: ${err instanceof Error ? err.message : err}`);
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async function addEnrichedMemory(endpoint, sessionId, summary, groupId, apiKey) {
|
|
109
|
+
try {
|
|
110
|
+
const payload = {
|
|
111
|
+
jsonrpc: '2.0',
|
|
112
|
+
id: '1',
|
|
113
|
+
method: 'tools/call',
|
|
114
|
+
params: {
|
|
115
|
+
name: 'add_memory',
|
|
116
|
+
arguments: {
|
|
117
|
+
name: 'INIT-REVIEW (AI Enriched): ' + summary.slice(0, 60),
|
|
118
|
+
episode_body: `INIT-REVIEW: ${summary}`,
|
|
119
|
+
source: 'skill:init-review-enrich',
|
|
120
|
+
group_id: groupId,
|
|
121
|
+
tags: ['type:init-review', 'scope:codebase', 'ai:enriched'],
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
const headers = {
|
|
126
|
+
'Content-Type': 'application/json',
|
|
127
|
+
'MCP-SESSION-ID': sessionId,
|
|
128
|
+
Accept: 'application/json, text/event-stream',
|
|
129
|
+
};
|
|
130
|
+
// Add Authorization header for Zep Cloud endpoints
|
|
131
|
+
if (apiKey && endpoint.includes('getzep.com')) {
|
|
132
|
+
headers['Authorization'] = `Api-Key ${apiKey}`;
|
|
133
|
+
}
|
|
134
|
+
const resp = await fetch(endpoint, {
|
|
135
|
+
method: 'POST',
|
|
136
|
+
headers,
|
|
137
|
+
body: JSON.stringify(payload),
|
|
138
|
+
signal: AbortSignal.timeout(30000),
|
|
139
|
+
});
|
|
140
|
+
if (!resp.ok) {
|
|
141
|
+
log(`Add memory failed: HTTP ${resp.status}`);
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
log(`Add memory error: ${err instanceof Error ? err.message : err}`);
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function generateEnrichedSummary(analysis) {
|
|
152
|
+
const r = analysis.result;
|
|
153
|
+
const parts = [];
|
|
154
|
+
// Project identity
|
|
155
|
+
parts.push(`Project: ${r.project.name}`);
|
|
156
|
+
// Tech stack
|
|
157
|
+
const stack = [r.codebase.language];
|
|
158
|
+
if (r.codebase.framework)
|
|
159
|
+
stack.push(r.codebase.framework);
|
|
160
|
+
parts.push(`Stack: ${stack.join(' + ')}`);
|
|
161
|
+
// Architecture
|
|
162
|
+
if (r.patterns.architecture) {
|
|
163
|
+
parts.push(`Architecture: ${r.patterns.architecture}`);
|
|
164
|
+
}
|
|
165
|
+
// Key modules
|
|
166
|
+
if (r.structure.mainModules.length > 0) {
|
|
167
|
+
parts.push(`Core modules: ${r.structure.mainModules.slice(0, 5).join(', ')}`);
|
|
168
|
+
}
|
|
169
|
+
// Entry points
|
|
170
|
+
if (r.structure.entryPoints.length > 0) {
|
|
171
|
+
parts.push(`Entry: ${r.structure.entryPoints.slice(0, 3).join(', ')}`);
|
|
172
|
+
}
|
|
173
|
+
// Key dependencies
|
|
174
|
+
if (r.dependencies.noteworthy.length > 0) {
|
|
175
|
+
parts.push(`Key deps: ${r.dependencies.noteworthy.slice(0, 5).join(', ')}`);
|
|
176
|
+
}
|
|
177
|
+
// Build & test
|
|
178
|
+
if (r.codebase.buildTools.length > 0) {
|
|
179
|
+
parts.push(`Build: ${r.codebase.buildTools.join(', ')}`);
|
|
180
|
+
}
|
|
181
|
+
if (r.patterns.testing) {
|
|
182
|
+
parts.push(`Testing: ${r.patterns.testing}`);
|
|
183
|
+
}
|
|
184
|
+
// Metrics
|
|
185
|
+
parts.push(`Size: ${r.metrics.fileCount} files${r.metrics.hasTests ? ', has tests' : ''}`);
|
|
186
|
+
return parts.join('. ') + '.';
|
|
187
|
+
}
|
|
188
|
+
// ============================================================================
|
|
189
|
+
// Marker File
|
|
190
|
+
// ============================================================================
|
|
191
|
+
function updateMarker(enriched) {
|
|
192
|
+
try {
|
|
193
|
+
let content = {};
|
|
194
|
+
if (fs.existsSync(MARKER_FILE)) {
|
|
195
|
+
content = JSON.parse(fs.readFileSync(MARKER_FILE, 'utf8'));
|
|
196
|
+
}
|
|
197
|
+
content.enriched = enriched;
|
|
198
|
+
content.enrichedAt = new Date().toISOString();
|
|
199
|
+
fs.writeFileSync(MARKER_FILE, JSON.stringify(content, null, 2));
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
log(`Failed to update marker: ${err instanceof Error ? err.message : err}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// ============================================================================
|
|
206
|
+
// Main
|
|
207
|
+
// ============================================================================
|
|
208
|
+
async function main() {
|
|
209
|
+
log('AI enrichment worker started');
|
|
210
|
+
// Check for static analysis file
|
|
211
|
+
if (!fs.existsSync(STATIC_ANALYSIS_FILE)) {
|
|
212
|
+
log('No static analysis file found, exiting');
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
// Read static analysis
|
|
216
|
+
let analysis;
|
|
217
|
+
try {
|
|
218
|
+
analysis = JSON.parse(fs.readFileSync(STATIC_ANALYSIS_FILE, 'utf8'));
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
log(`Failed to read static analysis: ${err instanceof Error ? err.message : err}`);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
// Generate enriched summary
|
|
225
|
+
const enrichedSummary = generateEnrichedSummary(analysis);
|
|
226
|
+
log(`Generated enriched summary: ${enrichedSummary.slice(0, 100)}...`);
|
|
227
|
+
// Load config
|
|
228
|
+
const config = loadConfig();
|
|
229
|
+
log(`Using endpoint: ${config.endpoint}, group: ${config.groupId}`);
|
|
230
|
+
// Initialize MCP (pass API key for Zep Cloud auth)
|
|
231
|
+
const sessionId = await initializeMCP(config.endpoint, config.zepApiKey);
|
|
232
|
+
if (!sessionId) {
|
|
233
|
+
log('Could not initialize MCP, skipping enrichment');
|
|
234
|
+
// Still mark as done but not enriched
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
// Add enriched memory (pass API key for Zep Cloud auth)
|
|
238
|
+
const success = await addEnrichedMemory(config.endpoint, sessionId, enrichedSummary, config.groupId, config.zepApiKey);
|
|
239
|
+
if (success) {
|
|
240
|
+
log('Successfully stored enriched memory');
|
|
241
|
+
updateMarker(true);
|
|
242
|
+
// Clean up static analysis file
|
|
243
|
+
try {
|
|
244
|
+
fs.unlinkSync(STATIC_ANALYSIS_FILE);
|
|
245
|
+
}
|
|
246
|
+
catch (_) {
|
|
247
|
+
// Ignore cleanup errors
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
log('Failed to store enriched memory');
|
|
252
|
+
}
|
|
253
|
+
log('AI enrichment worker completed');
|
|
254
|
+
}
|
|
255
|
+
main().catch((err) => {
|
|
256
|
+
log(`Worker error: ${err instanceof Error ? err.message : err}`);
|
|
257
|
+
process.exit(1);
|
|
258
|
+
});
|