(batch: string[])
| 226 | } |
| 227 | |
| 228 | async function embedBatchAdaptive(batch: string[]): Promise<number[][]> { |
| 229 | try { |
| 230 | const timeoutCtrl = AbortSignal.timeout(EMBED_TIMEOUT_MS); |
| 231 | const signal = AbortSignal.any([embedAbortController.signal, timeoutCtrl]); |
| 232 | const embeddings = await callProviderEmbed(batch, signal); |
| 233 | if (embeddings.length !== batch.length) { |
| 234 | throw new Error(`Embedding response size mismatch: expected ${batch.length}, got ${embeddings.length}`); |
| 235 | } |
| 236 | return embeddings; |
| 237 | } catch (error) { |
| 238 | if (!isContextLengthError(error)) throw error; |
| 239 | if (batch.length === 1) { |
| 240 | return [await embedSingleAdaptive(batch[0])]; |
| 241 | } |
| 242 | const middle = Math.ceil(batch.length / 2); |
| 243 | const left = await embedBatchAdaptive(batch.slice(0, middle)); |
| 244 | const right = await embedBatchAdaptive(batch.slice(middle)); |
| 245 | return [...left, ...right]; |
| 246 | } |
| 247 | } |
| 248 | |
| 249 | function splitEmbeddingInput(input: string): string[] { |
| 250 | const chunkChars = getEmbedChunkChars(); |
no test coverage detected