Skip to content

Commit edce2ce

Browse files
p4w4nclaude
andcommitted
boot the reflection worker (embedder optional)
ReflectionWorkerOpts.embedder is now optional. reflectionTick returns zeroed counts when no embedder is wired so the cadence exists from boot — once a tenant adds Voyage / OpenAI keys, the next tick picks up the backlog. Wired into server/src/index.ts boot next to the MemoryService init: starts the 30s interval, .unref()'d so it doesn't pin the event loop on shutdown. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent cb554d8 commit edce2ce

2 files changed

Lines changed: 20 additions & 1 deletion

File tree

server/src/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,15 @@ export async function startServer(): Promise<StartedServer> {
621621
createPgvectorMemoryBackend(db as any),
622622
createPgvectorWikiBackend(db as any),
623623
);
624+
625+
// Reflection worker — backfills embeddings for memory_entries +
626+
// memory_pages where embedding IS NULL. Booted even without an
627+
// embedder configured (the tick no-ops); once a tenant adds an
628+
// embedder, the next tick picks up the backlog. Interval is 30s.
629+
const { startReflectionWorker } = await import(
630+
"./services/memory/reflection-worker.js"
631+
);
632+
startReflectionWorker({ db: db as any });
624633
const app = await createApp(db as any, {
625634
uiMode,
626635
serverPort: listenPort,

server/src/services/memory/reflection-worker.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ import type { EmbeddingProvider } from "./embedding.js";
2626

2727
export interface ReflectionWorkerOpts {
2828
db: Db;
29-
embedder: EmbeddingProvider;
29+
// Optional. When absent, the embed stages are skipped (no-op tick).
30+
// Boot can wire the worker before any embedder is configured —
31+
// the worker quietly idles until createEmbeddingProvider lands.
32+
embedder?: EmbeddingProvider;
3033
// How many rows per tick. Default 32; embedding APIs are happiest
3134
// with batches up to ~100 (see embedding.ts MAX_BATCH).
3235
batchSize?: number;
@@ -116,6 +119,13 @@ export async function reflectionTick(
116119
let factsEmbedded = 0;
117120
let pagesEmbedded = 0;
118121
let errors = 0;
122+
// No-op when no embedder is wired. Boot installs the worker even
123+
// before an embedder is configured so the cadence exists; once a
124+
// tenant adds Voyage / OpenAI keys, the next tick picks up the
125+
// pending backlog.
126+
if (!opts.embedder) {
127+
return { factsEmbedded: 0, pagesEmbedded: 0, errors: 0 };
128+
}
119129
try {
120130
const facts = await embedPendingFacts(opts.db, opts.embedder, batchSize);
121131
factsEmbedded = facts.embedded;

0 commit comments

Comments
 (0)