// Seed a few sample knowledge-base docs so the RAG agent has something // to retrieve on first boot. // // `lifecycle: 'boot'` runs this once per `voltro dev` boot, re-running // only when the seed file's content fingerprint changes. `upsertByUnique` // keys on `title`, so re-runs UPDATE rather than duplicate — idempotent. // // The `docs` table carries `vectorEmbedding({ from: 'body' })`, so each // insert/update AUTO-EMBEDS the body via `@voltro/ai`'s `embed` — no // embedding code here. NOTE: that embed needs a provider key // (AI_PROVIDER / AI_MODEL + the key var). Without one the rows still seed // (title + body persist) but the `embedding` column stays empty; run // `voltro embeddings backfill docs --text body --vector embedding` // after setting a key to fill them in. See the README. import { defineSeed } from '@voltro/database' const SAMPLE_DOCS: ReadonlyArray<{ title: string; body: string }> = [ { title: 'Resetting your password', body: 'To reset your password, open Settings → Security and click "Reset password". ' + 'You will receive an email with a one-time link valid for 30 minutes. If the ' + 'link expires, request a new one from the same screen. Passwords must be at ' + 'least 12 characters and include a number and a symbol.', }, { title: 'Inviting teammates', body: 'Admins can invite teammates from the Members page. Enter the teammate\'s email ' + 'and pick a role (Viewer, Member, or Admin). Invites expire after 7 days. A ' + 'pending invite can be revoked or resent from the same list. Billing is per ' + 'active seat — a revoked invite is never charged.', }, { title: 'Exporting your data', body: 'You can export all of your workspace data from Settings → Data → Export. ' + 'We generate a downloadable ZIP of newline-delimited JSON, one file per table. ' + 'Large workspaces are processed in the background; you get an email with the ' + 'download link when it is ready. Export links expire after 24 hours.', }, { title: 'API rate limits', body: 'The API allows 100 requests per minute per API key by default. Exceeding the ' + 'limit returns HTTP 429 with a Retry-After header. Enterprise plans can request ' + 'a higher limit. Use exponential backoff on 429 responses; do not retry 4xx ' + 'errors other than 429.', }, ] export default defineSeed({ id: 'docs', name: 'Sample knowledge-base docs', lifecycle: 'boot', steps: ({ step }) => [ step('seed-docs', async ({ upsertByUnique }) => { let rowsTouched = 0 for (const doc of SAMPLE_DOCS) { await upsertByUnique('docs', { title: doc.title }, { title: doc.title, body: doc.body }) rowsTouched += 1 } return { rowsTouched } }), ], })