Quickstart: Node.js
-
Install
Terminal window npm install @equationalapplications/core-llm-wiki better-sqlite3 -
Create an adapter and the wiki
memory.ts import Database from 'better-sqlite3';import OpenAI from 'openai';import { createWiki, type SQLiteAdapter } from '@equationalapplications/core-llm-wiki';const db = new Database('memory.db');const adapter: SQLiteAdapter = {async execAsync(sql) { db.exec(sql); },async runAsync(sql, params = []) {const info = db.prepare(sql).run(...(params as any[]));return { changes: info.changes, lastInsertRowId: Number(info.lastInsertRowid) };},async getAllAsync(sql, params = []) { return db.prepare(sql).all(...(params as any[])) as any; },async getFirstAsync(sql, params = []) { return (db.prepare(sql).get(...(params as any[])) ?? null) as any; },async withTransactionAsync(fn) {db.exec('BEGIN');try { const r = await fn(adapter); db.exec('COMMIT'); return r; }catch (e) { db.exec('ROLLBACK'); throw e; }},async closeAsync() { db.close(); },};const openai = new OpenAI();export const wiki = createWiki(adapter, {llmProvider: {generateText: async ({ systemPrompt, userPrompt }) => {const r = await openai.chat.completions.create({model: 'gpt-4o-mini',messages: [{ role: 'system', content: systemPrompt },{ role: 'user', content: userPrompt },],});return r.choices[0].message.content ?? '{}';},embed: async (text) => {const r = await openai.embeddings.create({ model: 'text-embedding-3-small', input: text });return r.data[0].embedding;},},});await wiki.setup(); -
Ingest, read, and answer
main.ts import { createHash } from 'node:crypto';import { readFile } from 'node:fs/promises';import { formatContext } from '@equationalapplications/core-llm-wiki';import { wiki } from './memory';const content = await readFile('handbook.md', 'utf8');const sourceHash = createHash('sha256').update(content).digest('hex');if (await wiki.hasChanged('team', 'handbook.md', sourceHash)) {await wiki.ingestDocument('team', { sourceRef: 'handbook.md', sourceHash, documentChunk: content });}const memory = await wiki.read('team', 'what is the on-call policy?');console.log(formatContext(memory));
Server checklist
Section titled “Server checklist”- One connection per database file per process. The engine serializes its own transactions on that connection. Don’t open a second writer.
- Turning events into facts. Maintenance doesn’t run by itself: call
runPendingMaintenance()on your own schedule, or setmaintenance: 'auto'on a long-lived host. On a request-scoped or serverless host, always run it explicitly. See Serverless & multi-tenant hosting. - Shutting down? In
'auto'maintenance mode,await wiki.drain()before you close, so background librarian and heal jobs can finish.