@vfarcic/dot-ai 1.2.4 → 1.3.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/dist/core/embedding-service.d.ts +1 -1
- package/dist/core/embedding-service.d.ts.map +1 -1
- package/dist/core/embedding-service.js +65 -36
- package/dist/core/model-config.d.ts +3 -3
- package/dist/core/model-config.js +3 -3
- package/dist/interfaces/embedding-migration-handler.d.ts +16 -0
- package/dist/interfaces/embedding-migration-handler.d.ts.map +1 -0
- package/dist/interfaces/embedding-migration-handler.js +296 -0
- package/dist/interfaces/rest-api.d.ts +4 -0
- package/dist/interfaces/rest-api.d.ts.map +1 -1
- package/dist/interfaces/rest-api.js +259 -132
- package/dist/interfaces/routes/index.d.ts.map +1 -1
- package/dist/interfaces/routes/index.js +62 -12
- package/dist/interfaces/schemas/common.d.ts +1 -0
- package/dist/interfaces/schemas/common.d.ts.map +1 -1
- package/dist/interfaces/schemas/common.js +1 -0
- package/dist/interfaces/schemas/embeddings.d.ts +138 -0
- package/dist/interfaces/schemas/embeddings.d.ts.map +1 -0
- package/dist/interfaces/schemas/embeddings.js +79 -0
- package/dist/interfaces/schemas/index.d.ts +1 -0
- package/dist/interfaces/schemas/index.d.ts.map +1 -1
- package/dist/interfaces/schemas/index.js +10 -1
- package/dist/tools/operate-analysis.js +9 -2
- package/dist/tools/remediate.d.ts.map +1 -1
- package/dist/tools/remediate.js +6 -1
- package/package.json +1 -1
- package/prompts/remediate-system.md +1 -1
|
@@ -9,7 +9,7 @@ import { CircuitBreakerStats } from './circuit-breaker';
|
|
|
9
9
|
* Supported embedding providers - single source of truth
|
|
10
10
|
*/
|
|
11
11
|
export declare const EMBEDDING_PROVIDERS: readonly ["openai", "google", "amazon_bedrock"];
|
|
12
|
-
export type EmbeddingProviderType = typeof EMBEDDING_PROVIDERS[number];
|
|
12
|
+
export type EmbeddingProviderType = (typeof EMBEDDING_PROVIDERS)[number];
|
|
13
13
|
export interface EmbeddingConfig {
|
|
14
14
|
provider?: EmbeddingProviderType;
|
|
15
15
|
apiKey?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embedding-service.d.ts","sourceRoot":"","sources":["../../src/core/embedding-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,
|
|
1
|
+
{"version":3,"file":"embedding-service.d.ts","sourceRoot":"","sources":["../../src/core/embedding-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAEL,mBAAmB,EAEpB,MAAM,mBAAmB,CAAC;AAc3B;;GAEG;AACH,eAAO,MAAM,mBAAmB,iDAItB,CAAC;AACX,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACnD,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACzD,WAAW,IAAI,OAAO,CAAC;IACvB,aAAa,IAAI,MAAM,CAAC;IACxB,QAAQ,IAAI,MAAM,CAAC;CACpB;AAgBD;;;GAGG;AACH,qBAAa,uBAAwB,YAAW,iBAAiB;IAC/D,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,aAAa,CAAqC;gBAE9C,MAAM,EAAE,eAAe,GAAG;QAAE,QAAQ,EAAE,qBAAqB,CAAA;KAAE;IAmFnE,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA4DlD,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IAuE9D,WAAW,IAAI,OAAO;IAItB,aAAa,IAAI,MAAM;IAIvB,QAAQ,IAAI,MAAM;IAIlB,eAAe,IAAI,MAAM;CAG1B;AAqCD;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAA2B;gBAE/B,MAAM,GAAE,eAAoB;IAKxC;;;OAGG;IACG,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAexD;;;OAGG;IACG,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IAiB9D;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACH,SAAS,IAAI;QACX,SAAS,EAAE,OAAO,CAAC;QACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;IAqCD;;OAEG;IACH,uBAAuB,CAAC,OAAO,EAAE;QAC/B,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,kBAAkB,EAAE,MAAM,EAAE,CAAC;QAC7B,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,MAAM;IAYV;;;OAGG;IACH,sBAAsB,IAAI,mBAAmB,GAAG,IAAI;CAGrD"}
|
|
@@ -21,12 +21,16 @@ const tracing_1 = require("./tracing");
|
|
|
21
21
|
const embeddingCircuitBreaker = new circuit_breaker_1.CircuitBreaker('embedding-api', {
|
|
22
22
|
failureThreshold: 3, // Open after 3 consecutive failures
|
|
23
23
|
cooldownPeriodMs: 30000, // 30s cooldown before half-open
|
|
24
|
-
halfOpenMaxAttempts: 1 // Allow 1 test request in half-open
|
|
24
|
+
halfOpenMaxAttempts: 1, // Allow 1 test request in half-open
|
|
25
25
|
});
|
|
26
26
|
/**
|
|
27
27
|
* Supported embedding providers - single source of truth
|
|
28
28
|
*/
|
|
29
|
-
exports.EMBEDDING_PROVIDERS = [
|
|
29
|
+
exports.EMBEDDING_PROVIDERS = [
|
|
30
|
+
'openai',
|
|
31
|
+
'google',
|
|
32
|
+
'amazon_bedrock',
|
|
33
|
+
];
|
|
30
34
|
/**
|
|
31
35
|
* Unified Vercel AI SDK Embedding Provider
|
|
32
36
|
* Supports OpenAI, Google, and Amazon Bedrock through Vercel AI SDK
|
|
@@ -43,20 +47,39 @@ class VercelEmbeddingProvider {
|
|
|
43
47
|
this.available = false;
|
|
44
48
|
// Get API key based on provider
|
|
45
49
|
switch (this.providerType) {
|
|
46
|
-
case 'openai':
|
|
47
|
-
this.apiKey =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
case 'openai': {
|
|
51
|
+
this.apiKey =
|
|
52
|
+
config.apiKey ||
|
|
53
|
+
process.env.CUSTOM_EMBEDDINGS_API_KEY ||
|
|
54
|
+
process.env.OPENAI_API_KEY ||
|
|
55
|
+
'';
|
|
56
|
+
this.model =
|
|
57
|
+
config.model ||
|
|
58
|
+
process.env.EMBEDDINGS_MODEL ||
|
|
59
|
+
'text-embedding-3-small';
|
|
60
|
+
const envDimensions = process.env.EMBEDDINGS_DIMENSIONS
|
|
61
|
+
? parseInt(process.env.EMBEDDINGS_DIMENSIONS, 10)
|
|
62
|
+
: undefined;
|
|
63
|
+
this.dimensions =
|
|
64
|
+
config.dimensions ||
|
|
65
|
+
(Number.isFinite(envDimensions) ? envDimensions : 1536);
|
|
50
66
|
break;
|
|
67
|
+
}
|
|
51
68
|
case 'google':
|
|
52
69
|
this.apiKey = config.apiKey || process.env.GOOGLE_API_KEY || '';
|
|
53
|
-
this.model =
|
|
70
|
+
this.model =
|
|
71
|
+
config.model ||
|
|
72
|
+
process.env.EMBEDDINGS_MODEL ||
|
|
73
|
+
'gemini-embedding-001';
|
|
54
74
|
this.dimensions = config.dimensions || 768;
|
|
55
75
|
break;
|
|
56
76
|
case 'amazon_bedrock':
|
|
57
77
|
// AWS SDK handles credentials automatically - no API key needed
|
|
58
78
|
this.apiKey = 'bedrock-uses-aws-credentials';
|
|
59
|
-
this.model =
|
|
79
|
+
this.model =
|
|
80
|
+
config.model ||
|
|
81
|
+
process.env.EMBEDDINGS_MODEL ||
|
|
82
|
+
'amazon.titan-embed-text-v2:0';
|
|
60
83
|
this.dimensions = config.dimensions || 1024; // Titan v2 default
|
|
61
84
|
break;
|
|
62
85
|
}
|
|
@@ -71,7 +94,7 @@ class VercelEmbeddingProvider {
|
|
|
71
94
|
const baseURL = process.env.CUSTOM_EMBEDDINGS_BASE_URL;
|
|
72
95
|
const openai = (0, openai_1.createOpenAI)({
|
|
73
96
|
apiKey: this.apiKey,
|
|
74
|
-
...(baseURL && { baseURL })
|
|
97
|
+
...(baseURL && { baseURL }),
|
|
75
98
|
});
|
|
76
99
|
this.modelInstance = openai.textEmbedding(this.model);
|
|
77
100
|
break;
|
|
@@ -110,22 +133,22 @@ class VercelEmbeddingProvider {
|
|
|
110
133
|
return await (0, tracing_1.withAITracing)({
|
|
111
134
|
provider: this.providerType,
|
|
112
135
|
model: this.model,
|
|
113
|
-
operation: 'embeddings'
|
|
136
|
+
operation: 'embeddings',
|
|
114
137
|
}, async () => {
|
|
115
138
|
try {
|
|
116
139
|
// Execute through circuit breaker to prevent cascading failures
|
|
117
140
|
return await embeddingCircuitBreaker.execute(async () => {
|
|
118
141
|
const embedOptions = {
|
|
119
142
|
model: this.modelInstance,
|
|
120
|
-
value: text.trim()
|
|
143
|
+
value: text.trim(),
|
|
121
144
|
};
|
|
122
145
|
// Add Google-specific options
|
|
123
146
|
if (this.providerType === 'google') {
|
|
124
147
|
embedOptions.providerOptions = {
|
|
125
148
|
google: {
|
|
126
149
|
outputDimensionality: this.dimensions,
|
|
127
|
-
taskType: 'SEMANTIC_SIMILARITY'
|
|
128
|
-
}
|
|
150
|
+
taskType: 'SEMANTIC_SIMILARITY',
|
|
151
|
+
},
|
|
129
152
|
};
|
|
130
153
|
}
|
|
131
154
|
const result = await (0, ai_1.embed)(embedOptions);
|
|
@@ -142,9 +165,9 @@ class VercelEmbeddingProvider {
|
|
|
142
165
|
}
|
|
143
166
|
throw new Error(`${this.providerType} embedding failed: ${String(error)}`);
|
|
144
167
|
}
|
|
145
|
-
},
|
|
168
|
+
}, embedding => ({
|
|
146
169
|
embeddingCount: 1,
|
|
147
|
-
embeddingDimensions: embedding.length
|
|
170
|
+
embeddingDimensions: embedding.length,
|
|
148
171
|
}));
|
|
149
172
|
}
|
|
150
173
|
async generateEmbeddings(texts) {
|
|
@@ -154,9 +177,7 @@ class VercelEmbeddingProvider {
|
|
|
154
177
|
if (!texts || texts.length === 0) {
|
|
155
178
|
return [];
|
|
156
179
|
}
|
|
157
|
-
const validTexts = texts
|
|
158
|
-
.map(t => t?.trim())
|
|
159
|
-
.filter(t => t && t.length > 0);
|
|
180
|
+
const validTexts = texts.map(t => t?.trim()).filter(t => t && t.length > 0);
|
|
160
181
|
if (validTexts.length === 0) {
|
|
161
182
|
return [];
|
|
162
183
|
}
|
|
@@ -164,7 +185,7 @@ class VercelEmbeddingProvider {
|
|
|
164
185
|
return await (0, tracing_1.withAITracing)({
|
|
165
186
|
provider: this.providerType,
|
|
166
187
|
model: this.model,
|
|
167
|
-
operation: 'embeddings'
|
|
188
|
+
operation: 'embeddings',
|
|
168
189
|
}, async () => {
|
|
169
190
|
try {
|
|
170
191
|
// Execute through circuit breaker to prevent cascading failures
|
|
@@ -172,15 +193,15 @@ class VercelEmbeddingProvider {
|
|
|
172
193
|
const results = await Promise.all(validTexts.map(text => {
|
|
173
194
|
const embedOptions = {
|
|
174
195
|
model: this.modelInstance,
|
|
175
|
-
value: text
|
|
196
|
+
value: text,
|
|
176
197
|
};
|
|
177
198
|
// Add Google-specific options
|
|
178
199
|
if (this.providerType === 'google') {
|
|
179
200
|
embedOptions.providerOptions = {
|
|
180
201
|
google: {
|
|
181
202
|
outputDimensionality: this.dimensions,
|
|
182
|
-
taskType: 'SEMANTIC_SIMILARITY'
|
|
183
|
-
}
|
|
203
|
+
taskType: 'SEMANTIC_SIMILARITY',
|
|
204
|
+
},
|
|
184
205
|
};
|
|
185
206
|
}
|
|
186
207
|
return (0, ai_1.embed)(embedOptions);
|
|
@@ -198,9 +219,9 @@ class VercelEmbeddingProvider {
|
|
|
198
219
|
}
|
|
199
220
|
throw new Error(`${this.providerType} batch embedding failed: ${String(error)}`);
|
|
200
221
|
}
|
|
201
|
-
},
|
|
222
|
+
}, embeddings => ({
|
|
202
223
|
embeddingCount: embeddings.length,
|
|
203
|
-
embeddingDimensions: embeddings[0]?.length || this.dimensions
|
|
224
|
+
embeddingDimensions: embeddings[0]?.length || this.dimensions,
|
|
204
225
|
}));
|
|
205
226
|
}
|
|
206
227
|
isAvailable() {
|
|
@@ -221,7 +242,9 @@ exports.VercelEmbeddingProvider = VercelEmbeddingProvider;
|
|
|
221
242
|
* Factory function to create embedding provider based on configuration
|
|
222
243
|
*/
|
|
223
244
|
function createEmbeddingProvider(config = {}) {
|
|
224
|
-
const providerType = (config.provider ||
|
|
245
|
+
const providerType = (config.provider ||
|
|
246
|
+
process.env.EMBEDDINGS_PROVIDER ||
|
|
247
|
+
'openai').toLowerCase();
|
|
225
248
|
// Validate provider type using centralized list
|
|
226
249
|
if (!exports.EMBEDDING_PROVIDERS.includes(providerType)) {
|
|
227
250
|
console.warn(`Unknown embedding provider: ${providerType}, falling back to openai`);
|
|
@@ -230,7 +253,7 @@ function createEmbeddingProvider(config = {}) {
|
|
|
230
253
|
try {
|
|
231
254
|
const provider = new VercelEmbeddingProvider({
|
|
232
255
|
...config,
|
|
233
|
-
provider: providerType
|
|
256
|
+
provider: providerType,
|
|
234
257
|
});
|
|
235
258
|
return provider.isAvailable() ? provider : null;
|
|
236
259
|
}
|
|
@@ -300,25 +323,29 @@ class EmbeddingService {
|
|
|
300
323
|
getStatus() {
|
|
301
324
|
if (this.isAvailable()) {
|
|
302
325
|
// Get provider type from VercelEmbeddingProvider
|
|
303
|
-
const providerName = this.provider.getProviderType?.() ||
|
|
326
|
+
const providerName = this.provider.getProviderType?.() ||
|
|
327
|
+
'unknown';
|
|
328
|
+
const isCustomEndpoint = providerName === 'openai' && !!process.env.CUSTOM_EMBEDDINGS_BASE_URL;
|
|
304
329
|
return {
|
|
305
330
|
available: true,
|
|
306
|
-
provider: providerName,
|
|
307
|
-
model:
|
|
308
|
-
|
|
331
|
+
provider: isCustomEndpoint ? 'custom' : providerName,
|
|
332
|
+
model: isCustomEndpoint && !process.env.EMBEDDINGS_MODEL
|
|
333
|
+
? 'custom'
|
|
334
|
+
: this.provider.getModel(),
|
|
335
|
+
dimensions: this.provider.getDimensions(),
|
|
309
336
|
};
|
|
310
337
|
}
|
|
311
338
|
const requestedProvider = process.env.EMBEDDINGS_PROVIDER || 'openai';
|
|
312
339
|
const keyMap = {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
340
|
+
openai: 'OPENAI_API_KEY',
|
|
341
|
+
google: 'GOOGLE_API_KEY',
|
|
342
|
+
amazon_bedrock: 'AWS credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION)',
|
|
316
343
|
};
|
|
317
344
|
const requiredKey = keyMap[requestedProvider] || 'OPENAI_API_KEY';
|
|
318
345
|
return {
|
|
319
346
|
available: false,
|
|
320
347
|
provider: null,
|
|
321
|
-
reason: `${requiredKey} not set - vector operations will fail
|
|
348
|
+
reason: `${requiredKey} not set - vector operations will fail`,
|
|
322
349
|
};
|
|
323
350
|
}
|
|
324
351
|
/**
|
|
@@ -330,8 +357,10 @@ class EmbeddingService {
|
|
|
330
357
|
...pattern.triggers,
|
|
331
358
|
pattern.rationale,
|
|
332
359
|
// Include resource types for better semantic matching
|
|
333
|
-
...pattern.suggestedResources.map(r => `kubernetes ${r.toLowerCase()}`)
|
|
334
|
-
]
|
|
360
|
+
...pattern.suggestedResources.map(r => `kubernetes ${r.toLowerCase()}`),
|
|
361
|
+
]
|
|
362
|
+
.join(' ')
|
|
363
|
+
.trim();
|
|
335
364
|
}
|
|
336
365
|
/**
|
|
337
366
|
* Get circuit breaker statistics for monitoring
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
* Update versions here to change them everywhere.
|
|
6
6
|
*/
|
|
7
7
|
export declare const CURRENT_MODELS: {
|
|
8
|
-
readonly anthropic: "claude-sonnet-4-
|
|
8
|
+
readonly anthropic: "claude-sonnet-4-6";
|
|
9
9
|
readonly anthropic_opus: "claude-opus-4-6";
|
|
10
10
|
readonly anthropic_haiku: "claude-haiku-4-5-20251001";
|
|
11
11
|
readonly openai: "gpt-5.1-codex";
|
|
12
|
-
readonly google: "gemini-3-pro-preview";
|
|
12
|
+
readonly google: "gemini-3.1-pro-preview";
|
|
13
13
|
readonly google_flash: "gemini-3-flash-preview";
|
|
14
14
|
readonly kimi: "kimi-k2-0905-preview";
|
|
15
15
|
readonly kimi_thinking: "kimi-k2-thinking";
|
|
@@ -17,7 +17,7 @@ export declare const CURRENT_MODELS: {
|
|
|
17
17
|
readonly host: "host";
|
|
18
18
|
readonly openrouter: "anthropic/claude-haiku-4.5";
|
|
19
19
|
readonly custom: "gpt-5.1-codex";
|
|
20
|
-
readonly amazon_bedrock: "global.anthropic.claude-sonnet-4-
|
|
20
|
+
readonly amazon_bedrock: "global.anthropic.claude-sonnet-4-6";
|
|
21
21
|
};
|
|
22
22
|
/**
|
|
23
23
|
* Get current model for a provider
|
|
@@ -9,11 +9,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
9
9
|
exports.CURRENT_MODELS = void 0;
|
|
10
10
|
exports.getCurrentModel = getCurrentModel;
|
|
11
11
|
exports.CURRENT_MODELS = {
|
|
12
|
-
anthropic: 'claude-sonnet-4-
|
|
12
|
+
anthropic: 'claude-sonnet-4-6',
|
|
13
13
|
anthropic_opus: 'claude-opus-4-6',
|
|
14
14
|
anthropic_haiku: 'claude-haiku-4-5-20251001',
|
|
15
15
|
openai: 'gpt-5.1-codex',
|
|
16
|
-
google: 'gemini-3-pro-preview',
|
|
16
|
+
google: 'gemini-3.1-pro-preview',
|
|
17
17
|
google_flash: 'gemini-3-flash-preview', // PRD #294: Gemini 3 Flash - faster/cheaper variant with same 1M context
|
|
18
18
|
kimi: 'kimi-k2-0905-preview', // PRD #237: Moonshot AI Kimi K2 - standard model with 256K context
|
|
19
19
|
kimi_thinking: 'kimi-k2-thinking', // PRD #237: Moonshot AI Kimi K2 - extended thinking variant
|
|
@@ -21,7 +21,7 @@ exports.CURRENT_MODELS = {
|
|
|
21
21
|
host: 'host', // Delegates generation to the client via MCP Sampling
|
|
22
22
|
openrouter: 'anthropic/claude-haiku-4.5', // PRD #194: OpenRouter default model (overridden by AI_MODEL env var)
|
|
23
23
|
custom: 'gpt-5.1-codex', // PRD #194: Custom endpoint default model (overridden by AI_MODEL env var)
|
|
24
|
-
amazon_bedrock: 'global.anthropic.claude-sonnet-4-
|
|
24
|
+
amazon_bedrock: 'global.anthropic.claude-sonnet-4-6' // PRD #175: Amazon Bedrock default model (overridden by AI_MODEL env var)
|
|
25
25
|
};
|
|
26
26
|
/**
|
|
27
27
|
* Get current model for a provider
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedding Migration Handler
|
|
3
|
+
*
|
|
4
|
+
* Handles POST /api/v1/embeddings/migrate requests.
|
|
5
|
+
* Re-embeds all data in vector collections when switching embedding providers
|
|
6
|
+
* (e.g., OpenAI 1536-dim → local TEI 384-dim).
|
|
7
|
+
*
|
|
8
|
+
* PRD #384: Optional Local Embedding Service
|
|
9
|
+
*/
|
|
10
|
+
import { Logger } from '../core/error-handling';
|
|
11
|
+
import { RestApiResponse } from './rest-api';
|
|
12
|
+
/**
|
|
13
|
+
* Handle embedding migration request
|
|
14
|
+
*/
|
|
15
|
+
export declare function handleEmbeddingMigration(body: unknown, logger: Logger, requestId: string): Promise<RestApiResponse>;
|
|
16
|
+
//# sourceMappingURL=embedding-migration-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedding-migration-handler.d.ts","sourceRoot":"","sources":["../../src/interfaces/embedding-migration-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGhD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA+N7C;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CA8I1B"}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Embedding Migration Handler
|
|
4
|
+
*
|
|
5
|
+
* Handles POST /api/v1/embeddings/migrate requests.
|
|
6
|
+
* Re-embeds all data in vector collections when switching embedding providers
|
|
7
|
+
* (e.g., OpenAI 1536-dim → local TEI 384-dim).
|
|
8
|
+
*
|
|
9
|
+
* PRD #384: Optional Local Embedding Service
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.handleEmbeddingMigration = handleEmbeddingMigration;
|
|
13
|
+
const embedding_service_1 = require("../core/embedding-service");
|
|
14
|
+
const plugin_registry_1 = require("../core/plugin-registry");
|
|
15
|
+
const PLUGIN_NAME = 'agentic-tools';
|
|
16
|
+
const BATCH_SIZE = 50;
|
|
17
|
+
/**
|
|
18
|
+
* Invoke a plugin tool and extract the result data
|
|
19
|
+
*/
|
|
20
|
+
async function invokePlugin(tool, args) {
|
|
21
|
+
const response = await (0, plugin_registry_1.invokePluginTool)(PLUGIN_NAME, tool, args);
|
|
22
|
+
if (!response.success) {
|
|
23
|
+
const error = response.error;
|
|
24
|
+
const message = typeof error === 'object' && error?.message
|
|
25
|
+
? error.message
|
|
26
|
+
: String(error || `Plugin tool ${tool} failed`);
|
|
27
|
+
throw new Error(message);
|
|
28
|
+
}
|
|
29
|
+
const toolResult = response.result;
|
|
30
|
+
if (!toolResult || typeof toolResult !== 'object') {
|
|
31
|
+
throw new Error(`Plugin tool ${tool} returned invalid result`);
|
|
32
|
+
}
|
|
33
|
+
if (toolResult.success === false) {
|
|
34
|
+
throw new Error(toolResult.error || toolResult.message || `Plugin tool ${tool} failed`);
|
|
35
|
+
}
|
|
36
|
+
return toolResult.data;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Migrate a single collection: read all points, re-embed, recreate collection, store
|
|
40
|
+
*/
|
|
41
|
+
async function migrateCollection(collectionName, embeddingService, targetDimensions, logger, requestId) {
|
|
42
|
+
// Get current collection stats
|
|
43
|
+
const stats = await invokePlugin('collection_stats', {
|
|
44
|
+
collection: collectionName,
|
|
45
|
+
});
|
|
46
|
+
if (!stats.exists) {
|
|
47
|
+
return {
|
|
48
|
+
collection: collectionName,
|
|
49
|
+
status: 'failed',
|
|
50
|
+
previousDimensions: 0,
|
|
51
|
+
newDimensions: targetDimensions,
|
|
52
|
+
total: 0,
|
|
53
|
+
processed: 0,
|
|
54
|
+
failed: 0,
|
|
55
|
+
error: `Collection '${collectionName}' does not exist`,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const previousDimensions = stats.vectorSize;
|
|
59
|
+
// Skip if dimensions already match
|
|
60
|
+
if (previousDimensions === targetDimensions) {
|
|
61
|
+
return {
|
|
62
|
+
collection: collectionName,
|
|
63
|
+
status: 'skipped',
|
|
64
|
+
previousDimensions,
|
|
65
|
+
newDimensions: targetDimensions,
|
|
66
|
+
total: stats.pointsCount,
|
|
67
|
+
processed: 0,
|
|
68
|
+
failed: 0,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
logger.info('Starting collection migration', {
|
|
72
|
+
requestId,
|
|
73
|
+
collection: collectionName,
|
|
74
|
+
previousDimensions,
|
|
75
|
+
targetDimensions,
|
|
76
|
+
pointsCount: stats.pointsCount,
|
|
77
|
+
});
|
|
78
|
+
// List all points (payload only, no vectors)
|
|
79
|
+
const documents = await invokePlugin('vector_list', {
|
|
80
|
+
collection: collectionName,
|
|
81
|
+
limit: 10000,
|
|
82
|
+
});
|
|
83
|
+
const total = documents.length;
|
|
84
|
+
// Extract searchText from each document
|
|
85
|
+
const pointsWithText = documents.map(doc => ({
|
|
86
|
+
id: doc.id,
|
|
87
|
+
payload: doc.payload,
|
|
88
|
+
searchText: doc.payload.searchText || '',
|
|
89
|
+
}));
|
|
90
|
+
// Filter out points without searchText
|
|
91
|
+
const migrateablePoints = pointsWithText.filter(p => p.searchText.length > 0);
|
|
92
|
+
const skippedNoText = total - migrateablePoints.length;
|
|
93
|
+
if (skippedNoText > 0) {
|
|
94
|
+
logger.warn('Some points have no searchText and will be skipped', {
|
|
95
|
+
requestId,
|
|
96
|
+
collection: collectionName,
|
|
97
|
+
skippedNoText,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
// Batch re-embed all texts
|
|
101
|
+
const allTexts = migrateablePoints.map(p => p.searchText);
|
|
102
|
+
const allEmbeddings = [];
|
|
103
|
+
let failedEmbeddings = 0;
|
|
104
|
+
for (let i = 0; i < allTexts.length; i += BATCH_SIZE) {
|
|
105
|
+
const batch = allTexts.slice(i, i + BATCH_SIZE);
|
|
106
|
+
try {
|
|
107
|
+
const embeddings = await embeddingService.generateEmbeddings(batch);
|
|
108
|
+
allEmbeddings.push(...embeddings);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
logger.error('Batch embedding failed', error instanceof Error ? error : new Error(String(error)), {
|
|
112
|
+
requestId,
|
|
113
|
+
collection: collectionName,
|
|
114
|
+
batchStart: i,
|
|
115
|
+
batchSize: batch.length,
|
|
116
|
+
});
|
|
117
|
+
// Fill with empty arrays to track failures
|
|
118
|
+
for (let j = 0; j < batch.length; j++) {
|
|
119
|
+
allEmbeddings.push([]);
|
|
120
|
+
}
|
|
121
|
+
failedEmbeddings += batch.length;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Recreate collection with new dimensions (initializeCollection auto-deletes on mismatch)
|
|
125
|
+
await invokePlugin('collection_initialize', {
|
|
126
|
+
collection: collectionName,
|
|
127
|
+
vectorSize: targetDimensions,
|
|
128
|
+
createTextIndex: true,
|
|
129
|
+
});
|
|
130
|
+
// Store all re-embedded points
|
|
131
|
+
let processed = 0;
|
|
132
|
+
let failed = failedEmbeddings + skippedNoText;
|
|
133
|
+
for (let i = 0; i < migrateablePoints.length; i++) {
|
|
134
|
+
const point = migrateablePoints[i];
|
|
135
|
+
const embedding = allEmbeddings[i];
|
|
136
|
+
// Skip points where embedding failed
|
|
137
|
+
if (!embedding || embedding.length === 0) {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
await invokePlugin('vector_store', {
|
|
142
|
+
collection: collectionName,
|
|
143
|
+
id: point.id,
|
|
144
|
+
embedding,
|
|
145
|
+
payload: point.payload,
|
|
146
|
+
});
|
|
147
|
+
processed++;
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
logger.error('Failed to store re-embedded point', error instanceof Error ? error : new Error(String(error)), {
|
|
151
|
+
requestId,
|
|
152
|
+
collection: collectionName,
|
|
153
|
+
pointId: point.id,
|
|
154
|
+
});
|
|
155
|
+
failed++;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
logger.info('Collection migration complete', {
|
|
159
|
+
requestId,
|
|
160
|
+
collection: collectionName,
|
|
161
|
+
total,
|
|
162
|
+
processed,
|
|
163
|
+
failed,
|
|
164
|
+
});
|
|
165
|
+
return {
|
|
166
|
+
collection: collectionName,
|
|
167
|
+
status: 'migrated',
|
|
168
|
+
previousDimensions,
|
|
169
|
+
newDimensions: targetDimensions,
|
|
170
|
+
total,
|
|
171
|
+
processed,
|
|
172
|
+
failed,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Handle embedding migration request
|
|
177
|
+
*/
|
|
178
|
+
async function handleEmbeddingMigration(body, logger, requestId) {
|
|
179
|
+
// Check plugin availability
|
|
180
|
+
if (!(0, plugin_registry_1.isPluginInitialized)()) {
|
|
181
|
+
return {
|
|
182
|
+
success: false,
|
|
183
|
+
error: {
|
|
184
|
+
code: 'PLUGIN_UNAVAILABLE',
|
|
185
|
+
message: 'Plugin system is not initialized. Vector database operations are unavailable.',
|
|
186
|
+
},
|
|
187
|
+
meta: {
|
|
188
|
+
timestamp: new Date().toISOString(),
|
|
189
|
+
requestId,
|
|
190
|
+
version: 'v1',
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
// Check embedding service availability
|
|
195
|
+
const embeddingService = new embedding_service_1.EmbeddingService();
|
|
196
|
+
if (!embeddingService.isAvailable()) {
|
|
197
|
+
const status = embeddingService.getStatus();
|
|
198
|
+
return {
|
|
199
|
+
success: false,
|
|
200
|
+
error: {
|
|
201
|
+
code: 'EMBEDDING_SERVICE_UNAVAILABLE',
|
|
202
|
+
message: `Embedding service is not available: ${status.reason || 'No embedding provider configured'}`,
|
|
203
|
+
},
|
|
204
|
+
meta: {
|
|
205
|
+
timestamp: new Date().toISOString(),
|
|
206
|
+
requestId,
|
|
207
|
+
version: 'v1',
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
const targetDimensions = embeddingService.getDimensions();
|
|
212
|
+
// Parse request body
|
|
213
|
+
const parsedBody = body && typeof body === 'object' ? body : {};
|
|
214
|
+
const requestedCollection = typeof parsedBody.collection === 'string'
|
|
215
|
+
? parsedBody.collection
|
|
216
|
+
: undefined;
|
|
217
|
+
// Discover collections
|
|
218
|
+
let collectionsToMigrate;
|
|
219
|
+
if (requestedCollection) {
|
|
220
|
+
collectionsToMigrate = [requestedCollection];
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
try {
|
|
224
|
+
collectionsToMigrate = await invokePlugin('collection_list', {});
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
228
|
+
return {
|
|
229
|
+
success: false,
|
|
230
|
+
error: {
|
|
231
|
+
code: 'MIGRATION_ERROR',
|
|
232
|
+
message: `Failed to list collections: ${message}`,
|
|
233
|
+
},
|
|
234
|
+
meta: {
|
|
235
|
+
timestamp: new Date().toISOString(),
|
|
236
|
+
requestId,
|
|
237
|
+
version: 'v1',
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
logger.info('Starting embedding migration', {
|
|
243
|
+
requestId,
|
|
244
|
+
targetDimensions,
|
|
245
|
+
collections: collectionsToMigrate,
|
|
246
|
+
requestedCollection: requestedCollection || 'all',
|
|
247
|
+
});
|
|
248
|
+
// Migrate each collection
|
|
249
|
+
const results = [];
|
|
250
|
+
for (const collectionName of collectionsToMigrate) {
|
|
251
|
+
try {
|
|
252
|
+
const result = await migrateCollection(collectionName, embeddingService, targetDimensions, logger, requestId);
|
|
253
|
+
results.push(result);
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
257
|
+
logger.error('Collection migration failed', error instanceof Error ? error : new Error(message), {
|
|
258
|
+
requestId,
|
|
259
|
+
collection: collectionName,
|
|
260
|
+
});
|
|
261
|
+
results.push({
|
|
262
|
+
collection: collectionName,
|
|
263
|
+
status: 'failed',
|
|
264
|
+
previousDimensions: 0,
|
|
265
|
+
newDimensions: targetDimensions,
|
|
266
|
+
total: 0,
|
|
267
|
+
processed: 0,
|
|
268
|
+
failed: 0,
|
|
269
|
+
error: message,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// Build summary
|
|
274
|
+
const summary = {
|
|
275
|
+
totalCollections: results.length,
|
|
276
|
+
migrated: results.filter(r => r.status === 'migrated').length,
|
|
277
|
+
skipped: results.filter(r => r.status === 'skipped').length,
|
|
278
|
+
failed: results.filter(r => r.status === 'failed').length,
|
|
279
|
+
};
|
|
280
|
+
logger.info('Embedding migration complete', {
|
|
281
|
+
requestId,
|
|
282
|
+
summary,
|
|
283
|
+
});
|
|
284
|
+
return {
|
|
285
|
+
success: true,
|
|
286
|
+
data: {
|
|
287
|
+
collections: results,
|
|
288
|
+
summary,
|
|
289
|
+
},
|
|
290
|
+
meta: {
|
|
291
|
+
timestamp: new Date().toISOString(),
|
|
292
|
+
requestId,
|
|
293
|
+
version: 'v1',
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
}
|
|
@@ -244,6 +244,10 @@ export declare class RestApiRouter {
|
|
|
244
244
|
* Uses an agentic approach with toolLoop to allow multiple searches if needed.
|
|
245
245
|
*/
|
|
246
246
|
private handleKnowledgeAsk;
|
|
247
|
+
/**
|
|
248
|
+
* Handle embedding migration request (PRD #384)
|
|
249
|
+
*/
|
|
250
|
+
private handleEmbeddingMigrationRequest;
|
|
247
251
|
/**
|
|
248
252
|
* Set CORS headers
|
|
249
253
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest-api.d.ts","sourceRoot":"","sources":["../../src/interfaces/rest-api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE5D,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,EAAE,iBAAiB,EAAc,MAAM,uBAAuB,CAAC;AAEtE,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"rest-api.d.ts","sourceRoot":"","sources":["../../src/interfaces/rest-api.ts"],"names":[],"mappings":"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"}
|