* Run embedding sequentially on all queued nodes. The model was * pre-loaded in the constructor so init is already done by now.
(
onProgress?: (embedded: number, total: number) => void,
)
| 584 | * pre-loaded in the constructor so init is already done by now. |
| 585 | */ |
| 586 | async settle( |
| 587 | onProgress?: (embedded: number, total: number) => void, |
| 588 | ): Promise<void> { |
| 589 | const embedder = await this.ensureModel(); |
| 590 | if (!embedder) { |
| 591 | // Init failed — drop queued nodes so the (potentially long-lived) |
| 592 | // EmbedStage instance does not retain File-node references and their |
| 593 | // attached source/summary properties. For large repos the queue can |
| 594 | // hold thousands of entries. |
| 595 | this.queue = []; |
| 596 | return; |
| 597 | } |
| 598 | if (this.queue.length === 0) return; |
| 599 | |
| 600 | const BATCH = 8; |
| 601 | for (let off = 0; off < this.queue.length; off += BATCH) { |
| 602 | const batch = this.queue.slice(off, off + BATCH); |
| 603 | const texts = batch.map((n) => { |
| 604 | const parts = [n.name, n.type]; |
| 605 | const props = n.properties ?? {}; |
| 606 | if (typeof props.summary === 'string') parts.push(props.summary); |
| 607 | if (typeof props.path === 'string') parts.push(props.path); |
| 608 | return parts.join(' '); |
| 609 | }); |
| 610 | |
| 611 | try { |
| 612 | const vectors = await embedder.embed(texts); |
| 613 | const pending: { id: string; vec: number[] }[] = []; |
| 614 | for (let i = 0; i < batch.length; i++) { |
| 615 | if (vectors[i] && vectors[i].length > 0) { |
| 616 | pending.push({ id: batch[i].id, vec: vectors[i] }); |
| 617 | } |
| 618 | } |
| 619 | if (pending.length > 0 && this.store.importVectors) { |
| 620 | await this.store.importVectors(pending); |
| 621 | this.embedded += pending.length; |
| 622 | } |
| 623 | } catch (err) { |
| 624 | // Skip the bad batch but keep going — one toxic input shouldn't |
| 625 | // abort the whole indexing run. Log so the failure is debuggable |
| 626 | // instead of silently dropping vectors. |
| 627 | console.error( |
| 628 | `[EmbedStage] batch failed (offset ${off}, size ${batch.length}):`, |
| 629 | err, |
| 630 | ); |
| 631 | } |
| 632 | |
| 633 | onProgress?.(this.embedded, this.queue.length); |
| 634 | await new Promise<void>((r) => setTimeout(r, 0)); |
| 635 | } |
| 636 | |
| 637 | // Free node references — they're persisted in the DB now |
| 638 | this.queue = []; |
| 639 | } |
| 640 | |
| 641 | get embeddedCount(): number { |
| 642 | return this.embedded; |
no test coverage detected