@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.
Files changed (48) hide show
  1. package/README.md +42 -0
  2. package/dist/cli.js +390 -0
  3. package/dist/lib/interfaces/IDockerClient.js +2 -0
  4. package/dist/lib/interfaces/IMcpClient.js +2 -0
  5. package/dist/lib/interfaces/IServices.js +2 -0
  6. package/dist/lib/interfaces/ITemplateCopier.js +2 -0
  7. package/dist/lib/mcp.js +35 -0
  8. package/dist/lib/services.js +57 -0
  9. package/dist/package.json +36 -0
  10. package/dist/templates/agents/.sample.env +12 -0
  11. package/dist/templates/agents/docs/STORAGE_SETUP.md +161 -0
  12. package/dist/templates/agents/skills/common/group-id.js +193 -0
  13. package/dist/templates/agents/skills/init-review/SKILL.md +119 -0
  14. package/dist/templates/agents/skills/init-review/scripts/ai-enrich.js +258 -0
  15. package/dist/templates/agents/skills/init-review/scripts/init-review.js +769 -0
  16. package/dist/templates/agents/skills/lisa/SKILL.md +92 -0
  17. package/dist/templates/agents/skills/lisa/cache/.gitkeep +0 -0
  18. package/dist/templates/agents/skills/lisa/scripts/storage.js +374 -0
  19. package/dist/templates/agents/skills/memory/SKILL.md +31 -0
  20. package/dist/templates/agents/skills/memory/scripts/memory.js +533 -0
  21. package/dist/templates/agents/skills/prompt/SKILL.md +19 -0
  22. package/dist/templates/agents/skills/prompt/scripts/prompt.js +184 -0
  23. package/dist/templates/agents/skills/tasks/SKILL.md +31 -0
  24. package/dist/templates/agents/skills/tasks/scripts/tasks.js +489 -0
  25. package/dist/templates/claude/config.js +40 -0
  26. package/dist/templates/claude/hooks/README.md +158 -0
  27. package/dist/templates/claude/hooks/common/complexity-rater.js +290 -0
  28. package/dist/templates/claude/hooks/common/context.js +263 -0
  29. package/dist/templates/claude/hooks/common/group-id.js +188 -0
  30. package/dist/templates/claude/hooks/common/mcp-client.js +131 -0
  31. package/dist/templates/claude/hooks/common/transcript-parser.js +256 -0
  32. package/dist/templates/claude/hooks/common/zep-client.js +175 -0
  33. package/dist/templates/claude/hooks/session-start.js +401 -0
  34. package/dist/templates/claude/hooks/session-stop-worker.js +341 -0
  35. package/dist/templates/claude/hooks/session-stop.js +122 -0
  36. package/dist/templates/claude/hooks/user-prompt-submit.js +256 -0
  37. package/dist/templates/claude/settings.json +46 -0
  38. package/dist/templates/docker/.env.lisa.example +17 -0
  39. package/dist/templates/docker/docker-compose.graphiti.yml +45 -0
  40. package/dist/templates/rules/shared/clean-architecture.md +333 -0
  41. package/dist/templates/rules/shared/code-quality-rules.md +469 -0
  42. package/dist/templates/rules/shared/git-rules.md +64 -0
  43. package/dist/templates/rules/shared/testing-principles.md +469 -0
  44. package/dist/templates/rules/typescript/coding-standards.md +751 -0
  45. package/dist/templates/rules/typescript/testing.md +629 -0
  46. package/dist/templates/rules/typescript/typescript-config-guide.md +465 -0
  47. package/package.json +64 -0
  48. 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
+ });