{"_id":"@blackridder22/sonomem","name":"@blackridder22/sonomem","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"@blackridder22/sonomem","version":"0.0.1","description":"Provider-neutral hybrid memory engine for AI chat/agent apps. Postgres + pgvector. The model proposes; the database disposes.","type":"module","license":"MIT","sideEffects":false,"publishConfig":{"access":"public"},"keywords":["ai","memory","agent","chat","pgvector","postgres","rag","ai-sdk","long-term-memory"],"engines":{"node":">=20"},"types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./converters":{"types":"./dist/converters/index.d.ts","import":"./dist/converters/index.js"},"./schema":{"types":"./dist/db/schema.d.ts","import":"./dist/db/schema.js"},"./migrations":{"types":"./dist/db/migrations.d.ts","import":"./dist/db/migrations.js"},"./ai-sdk":{"types":"./dist/ai-sdk/index.d.ts","import":"./dist/ai-sdk/index.js"}},"peerDependencies":{"ai":">=5","drizzle-orm":">=0.36","zod":">=3.23"},"peerDependenciesMeta":{"ai":{"optional":true}},"repository":{"type":"git","url":"git+https://github.com/blackridder22/SonoMem.git"},"devDependencies":{"@types/node":"^26.1.1","ai":"^7.0.22","drizzle-orm":"^0.45.2","postgres":"^3.4.9","tsup":"^8.5.1","typescript":"^5.9.3","vitest":"^4.1.10","zod":"^4.4.3"},"scripts":{"build":"tsup","typecheck":"tsc --noEmit","test":"vitest run","test:watch":"vitest"},"_id":"@blackridder22/sonomem@0.0.1","bugs":{"url":"https://github.com/blackridder22/SonoMem/issues"},"homepage":"https://github.com/blackridder22/SonoMem#readme","_integrity":"sha512-kgUtl+ods1PIsAv7/ACtmlajO79sKJxUh5iTtY9hpC+Lf22hR8KN9DKW6mSaKa9uABLZyYAns1LHUEtd4/KjZQ==","_resolved":"/private/var/folders/cj/s_wg_k5d105dmxg3nskrk9t00000gn/T/4ea72c28fc5d1e8cbfe75e0912aee024/blackridder22-sonomem-0.0.1.tgz","_from":"file:blackridder22-sonomem-0.0.1.tgz","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-kgUtl+ods1PIsAv7/ACtmlajO79sKJxUh5iTtY9hpC+Lf22hR8KN9DKW6mSaKa9uABLZyYAns1LHUEtd4/KjZQ==","shasum":"46ac25947a676e91b824a48fbfc996a4b072b946","tarball":"https://registry.npmjs.org/@blackridder22/sonomem/-/sonomem-0.0.1.tgz","fileCount":25,"unpackedSize":524307,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCjCfYabNimKbnajxulU7LAP8UzBK/igJ7T7ddZuPxuswIgch9axzGwjDpYW1DP+mt2ObCTd291ID+sQjw1OVabur8="}]},"_npmUser":{"name":"blackridder22","email":"blackridder22@gmail.com"},"directories":{},"maintainers":[{"name":"blackridder22","email":"blackridder22@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sonomem_0.0.1_1783864162922_0.035550416073799385"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-12T13:49:22.744Z","0.0.1":"2026-07-12T13:49:23.053Z","modified":"2026-07-12T13:49:23.262Z"},"maintainers":[{"name":"blackridder22","email":"blackridder22@gmail.com"}],"description":"Provider-neutral hybrid memory engine for AI chat/agent apps. Postgres + pgvector. The model proposes; the database disposes.","homepage":"https://github.com/blackridder22/SonoMem#readme","keywords":["ai","memory","agent","chat","pgvector","postgres","rag","ai-sdk","long-term-memory"],"repository":{"type":"git","url":"git+https://github.com/blackridder22/SonoMem.git"},"bugs":{"url":"https://github.com/blackridder22/SonoMem/issues"},"license":"MIT","readme":"# @blackridder22/sonomem\n\nA built-in, provider-neutral hybrid memory engine for AI chat/agent apps.\nBuilt *for* [Sonoa Search](../Sonoa%20Search1.0), designed to drop into any host\nthat can push messages with stable IDs.\n\n> The model proposes; the database disposes. And memory must never be able to\n> break the chat.\n\nSpec: [DESIGN.md](DESIGN.md) · Agent skill: [skills/sonomem/SKILL.md](skills/sonomem/SKILL.md)\n· Prior design reviews: [chats/](chats/)\n\n## What works\n\n- **Layer 2 — conversation recall**: retrieval units per exchange, edit/regen\n  lineage, rolling chat summaries (optional `summarizer` port), hybrid\n  retrieval (pgvector HNSW + Postgres FTS `simple`, RRF fusion, recency decay,\n  dense similarity floor).\n- **Layer 1 — learned memory**: versioned assertions with categories, fact\n  keys, sensitivity, quoted evidence spans, revisions, supersede-never-\n  overwrite, hash dedup, hot profile projection with snapshots + rollback.\n- **Write path**: `ingestTurn` persists units and enqueues extraction in the\n  same transaction (outbox); deterministic secret pre-filter (EN/FR patterns +\n  entropy); ONE structured extractor call; policy gate (user-authored quotes\n  only, sensitivity opt-in, confidence threshold); resolver ops\n  ADD/CONFIRM/SUPERSEDE/MERGE/CONTRADICT/REVIEW/IGNORE; **shadow mode**;\n  per-chat debounce; batched embed backfill.\n- **Manual Layer 1**: `remember` / `forget` / `pin` / `correct` +\n  activity feed (`listEvents`) with **undo** for saves, forgets, supersessions.\n- **Deletion semantics**: `onChatDeleted` (cascade + solely-evidenced memory\n  forgetting), `onMessageEdited` (stale units/evidence), `onUserDeleted`,\n  nightly consolidation (expiry, stale-evidence review) + orphan sweep via\n  `existsCheck`.\n- **Files**: `ingestFile` → chunks (searchable, `source: 'file'`) + an event\n  memory; contents never auto-become facts.\n- **Jobs**: transactional outbox in Postgres — `runPendingJobs()` (serverless\n  `after()`/cron) or `startWorker()` (long-lived), retries with backoff, dead\n  letters in the activity feed.\n- **Guarantees**: fail-open `buildContext` (timeout + circuit breaker, never\n  throws), scope required on every call, `doctor()` health checks,\n  `migrate()` idempotent migrations, versioned embeddings.\n- **AI SDK glue** (`/ai-sdk`): `createAiSdkEmbedder`, `createAiSdkExtractor`\n  (generateObject + repair retry), `createSonomemTools` (remember/forget/\n  recall), `formatContextForPrompt` (quoted-data injection template).\n\nVerified by 51 tests including an end-to-end suite against real\nPostgres + pgvector (extraction, supersession + undo, shadow mode, secret\nredaction, two-user isolation, deletion cascades, fail-open).\n\n## Quick start\n\n```ts\nimport { createSonoMem } from '@blackridder22/sonomem'\nimport { createAiSdkEmbedder, createAiSdkExtractor, createSonomemTools,\n         formatContextForPrompt } from '@blackridder22/sonomem/ai-sdk'\nimport { fromUIMessages } from '@blackridder22/sonomem/converters'\nimport { openai } from '@ai-sdk/openai'\n\nconst sonomem = createSonoMem({\n  db, // your Drizzle Postgres instance (pgvector enabled)\n  embedder: createAiSdkEmbedder({ model: openai.textEmbeddingModel('text-embedding-3-small'), dimensions: 1536 }),\n  extractor: createAiSdkExtractor({ model: openai('gpt-4.1-mini') }),\n  config: { shadowMode: true },\n})\nawait sonomem.migrate()\nawait sonomem.doctor()\n\n// per turn:\nconst scope = { userId }\nconst bundle = await sonomem.buildContext({ scope, query })   // fail-open, ≤300ms\nconst memoryBlock = formatContextForPrompt(bundle)            // → system prompt\n// ...generate with tools: createSonomemTools({ sonomem, scope, chatId })\nawait sonomem.ingestTurn({ scope, chatId, messages: fromUIMessages(uiMessages) })\nawait sonomem.runPendingJobs()                                // or startWorker()\n```\n\nSee the [skill](skills/sonomem/SKILL.md) for the full integration protocol\n(lifecycle calls, shadow-mode launch, debugging).\n\n## Development\n\n```sh\npnpm install\npnpm test        # 51 tests; integration suite needs local Postgres\n                 # (SONOMEM_TEST_DB=postgres://... to override, skips if absent)\npnpm typecheck\npnpm build       # tsup → dist/ (esm + d.ts, 5 entries)\n```\n\nNotes: `typescript` pinned to 5.x (`rollup-plugin-dts` can't drive the TS 7\nnative compiler yet). FTS uses the `simple` config so French/English/Kreyòl all\nwork unstemmed; semantic weight comes from the (multilingual) embedder.\n","readmeFilename":"README.md","_rev":"1-23bd4a8558a439027d9dd9aed9daf3dc"}