v0.6.0

Embedding

See how pending chunks are embedded with OpenAI, applied to SQLite without races, and loaded into the in-memory vector cache.

Embedding scheduler

Every five seconds, runEmbedder selects up to 64 rows, oldest ID first, where:

is_embed = FALSE AND dismiss = FALSE

The scheduler sends their content to EmbedBatch. Input longer than 8,000 Unicode runes is truncated before the request. The client requests text-embedding-3-small with 512 dimensions and a one-minute HTTP timeout.

The batch is rejected if OpenAI returns the wrong number of vectors or any vector has the wrong dimension. A rejected or failed batch is logged and the rows stay pending, so the next tick retries them.

Race-safe application

UpdateEmbedding runs in one transaction and updates each row only when all of these still match:

This prevents a slow OpenAI response from attaching an obsolete vector after a file changes. The function returns only IDs whose updates were applied.

Vector-cache update

For applied IDs, KuraDB stores each vector in the database bucket, tracks the source-to-chunk relationship, and rebuilds every affected source vector. Source vectors are normalized sums of valid, same-dimension chunk vectors.

The running cache is only added to, never evicted. Vectors of dismissed rows stay in memory until restart, and a chunk whose content changed keeps its previous vector until the new one is applied. Semantic results are still correct about content because hydration reads SQLite with dismiss = FALSE, which drops dismissed rows and returns current text.

On daemon startup, the cache is reconstructed from active embedded rows in SQLite, then all source vectors are rebuilt. SQLite remains authoritative if the in-memory cache is lost.

中文