codehere 0.2.1 → 0.3.0-rc.1
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 +88 -68
- package/dist/domain/entities/task.js +4 -4
- package/dist/error-handler.js +4 -9
- package/dist/index.js +253 -1219
- package/dist/infrastructure/config/product-context.js +7 -6
- package/dist/infrastructure/hooks/claude-sdk-hook.js +335 -63
- package/dist/infrastructure/observability/execution-tracer.js +11 -6
- package/dist/infrastructure/orchestration/agent-adapter.js +13 -0
- package/dist/infrastructure/orchestration/agent-installer.js +101 -0
- package/dist/infrastructure/orchestration/agents-config-seed.js +56 -0
- package/dist/infrastructure/orchestration/aider-adapter.js +319 -0
- package/dist/infrastructure/orchestration/artifacts-extractor.js +175 -0
- package/dist/infrastructure/orchestration/claude-code-adapter.js +352 -0
- package/dist/infrastructure/orchestration/codex-adapter.js +310 -0
- package/dist/infrastructure/orchestration/generic-cli-adapter.js +553 -0
- package/dist/infrastructure/orchestration/opencode-adapter.js +275 -0
- package/dist/infrastructure/orchestration/progress-aggregator.js +189 -0
- package/dist/infrastructure/orchestration/readiness.js +106 -0
- package/dist/infrastructure/orchestration/session-manager.js +272 -0
- package/dist/infrastructure/orchestration/session-persistence.js +109 -0
- package/dist/infrastructure/protocols/mcp-helpers.js +10 -30
- package/dist/infrastructure/protocols/mcp-server-impl.js +359 -21
- package/dist/infrastructure/protocols/ui-page.js +1827 -0
- package/dist/infrastructure/security/file-collection.js +115 -0
- package/dist/infrastructure/security/trust-scorer.js +301 -56
- package/dist/infrastructure/storage/task-repository.js +8 -7
- package/dist/monitoring.js +10 -49
- package/dist/presentation/cli/commands/help-command.js +96 -139
- package/dist/presentation/cli/commands/hook-command.js +17 -24
- package/dist/presentation/cli/commands/report-command.js +59 -72
- package/dist/presentation/cli/commands/setup-command.js +4 -4
- package/dist/presentation/cli/commands/status-command.js +334 -43
- package/dist/presentation/cli/commands/trust-command.js +115 -99
- package/dist/presentation/cli/error-display.js +17 -21
- package/dist/ui.js +17 -12
- package/package.json +35 -67
- package/dist/agents/base.js +0 -101
- package/dist/agents/orchestrator-model-driven.js +0 -141
- package/dist/agents/react-orchestrator-agent.js +0 -54
- package/dist/application/agents/execution-agent.js +0 -508
- package/dist/application/agents/multi-agent-orchestrator.js +0 -295
- package/dist/application/agents/planning-agent.js +0 -433
- package/dist/application/agents/validation-agent.js +0 -317
- package/dist/application/architectures/plan-and-act.js +0 -242
- package/dist/application/index.js +0 -12
- package/dist/application/services/agent-factory.js +0 -28
- package/dist/application/services/dependency-container.js +0 -596
- package/dist/application/services/git-context-service.js +0 -83
- package/dist/application/services/intelligent-router.js +0 -934
- package/dist/application/services/tool-executor-service.js +0 -94
- package/dist/application/use-cases/ask-question-use-case.js +0 -338
- package/dist/application/use-cases/edit-file-use-case.js +0 -830
- package/dist/application/use-cases/explain-file-use-case.js +0 -50
- package/dist/application/use-cases/index-codebase-use-case.js +0 -113
- package/dist/application/use-cases/planning-use-case.js +0 -276
- package/dist/application/use-cases/react-orchestration-use-case.js +0 -329
- package/dist/application/use-cases/reflexion-use-case.js +0 -30
- package/dist/application/workflows/deterministic-workflows.js +0 -189
- package/dist/ast-parser.js +0 -331
- package/dist/cache.js +0 -180
- package/dist/chat.js +0 -251
- package/dist/code-analysis.js +0 -327
- package/dist/context.js +0 -187
- package/dist/docs.js +0 -146
- package/dist/domain/entities/code-chunk.js +0 -6
- package/dist/domain/entities/decision.js +0 -9
- package/dist/domain/entities/edit.js +0 -6
- package/dist/domain/entities/knowledge-node.js +0 -9
- package/dist/domain/entities/knowledge-preservation.js +0 -10
- package/dist/domain/entities/memory.js +0 -6
- package/dist/domain/entities/pattern.js +0 -7
- package/dist/domain/entities/plan.js +0 -6
- package/dist/domain/entities/query.js +0 -6
- package/dist/domain/errors/embeddings-not-found-error.js +0 -13
- package/dist/domain/index.js +0 -19
- package/dist/domain/interfaces/ai-service.interface.js +0 -6
- package/dist/domain/interfaces/code-analyzer.interface.js +0 -6
- package/dist/domain/interfaces/decision-repository.interface.js +0 -9
- package/dist/domain/interfaces/embedding-repository.interface.js +0 -6
- package/dist/domain/interfaces/knowledge-graph-repository.interface.js +0 -9
- package/dist/domain/interfaces/knowledge-preservation-repository.interface.js +0 -8
- package/dist/domain/interfaces/memory-repository.interface.js +0 -6
- package/dist/domain/interfaces/pattern-repository.interface.js +0 -6
- package/dist/domain/interfaces/verification-service.interface.js +0 -6
- package/dist/domain/services/cross-team-pattern-sharing.js +0 -125
- package/dist/domain/services/decision-recorder.js +0 -223
- package/dist/domain/services/decision-retriever.js +0 -133
- package/dist/domain/services/environment-mode-manager.js +0 -22
- package/dist/domain/services/graded-memory-activation.js +0 -69
- package/dist/domain/services/knowledge-access.js +0 -132
- package/dist/domain/services/knowledge-extractor.js +0 -247
- package/dist/domain/services/knowledge-graph-builder.js +0 -268
- package/dist/domain/services/knowledge-graph-query.js +0 -187
- package/dist/domain/services/memory-retriever.js +0 -82
- package/dist/domain/services/memory-synthesizer.js +0 -91
- package/dist/domain/services/pattern-extractor.js +0 -442
- package/dist/domain/services/query-intent-classifier.js +0 -140
- package/dist/domain/services/react-loop.js +0 -186
- package/dist/domain/services/risk-tier-detector.js +0 -78
- package/dist/edit.js +0 -319
- package/dist/embed.js +0 -459
- package/dist/formatter.js +0 -168
- package/dist/git.js +0 -198
- package/dist/infrastructure/ai/cohere-ai-service.js +0 -607
- package/dist/infrastructure/ai/command-r-evaluation.js +0 -206
- package/dist/infrastructure/ai/model-config.js +0 -84
- package/dist/infrastructure/ai/provider-ai-service.js +0 -477
- package/dist/infrastructure/cache/embedding-cache.js +0 -175
- package/dist/infrastructure/cache/query-result-cache.js +0 -66
- package/dist/infrastructure/cache/response-cache.js +0 -48
- package/dist/infrastructure/cache/security-scan-cache.js +0 -47
- package/dist/infrastructure/chunking/ast-code-chunker.js +0 -19
- package/dist/infrastructure/chunking/code-aware-chunker.js +0 -397
- package/dist/infrastructure/context/context-compressor.js +0 -329
- package/dist/infrastructure/context/conversation-context.js +0 -128
- package/dist/infrastructure/context/session-manager.js +0 -94
- package/dist/infrastructure/cost/cost-tracker.js +0 -360
- package/dist/infrastructure/file-scanner/file-scanner.js +0 -106
- package/dist/infrastructure/governance/nist-ai-rmf.js +0 -292
- package/dist/infrastructure/governance/policy-as-code.js +0 -258
- package/dist/infrastructure/governance/prompt-to-code-lineage.js +0 -239
- package/dist/infrastructure/index.js +0 -7
- package/dist/infrastructure/observability/prompt-versioner.js +0 -145
- package/dist/infrastructure/protocols/a2a-metadata.js +0 -137
- package/dist/infrastructure/protocols/a2a-protocol.js +0 -314
- package/dist/infrastructure/protocols/mcp-oauth.js +0 -184
- package/dist/infrastructure/protocols/mcp-server.js +0 -333
- package/dist/infrastructure/protocols/streaming-handler.js +0 -103
- package/dist/infrastructure/providers/cohere-provider.js +0 -444
- package/dist/infrastructure/providers/fake-provider.js +0 -130
- package/dist/infrastructure/providers/local-llm-provider.js +0 -330
- package/dist/infrastructure/providers/model-config.types.js +0 -9
- package/dist/infrastructure/providers/model-provider.interface.js +0 -8
- package/dist/infrastructure/providers/openai-provider.js +0 -413
- package/dist/infrastructure/providers/openrouter-provider.js +0 -399
- package/dist/infrastructure/providers/operation-provider-resolver.js +0 -105
- package/dist/infrastructure/providers/provider-config-loader.js +0 -120
- package/dist/infrastructure/providers/provider-registry.js +0 -88
- package/dist/infrastructure/safety/pattern-detector.js +0 -133
- package/dist/infrastructure/security/ai-sast-scanner.js +0 -290
- package/dist/infrastructure/security/docker-sandbox.js +0 -178
- package/dist/infrastructure/security/enhanced-security-gate.js +0 -151
- package/dist/infrastructure/security/license-scanner.js +0 -167
- package/dist/infrastructure/security/provider-bias-detector.js +0 -164
- package/dist/infrastructure/security/sandbox-executor.js +0 -64
- package/dist/infrastructure/serialization/toon-serializer.js +0 -119
- package/dist/infrastructure/storage/memory-stream-service.js +0 -204
- package/dist/infrastructure/storage/plan-repository.js +0 -96
- package/dist/infrastructure/storage/sqlite-decision-repository.js +0 -232
- package/dist/infrastructure/storage/sqlite-embedding-repository.js +0 -311
- package/dist/infrastructure/storage/sqlite-knowledge-graph-repository.js +0 -417
- package/dist/infrastructure/storage/sqlite-knowledge-preservation-repository.js +0 -230
- package/dist/infrastructure/storage/sqlite-memory-repository.js +0 -229
- package/dist/infrastructure/storage/sqlite-pattern-repository.js +0 -249
- package/dist/infrastructure/storage/task-helpers.js +0 -197
- package/dist/infrastructure/telemetry/telemetry-service.js +0 -167
- package/dist/infrastructure/ux/appropriate-friction.js +0 -213
- package/dist/infrastructure/ux/bi-directional-learning.js +0 -337
- package/dist/infrastructure/ux/capability-boundaries.js +0 -42
- package/dist/infrastructure/ux/comprehensive-formatter.js +0 -117
- package/dist/infrastructure/ux/contextual-feature-discovery.js +0 -10
- package/dist/infrastructure/ux/expectation-management.js +0 -327
- package/dist/infrastructure/ux/feature-discovery.js +0 -14
- package/dist/infrastructure/ux/feedback-prompt.js +0 -45
- package/dist/infrastructure/ux/hitl-validation.js +0 -297
- package/dist/infrastructure/ux/progress-indicator.js +0 -116
- package/dist/infrastructure/ux/progressive-disclosure.js +0 -236
- package/dist/infrastructure/ux/review-checkpoint.js +0 -72
- package/dist/infrastructure/ux/staged-feature-intro.js +0 -24
- package/dist/infrastructure/ux/stream-markdown.js +0 -151
- package/dist/infrastructure/ux/syntax-highlighter.js +0 -91
- package/dist/infrastructure/ux/team-standards.js +0 -196
- package/dist/infrastructure/ux/transparency.js +0 -71
- package/dist/infrastructure/validation/agent-feedback.js +0 -55
- package/dist/infrastructure/validation/agent-validation-helper.js +0 -137
- package/dist/infrastructure/validation/review-handler.js +0 -40
- package/dist/infrastructure/validation/summary-aggregator.js +0 -70
- package/dist/infrastructure/validation/summary-extractor.js +0 -45
- package/dist/infrastructure/validation/trace-summary.js +0 -52
- package/dist/infrastructure/verification/verification-service.js +0 -47
- package/dist/infrastructure/xai/attention-visualizer.js +0 -172
- package/dist/infrastructure/xai/cot-visualizer.js +0 -283
- package/dist/infrastructure/xai/decision-tree-log.js +0 -212
- package/dist/infrastructure/xai/interactive-xai.js +0 -260
- package/dist/infrastructure/xai/uncertainty-quantifier.js +0 -198
- package/dist/intelligent-retrieval.js +0 -272
- package/dist/intent/classifier.js +0 -2
- package/dist/intent/context.js +0 -2
- package/dist/iterative-refinement.js +0 -189
- package/dist/learning.js +0 -232
- package/dist/log.js +0 -31
- package/dist/migrate.js +0 -133
- package/dist/parallel-processor.js +0 -530
- package/dist/planner.js +0 -198
- package/dist/policy.js +0 -26
- package/dist/presentation/cli/commands/ask-command.js +0 -314
- package/dist/presentation/cli/commands/cost-command.js +0 -191
- package/dist/presentation/cli/commands/decision-command.js +0 -207
- package/dist/presentation/cli/commands/docs-command.js +0 -25
- package/dist/presentation/cli/commands/fix-command.js +0 -53
- package/dist/presentation/cli/commands/knowledge-command.js +0 -129
- package/dist/presentation/cli/commands/learning-dashboard-command.js +0 -183
- package/dist/presentation/cli/commands/models-command.js +0 -194
- package/dist/presentation/cli/commands/orchestrate-command.js +0 -207
- package/dist/presentation/cli/commands/plan-command.js +0 -246
- package/dist/presentation/cli/commands/product-command.js +0 -199
- package/dist/presentation/cli/commands/react-command.js +0 -181
- package/dist/presentation/cli/commands/review-command.js +0 -154
- package/dist/presentation/cli/commands/run-command.js +0 -188
- package/dist/presentation/cli/commands/smart-command.js +0 -395
- package/dist/presentation/cli/commands/suggest-command.js +0 -138
- package/dist/presentation/cli/commands/trace-command.js +0 -129
- package/dist/presentation/cli/commands/undo-command.js +0 -150
- package/dist/query-optimizer.js +0 -205
- package/dist/refactor.js +0 -116
- package/dist/review.js +0 -206
- package/dist/search.js +0 -163
- package/dist/session.js +0 -652
- package/dist/task-verification.js +0 -336
- package/dist/testgen.js +0 -166
- package/dist/token-optimizer.js +0 -277
- package/dist/tools/bash.js +0 -213
- package/dist/tools/edit.js +0 -235
- package/dist/tools/executor.js +0 -153
- package/dist/tools/git-tool.js +0 -292
- package/dist/tools/parser.js +0 -158
- package/dist/tools/registry.js +0 -302
- package/dist/tools/search.js +0 -100
- package/dist/types.js +0 -2
- package/dist/utils/check-api-status.js +0 -100
- package/dist/utils/diff-parser.js +0 -162
- package/dist/verification/backup.js +0 -259
- package/dist/verification/compiler.js +0 -264
- package/dist/verification/index.js +0 -273
- package/dist/verification/test-runner.js +0 -379
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Infrastructure: SQLiteDecisionRepository
|
|
3
|
-
* SQLite implementation of decision storage
|
|
4
|
-
*
|
|
5
|
-
* Clean Architecture: Infrastructure Layer
|
|
6
|
-
* Pattern: Repository Pattern Implementation
|
|
7
|
-
*/
|
|
8
|
-
import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
9
|
-
import { join, dirname } from 'path';
|
|
10
|
-
import { fileURLToPath } from 'url';
|
|
11
|
-
import initSqlJs from 'sql.js';
|
|
12
|
-
import { randomUUID } from 'crypto';
|
|
13
|
-
function getDbPath() {
|
|
14
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
-
const __dirname = dirname(__filename);
|
|
16
|
-
const agentDir = join(__dirname, '../../..');
|
|
17
|
-
if (existsSync(join(agentDir, 'package.json'))) {
|
|
18
|
-
return join(agentDir, 'data', 'decisions.sqlite');
|
|
19
|
-
}
|
|
20
|
-
return join(process.cwd(), 'agent', 'data', 'decisions.sqlite');
|
|
21
|
-
}
|
|
22
|
-
export class SQLiteDecisionRepository {
|
|
23
|
-
dbPath;
|
|
24
|
-
db = null;
|
|
25
|
-
constructor() {
|
|
26
|
-
this.dbPath = getDbPath();
|
|
27
|
-
}
|
|
28
|
-
async getDb() {
|
|
29
|
-
if (this.db)
|
|
30
|
-
return this.db;
|
|
31
|
-
const SQL = await initSqlJs();
|
|
32
|
-
const dbDir = dirname(this.dbPath);
|
|
33
|
-
if (!existsSync(dbDir)) {
|
|
34
|
-
mkdirSync(dbDir, { recursive: true });
|
|
35
|
-
}
|
|
36
|
-
if (existsSync(this.dbPath)) {
|
|
37
|
-
const buffer = readFileSync(this.dbPath);
|
|
38
|
-
this.db = new SQL.Database(buffer);
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
this.db = new SQL.Database();
|
|
42
|
-
}
|
|
43
|
-
// Create decisions table
|
|
44
|
-
this.db.run(`
|
|
45
|
-
CREATE TABLE IF NOT EXISTS decisions (
|
|
46
|
-
id TEXT PRIMARY KEY,
|
|
47
|
-
codebaseId TEXT NOT NULL,
|
|
48
|
-
type TEXT NOT NULL,
|
|
49
|
-
title TEXT NOT NULL,
|
|
50
|
-
description TEXT NOT NULL,
|
|
51
|
-
rationale TEXT NOT NULL,
|
|
52
|
-
alternatives TEXT,
|
|
53
|
-
constraints TEXT,
|
|
54
|
-
tradeoffs TEXT,
|
|
55
|
-
consequences TEXT,
|
|
56
|
-
metadata TEXT,
|
|
57
|
-
createdAt INTEGER NOT NULL,
|
|
58
|
-
updatedAt INTEGER,
|
|
59
|
-
author TEXT
|
|
60
|
-
)
|
|
61
|
-
`);
|
|
62
|
-
// Create indexes
|
|
63
|
-
this.db.run(`CREATE INDEX IF NOT EXISTS idx_codebase ON decisions(codebaseId)`);
|
|
64
|
-
this.db.run(`CREATE INDEX IF NOT EXISTS idx_type ON decisions(codebaseId, type)`);
|
|
65
|
-
this.db.run(`CREATE INDEX IF NOT EXISTS idx_created ON decisions(codebaseId, createdAt DESC)`);
|
|
66
|
-
this.db.run(`CREATE INDEX IF NOT EXISTS idx_status ON decisions(codebaseId, json_extract(metadata, '$.status'))`);
|
|
67
|
-
return this.db;
|
|
68
|
-
}
|
|
69
|
-
async store(decision) {
|
|
70
|
-
const db = await this.getDb();
|
|
71
|
-
const id = decision.id || randomUUID();
|
|
72
|
-
const now = Date.now();
|
|
73
|
-
const stmt = db.prepare(`
|
|
74
|
-
INSERT OR REPLACE INTO decisions
|
|
75
|
-
(id, codebaseId, type, title, description, rationale, alternatives, constraints,
|
|
76
|
-
tradeoffs, consequences, metadata, createdAt, updatedAt, author)
|
|
77
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
78
|
-
`);
|
|
79
|
-
stmt.run([
|
|
80
|
-
id,
|
|
81
|
-
decision.codebaseId,
|
|
82
|
-
decision.type,
|
|
83
|
-
decision.title,
|
|
84
|
-
decision.description,
|
|
85
|
-
decision.rationale,
|
|
86
|
-
JSON.stringify(decision.alternatives ?? []),
|
|
87
|
-
JSON.stringify(decision.constraints ?? []),
|
|
88
|
-
JSON.stringify(decision.tradeoffs ?? []),
|
|
89
|
-
JSON.stringify(decision.consequences ?? []),
|
|
90
|
-
JSON.stringify(decision.metadata ?? {}),
|
|
91
|
-
decision.createdAt.getTime(),
|
|
92
|
-
decision.updatedAt?.getTime() ?? now,
|
|
93
|
-
decision.author ?? null,
|
|
94
|
-
]);
|
|
95
|
-
stmt.free();
|
|
96
|
-
this.saveDb();
|
|
97
|
-
}
|
|
98
|
-
async getById(id) {
|
|
99
|
-
const db = await this.getDb();
|
|
100
|
-
const stmt = db.prepare('SELECT * FROM decisions WHERE id = ?');
|
|
101
|
-
stmt.bind([id]);
|
|
102
|
-
if (!stmt.step()) {
|
|
103
|
-
stmt.free();
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
const row = stmt.getAsObject();
|
|
107
|
-
stmt.free();
|
|
108
|
-
return this.mapRowToDecision(row);
|
|
109
|
-
}
|
|
110
|
-
async findByCodebase(codebaseId, limit = 100) {
|
|
111
|
-
const db = await this.getDb();
|
|
112
|
-
const stmt = db.prepare(`
|
|
113
|
-
SELECT * FROM decisions
|
|
114
|
-
WHERE codebaseId = ?
|
|
115
|
-
ORDER BY createdAt DESC
|
|
116
|
-
LIMIT ?
|
|
117
|
-
`);
|
|
118
|
-
stmt.bind([codebaseId, limit]);
|
|
119
|
-
return this.executeAndMap(stmt);
|
|
120
|
-
}
|
|
121
|
-
async findByType(codebaseId, type, limit = 100) {
|
|
122
|
-
const db = await this.getDb();
|
|
123
|
-
const stmt = db.prepare(`
|
|
124
|
-
SELECT * FROM decisions
|
|
125
|
-
WHERE codebaseId = ? AND type = ?
|
|
126
|
-
ORDER BY createdAt DESC
|
|
127
|
-
LIMIT ?
|
|
128
|
-
`);
|
|
129
|
-
stmt.bind([codebaseId, type, limit]);
|
|
130
|
-
return this.executeAndMap(stmt);
|
|
131
|
-
}
|
|
132
|
-
async search(codebaseId, query, limit = 50) {
|
|
133
|
-
const db = await this.getDb();
|
|
134
|
-
const searchTerm = `%${query}%`;
|
|
135
|
-
const stmt = db.prepare(`
|
|
136
|
-
SELECT * FROM decisions
|
|
137
|
-
WHERE codebaseId = ?
|
|
138
|
-
AND (title LIKE ? OR description LIKE ? OR rationale LIKE ?)
|
|
139
|
-
ORDER BY createdAt DESC
|
|
140
|
-
LIMIT ?
|
|
141
|
-
`);
|
|
142
|
-
stmt.bind([codebaseId, searchTerm, searchTerm, searchTerm, limit]);
|
|
143
|
-
return this.executeAndMap(stmt);
|
|
144
|
-
}
|
|
145
|
-
async update(decision) {
|
|
146
|
-
if (!decision.id) {
|
|
147
|
-
throw new Error('Decision ID required for update');
|
|
148
|
-
}
|
|
149
|
-
decision.updatedAt = new Date();
|
|
150
|
-
await this.store(decision); // INSERT OR REPLACE handles update
|
|
151
|
-
}
|
|
152
|
-
async delete(id) {
|
|
153
|
-
const db = await this.getDb();
|
|
154
|
-
const stmt = db.prepare('DELETE FROM decisions WHERE id = ?');
|
|
155
|
-
stmt.run([id]);
|
|
156
|
-
stmt.free();
|
|
157
|
-
this.saveDb();
|
|
158
|
-
}
|
|
159
|
-
async getRecent(codebaseId, limit = 10) {
|
|
160
|
-
const db = await this.getDb();
|
|
161
|
-
const stmt = db.prepare(`
|
|
162
|
-
SELECT * FROM decisions
|
|
163
|
-
WHERE codebaseId = ?
|
|
164
|
-
ORDER BY createdAt DESC
|
|
165
|
-
LIMIT ?
|
|
166
|
-
`);
|
|
167
|
-
stmt.bind([codebaseId, limit]);
|
|
168
|
-
return this.executeAndMap(stmt);
|
|
169
|
-
}
|
|
170
|
-
async getByStatus(codebaseId, status, limit = 100) {
|
|
171
|
-
const db = await this.getDb();
|
|
172
|
-
const stmt = db.prepare(`
|
|
173
|
-
SELECT * FROM decisions
|
|
174
|
-
WHERE codebaseId = ?
|
|
175
|
-
AND json_extract(metadata, '$.status') = ?
|
|
176
|
-
ORDER BY createdAt DESC
|
|
177
|
-
LIMIT ?
|
|
178
|
-
`);
|
|
179
|
-
stmt.bind([codebaseId, status, limit]);
|
|
180
|
-
return this.executeAndMap(stmt);
|
|
181
|
-
}
|
|
182
|
-
async findRelated(decisionId, limit = 10) {
|
|
183
|
-
const decision = await this.getById(decisionId);
|
|
184
|
-
if (!decision || !decision.metadata?.relatedDecisions) {
|
|
185
|
-
return [];
|
|
186
|
-
}
|
|
187
|
-
const relatedIds = decision.metadata.relatedDecisions.slice(0, limit);
|
|
188
|
-
const related = [];
|
|
189
|
-
for (const id of relatedIds) {
|
|
190
|
-
const relatedDecision = await this.getById(id);
|
|
191
|
-
if (relatedDecision) {
|
|
192
|
-
related.push(relatedDecision);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
return related;
|
|
196
|
-
}
|
|
197
|
-
mapRowToDecision(row) {
|
|
198
|
-
const metadata = JSON.parse(row.metadata ?? '{}');
|
|
199
|
-
return {
|
|
200
|
-
id: row.id,
|
|
201
|
-
codebaseId: row.codebaseId,
|
|
202
|
-
type: row.type,
|
|
203
|
-
title: row.title,
|
|
204
|
-
description: row.description,
|
|
205
|
-
rationale: row.rationale,
|
|
206
|
-
alternatives: JSON.parse(row.alternatives ?? '[]'),
|
|
207
|
-
constraints: JSON.parse(row.constraints ?? '[]'),
|
|
208
|
-
tradeoffs: JSON.parse(row.tradeoffs ?? '[]'),
|
|
209
|
-
consequences: JSON.parse(row.consequences ?? '[]'),
|
|
210
|
-
metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
|
|
211
|
-
createdAt: new Date(row.createdAt),
|
|
212
|
-
updatedAt: row.updatedAt ? new Date(row.updatedAt) : undefined,
|
|
213
|
-
author: row.author ?? undefined,
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
executeAndMap(stmt) {
|
|
217
|
-
const decisions = [];
|
|
218
|
-
while (stmt.step()) {
|
|
219
|
-
decisions.push(this.mapRowToDecision(stmt.getAsObject()));
|
|
220
|
-
}
|
|
221
|
-
stmt.free();
|
|
222
|
-
return decisions;
|
|
223
|
-
}
|
|
224
|
-
saveDb() {
|
|
225
|
-
if (!this.db)
|
|
226
|
-
return;
|
|
227
|
-
const data = this.db.export();
|
|
228
|
-
const buffer = Buffer.from(data);
|
|
229
|
-
writeFileSync(this.dbPath, buffer);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
//# sourceMappingURL=sqlite-decision-repository.js.map
|
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Infrastructure: SQLiteEmbeddingRepository
|
|
3
|
-
* Implements IEmbeddingRepository using SQLite
|
|
4
|
-
*/
|
|
5
|
-
import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
6
|
-
import { join, dirname } from 'path';
|
|
7
|
-
import { fileURLToPath } from 'url';
|
|
8
|
-
import initSqlJs from 'sql.js';
|
|
9
|
-
import { getQueryResultCache } from '../cache/query-result-cache.js';
|
|
10
|
-
import { getEmbeddingsDbPath } from './embeddings-path.js';
|
|
11
|
-
/**
|
|
12
|
-
* @deprecated Legacy global DB path - use getEmbeddingsDbPath() instead
|
|
13
|
-
* This function is not used - SQLiteEmbeddingRepository now uses per-repo paths by default
|
|
14
|
-
* Kept only for reference during migration
|
|
15
|
-
*/
|
|
16
|
-
function getLegacyDbPath() {
|
|
17
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
-
const __dirname = dirname(__filename);
|
|
19
|
-
const agentDir = join(__dirname, '../../..');
|
|
20
|
-
if (existsSync(join(agentDir, 'package.json'))) {
|
|
21
|
-
return join(agentDir, 'data', 'embeddings.sqlite');
|
|
22
|
-
}
|
|
23
|
-
return join(process.cwd(), 'agent', 'data', 'embeddings.sqlite');
|
|
24
|
-
}
|
|
25
|
-
function cosineSimilarity(a, b) {
|
|
26
|
-
if (a.length !== b.length)
|
|
27
|
-
return 0;
|
|
28
|
-
let dotProduct = 0;
|
|
29
|
-
let normA = 0;
|
|
30
|
-
let normB = 0;
|
|
31
|
-
for (let i = 0; i < a.length; i++) {
|
|
32
|
-
dotProduct += a[i] * b[i];
|
|
33
|
-
normA += a[i] * a[i];
|
|
34
|
-
normB += b[i] * b[i];
|
|
35
|
-
}
|
|
36
|
-
const denominator = Math.sqrt(normA) * Math.sqrt(normB);
|
|
37
|
-
return denominator === 0 ? 0 : dotProduct / denominator;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Optimized cosine similarity with pre-computed query norm
|
|
41
|
-
* Reduces redundant calculations when comparing same query to multiple embeddings
|
|
42
|
-
*/
|
|
43
|
-
function cosineSimilarityOptimized(queryEmbedding, queryNorm, docEmbedding) {
|
|
44
|
-
if (queryEmbedding.length !== docEmbedding.length)
|
|
45
|
-
return 0;
|
|
46
|
-
let dotProduct = 0;
|
|
47
|
-
let docNorm = 0;
|
|
48
|
-
for (let i = 0; i < docEmbedding.length; i++) {
|
|
49
|
-
dotProduct += queryEmbedding[i] * docEmbedding[i];
|
|
50
|
-
docNorm += docEmbedding[i] * docEmbedding[i];
|
|
51
|
-
}
|
|
52
|
-
const denominator = queryNorm * Math.sqrt(docNorm);
|
|
53
|
-
return denominator === 0 ? 0 : dotProduct / denominator;
|
|
54
|
-
}
|
|
55
|
-
export class SQLiteEmbeddingRepository {
|
|
56
|
-
dbPath;
|
|
57
|
-
db = null;
|
|
58
|
-
/**
|
|
59
|
-
* @param dbPath - Optional database path. If not provided, uses per-repo path via getEmbeddingsDbPath()
|
|
60
|
-
* @param cwd - Optional current working directory for codebase root detection (defaults to process.cwd())
|
|
61
|
-
*/
|
|
62
|
-
constructor(dbPath, cwd) {
|
|
63
|
-
if (dbPath) {
|
|
64
|
-
// Use provided path
|
|
65
|
-
this.dbPath = dbPath;
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
// Use per-repo path based on codebase root
|
|
69
|
-
const pathInfo = getEmbeddingsDbPath(cwd);
|
|
70
|
-
this.dbPath = pathInfo.dbPath;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
async getDb() {
|
|
74
|
-
if (this.db)
|
|
75
|
-
return this.db;
|
|
76
|
-
const SQL = await initSqlJs();
|
|
77
|
-
const dbDir = dirname(this.dbPath);
|
|
78
|
-
if (!existsSync(dbDir)) {
|
|
79
|
-
mkdirSync(dbDir, { recursive: true });
|
|
80
|
-
}
|
|
81
|
-
if (existsSync(this.dbPath)) {
|
|
82
|
-
const buffer = readFileSync(this.dbPath);
|
|
83
|
-
this.db = new SQL.Database(buffer);
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
this.db = new SQL.Database();
|
|
87
|
-
}
|
|
88
|
-
this.db.run(`
|
|
89
|
-
CREATE TABLE IF NOT EXISTS embeddings (
|
|
90
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
91
|
-
filepath TEXT NOT NULL,
|
|
92
|
-
chunkIndex INTEGER NOT NULL,
|
|
93
|
-
content TEXT NOT NULL,
|
|
94
|
-
embedding TEXT NOT NULL
|
|
95
|
-
)
|
|
96
|
-
`);
|
|
97
|
-
this.db.run(`
|
|
98
|
-
CREATE INDEX IF NOT EXISTS idx_filepath ON embeddings(filepath)
|
|
99
|
-
`);
|
|
100
|
-
return this.db;
|
|
101
|
-
}
|
|
102
|
-
async store(chunks) {
|
|
103
|
-
const db = await this.getDb();
|
|
104
|
-
db.run('DELETE FROM embeddings');
|
|
105
|
-
const stmt = db.prepare(`
|
|
106
|
-
INSERT INTO embeddings (filepath, chunkIndex, content, embedding)
|
|
107
|
-
VALUES (?, ?, ?, ?)
|
|
108
|
-
`);
|
|
109
|
-
for (const chunk of chunks) {
|
|
110
|
-
if (!chunk.embedding)
|
|
111
|
-
continue;
|
|
112
|
-
stmt.run([
|
|
113
|
-
chunk.filepath,
|
|
114
|
-
chunk.chunkIndex || 0,
|
|
115
|
-
chunk.content,
|
|
116
|
-
JSON.stringify(chunk.embedding),
|
|
117
|
-
]);
|
|
118
|
-
}
|
|
119
|
-
stmt.free();
|
|
120
|
-
this.saveDb();
|
|
121
|
-
// Clear query result cache when codebase is re-indexed
|
|
122
|
-
getQueryResultCache().clear();
|
|
123
|
-
}
|
|
124
|
-
async search(query, topK) {
|
|
125
|
-
// For now, return empty - will implement with query embedding
|
|
126
|
-
// This requires AI service, which creates circular dependency
|
|
127
|
-
// Will be resolved via dependency injection in application layer
|
|
128
|
-
return [];
|
|
129
|
-
}
|
|
130
|
-
async getByFilepath(filepath) {
|
|
131
|
-
const db = await this.getDb();
|
|
132
|
-
const stmt = db.prepare('SELECT * FROM embeddings WHERE filepath = ?');
|
|
133
|
-
stmt.bind([filepath]);
|
|
134
|
-
const results = [];
|
|
135
|
-
while (stmt.step()) {
|
|
136
|
-
const row = stmt.getAsObject();
|
|
137
|
-
results.push({
|
|
138
|
-
filepath: row.filepath,
|
|
139
|
-
content: row.content,
|
|
140
|
-
score: 1.0,
|
|
141
|
-
chunkIndex: row.chunkIndex,
|
|
142
|
-
embedding: JSON.parse(row.embedding),
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
stmt.free();
|
|
146
|
-
return results;
|
|
147
|
-
}
|
|
148
|
-
async isIndexed(filepath) {
|
|
149
|
-
const db = await this.getDb();
|
|
150
|
-
const stmt = db.prepare('SELECT COUNT(*) as count FROM embeddings WHERE filepath = ?');
|
|
151
|
-
stmt.bind([filepath]);
|
|
152
|
-
stmt.step();
|
|
153
|
-
const result = stmt.getAsObject();
|
|
154
|
-
stmt.free();
|
|
155
|
-
return result.count > 0;
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Check if any embeddings exist for this repository
|
|
159
|
-
* Used to detect when a repo has never been indexed
|
|
160
|
-
*/
|
|
161
|
-
async hasEmbeddings() {
|
|
162
|
-
// Check if DB file exists
|
|
163
|
-
if (!existsSync(this.dbPath)) {
|
|
164
|
-
return false;
|
|
165
|
-
}
|
|
166
|
-
const db = await this.getDb();
|
|
167
|
-
const stmt = db.prepare('SELECT COUNT(*) as count FROM embeddings');
|
|
168
|
-
stmt.step();
|
|
169
|
-
const result = stmt.getAsObject();
|
|
170
|
-
stmt.free();
|
|
171
|
-
return result.count > 0;
|
|
172
|
-
}
|
|
173
|
-
async clear() {
|
|
174
|
-
const db = await this.getDb();
|
|
175
|
-
db.run('DELETE FROM embeddings');
|
|
176
|
-
this.saveDb();
|
|
177
|
-
}
|
|
178
|
-
saveDb() {
|
|
179
|
-
if (!this.db)
|
|
180
|
-
return;
|
|
181
|
-
const data = this.db.export();
|
|
182
|
-
const buffer = Buffer.from(data);
|
|
183
|
-
writeFileSync(this.dbPath, buffer);
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Search with pre-computed query embedding
|
|
187
|
-
* (Used by application layer to avoid circular dependency)
|
|
188
|
-
*
|
|
189
|
-
* PERFORMANCE OPTIMIZATION:
|
|
190
|
-
* 1. Uses min-heap to maintain only topK results (O(n log k) vs O(n log n))
|
|
191
|
-
* 2. Pre-computes query norm once (avoids redundant calculations)
|
|
192
|
-
* 3. Optimized cosine similarity calculation
|
|
193
|
-
* 4. Result caching (query + topK results) to avoid redundant searches
|
|
194
|
-
* 5. Batch processing with early termination for large datasets
|
|
195
|
-
* 6. Optimized JSON parsing (cache parsed embeddings per row)
|
|
196
|
-
*
|
|
197
|
-
* Note: Cache key should be generated from query string, not embedding
|
|
198
|
-
* This method receives embedding, so caching should be done at call site
|
|
199
|
-
*/
|
|
200
|
-
async searchWithEmbedding(queryEmbedding, topK) {
|
|
201
|
-
const db = await this.getDb();
|
|
202
|
-
// Pre-compute query norm once (used for all similarity calculations)
|
|
203
|
-
let queryNorm = 0;
|
|
204
|
-
for (let i = 0; i < queryEmbedding.length; i++) {
|
|
205
|
-
queryNorm += queryEmbedding[i] * queryEmbedding[i];
|
|
206
|
-
}
|
|
207
|
-
queryNorm = Math.sqrt(queryNorm);
|
|
208
|
-
// Get total count for optimization decisions
|
|
209
|
-
const countStmt = db.prepare('SELECT COUNT(*) as count FROM embeddings');
|
|
210
|
-
countStmt.step();
|
|
211
|
-
const totalCount = countStmt.getAsObject().count;
|
|
212
|
-
countStmt.free();
|
|
213
|
-
// OPTIMIZATION: Early termination for large datasets
|
|
214
|
-
// Process with early termination if dataset is large
|
|
215
|
-
const USE_EARLY_TERMINATION = totalCount > 500;
|
|
216
|
-
const MAX_PROCESS = USE_EARLY_TERMINATION ? Math.min(totalCount, 1000) : totalCount;
|
|
217
|
-
// Min-heap to maintain topK results (smallest score at root)
|
|
218
|
-
const heap = [];
|
|
219
|
-
const heapInsert = (item) => {
|
|
220
|
-
if (heap.length < topK) {
|
|
221
|
-
heap.push(item);
|
|
222
|
-
// Bubble up
|
|
223
|
-
let i = heap.length - 1;
|
|
224
|
-
while (i > 0) {
|
|
225
|
-
const parent = Math.floor((i - 1) / 2);
|
|
226
|
-
if (heap[parent].score <= heap[i].score)
|
|
227
|
-
break;
|
|
228
|
-
[heap[parent], heap[i]] = [heap[i], heap[parent]];
|
|
229
|
-
i = parent;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
else if (item.score > heap[0].score) {
|
|
233
|
-
// Replace root (smallest) with new item if it's larger
|
|
234
|
-
heap[0] = item;
|
|
235
|
-
// Bubble down
|
|
236
|
-
let i = 0;
|
|
237
|
-
while (true) {
|
|
238
|
-
const left = 2 * i + 1;
|
|
239
|
-
const right = 2 * i + 2;
|
|
240
|
-
let smallest = i;
|
|
241
|
-
if (left < heap.length && heap[left].score < heap[smallest].score) {
|
|
242
|
-
smallest = left;
|
|
243
|
-
}
|
|
244
|
-
if (right < heap.length && heap[right].score < heap[smallest].score) {
|
|
245
|
-
smallest = right;
|
|
246
|
-
}
|
|
247
|
-
if (smallest === i)
|
|
248
|
-
break;
|
|
249
|
-
[heap[i], heap[smallest]] = [heap[smallest], heap[i]];
|
|
250
|
-
i = smallest;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
};
|
|
254
|
-
// Standard query - early termination will handle large datasets
|
|
255
|
-
const stmt = db.prepare('SELECT * FROM embeddings');
|
|
256
|
-
let processed = 0;
|
|
257
|
-
let consecutiveLowScores = 0;
|
|
258
|
-
const EARLY_TERMINATION_THRESHOLD = USE_EARLY_TERMINATION ? 150 : Infinity; // More aggressive for large datasets
|
|
259
|
-
// Process embeddings in batches with early termination
|
|
260
|
-
while (stmt.step()) {
|
|
261
|
-
const row = stmt.getAsObject();
|
|
262
|
-
// Parse embedding (try-catch for invalid JSON)
|
|
263
|
-
let embedding;
|
|
264
|
-
try {
|
|
265
|
-
embedding = JSON.parse(row.embedding);
|
|
266
|
-
}
|
|
267
|
-
catch {
|
|
268
|
-
continue; // Skip invalid embeddings
|
|
269
|
-
}
|
|
270
|
-
// Compute similarity using optimized function (pre-computed query norm)
|
|
271
|
-
const score = cosineSimilarityOptimized(queryEmbedding, queryNorm, embedding);
|
|
272
|
-
// Insert into heap (maintains topK)
|
|
273
|
-
heapInsert({
|
|
274
|
-
chunk: {
|
|
275
|
-
filepath: row.filepath,
|
|
276
|
-
content: row.content,
|
|
277
|
-
score,
|
|
278
|
-
chunkIndex: row.chunkIndex,
|
|
279
|
-
embedding,
|
|
280
|
-
},
|
|
281
|
-
score,
|
|
282
|
-
});
|
|
283
|
-
processed++;
|
|
284
|
-
// Early termination: If we have topK results and many consecutive low scores,
|
|
285
|
-
// likely we've found the best matches
|
|
286
|
-
if (heap.length >= topK) {
|
|
287
|
-
const minScore = heap[0].score;
|
|
288
|
-
if (score < minScore * 0.8) { // Score significantly lower than current min
|
|
289
|
-
consecutiveLowScores++;
|
|
290
|
-
if (consecutiveLowScores > EARLY_TERMINATION_THRESHOLD) {
|
|
291
|
-
break; // Early termination
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
consecutiveLowScores = 0; // Reset counter
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
// Limit total processing for very large datasets (early termination optimization)
|
|
299
|
-
if (processed >= MAX_PROCESS) {
|
|
300
|
-
break;
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
stmt.free();
|
|
304
|
-
// Extract results from heap and sort descending (highest scores first)
|
|
305
|
-
const results = heap
|
|
306
|
-
.sort((a, b) => b.score - a.score)
|
|
307
|
-
.map(r => r.chunk);
|
|
308
|
-
return results;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
//# sourceMappingURL=sqlite-embedding-repository.js.map
|