@su-record/vibe 2.3.2 → 2.4.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/.claude/settings.json +35 -35
- package/.claude/settings.local.json +30 -24
- package/.claude/vibe/constitution.md +184 -184
- package/.claude/vibe/rules/core/communication-guide.md +104 -104
- package/.claude/vibe/rules/core/development-philosophy.md +52 -52
- package/.claude/vibe/rules/core/quick-start.md +120 -120
- package/.claude/vibe/rules/languages/dart-flutter.md +509 -509
- package/.claude/vibe/rules/languages/go.md +396 -396
- package/.claude/vibe/rules/languages/java-spring.md +586 -586
- package/.claude/vibe/rules/languages/kotlin-android.md +491 -491
- package/.claude/vibe/rules/languages/python-django.md +371 -371
- package/.claude/vibe/rules/languages/python-fastapi.md +386 -386
- package/.claude/vibe/rules/languages/rust.md +425 -425
- package/.claude/vibe/rules/languages/swift-ios.md +516 -516
- package/.claude/vibe/rules/languages/typescript-nextjs.md +441 -441
- package/.claude/vibe/rules/languages/typescript-node.md +375 -375
- package/.claude/vibe/rules/languages/typescript-nuxt.md +521 -521
- package/.claude/vibe/rules/languages/typescript-react-native.md +446 -446
- package/.claude/vibe/rules/languages/typescript-react.md +525 -525
- package/.claude/vibe/rules/languages/typescript-vue.md +353 -353
- package/.claude/vibe/rules/quality/bdd-contract-testing.md +388 -388
- package/.claude/vibe/rules/quality/checklist.md +276 -276
- package/.claude/vibe/rules/quality/testing-strategy.md +437 -437
- package/.claude/vibe/rules/standards/anti-patterns.md +369 -369
- package/.claude/vibe/rules/standards/code-structure.md +291 -291
- package/.claude/vibe/rules/standards/complexity-metrics.md +312 -312
- package/.claude/vibe/rules/standards/naming-conventions.md +198 -198
- package/.claude/vibe/setup.sh +31 -31
- package/.claude/vibe/templates/constitution-template.md +184 -184
- package/.claude/vibe/templates/contract-backend-template.md +517 -517
- package/.claude/vibe/templates/contract-frontend-template.md +594 -594
- package/.claude/vibe/templates/feature-template.md +96 -96
- package/.claude/vibe/templates/spec-template.md +199 -199
- package/CLAUDE.md +345 -345
- package/LICENSE +21 -21
- package/README.md +817 -744
- package/agents/compounder.md +261 -261
- package/agents/diagrammer.md +178 -178
- package/agents/e2e-tester.md +266 -266
- package/agents/explorer.md +48 -48
- package/agents/implementer.md +53 -53
- package/agents/research/best-practices-agent.md +139 -139
- package/agents/research/codebase-patterns-agent.md +147 -147
- package/agents/research/framework-docs-agent.md +181 -181
- package/agents/research/security-advisory-agent.md +167 -167
- package/agents/review/architecture-reviewer.md +107 -107
- package/agents/review/complexity-reviewer.md +116 -116
- package/agents/review/data-integrity-reviewer.md +88 -88
- package/agents/review/git-history-reviewer.md +103 -103
- package/agents/review/performance-reviewer.md +86 -86
- package/agents/review/python-reviewer.md +152 -152
- package/agents/review/rails-reviewer.md +139 -139
- package/agents/review/react-reviewer.md +144 -144
- package/agents/review/security-reviewer.md +80 -80
- package/agents/review/simplicity-reviewer.md +140 -140
- package/agents/review/test-coverage-reviewer.md +116 -116
- package/agents/review/typescript-reviewer.md +127 -127
- package/agents/searcher.md +54 -54
- package/agents/simplifier.md +119 -119
- package/agents/tester.md +49 -49
- package/agents/ui-previewer.md +137 -137
- package/commands/vibe.analyze.md +260 -245
- package/commands/vibe.reason.md +223 -223
- package/commands/vibe.review.md +213 -200
- package/commands/vibe.run.md +842 -838
- package/commands/vibe.spec.md +405 -419
- package/commands/vibe.utils.md +101 -101
- package/commands/vibe.verify.md +282 -282
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +422 -385
- package/dist/cli/index.js.map +1 -1
- package/dist/lib/MemoryManager.js +92 -92
- package/dist/lib/PythonParser.js +108 -108
- package/dist/lib/gemini-mcp.js +15 -15
- package/dist/lib/gemini-oauth.js +35 -35
- package/dist/lib/gpt-mcp.js +17 -17
- package/dist/lib/gpt-oauth.js +44 -44
- package/dist/orchestrator/agentDiscovery.d.ts +18 -0
- package/dist/orchestrator/agentDiscovery.d.ts.map +1 -0
- package/dist/orchestrator/agentDiscovery.js +174 -0
- package/dist/orchestrator/agentDiscovery.js.map +1 -0
- package/dist/orchestrator/backgroundAgent.d.ts +31 -0
- package/dist/orchestrator/backgroundAgent.d.ts.map +1 -0
- package/dist/orchestrator/backgroundAgent.js +325 -0
- package/dist/orchestrator/backgroundAgent.js.map +1 -0
- package/dist/orchestrator/index.d.ts +58 -0
- package/dist/orchestrator/index.d.ts.map +1 -0
- package/dist/orchestrator/index.js +115 -0
- package/dist/orchestrator/index.js.map +1 -0
- package/dist/orchestrator/orchestrator.d.ts +82 -0
- package/dist/orchestrator/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator/orchestrator.js +257 -0
- package/dist/orchestrator/orchestrator.js.map +1 -0
- package/dist/orchestrator/parallelResearch.d.ts +19 -0
- package/dist/orchestrator/parallelResearch.d.ts.map +1 -0
- package/dist/orchestrator/parallelResearch.js +214 -0
- package/dist/orchestrator/parallelResearch.js.map +1 -0
- package/dist/orchestrator/types.d.ts +109 -0
- package/dist/orchestrator/types.d.ts.map +1 -0
- package/dist/orchestrator/types.js +5 -0
- package/dist/orchestrator/types.js.map +1 -0
- package/dist/tools/analytics/getUsageAnalytics.js +12 -12
- package/dist/tools/memory/createMemoryTimeline.js +10 -10
- package/dist/tools/memory/getMemoryGraph.js +12 -12
- package/dist/tools/memory/getSessionContext.js +9 -9
- package/dist/tools/memory/linkMemories.js +14 -14
- package/dist/tools/memory/listMemories.js +4 -4
- package/dist/tools/memory/recallMemory.js +4 -4
- package/dist/tools/memory/saveMemory.js +4 -4
- package/dist/tools/memory/searchMemoriesAdvanced.js +22 -22
- package/dist/tools/planning/generatePrd.js +46 -46
- package/dist/tools/prompt/enhancePromptGemini.js +160 -160
- package/dist/tools/reasoning/applyReasoningFramework.js +56 -56
- package/dist/tools/semantic/analyzeDependencyGraph.js +12 -12
- package/hooks/hooks.json +121 -121
- package/package.json +75 -73
- package/skills/git-worktree.md +178 -178
- package/skills/priority-todos.md +236 -236
|
@@ -102,37 +102,37 @@ export class MemoryManager {
|
|
|
102
102
|
}
|
|
103
103
|
initializeDatabase() {
|
|
104
104
|
// Create memories table
|
|
105
|
-
this.db.exec(`
|
|
106
|
-
CREATE TABLE IF NOT EXISTS memories (
|
|
107
|
-
key TEXT PRIMARY KEY,
|
|
108
|
-
value TEXT NOT NULL,
|
|
109
|
-
category TEXT NOT NULL DEFAULT 'general',
|
|
110
|
-
timestamp TEXT NOT NULL,
|
|
111
|
-
lastAccessed TEXT NOT NULL,
|
|
112
|
-
priority INTEGER DEFAULT 0
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
CREATE INDEX IF NOT EXISTS idx_category ON memories(category);
|
|
116
|
-
CREATE INDEX IF NOT EXISTS idx_timestamp ON memories(timestamp);
|
|
117
|
-
CREATE INDEX IF NOT EXISTS idx_priority ON memories(priority);
|
|
118
|
-
CREATE INDEX IF NOT EXISTS idx_lastAccessed ON memories(lastAccessed);
|
|
105
|
+
this.db.exec(`
|
|
106
|
+
CREATE TABLE IF NOT EXISTS memories (
|
|
107
|
+
key TEXT PRIMARY KEY,
|
|
108
|
+
value TEXT NOT NULL,
|
|
109
|
+
category TEXT NOT NULL DEFAULT 'general',
|
|
110
|
+
timestamp TEXT NOT NULL,
|
|
111
|
+
lastAccessed TEXT NOT NULL,
|
|
112
|
+
priority INTEGER DEFAULT 0
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
CREATE INDEX IF NOT EXISTS idx_category ON memories(category);
|
|
116
|
+
CREATE INDEX IF NOT EXISTS idx_timestamp ON memories(timestamp);
|
|
117
|
+
CREATE INDEX IF NOT EXISTS idx_priority ON memories(priority);
|
|
118
|
+
CREATE INDEX IF NOT EXISTS idx_lastAccessed ON memories(lastAccessed);
|
|
119
119
|
`);
|
|
120
120
|
// v2.0: Create memory_relations table for Knowledge Graph
|
|
121
|
-
this.db.exec(`
|
|
122
|
-
CREATE TABLE IF NOT EXISTS memory_relations (
|
|
123
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
124
|
-
sourceKey TEXT NOT NULL,
|
|
125
|
-
targetKey TEXT NOT NULL,
|
|
126
|
-
relationType TEXT NOT NULL,
|
|
127
|
-
strength REAL DEFAULT 1.0,
|
|
128
|
-
metadata TEXT,
|
|
129
|
-
timestamp TEXT NOT NULL,
|
|
130
|
-
UNIQUE(sourceKey, targetKey, relationType)
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
CREATE INDEX IF NOT EXISTS idx_rel_source ON memory_relations(sourceKey);
|
|
134
|
-
CREATE INDEX IF NOT EXISTS idx_rel_target ON memory_relations(targetKey);
|
|
135
|
-
CREATE INDEX IF NOT EXISTS idx_rel_type ON memory_relations(relationType);
|
|
121
|
+
this.db.exec(`
|
|
122
|
+
CREATE TABLE IF NOT EXISTS memory_relations (
|
|
123
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
124
|
+
sourceKey TEXT NOT NULL,
|
|
125
|
+
targetKey TEXT NOT NULL,
|
|
126
|
+
relationType TEXT NOT NULL,
|
|
127
|
+
strength REAL DEFAULT 1.0,
|
|
128
|
+
metadata TEXT,
|
|
129
|
+
timestamp TEXT NOT NULL,
|
|
130
|
+
UNIQUE(sourceKey, targetKey, relationType)
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
CREATE INDEX IF NOT EXISTS idx_rel_source ON memory_relations(sourceKey);
|
|
134
|
+
CREATE INDEX IF NOT EXISTS idx_rel_target ON memory_relations(targetKey);
|
|
135
|
+
CREATE INDEX IF NOT EXISTS idx_rel_type ON memory_relations(relationType);
|
|
136
136
|
`);
|
|
137
137
|
// Enable WAL mode for better concurrency
|
|
138
138
|
this.db.pragma('journal_mode = WAL');
|
|
@@ -142,10 +142,10 @@ export class MemoryManager {
|
|
|
142
142
|
initializePreparedStatements() {
|
|
143
143
|
// Pre-compile recall statement
|
|
144
144
|
try {
|
|
145
|
-
this.recallStmt = this.db.prepare(`
|
|
146
|
-
UPDATE memories SET lastAccessed = ?
|
|
147
|
-
WHERE key = ?
|
|
148
|
-
RETURNING *
|
|
145
|
+
this.recallStmt = this.db.prepare(`
|
|
146
|
+
UPDATE memories SET lastAccessed = ?
|
|
147
|
+
WHERE key = ?
|
|
148
|
+
RETURNING *
|
|
149
149
|
`);
|
|
150
150
|
}
|
|
151
151
|
catch (error) {
|
|
@@ -155,9 +155,9 @@ export class MemoryManager {
|
|
|
155
155
|
this.recallUpdateStmt = this.db.prepare(`UPDATE memories SET lastAccessed = ? WHERE key = ?`);
|
|
156
156
|
}
|
|
157
157
|
// Pre-compile save statement
|
|
158
|
-
this.saveStmt = this.db.prepare(`
|
|
159
|
-
INSERT OR REPLACE INTO memories (key, value, category, timestamp, lastAccessed, priority)
|
|
160
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
158
|
+
this.saveStmt = this.db.prepare(`
|
|
159
|
+
INSERT OR REPLACE INTO memories (key, value, category, timestamp, lastAccessed, priority)
|
|
160
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
161
161
|
`);
|
|
162
162
|
}
|
|
163
163
|
/**
|
|
@@ -193,9 +193,9 @@ export class MemoryManager {
|
|
|
193
193
|
* Import memories into SQLite database
|
|
194
194
|
*/
|
|
195
195
|
importMemories(memories) {
|
|
196
|
-
const insert = this.db.prepare(`
|
|
197
|
-
INSERT OR REPLACE INTO memories (key, value, category, timestamp, lastAccessed, priority)
|
|
198
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
196
|
+
const insert = this.db.prepare(`
|
|
197
|
+
INSERT OR REPLACE INTO memories (key, value, category, timestamp, lastAccessed, priority)
|
|
198
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
199
199
|
`);
|
|
200
200
|
const insertMany = this.db.transaction((items) => {
|
|
201
201
|
for (const item of items) {
|
|
@@ -230,9 +230,9 @@ export class MemoryManager {
|
|
|
230
230
|
}
|
|
231
231
|
else {
|
|
232
232
|
// Fallback if prepared statement not available
|
|
233
|
-
const stmt = this.db.prepare(`
|
|
234
|
-
INSERT OR REPLACE INTO memories (key, value, category, timestamp, lastAccessed, priority)
|
|
235
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
233
|
+
const stmt = this.db.prepare(`
|
|
234
|
+
INSERT OR REPLACE INTO memories (key, value, category, timestamp, lastAccessed, priority)
|
|
235
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
236
236
|
`);
|
|
237
237
|
stmt.run(key, value, category, timestamp, timestamp, priority);
|
|
238
238
|
}
|
|
@@ -267,8 +267,8 @@ export class MemoryManager {
|
|
|
267
267
|
delete(key) {
|
|
268
268
|
// Also delete related relations
|
|
269
269
|
this.db.prepare(`DELETE FROM memory_relations WHERE sourceKey = ? OR targetKey = ?`).run(key, key);
|
|
270
|
-
const stmt = this.db.prepare(`
|
|
271
|
-
DELETE FROM memories WHERE key = ?
|
|
270
|
+
const stmt = this.db.prepare(`
|
|
271
|
+
DELETE FROM memories WHERE key = ?
|
|
272
272
|
`);
|
|
273
273
|
const result = stmt.run(key);
|
|
274
274
|
return result.changes > 0;
|
|
@@ -281,10 +281,10 @@ export class MemoryManager {
|
|
|
281
281
|
*/
|
|
282
282
|
update(key, value) {
|
|
283
283
|
const timestamp = new Date().toISOString();
|
|
284
|
-
const stmt = this.db.prepare(`
|
|
285
|
-
UPDATE memories
|
|
286
|
-
SET value = ?, timestamp = ?, lastAccessed = ?
|
|
287
|
-
WHERE key = ?
|
|
284
|
+
const stmt = this.db.prepare(`
|
|
285
|
+
UPDATE memories
|
|
286
|
+
SET value = ?, timestamp = ?, lastAccessed = ?
|
|
287
|
+
WHERE key = ?
|
|
288
288
|
`);
|
|
289
289
|
const result = stmt.run(value, timestamp, timestamp, key);
|
|
290
290
|
return result.changes > 0;
|
|
@@ -297,16 +297,16 @@ export class MemoryManager {
|
|
|
297
297
|
list(category) {
|
|
298
298
|
let stmt;
|
|
299
299
|
if (category) {
|
|
300
|
-
stmt = this.db.prepare(`
|
|
301
|
-
SELECT * FROM memories WHERE category = ?
|
|
302
|
-
ORDER BY priority DESC, timestamp DESC
|
|
300
|
+
stmt = this.db.prepare(`
|
|
301
|
+
SELECT * FROM memories WHERE category = ?
|
|
302
|
+
ORDER BY priority DESC, timestamp DESC
|
|
303
303
|
`);
|
|
304
304
|
return stmt.all(category);
|
|
305
305
|
}
|
|
306
306
|
else {
|
|
307
|
-
stmt = this.db.prepare(`
|
|
308
|
-
SELECT * FROM memories
|
|
309
|
-
ORDER BY priority DESC, timestamp DESC
|
|
307
|
+
stmt = this.db.prepare(`
|
|
308
|
+
SELECT * FROM memories
|
|
309
|
+
ORDER BY priority DESC, timestamp DESC
|
|
310
310
|
`);
|
|
311
311
|
return stmt.all();
|
|
312
312
|
}
|
|
@@ -317,10 +317,10 @@ export class MemoryManager {
|
|
|
317
317
|
* @returns Array of matching memory items
|
|
318
318
|
*/
|
|
319
319
|
search(query) {
|
|
320
|
-
const stmt = this.db.prepare(`
|
|
321
|
-
SELECT * FROM memories
|
|
322
|
-
WHERE key LIKE ? OR value LIKE ?
|
|
323
|
-
ORDER BY priority DESC, timestamp DESC
|
|
320
|
+
const stmt = this.db.prepare(`
|
|
321
|
+
SELECT * FROM memories
|
|
322
|
+
WHERE key LIKE ? OR value LIKE ?
|
|
323
|
+
ORDER BY priority DESC, timestamp DESC
|
|
324
324
|
`);
|
|
325
325
|
const pattern = `%${query}%`;
|
|
326
326
|
return stmt.all(pattern, pattern);
|
|
@@ -331,10 +331,10 @@ export class MemoryManager {
|
|
|
331
331
|
* @returns Array of memory items with specified priority
|
|
332
332
|
*/
|
|
333
333
|
getByPriority(priority) {
|
|
334
|
-
const stmt = this.db.prepare(`
|
|
335
|
-
SELECT * FROM memories
|
|
336
|
-
WHERE priority = ?
|
|
337
|
-
ORDER BY timestamp DESC
|
|
334
|
+
const stmt = this.db.prepare(`
|
|
335
|
+
SELECT * FROM memories
|
|
336
|
+
WHERE priority = ?
|
|
337
|
+
ORDER BY timestamp DESC
|
|
338
338
|
`);
|
|
339
339
|
return stmt.all(priority);
|
|
340
340
|
}
|
|
@@ -345,8 +345,8 @@ export class MemoryManager {
|
|
|
345
345
|
* @returns True if updated successfully
|
|
346
346
|
*/
|
|
347
347
|
setPriority(key, priority) {
|
|
348
|
-
const stmt = this.db.prepare(`
|
|
349
|
-
UPDATE memories SET priority = ? WHERE key = ?
|
|
348
|
+
const stmt = this.db.prepare(`
|
|
349
|
+
UPDATE memories SET priority = ? WHERE key = ?
|
|
350
350
|
`);
|
|
351
351
|
const result = stmt.run(priority, key);
|
|
352
352
|
return result.changes > 0;
|
|
@@ -357,10 +357,10 @@ export class MemoryManager {
|
|
|
357
357
|
*/
|
|
358
358
|
getStats() {
|
|
359
359
|
// Single query with ROLLUP or combined approach
|
|
360
|
-
const categories = this.db.prepare(`
|
|
361
|
-
SELECT category, COUNT(*) as count
|
|
362
|
-
FROM memories
|
|
363
|
-
GROUP BY category
|
|
360
|
+
const categories = this.db.prepare(`
|
|
361
|
+
SELECT category, COUNT(*) as count
|
|
362
|
+
FROM memories
|
|
363
|
+
GROUP BY category
|
|
364
364
|
`).all();
|
|
365
365
|
const byCategory = {};
|
|
366
366
|
let total = 0;
|
|
@@ -385,10 +385,10 @@ export class MemoryManager {
|
|
|
385
385
|
const timestamp = new Date().toISOString();
|
|
386
386
|
const metadataJson = metadata ? JSON.stringify(metadata) : null;
|
|
387
387
|
try {
|
|
388
|
-
const stmt = this.db.prepare(`
|
|
389
|
-
INSERT OR REPLACE INTO memory_relations
|
|
390
|
-
(sourceKey, targetKey, relationType, strength, metadata, timestamp)
|
|
391
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
388
|
+
const stmt = this.db.prepare(`
|
|
389
|
+
INSERT OR REPLACE INTO memory_relations
|
|
390
|
+
(sourceKey, targetKey, relationType, strength, metadata, timestamp)
|
|
391
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
392
392
|
`);
|
|
393
393
|
stmt.run(sourceKey, targetKey, relationType, strength, metadataJson, timestamp);
|
|
394
394
|
return true;
|
|
@@ -644,9 +644,9 @@ export class MemoryManager {
|
|
|
644
644
|
}
|
|
645
645
|
}
|
|
646
646
|
searchKeyword(query, limit, category) {
|
|
647
|
-
let sql = `
|
|
648
|
-
SELECT * FROM memories
|
|
649
|
-
WHERE (key LIKE ? OR value LIKE ?)
|
|
647
|
+
let sql = `
|
|
648
|
+
SELECT * FROM memories
|
|
649
|
+
WHERE (key LIKE ? OR value LIKE ?)
|
|
650
650
|
`;
|
|
651
651
|
const params = [`%${query}%`, `%${query}%`];
|
|
652
652
|
if (category) {
|
|
@@ -658,32 +658,32 @@ export class MemoryManager {
|
|
|
658
658
|
return this.db.prepare(sql).all(...params);
|
|
659
659
|
}
|
|
660
660
|
searchTemporal(query, limit) {
|
|
661
|
-
const sql = `
|
|
662
|
-
SELECT * FROM memories
|
|
663
|
-
WHERE key LIKE ? OR value LIKE ?
|
|
664
|
-
ORDER BY timestamp DESC
|
|
665
|
-
LIMIT ?
|
|
661
|
+
const sql = `
|
|
662
|
+
SELECT * FROM memories
|
|
663
|
+
WHERE key LIKE ? OR value LIKE ?
|
|
664
|
+
ORDER BY timestamp DESC
|
|
665
|
+
LIMIT ?
|
|
666
666
|
`;
|
|
667
667
|
return this.db.prepare(sql).all(`%${query}%`, `%${query}%`, limit);
|
|
668
668
|
}
|
|
669
669
|
searchByPriority(query, limit) {
|
|
670
|
-
const sql = `
|
|
671
|
-
SELECT * FROM memories
|
|
672
|
-
WHERE key LIKE ? OR value LIKE ?
|
|
673
|
-
ORDER BY priority DESC, lastAccessed DESC
|
|
674
|
-
LIMIT ?
|
|
670
|
+
const sql = `
|
|
671
|
+
SELECT * FROM memories
|
|
672
|
+
WHERE key LIKE ? OR value LIKE ?
|
|
673
|
+
ORDER BY priority DESC, lastAccessed DESC
|
|
674
|
+
LIMIT ?
|
|
675
675
|
`;
|
|
676
676
|
return this.db.prepare(sql).all(`%${query}%`, `%${query}%`, limit);
|
|
677
677
|
}
|
|
678
678
|
searchContextAware(query, limit, category) {
|
|
679
679
|
// Combined strategy: keyword + priority + recency
|
|
680
|
-
let sql = `
|
|
681
|
-
SELECT *,
|
|
682
|
-
(CASE WHEN key LIKE ? THEN 3 ELSE 0 END +
|
|
683
|
-
CASE WHEN value LIKE ? THEN 2 ELSE 0 END +
|
|
684
|
-
priority * 0.5) as relevance_score
|
|
685
|
-
FROM memories
|
|
686
|
-
WHERE key LIKE ? OR value LIKE ?
|
|
680
|
+
let sql = `
|
|
681
|
+
SELECT *,
|
|
682
|
+
(CASE WHEN key LIKE ? THEN 3 ELSE 0 END +
|
|
683
|
+
CASE WHEN value LIKE ? THEN 2 ELSE 0 END +
|
|
684
|
+
priority * 0.5) as relevance_score
|
|
685
|
+
FROM memories
|
|
686
|
+
WHERE key LIKE ? OR value LIKE ?
|
|
687
687
|
`;
|
|
688
688
|
const params = [`%${query}%`, `%${query}%`, `%${query}%`, `%${query}%`];
|
|
689
689
|
if (category) {
|
package/dist/lib/PythonParser.js
CHANGED
|
@@ -35,114 +35,114 @@ function getPythonCommand() {
|
|
|
35
35
|
const PYTHON_CMD = getPythonCommand();
|
|
36
36
|
export class PythonParser {
|
|
37
37
|
static cleanupRegistered = false;
|
|
38
|
-
static pythonScript = `
|
|
39
|
-
import ast
|
|
40
|
-
import sys
|
|
41
|
-
import json
|
|
42
|
-
|
|
43
|
-
def analyze_code(code):
|
|
44
|
-
try:
|
|
45
|
-
tree = ast.parse(code)
|
|
46
|
-
symbols = []
|
|
47
|
-
|
|
48
|
-
for node in ast.walk(tree):
|
|
49
|
-
if isinstance(node, ast.FunctionDef):
|
|
50
|
-
symbols.append({
|
|
51
|
-
'name': node.name,
|
|
52
|
-
'kind': 'function',
|
|
53
|
-
'line': node.lineno,
|
|
54
|
-
'column': node.col_offset,
|
|
55
|
-
'endLine': node.end_lineno,
|
|
56
|
-
'docstring': ast.get_docstring(node)
|
|
57
|
-
})
|
|
58
|
-
elif isinstance(node, ast.ClassDef):
|
|
59
|
-
symbols.append({
|
|
60
|
-
'name': node.name,
|
|
61
|
-
'kind': 'class',
|
|
62
|
-
'line': node.lineno,
|
|
63
|
-
'column': node.col_offset,
|
|
64
|
-
'endLine': node.end_lineno,
|
|
65
|
-
'docstring': ast.get_docstring(node)
|
|
66
|
-
})
|
|
67
|
-
elif isinstance(node, ast.Assign):
|
|
68
|
-
for target in node.targets:
|
|
69
|
-
if isinstance(target, ast.Name):
|
|
70
|
-
symbols.append({
|
|
71
|
-
'name': target.id,
|
|
72
|
-
'kind': 'variable',
|
|
73
|
-
'line': node.lineno,
|
|
74
|
-
'column': node.col_offset
|
|
75
|
-
})
|
|
76
|
-
elif isinstance(node, ast.Import) or isinstance(node, ast.ImportFrom):
|
|
77
|
-
for alias in node.names:
|
|
78
|
-
symbols.append({
|
|
79
|
-
'name': alias.name,
|
|
80
|
-
'kind': 'import',
|
|
81
|
-
'line': node.lineno,
|
|
82
|
-
'column': node.col_offset
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
return {'success': True, 'symbols': symbols}
|
|
86
|
-
except SyntaxError as e:
|
|
87
|
-
return {'success': False, 'error': str(e)}
|
|
88
|
-
except Exception as e:
|
|
89
|
-
return {'success': False, 'error': str(e)}
|
|
90
|
-
|
|
91
|
-
def calculate_complexity(code):
|
|
92
|
-
try:
|
|
93
|
-
tree = ast.parse(code)
|
|
94
|
-
|
|
95
|
-
def cyclomatic_complexity(node):
|
|
96
|
-
complexity = 1
|
|
97
|
-
for child in ast.walk(node):
|
|
98
|
-
if isinstance(child, (ast.If, ast.For, ast.While, ast.And, ast.Or, ast.ExceptHandler)):
|
|
99
|
-
complexity += 1
|
|
100
|
-
elif isinstance(child, ast.BoolOp):
|
|
101
|
-
complexity += len(child.values) - 1
|
|
102
|
-
return complexity
|
|
103
|
-
|
|
104
|
-
functions = []
|
|
105
|
-
classes = []
|
|
106
|
-
total_complexity = 1
|
|
107
|
-
|
|
108
|
-
for node in ast.walk(tree):
|
|
109
|
-
if isinstance(node, ast.FunctionDef):
|
|
110
|
-
func_complexity = cyclomatic_complexity(node)
|
|
111
|
-
functions.append({
|
|
112
|
-
'name': node.name,
|
|
113
|
-
'complexity': func_complexity,
|
|
114
|
-
'line': node.lineno
|
|
115
|
-
})
|
|
116
|
-
total_complexity += func_complexity
|
|
117
|
-
elif isinstance(node, ast.ClassDef):
|
|
118
|
-
method_count = sum(1 for n in node.body if isinstance(n, ast.FunctionDef))
|
|
119
|
-
classes.append({
|
|
120
|
-
'name': node.name,
|
|
121
|
-
'methods': method_count,
|
|
122
|
-
'line': node.lineno
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
return {
|
|
126
|
-
'success': True,
|
|
127
|
-
'cyclomaticComplexity': total_complexity,
|
|
128
|
-
'functions': functions,
|
|
129
|
-
'classes': classes
|
|
130
|
-
}
|
|
131
|
-
except Exception as e:
|
|
132
|
-
return {'success': False, 'error': str(e)}
|
|
133
|
-
|
|
134
|
-
if __name__ == '__main__':
|
|
135
|
-
code = sys.stdin.read()
|
|
136
|
-
action = sys.argv[1] if len(sys.argv) > 1 else 'symbols'
|
|
137
|
-
|
|
138
|
-
if action == 'symbols':
|
|
139
|
-
result = analyze_code(code)
|
|
140
|
-
elif action == 'complexity':
|
|
141
|
-
result = calculate_complexity(code)
|
|
142
|
-
else:
|
|
143
|
-
result = {'success': False, 'error': 'Unknown action'}
|
|
144
|
-
|
|
145
|
-
print(json.dumps(result))
|
|
38
|
+
static pythonScript = `
|
|
39
|
+
import ast
|
|
40
|
+
import sys
|
|
41
|
+
import json
|
|
42
|
+
|
|
43
|
+
def analyze_code(code):
|
|
44
|
+
try:
|
|
45
|
+
tree = ast.parse(code)
|
|
46
|
+
symbols = []
|
|
47
|
+
|
|
48
|
+
for node in ast.walk(tree):
|
|
49
|
+
if isinstance(node, ast.FunctionDef):
|
|
50
|
+
symbols.append({
|
|
51
|
+
'name': node.name,
|
|
52
|
+
'kind': 'function',
|
|
53
|
+
'line': node.lineno,
|
|
54
|
+
'column': node.col_offset,
|
|
55
|
+
'endLine': node.end_lineno,
|
|
56
|
+
'docstring': ast.get_docstring(node)
|
|
57
|
+
})
|
|
58
|
+
elif isinstance(node, ast.ClassDef):
|
|
59
|
+
symbols.append({
|
|
60
|
+
'name': node.name,
|
|
61
|
+
'kind': 'class',
|
|
62
|
+
'line': node.lineno,
|
|
63
|
+
'column': node.col_offset,
|
|
64
|
+
'endLine': node.end_lineno,
|
|
65
|
+
'docstring': ast.get_docstring(node)
|
|
66
|
+
})
|
|
67
|
+
elif isinstance(node, ast.Assign):
|
|
68
|
+
for target in node.targets:
|
|
69
|
+
if isinstance(target, ast.Name):
|
|
70
|
+
symbols.append({
|
|
71
|
+
'name': target.id,
|
|
72
|
+
'kind': 'variable',
|
|
73
|
+
'line': node.lineno,
|
|
74
|
+
'column': node.col_offset
|
|
75
|
+
})
|
|
76
|
+
elif isinstance(node, ast.Import) or isinstance(node, ast.ImportFrom):
|
|
77
|
+
for alias in node.names:
|
|
78
|
+
symbols.append({
|
|
79
|
+
'name': alias.name,
|
|
80
|
+
'kind': 'import',
|
|
81
|
+
'line': node.lineno,
|
|
82
|
+
'column': node.col_offset
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
return {'success': True, 'symbols': symbols}
|
|
86
|
+
except SyntaxError as e:
|
|
87
|
+
return {'success': False, 'error': str(e)}
|
|
88
|
+
except Exception as e:
|
|
89
|
+
return {'success': False, 'error': str(e)}
|
|
90
|
+
|
|
91
|
+
def calculate_complexity(code):
|
|
92
|
+
try:
|
|
93
|
+
tree = ast.parse(code)
|
|
94
|
+
|
|
95
|
+
def cyclomatic_complexity(node):
|
|
96
|
+
complexity = 1
|
|
97
|
+
for child in ast.walk(node):
|
|
98
|
+
if isinstance(child, (ast.If, ast.For, ast.While, ast.And, ast.Or, ast.ExceptHandler)):
|
|
99
|
+
complexity += 1
|
|
100
|
+
elif isinstance(child, ast.BoolOp):
|
|
101
|
+
complexity += len(child.values) - 1
|
|
102
|
+
return complexity
|
|
103
|
+
|
|
104
|
+
functions = []
|
|
105
|
+
classes = []
|
|
106
|
+
total_complexity = 1
|
|
107
|
+
|
|
108
|
+
for node in ast.walk(tree):
|
|
109
|
+
if isinstance(node, ast.FunctionDef):
|
|
110
|
+
func_complexity = cyclomatic_complexity(node)
|
|
111
|
+
functions.append({
|
|
112
|
+
'name': node.name,
|
|
113
|
+
'complexity': func_complexity,
|
|
114
|
+
'line': node.lineno
|
|
115
|
+
})
|
|
116
|
+
total_complexity += func_complexity
|
|
117
|
+
elif isinstance(node, ast.ClassDef):
|
|
118
|
+
method_count = sum(1 for n in node.body if isinstance(n, ast.FunctionDef))
|
|
119
|
+
classes.append({
|
|
120
|
+
'name': node.name,
|
|
121
|
+
'methods': method_count,
|
|
122
|
+
'line': node.lineno
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
'success': True,
|
|
127
|
+
'cyclomaticComplexity': total_complexity,
|
|
128
|
+
'functions': functions,
|
|
129
|
+
'classes': classes
|
|
130
|
+
}
|
|
131
|
+
except Exception as e:
|
|
132
|
+
return {'success': False, 'error': str(e)}
|
|
133
|
+
|
|
134
|
+
if __name__ == '__main__':
|
|
135
|
+
code = sys.stdin.read()
|
|
136
|
+
action = sys.argv[1] if len(sys.argv) > 1 else 'symbols'
|
|
137
|
+
|
|
138
|
+
if action == 'symbols':
|
|
139
|
+
result = analyze_code(code)
|
|
140
|
+
elif action == 'complexity':
|
|
141
|
+
result = calculate_complexity(code)
|
|
142
|
+
else:
|
|
143
|
+
result = {'success': False, 'error': 'Unknown action'}
|
|
144
|
+
|
|
145
|
+
print(json.dumps(result))
|
|
146
146
|
`;
|
|
147
147
|
// Singleton Python script path to avoid recreating it
|
|
148
148
|
static scriptPath = null;
|
package/dist/lib/gemini-mcp.js
CHANGED
|
@@ -161,12 +161,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
161
161
|
}
|
|
162
162
|
case 'gemini_analyze_code': {
|
|
163
163
|
const { code, language, focus } = args;
|
|
164
|
-
const sysPrompt = `You are an expert code reviewer. Analyze the given ${language || 'code'} and provide detailed feedback focusing on: ${focus || 'all aspects including performance, security, readability, and best practices'}.
|
|
165
|
-
|
|
166
|
-
Respond in Korean and provide:
|
|
167
|
-
1. 코드 요약
|
|
168
|
-
2. 주요 이슈 (있다면)
|
|
169
|
-
3. 개선 제안
|
|
164
|
+
const sysPrompt = `You are an expert code reviewer. Analyze the given ${language || 'code'} and provide detailed feedback focusing on: ${focus || 'all aspects including performance, security, readability, and best practices'}.
|
|
165
|
+
|
|
166
|
+
Respond in Korean and provide:
|
|
167
|
+
1. 코드 요약
|
|
168
|
+
2. 주요 이슈 (있다면)
|
|
169
|
+
3. 개선 제안
|
|
170
170
|
4. 전체 품질 점수 (1-10)`;
|
|
171
171
|
const result = await geminiApi.chat({
|
|
172
172
|
model: 'gemini-2.5-flash',
|
|
@@ -186,15 +186,15 @@ Respond in Korean and provide:
|
|
|
186
186
|
}
|
|
187
187
|
case 'gemini_review_ui': {
|
|
188
188
|
const { description, context } = args;
|
|
189
|
-
const sysPrompt = `You are a UI/UX expert. Review the given UI description and provide detailed feedback.
|
|
190
|
-
|
|
191
|
-
${context ? `Project context: ${context}` : ''}
|
|
192
|
-
|
|
193
|
-
Respond in Korean and provide:
|
|
194
|
-
1. UI 구조 평가
|
|
195
|
-
2. UX 개선점
|
|
196
|
-
3. 접근성 체크
|
|
197
|
-
4. 모범 사례 비교
|
|
189
|
+
const sysPrompt = `You are a UI/UX expert. Review the given UI description and provide detailed feedback.
|
|
190
|
+
|
|
191
|
+
${context ? `Project context: ${context}` : ''}
|
|
192
|
+
|
|
193
|
+
Respond in Korean and provide:
|
|
194
|
+
1. UI 구조 평가
|
|
195
|
+
2. UX 개선점
|
|
196
|
+
3. 접근성 체크
|
|
197
|
+
4. 모범 사례 비교
|
|
198
198
|
5. 구체적인 개선 제안`;
|
|
199
199
|
const result = await geminiApi.chat({
|
|
200
200
|
model: 'gemini-2.5-flash',
|
package/dist/lib/gemini-oauth.js
CHANGED
|
@@ -212,15 +212,15 @@ export function startOAuthFlow() {
|
|
|
212
212
|
const error = url.searchParams.get('error');
|
|
213
213
|
if (error) {
|
|
214
214
|
res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
215
|
-
res.end(`
|
|
216
|
-
<html>
|
|
217
|
-
<head><title>인증 실패</title></head>
|
|
218
|
-
<body style="font-family: sans-serif; text-align: center; padding-top: 50px;">
|
|
219
|
-
<h1>인증 실패</h1>
|
|
220
|
-
<p>오류: ${error}</p>
|
|
221
|
-
<p>이 창을 닫고 다시 시도해주세요.</p>
|
|
222
|
-
</body>
|
|
223
|
-
</html>
|
|
215
|
+
res.end(`
|
|
216
|
+
<html>
|
|
217
|
+
<head><title>인증 실패</title></head>
|
|
218
|
+
<body style="font-family: sans-serif; text-align: center; padding-top: 50px;">
|
|
219
|
+
<h1>인증 실패</h1>
|
|
220
|
+
<p>오류: ${error}</p>
|
|
221
|
+
<p>이 창을 닫고 다시 시도해주세요.</p>
|
|
222
|
+
</body>
|
|
223
|
+
</html>
|
|
224
224
|
`);
|
|
225
225
|
if (!isResolved) {
|
|
226
226
|
isResolved = true;
|
|
@@ -231,14 +231,14 @@ export function startOAuthFlow() {
|
|
|
231
231
|
}
|
|
232
232
|
if (!code || !state) {
|
|
233
233
|
res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
234
|
-
res.end(`
|
|
235
|
-
<html>
|
|
236
|
-
<head><title>인증 실패</title></head>
|
|
237
|
-
<body style="font-family: sans-serif; text-align: center; padding-top: 50px;">
|
|
238
|
-
<h1>인증 실패</h1>
|
|
239
|
-
<p>필수 파라미터가 없습니다.</p>
|
|
240
|
-
</body>
|
|
241
|
-
</html>
|
|
234
|
+
res.end(`
|
|
235
|
+
<html>
|
|
236
|
+
<head><title>인증 실패</title></head>
|
|
237
|
+
<body style="font-family: sans-serif; text-align: center; padding-top: 50px;">
|
|
238
|
+
<h1>인증 실패</h1>
|
|
239
|
+
<p>필수 파라미터가 없습니다.</p>
|
|
240
|
+
</body>
|
|
241
|
+
</html>
|
|
242
242
|
`);
|
|
243
243
|
if (!isResolved) {
|
|
244
244
|
isResolved = true;
|
|
@@ -250,16 +250,16 @@ export function startOAuthFlow() {
|
|
|
250
250
|
try {
|
|
251
251
|
const tokens = await exchangeCodeForTokens(code, state);
|
|
252
252
|
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
253
|
-
res.end(`
|
|
254
|
-
<html>
|
|
255
|
-
<head><title>인증 성공</title></head>
|
|
256
|
-
<body style="font-family: sans-serif; text-align: center; padding-top: 50px;">
|
|
257
|
-
<h1>인증 성공!</h1>
|
|
258
|
-
<p>${tokens.email}로 로그인되었습니다.</p>
|
|
259
|
-
<p>이 창을 닫아도 됩니다.</p>
|
|
260
|
-
<script>setTimeout(() => window.close(), 2000);</script>
|
|
261
|
-
</body>
|
|
262
|
-
</html>
|
|
253
|
+
res.end(`
|
|
254
|
+
<html>
|
|
255
|
+
<head><title>인증 성공</title></head>
|
|
256
|
+
<body style="font-family: sans-serif; text-align: center; padding-top: 50px;">
|
|
257
|
+
<h1>인증 성공!</h1>
|
|
258
|
+
<p>${tokens.email}로 로그인되었습니다.</p>
|
|
259
|
+
<p>이 창을 닫아도 됩니다.</p>
|
|
260
|
+
<script>setTimeout(() => window.close(), 2000);</script>
|
|
261
|
+
</body>
|
|
262
|
+
</html>
|
|
263
263
|
`);
|
|
264
264
|
if (!isResolved) {
|
|
265
265
|
isResolved = true;
|
|
@@ -269,14 +269,14 @@ export function startOAuthFlow() {
|
|
|
269
269
|
}
|
|
270
270
|
catch (err) {
|
|
271
271
|
res.writeHead(500, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
272
|
-
res.end(`
|
|
273
|
-
<html>
|
|
274
|
-
<head><title>인증 실패</title></head>
|
|
275
|
-
<body style="font-family: sans-serif; text-align: center; padding-top: 50px;">
|
|
276
|
-
<h1>인증 실패</h1>
|
|
277
|
-
<p>${err.message}</p>
|
|
278
|
-
</body>
|
|
279
|
-
</html>
|
|
272
|
+
res.end(`
|
|
273
|
+
<html>
|
|
274
|
+
<head><title>인증 실패</title></head>
|
|
275
|
+
<body style="font-family: sans-serif; text-align: center; padding-top: 50px;">
|
|
276
|
+
<h1>인증 실패</h1>
|
|
277
|
+
<p>${err.message}</p>
|
|
278
|
+
</body>
|
|
279
|
+
</html>
|
|
280
280
|
`);
|
|
281
281
|
if (!isResolved) {
|
|
282
282
|
isResolved = true;
|