2026-09-13 14:29:16 +03:00
|
|
|
/**
|
2026-09-23 03:53:57 +03:00
|
|
|
* Embed the whole graph (backfill / cold start / model change): one-time
|
|
|
|
|
* pass that fills the embedding ledger for every node — the same
|
|
|
|
|
* embedNewNodes the post-merge hook runs, just with an empty (or
|
|
|
|
|
* stale-model) ledger so every node is "new".
|
|
|
|
|
*
|
|
|
|
|
* BYOK (wave 6, 2026-09-23): vectors come from the configured provider
|
|
|
|
|
* (graph.embeddingModel, keys from the auth store) — this script resolves
|
|
|
|
|
* the live state up front so an unconfigured machine says so before
|
|
|
|
|
* anything bills. A model CHANGE re-embeds everything (ledger staleness).
|
2026-09-13 14:29:16 +03:00
|
|
|
*
|
|
|
|
|
* npx tsx scripts/embed-graph.ts
|
|
|
|
|
*/
|
2026-09-23 03:53:57 +03:00
|
|
|
import { embedNewNodes, embeddingPort } from "../src/server/embeddings.ts";
|
2026-09-13 14:29:16 +03:00
|
|
|
import { graphStore } from "../src/store/graph.ts";
|
|
|
|
|
|
|
|
|
|
async function main() {
|
2026-09-23 03:53:57 +03:00
|
|
|
const resolved = embeddingPort();
|
|
|
|
|
if (!resolved.ok) {
|
|
|
|
|
console.error(`[embed] cannot run — ${resolved.reason}`);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
2026-09-13 14:29:16 +03:00
|
|
|
const t0 = Date.now();
|
2026-09-23 03:53:57 +03:00
|
|
|
console.log(`[embed] model: ${resolved.port.model} (provider embeddings, batch 32)`);
|
2026-09-23 12:21:36 +03:00
|
|
|
const { embedded, total, usage, failed } = await embedNewNodes(graphStore);
|
|
|
|
|
const secs = ((Date.now() - t0) / 1000).toFixed(1);
|
2026-09-23 03:53:57 +03:00
|
|
|
if (usage) {
|
|
|
|
|
const tokens = usage.steps.reduce((sum, s) => sum + (s.inputTokens ?? 0), 0);
|
|
|
|
|
console.log(`[embed] embedding spend: ${tokens} prompt tokens over ${usage.steps.length} call(s)`);
|
|
|
|
|
}
|
2026-09-23 12:21:36 +03:00
|
|
|
// Usage-on-error + pay-once (owner ruling 2026-09-23): a mid-run provider
|
|
|
|
|
// failure still reports the landed batches' spend above; the landed
|
|
|
|
|
// vectors are persisted, so the honest count is what LANDED — the
|
|
|
|
|
// in-memory `total` would read as a ledger claim it can't make.
|
|
|
|
|
if (failed) {
|
|
|
|
|
console.error(
|
|
|
|
|
`[embed] failed after ${embedded} node(s) landed (${secs}s) — the ledger keeps exactly those (a retry embeds only the rest): ${failed}`,
|
|
|
|
|
);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
console.log(`[embed] embedded ${embedded} nodes → ledger holds ${total} vectors (${secs}s)`);
|
2026-09-13 14:29:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
main().catch((err) => {
|
|
|
|
|
console.error("[embed] failed:", err);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
});
|