claude-conversation-memory-mcp 0.1.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/LICENSE +21 -0
- package/README.md +223 -0
- package/dist/ConversationMemory.d.ts +80 -0
- package/dist/ConversationMemory.d.ts.map +1 -0
- package/dist/ConversationMemory.js +203 -0
- package/dist/ConversationMemory.js.map +1 -0
- package/dist/documentation/CodeAnalyzer.d.ts +29 -0
- package/dist/documentation/CodeAnalyzer.d.ts.map +1 -0
- package/dist/documentation/CodeAnalyzer.js +122 -0
- package/dist/documentation/CodeAnalyzer.js.map +1 -0
- package/dist/documentation/ConversationAnalyzer.d.ts +19 -0
- package/dist/documentation/ConversationAnalyzer.d.ts.map +1 -0
- package/dist/documentation/ConversationAnalyzer.js +156 -0
- package/dist/documentation/ConversationAnalyzer.js.map +1 -0
- package/dist/documentation/CrossReferencer.d.ts +67 -0
- package/dist/documentation/CrossReferencer.d.ts.map +1 -0
- package/dist/documentation/CrossReferencer.js +247 -0
- package/dist/documentation/CrossReferencer.js.map +1 -0
- package/dist/documentation/DocumentationGenerator.d.ts +22 -0
- package/dist/documentation/DocumentationGenerator.d.ts.map +1 -0
- package/dist/documentation/DocumentationGenerator.js +57 -0
- package/dist/documentation/DocumentationGenerator.js.map +1 -0
- package/dist/documentation/MarkdownFormatter.d.ts +26 -0
- package/dist/documentation/MarkdownFormatter.d.ts.map +1 -0
- package/dist/documentation/MarkdownFormatter.js +301 -0
- package/dist/documentation/MarkdownFormatter.js.map +1 -0
- package/dist/documentation/types.d.ts +176 -0
- package/dist/documentation/types.d.ts.map +1 -0
- package/dist/documentation/types.js +5 -0
- package/dist/documentation/types.js.map +1 -0
- package/dist/embeddings/EmbeddingConfig.d.ts +39 -0
- package/dist/embeddings/EmbeddingConfig.d.ts.map +1 -0
- package/dist/embeddings/EmbeddingConfig.js +132 -0
- package/dist/embeddings/EmbeddingConfig.js.map +1 -0
- package/dist/embeddings/EmbeddingGenerator.d.ts +45 -0
- package/dist/embeddings/EmbeddingGenerator.d.ts.map +1 -0
- package/dist/embeddings/EmbeddingGenerator.js +129 -0
- package/dist/embeddings/EmbeddingGenerator.js.map +1 -0
- package/dist/embeddings/EmbeddingProvider.d.ts +34 -0
- package/dist/embeddings/EmbeddingProvider.d.ts.map +1 -0
- package/dist/embeddings/EmbeddingProvider.js +6 -0
- package/dist/embeddings/EmbeddingProvider.js.map +1 -0
- package/dist/embeddings/VectorStore.d.ts +75 -0
- package/dist/embeddings/VectorStore.d.ts.map +1 -0
- package/dist/embeddings/VectorStore.js +220 -0
- package/dist/embeddings/VectorStore.js.map +1 -0
- package/dist/embeddings/providers/OllamaEmbeddings.d.ts +38 -0
- package/dist/embeddings/providers/OllamaEmbeddings.d.ts.map +1 -0
- package/dist/embeddings/providers/OllamaEmbeddings.js +132 -0
- package/dist/embeddings/providers/OllamaEmbeddings.js.map +1 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.d.ts +40 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.d.ts.map +1 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.js +128 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.js.map +1 -0
- package/dist/embeddings/providers/TransformersEmbeddings.d.ts +38 -0
- package/dist/embeddings/providers/TransformersEmbeddings.d.ts.map +1 -0
- package/dist/embeddings/providers/TransformersEmbeddings.js +114 -0
- package/dist/embeddings/providers/TransformersEmbeddings.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +127 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/ConversationParser.d.ts +138 -0
- package/dist/parsers/ConversationParser.d.ts.map +1 -0
- package/dist/parsers/ConversationParser.js +325 -0
- package/dist/parsers/ConversationParser.js.map +1 -0
- package/dist/parsers/DecisionExtractor.d.ts +76 -0
- package/dist/parsers/DecisionExtractor.d.ts.map +1 -0
- package/dist/parsers/DecisionExtractor.js +305 -0
- package/dist/parsers/DecisionExtractor.js.map +1 -0
- package/dist/parsers/GitIntegrator.d.ts +71 -0
- package/dist/parsers/GitIntegrator.d.ts.map +1 -0
- package/dist/parsers/GitIntegrator.js +283 -0
- package/dist/parsers/GitIntegrator.js.map +1 -0
- package/dist/parsers/MistakeExtractor.d.ts +86 -0
- package/dist/parsers/MistakeExtractor.d.ts.map +1 -0
- package/dist/parsers/MistakeExtractor.js +341 -0
- package/dist/parsers/MistakeExtractor.js.map +1 -0
- package/dist/parsers/RequirementsExtractor.d.ts +70 -0
- package/dist/parsers/RequirementsExtractor.d.ts.map +1 -0
- package/dist/parsers/RequirementsExtractor.js +252 -0
- package/dist/parsers/RequirementsExtractor.js.map +1 -0
- package/dist/search/SemanticSearch.d.ts +90 -0
- package/dist/search/SemanticSearch.d.ts.map +1 -0
- package/dist/search/SemanticSearch.js +352 -0
- package/dist/search/SemanticSearch.js.map +1 -0
- package/dist/storage/ConversationStorage.d.ts +53 -0
- package/dist/storage/ConversationStorage.d.ts.map +1 -0
- package/dist/storage/ConversationStorage.js +249 -0
- package/dist/storage/ConversationStorage.js.map +1 -0
- package/dist/storage/SQLiteManager.d.ts +88 -0
- package/dist/storage/SQLiteManager.d.ts.map +1 -0
- package/dist/storage/SQLiteManager.js +281 -0
- package/dist/storage/SQLiteManager.js.map +1 -0
- package/dist/storage/migrations.d.ts +54 -0
- package/dist/storage/migrations.d.ts.map +1 -0
- package/dist/storage/migrations.js +153 -0
- package/dist/storage/migrations.js.map +1 -0
- package/dist/storage/schema.sql +321 -0
- package/dist/tools/ToolDefinitions.d.ts +265 -0
- package/dist/tools/ToolDefinitions.d.ts.map +1 -0
- package/dist/tools/ToolDefinitions.js +261 -0
- package/dist/tools/ToolDefinitions.js.map +1 -0
- package/dist/tools/ToolHandlers.d.ts +56 -0
- package/dist/tools/ToolHandlers.d.ts.map +1 -0
- package/dist/tools/ToolHandlers.js +431 -0
- package/dist/tools/ToolHandlers.js.map +1 -0
- package/dist/types/ToolTypes.d.ts +333 -0
- package/dist/types/ToolTypes.d.ts.map +1 -0
- package/dist/types/ToolTypes.js +6 -0
- package/dist/types/ToolTypes.js.map +1 -0
- package/dist/utils/sanitization.d.ts +35 -0
- package/dist/utils/sanitization.d.ts.map +1 -0
- package/dist/utils/sanitization.js +97 -0
- package/dist/utils/sanitization.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedding Configuration Management
|
|
3
|
+
* Loads config from file and environment variables (env vars take precedence)
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, existsSync } from "fs";
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
import { homedir } from "os";
|
|
8
|
+
export class ConfigLoader {
|
|
9
|
+
static CONFIG_FILENAME = ".claude-memory-config.json";
|
|
10
|
+
/**
|
|
11
|
+
* Load configuration with precedence: env vars > project config > home config > defaults
|
|
12
|
+
*/
|
|
13
|
+
static load() {
|
|
14
|
+
// Start with defaults
|
|
15
|
+
let config = {
|
|
16
|
+
provider: "transformers",
|
|
17
|
+
model: "Xenova/all-MiniLM-L6-v2",
|
|
18
|
+
dimensions: 384,
|
|
19
|
+
};
|
|
20
|
+
// Try loading from home directory config
|
|
21
|
+
const homeConfigPath = join(homedir(), this.CONFIG_FILENAME);
|
|
22
|
+
if (existsSync(homeConfigPath)) {
|
|
23
|
+
const homeConfig = this.loadConfigFile(homeConfigPath);
|
|
24
|
+
if (homeConfig?.embedding) {
|
|
25
|
+
config = { ...config, ...homeConfig.embedding };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Try loading from project config (overrides home config)
|
|
29
|
+
const projectConfigPath = join(process.cwd(), this.CONFIG_FILENAME);
|
|
30
|
+
if (existsSync(projectConfigPath)) {
|
|
31
|
+
const projectConfig = this.loadConfigFile(projectConfigPath);
|
|
32
|
+
if (projectConfig?.embedding) {
|
|
33
|
+
config = { ...config, ...projectConfig.embedding };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Environment variables override everything
|
|
37
|
+
if (process.env.EMBEDDING_PROVIDER) {
|
|
38
|
+
config.provider = process.env.EMBEDDING_PROVIDER;
|
|
39
|
+
}
|
|
40
|
+
if (process.env.EMBEDDING_MODEL) {
|
|
41
|
+
config.model = process.env.EMBEDDING_MODEL;
|
|
42
|
+
}
|
|
43
|
+
if (process.env.EMBEDDING_DIMENSIONS) {
|
|
44
|
+
config.dimensions = parseInt(process.env.EMBEDDING_DIMENSIONS, 10);
|
|
45
|
+
}
|
|
46
|
+
if (process.env.EMBEDDING_BASE_URL) {
|
|
47
|
+
config.baseUrl = process.env.EMBEDDING_BASE_URL;
|
|
48
|
+
}
|
|
49
|
+
if (process.env.OPENAI_API_KEY) {
|
|
50
|
+
config.apiKey = process.env.OPENAI_API_KEY;
|
|
51
|
+
}
|
|
52
|
+
// Set provider-specific defaults
|
|
53
|
+
config = this.applyProviderDefaults(config);
|
|
54
|
+
return config;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Load and parse config file
|
|
58
|
+
*/
|
|
59
|
+
static loadConfigFile(path) {
|
|
60
|
+
try {
|
|
61
|
+
const content = readFileSync(path, "utf-8");
|
|
62
|
+
return JSON.parse(content);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
console.warn(`Warning: Could not load config file ${path}:`, error);
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Apply provider-specific defaults
|
|
71
|
+
*/
|
|
72
|
+
static applyProviderDefaults(config) {
|
|
73
|
+
switch (config.provider) {
|
|
74
|
+
case "ollama":
|
|
75
|
+
return {
|
|
76
|
+
...config,
|
|
77
|
+
baseUrl: config.baseUrl || "http://localhost:11434",
|
|
78
|
+
model: config.model || "mxbai-embed-large",
|
|
79
|
+
dimensions: config.dimensions || 1024, // mxbai-embed-large default
|
|
80
|
+
};
|
|
81
|
+
case "openai":
|
|
82
|
+
return {
|
|
83
|
+
...config,
|
|
84
|
+
model: config.model || "text-embedding-3-small",
|
|
85
|
+
dimensions: config.dimensions || 1536, // text-embedding-3-small default
|
|
86
|
+
};
|
|
87
|
+
case "transformers":
|
|
88
|
+
return {
|
|
89
|
+
...config,
|
|
90
|
+
model: config.model || "Xenova/all-MiniLM-L6-v2",
|
|
91
|
+
dimensions: config.dimensions || 384,
|
|
92
|
+
};
|
|
93
|
+
default:
|
|
94
|
+
return config;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Validate configuration
|
|
99
|
+
*/
|
|
100
|
+
static validate(config) {
|
|
101
|
+
const errors = [];
|
|
102
|
+
if (!["ollama", "transformers", "openai"].includes(config.provider)) {
|
|
103
|
+
errors.push(`Invalid provider: ${config.provider}. Must be 'ollama', 'transformers', or 'openai'`);
|
|
104
|
+
}
|
|
105
|
+
if (!config.model || config.model.trim() === "") {
|
|
106
|
+
errors.push("Model name is required");
|
|
107
|
+
}
|
|
108
|
+
if (config.provider === "openai" && !config.apiKey) {
|
|
109
|
+
errors.push("OpenAI provider requires OPENAI_API_KEY environment variable or apiKey in config");
|
|
110
|
+
}
|
|
111
|
+
if (config.dimensions && (config.dimensions < 1 || config.dimensions > 10000)) {
|
|
112
|
+
errors.push("Dimensions must be between 1 and 10000");
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
valid: errors.length === 0,
|
|
116
|
+
errors,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get example config for documentation
|
|
121
|
+
*/
|
|
122
|
+
static getExampleConfig() {
|
|
123
|
+
return JSON.stringify({
|
|
124
|
+
embedding: {
|
|
125
|
+
provider: "ollama",
|
|
126
|
+
model: "nomic-embed-text",
|
|
127
|
+
baseUrl: "http://localhost:11434",
|
|
128
|
+
},
|
|
129
|
+
}, null, 2);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=EmbeddingConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmbeddingConfig.js","sourceRoot":"","sources":["../../src/embeddings/EmbeddingConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedding Generator Factory
|
|
3
|
+
* Creates appropriate embedding provider based on configuration
|
|
4
|
+
*/
|
|
5
|
+
import type { EmbeddingProvider } from "./EmbeddingProvider.js";
|
|
6
|
+
/**
|
|
7
|
+
* Factory class for creating embedding providers
|
|
8
|
+
*/
|
|
9
|
+
export declare class EmbeddingGenerator {
|
|
10
|
+
private static instance;
|
|
11
|
+
/**
|
|
12
|
+
* Get or create embedding provider based on configuration
|
|
13
|
+
*/
|
|
14
|
+
static getProvider(): Promise<EmbeddingProvider>;
|
|
15
|
+
/**
|
|
16
|
+
* Create specific provider instance
|
|
17
|
+
*/
|
|
18
|
+
private static createProvider;
|
|
19
|
+
/**
|
|
20
|
+
* Auto-detect best available provider
|
|
21
|
+
* Tries in order: Ollama (fast, free, local) → Transformers (slower startup, offline)
|
|
22
|
+
*/
|
|
23
|
+
private static autoDetectProvider;
|
|
24
|
+
/**
|
|
25
|
+
* Reset singleton (useful for testing)
|
|
26
|
+
*/
|
|
27
|
+
static reset(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Get current provider info (if initialized)
|
|
30
|
+
*/
|
|
31
|
+
static getInfo(): {
|
|
32
|
+
provider: string;
|
|
33
|
+
model: string;
|
|
34
|
+
available: boolean;
|
|
35
|
+
} | null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Legacy API compatibility - returns provider instance
|
|
39
|
+
*/
|
|
40
|
+
export declare function getEmbeddingGenerator(): Promise<EmbeddingProvider>;
|
|
41
|
+
/**
|
|
42
|
+
* Legacy API compatibility - resets singleton
|
|
43
|
+
*/
|
|
44
|
+
export declare function resetEmbeddingGenerator(): void;
|
|
45
|
+
//# sourceMappingURL=EmbeddingGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmbeddingGenerator.d.ts","sourceRoot":"","sources":["../../src/embeddings/EmbeddingGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAMhE;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkC;IAEzD;;OAEG;WACU,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC;IA0CtD;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IA2B7B;;;OAGG;mBACkB,kBAAkB;IA6BvC;;OAEG;IACH,MAAM,CAAC,KAAK,IAAI,IAAI;IAIpB;;OAEG;IACH,MAAM,CAAC,OAAO,IAAI;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;CAYjF;AAED;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAExE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedding Generator Factory
|
|
3
|
+
* Creates appropriate embedding provider based on configuration
|
|
4
|
+
*/
|
|
5
|
+
import { ConfigLoader } from "./EmbeddingConfig.js";
|
|
6
|
+
import { OllamaEmbeddings } from "./providers/OllamaEmbeddings.js";
|
|
7
|
+
import { OpenAIEmbeddings } from "./providers/OpenAIEmbeddings.js";
|
|
8
|
+
import { TransformersEmbeddings } from "./providers/TransformersEmbeddings.js";
|
|
9
|
+
/**
|
|
10
|
+
* Factory class for creating embedding providers
|
|
11
|
+
*/
|
|
12
|
+
export class EmbeddingGenerator {
|
|
13
|
+
static instance = null;
|
|
14
|
+
/**
|
|
15
|
+
* Get or create embedding provider based on configuration
|
|
16
|
+
*/
|
|
17
|
+
static async getProvider() {
|
|
18
|
+
if (this.instance) {
|
|
19
|
+
return this.instance;
|
|
20
|
+
}
|
|
21
|
+
// Load configuration
|
|
22
|
+
const config = ConfigLoader.load();
|
|
23
|
+
// Validate configuration
|
|
24
|
+
const validation = ConfigLoader.validate(config);
|
|
25
|
+
if (!validation.valid) {
|
|
26
|
+
console.warn("⚠️ Invalid embedding configuration:");
|
|
27
|
+
validation.errors.forEach((error) => console.warn(` - ${error}`));
|
|
28
|
+
console.warn(" Falling back to auto-detection...");
|
|
29
|
+
}
|
|
30
|
+
// Try to create provider based on config (or auto-detect)
|
|
31
|
+
let provider;
|
|
32
|
+
if (validation.valid) {
|
|
33
|
+
console.log(`Attempting to use ${config.provider} embeddings...`);
|
|
34
|
+
provider = this.createProvider(config.provider, config);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// Auto-detect: try providers in order of preference
|
|
38
|
+
console.log("Auto-detecting available embedding provider...");
|
|
39
|
+
provider = await this.autoDetectProvider();
|
|
40
|
+
}
|
|
41
|
+
// Initialize the provider
|
|
42
|
+
await provider.initialize();
|
|
43
|
+
// If provider is not available, try fallback
|
|
44
|
+
if (!provider.isAvailable()) {
|
|
45
|
+
console.warn(`⚠️ ${config.provider} provider not available, trying fallback...`);
|
|
46
|
+
provider = await this.autoDetectProvider();
|
|
47
|
+
await provider.initialize();
|
|
48
|
+
}
|
|
49
|
+
this.instance = provider;
|
|
50
|
+
return provider;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create specific provider instance
|
|
54
|
+
*/
|
|
55
|
+
static createProvider(type, config) {
|
|
56
|
+
switch (type) {
|
|
57
|
+
case "ollama":
|
|
58
|
+
return new OllamaEmbeddings(config.baseUrl || "http://localhost:11434", config.model, config.dimensions);
|
|
59
|
+
case "openai":
|
|
60
|
+
return new OpenAIEmbeddings(config.apiKey || "", config.model, config.dimensions);
|
|
61
|
+
case "transformers":
|
|
62
|
+
return new TransformersEmbeddings(config.model, config.dimensions);
|
|
63
|
+
default:
|
|
64
|
+
throw new Error(`Unknown provider type: ${type}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Auto-detect best available provider
|
|
69
|
+
* Tries in order: Ollama (fast, free, local) → Transformers (slower startup, offline)
|
|
70
|
+
*/
|
|
71
|
+
static async autoDetectProvider() {
|
|
72
|
+
// Try Ollama first (fastest, no download required if already running)
|
|
73
|
+
const ollama = new OllamaEmbeddings();
|
|
74
|
+
await ollama.initialize();
|
|
75
|
+
if (ollama.isAvailable()) {
|
|
76
|
+
console.log("✓ Auto-detected: Using Ollama embeddings");
|
|
77
|
+
return ollama;
|
|
78
|
+
}
|
|
79
|
+
// Try Transformers.js (works offline, but requires download on first run)
|
|
80
|
+
const transformers = new TransformersEmbeddings();
|
|
81
|
+
await transformers.initialize();
|
|
82
|
+
if (transformers.isAvailable()) {
|
|
83
|
+
console.log("✓ Auto-detected: Using Transformers.js embeddings");
|
|
84
|
+
return transformers;
|
|
85
|
+
}
|
|
86
|
+
// No provider available - return transformers as placeholder
|
|
87
|
+
// It will fail gracefully when used, falling back to FTS
|
|
88
|
+
console.warn("⚠️ No embedding provider available");
|
|
89
|
+
console.warn(" Options:");
|
|
90
|
+
console.warn(" 1. Install Ollama: https://ollama.com");
|
|
91
|
+
console.warn(" 2. Install @xenova/transformers: npm install @xenova/transformers");
|
|
92
|
+
console.warn(" 3. Configure OpenAI: Set OPENAI_API_KEY environment variable");
|
|
93
|
+
console.warn(" Falling back to full-text search only.");
|
|
94
|
+
return transformers; // Return uninitialized provider (will fail gracefully)
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Reset singleton (useful for testing)
|
|
98
|
+
*/
|
|
99
|
+
static reset() {
|
|
100
|
+
this.instance = null;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get current provider info (if initialized)
|
|
104
|
+
*/
|
|
105
|
+
static getInfo() {
|
|
106
|
+
if (!this.instance) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const info = this.instance.getModelInfo();
|
|
110
|
+
return {
|
|
111
|
+
provider: info.provider,
|
|
112
|
+
model: info.model,
|
|
113
|
+
available: info.available,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Legacy API compatibility - returns provider instance
|
|
119
|
+
*/
|
|
120
|
+
export async function getEmbeddingGenerator() {
|
|
121
|
+
return EmbeddingGenerator.getProvider();
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Legacy API compatibility - resets singleton
|
|
125
|
+
*/
|
|
126
|
+
export function resetEmbeddingGenerator() {
|
|
127
|
+
EmbeddingGenerator.reset();
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=EmbeddingGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmbeddingGenerator.js","sourceRoot":"","sources":["../../src/embeddings/EmbeddingGenerator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedding Provider Interface
|
|
3
|
+
* Defines the contract for all embedding implementations
|
|
4
|
+
*/
|
|
5
|
+
export interface ModelInfo {
|
|
6
|
+
provider: string;
|
|
7
|
+
model: string;
|
|
8
|
+
dimensions: number;
|
|
9
|
+
available: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface EmbeddingProvider {
|
|
12
|
+
/**
|
|
13
|
+
* Initialize the embedding provider
|
|
14
|
+
* Should handle graceful failure if provider unavailable
|
|
15
|
+
*/
|
|
16
|
+
initialize(): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Check if embeddings are available
|
|
19
|
+
*/
|
|
20
|
+
isAvailable(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Generate embedding for a single text
|
|
23
|
+
*/
|
|
24
|
+
embed(text: string): Promise<Float32Array>;
|
|
25
|
+
/**
|
|
26
|
+
* Generate embeddings for multiple texts (batched for efficiency)
|
|
27
|
+
*/
|
|
28
|
+
embedBatch(texts: string[], batchSize?: number): Promise<Float32Array[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Get information about the model being used
|
|
31
|
+
*/
|
|
32
|
+
getModelInfo(): ModelInfo;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=EmbeddingProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmbeddingProvider.d.ts","sourceRoot":"","sources":["../../src/embeddings/EmbeddingProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;OAEG;IACH,WAAW,IAAI,OAAO,CAAC;IAEvB;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAE3C;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAEzE;;OAEG;IACH,YAAY,IAAI,SAAS,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmbeddingProvider.js","sourceRoot":"","sources":["../../src/embeddings/EmbeddingProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vector Store with sqlite-vec integration
|
|
3
|
+
* Dual-schema support (vector extension or BLOB fallback)
|
|
4
|
+
*/
|
|
5
|
+
import type { SQLiteManager } from "../storage/SQLiteManager.js";
|
|
6
|
+
export interface VectorSearchResult {
|
|
7
|
+
id: string;
|
|
8
|
+
content: string;
|
|
9
|
+
similarity: number;
|
|
10
|
+
metadata?: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
export declare class VectorStore {
|
|
13
|
+
private db;
|
|
14
|
+
private sqliteManager;
|
|
15
|
+
private hasVecExtension;
|
|
16
|
+
private vecTablesInitialized;
|
|
17
|
+
constructor(sqliteManager: SQLiteManager);
|
|
18
|
+
/**
|
|
19
|
+
* Detect if sqlite-vec extension is available
|
|
20
|
+
*/
|
|
21
|
+
private detectVecExtension;
|
|
22
|
+
/**
|
|
23
|
+
* Check if vec extension is enabled
|
|
24
|
+
*/
|
|
25
|
+
isVecEnabled(): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Ensure vec tables exist with correct dimensions
|
|
28
|
+
*/
|
|
29
|
+
private ensureVecTables;
|
|
30
|
+
/**
|
|
31
|
+
* Store an embedding for a message
|
|
32
|
+
*/
|
|
33
|
+
storeMessageEmbedding(messageId: string, content: string, embedding: Float32Array): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Store embedding in BLOB table (fallback)
|
|
36
|
+
*/
|
|
37
|
+
private storeInBlobTable;
|
|
38
|
+
/**
|
|
39
|
+
* Store an embedding for a decision
|
|
40
|
+
*/
|
|
41
|
+
storeDecisionEmbedding(decisionId: string, embedding: Float32Array): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Search for similar messages
|
|
44
|
+
*/
|
|
45
|
+
searchMessages(queryEmbedding: Float32Array, limit?: number): Promise<VectorSearchResult[]>;
|
|
46
|
+
/**
|
|
47
|
+
* Search using sqlite-vec extension
|
|
48
|
+
*/
|
|
49
|
+
private searchWithVecExtension;
|
|
50
|
+
/**
|
|
51
|
+
* Search using manual cosine similarity (fallback)
|
|
52
|
+
*/
|
|
53
|
+
private searchWithCosine;
|
|
54
|
+
/**
|
|
55
|
+
* Calculate cosine similarity between two vectors
|
|
56
|
+
*/
|
|
57
|
+
private cosineSimilarity;
|
|
58
|
+
/**
|
|
59
|
+
* Convert Float32Array to Buffer for storage
|
|
60
|
+
*/
|
|
61
|
+
private float32ArrayToBuffer;
|
|
62
|
+
/**
|
|
63
|
+
* Convert Buffer to Float32Array for retrieval
|
|
64
|
+
*/
|
|
65
|
+
private bufferToFloat32Array;
|
|
66
|
+
/**
|
|
67
|
+
* Get embedding count
|
|
68
|
+
*/
|
|
69
|
+
getEmbeddingCount(): number;
|
|
70
|
+
/**
|
|
71
|
+
* Clear all embeddings
|
|
72
|
+
*/
|
|
73
|
+
clearAllEmbeddings(): void;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=VectorStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VectorStore.d.ts","sourceRoot":"","sources":["../../src/embeddings/VectorStore.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAGjE,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,oBAAoB,CAAkB;gBAElC,aAAa,EAAE,aAAa;IAMxC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACH,OAAO,CAAC,eAAe;IASvB;;OAEG;IACG,qBAAqB,CACzB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,YAAY,GACtB,OAAO,CAAC,IAAI,CAAC;IAuChB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAqBxB;;OAEG;IACG,sBAAsB,CAC1B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,YAAY,GACtB,OAAO,CAAC,IAAI,CAAC;IAehB;;OAEG;IACG,cAAc,CAClB,cAAc,EAAE,YAAY,EAC5B,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAQhC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAoC9B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA8BxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAQ5B;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAO3B;;OAEG;IACH,kBAAkB,IAAI,IAAI;CAY3B"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vector Store with sqlite-vec integration
|
|
3
|
+
* Dual-schema support (vector extension or BLOB fallback)
|
|
4
|
+
*/
|
|
5
|
+
export class VectorStore {
|
|
6
|
+
db;
|
|
7
|
+
sqliteManager;
|
|
8
|
+
hasVecExtension = false;
|
|
9
|
+
vecTablesInitialized = false;
|
|
10
|
+
constructor(sqliteManager) {
|
|
11
|
+
this.db = sqliteManager.getDatabase();
|
|
12
|
+
this.sqliteManager = sqliteManager;
|
|
13
|
+
this.detectVecExtension();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Detect if sqlite-vec extension is available
|
|
17
|
+
*/
|
|
18
|
+
detectVecExtension() {
|
|
19
|
+
try {
|
|
20
|
+
// Try to create a test virtual table
|
|
21
|
+
this.db.exec("CREATE VIRTUAL TABLE IF NOT EXISTS vec_test USING vec0(test float[1])");
|
|
22
|
+
this.db.exec("DROP TABLE vec_test");
|
|
23
|
+
this.hasVecExtension = true;
|
|
24
|
+
console.log("✓ sqlite-vec extension detected");
|
|
25
|
+
}
|
|
26
|
+
catch (_error) {
|
|
27
|
+
this.hasVecExtension = false;
|
|
28
|
+
console.log("⚠ sqlite-vec not available, using BLOB fallback");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Check if vec extension is enabled
|
|
33
|
+
*/
|
|
34
|
+
isVecEnabled() {
|
|
35
|
+
return this.hasVecExtension;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Ensure vec tables exist with correct dimensions
|
|
39
|
+
*/
|
|
40
|
+
ensureVecTables(dimensions) {
|
|
41
|
+
if (!this.hasVecExtension || this.vecTablesInitialized) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
this.sqliteManager.createVecTablesWithDimensions(dimensions);
|
|
45
|
+
this.vecTablesInitialized = true;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Store an embedding for a message
|
|
49
|
+
*/
|
|
50
|
+
async storeMessageEmbedding(messageId, content, embedding) {
|
|
51
|
+
const embedId = `msg_${messageId}`;
|
|
52
|
+
if (this.hasVecExtension) {
|
|
53
|
+
// Ensure vec tables exist with correct dimensions
|
|
54
|
+
this.ensureVecTables(embedding.length);
|
|
55
|
+
// Use sqlite-vec virtual table
|
|
56
|
+
try {
|
|
57
|
+
// Try to delete existing entry first (handles dimension mismatches)
|
|
58
|
+
try {
|
|
59
|
+
this.db
|
|
60
|
+
.prepare("DELETE FROM vec_message_embeddings WHERE id = ?")
|
|
61
|
+
.run(embedId);
|
|
62
|
+
}
|
|
63
|
+
catch (_deleteError) {
|
|
64
|
+
// Ignore - entry might not exist
|
|
65
|
+
}
|
|
66
|
+
// Now insert the new embedding
|
|
67
|
+
this.db
|
|
68
|
+
.prepare("INSERT INTO vec_message_embeddings (id, embedding) VALUES (?, ?)")
|
|
69
|
+
.run(embedId, this.float32ArrayToBuffer(embedding));
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
// Only log non-UNIQUE-constraint errors
|
|
73
|
+
const errorMessage = error.message;
|
|
74
|
+
if (!errorMessage.includes("UNIQUE constraint")) {
|
|
75
|
+
console.error("Error storing vector embedding:", error);
|
|
76
|
+
}
|
|
77
|
+
// Fallback to BLOB
|
|
78
|
+
this.storeInBlobTable(messageId, content, embedding);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
// Use BLOB storage
|
|
83
|
+
this.storeInBlobTable(messageId, content, embedding);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Store embedding in BLOB table (fallback)
|
|
88
|
+
*/
|
|
89
|
+
storeInBlobTable(messageId, content, embedding) {
|
|
90
|
+
this.db
|
|
91
|
+
.prepare(`INSERT OR REPLACE INTO message_embeddings
|
|
92
|
+
(id, message_id, content, embedding, model_name, created_at)
|
|
93
|
+
VALUES (?, ?, ?, ?, ?, ?)`)
|
|
94
|
+
.run(`msg_${messageId}`, messageId, content, this.float32ArrayToBuffer(embedding), "all-MiniLM-L6-v2", Date.now());
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Store an embedding for a decision
|
|
98
|
+
*/
|
|
99
|
+
async storeDecisionEmbedding(decisionId, embedding) {
|
|
100
|
+
this.db
|
|
101
|
+
.prepare(`INSERT OR REPLACE INTO decision_embeddings
|
|
102
|
+
(id, decision_id, embedding, created_at)
|
|
103
|
+
VALUES (?, ?, ?, ?)`)
|
|
104
|
+
.run(`dec_${decisionId}`, decisionId, this.float32ArrayToBuffer(embedding), Date.now());
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Search for similar messages
|
|
108
|
+
*/
|
|
109
|
+
async searchMessages(queryEmbedding, limit = 10) {
|
|
110
|
+
if (this.hasVecExtension) {
|
|
111
|
+
return this.searchWithVecExtension(queryEmbedding, limit);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
return this.searchWithCosine(queryEmbedding, limit);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Search using sqlite-vec extension
|
|
119
|
+
*/
|
|
120
|
+
searchWithVecExtension(queryEmbedding, limit) {
|
|
121
|
+
try {
|
|
122
|
+
const queryBuffer = this.float32ArrayToBuffer(queryEmbedding);
|
|
123
|
+
const results = this.db
|
|
124
|
+
.prepare(`SELECT
|
|
125
|
+
vec.id,
|
|
126
|
+
me.content,
|
|
127
|
+
vec_distance_cosine(vec.embedding, ?) as distance
|
|
128
|
+
FROM vec_message_embeddings vec
|
|
129
|
+
JOIN message_embeddings me ON vec.id = me.id
|
|
130
|
+
ORDER BY distance
|
|
131
|
+
LIMIT ?`)
|
|
132
|
+
.all(queryBuffer, limit);
|
|
133
|
+
return results.map((r) => ({
|
|
134
|
+
id: r.id.replace("msg_", ""),
|
|
135
|
+
content: r.content,
|
|
136
|
+
similarity: 1 - r.distance, // Convert distance to similarity
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
console.error("Error in vec search:", error);
|
|
141
|
+
// Fallback to cosine
|
|
142
|
+
return this.searchWithCosine(queryEmbedding, limit);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Search using manual cosine similarity (fallback)
|
|
147
|
+
*/
|
|
148
|
+
searchWithCosine(queryEmbedding, limit) {
|
|
149
|
+
const allEmbeddings = this.db
|
|
150
|
+
.prepare("SELECT id, message_id, content, embedding FROM message_embeddings")
|
|
151
|
+
.all();
|
|
152
|
+
const results = allEmbeddings
|
|
153
|
+
.map((row) => {
|
|
154
|
+
const embedding = this.bufferToFloat32Array(row.embedding);
|
|
155
|
+
const similarity = this.cosineSimilarity(queryEmbedding, embedding);
|
|
156
|
+
return {
|
|
157
|
+
id: row.message_id,
|
|
158
|
+
content: row.content,
|
|
159
|
+
similarity,
|
|
160
|
+
};
|
|
161
|
+
})
|
|
162
|
+
.sort((a, b) => b.similarity - a.similarity)
|
|
163
|
+
.slice(0, limit);
|
|
164
|
+
return results;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Calculate cosine similarity between two vectors
|
|
168
|
+
*/
|
|
169
|
+
cosineSimilarity(a, b) {
|
|
170
|
+
if (a.length !== b.length) {
|
|
171
|
+
throw new Error("Vectors must have same length");
|
|
172
|
+
}
|
|
173
|
+
let dotProduct = 0;
|
|
174
|
+
let normA = 0;
|
|
175
|
+
let normB = 0;
|
|
176
|
+
for (let i = 0; i < a.length; i++) {
|
|
177
|
+
dotProduct += a[i] * b[i];
|
|
178
|
+
normA += a[i] * a[i];
|
|
179
|
+
normB += b[i] * b[i];
|
|
180
|
+
}
|
|
181
|
+
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Convert Float32Array to Buffer for storage
|
|
185
|
+
*/
|
|
186
|
+
float32ArrayToBuffer(array) {
|
|
187
|
+
return Buffer.from(array.buffer, array.byteOffset, array.byteLength);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Convert Buffer to Float32Array for retrieval
|
|
191
|
+
*/
|
|
192
|
+
bufferToFloat32Array(buffer) {
|
|
193
|
+
return new Float32Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / 4);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Get embedding count
|
|
197
|
+
*/
|
|
198
|
+
getEmbeddingCount() {
|
|
199
|
+
const result = this.db
|
|
200
|
+
.prepare("SELECT COUNT(*) as count FROM message_embeddings")
|
|
201
|
+
.get();
|
|
202
|
+
return result.count;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Clear all embeddings
|
|
206
|
+
*/
|
|
207
|
+
clearAllEmbeddings() {
|
|
208
|
+
this.db.exec("DELETE FROM message_embeddings");
|
|
209
|
+
this.db.exec("DELETE FROM decision_embeddings");
|
|
210
|
+
if (this.hasVecExtension) {
|
|
211
|
+
try {
|
|
212
|
+
this.db.exec("DELETE FROM vec_message_embeddings");
|
|
213
|
+
}
|
|
214
|
+
catch (_e) {
|
|
215
|
+
// Vector table might not exist
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=VectorStore.js.map
|