{"_id":"@alagappan17/memory-soda","_rev":"5-646186a7b3b13b0473e8a517eb25094b","name":"@alagappan17/memory-soda","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@alagappan17/memory-soda","version":"0.1.0","keywords":["ai","memory","agent","llm","sdk"],"license":"MIT","_id":"@alagappan17/memory-soda@0.1.0","maintainers":[{"name":"alagappan17","email":"alagappanforwork@gmail.com"}],"nx":{"targets":{"build":{"cache":true,"options":{"cwd":"packages/sdk","command":"tsup"},"outputs":["{projectRoot}/dist"],"executor":"nx:run-commands","dependsOn":["^build"]}}},"dist":{"shasum":"6609865c1e59b2b52dca60abf5d4c02902408851","tarball":"https://registry.npmjs.org/@alagappan17/memory-soda/-/memory-soda-0.1.0.tgz","fileCount":22,"integrity":"sha512-Fkl9XSWJQRPc7LFO/Z+GFhfteeVJvzqOACI18WXaTd94rd5vOZwRbVeW7yZ4H+QjrAKoxz3WHpzV+97ig/d9Lg==","signatures":[{"sig":"MEUCIBknlL4tvkVkgJkQiE1r+x/R4neAOm9+9MJXegu03kGMAiEAlnRfjoA8cO8Kcy5w+/KndQw2ZAYqG24N+OzUK8nQlYg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":162337},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js","require":"./dist/index.cjs","@memory-soda/source":"./src/index.ts"},"./package.json":"./package.json"},"gitHead":"3c262195becb15e42f4abd4b2caf0a4bcb88d132","_npmUser":{"name":"alagappan17","email":"alagappanforwork@gmail.com"},"deprecated":"Moved to @memory-soda/sdk","_npmVersion":"11.11.0","description":"Memory layer SDK for AI agents","directories":{},"sideEffects":false,"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0"},"_npmOperationalInternal":{"tmp":"tmp/memory-soda_0.1.0_1787389078301_0.4934038615545384","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@alagappan17/memory-soda","version":"0.1.1","keywords":["ai","memory","agent","llm","sdk"],"license":"MIT","_id":"@alagappan17/memory-soda@0.1.1","maintainers":[{"name":"alagappan17","email":"alagappanforwork@gmail.com"}],"nx":{"targets":{"build":{"cache":true,"options":{"cwd":"packages/sdk","command":"tsup"},"outputs":["{projectRoot}/dist"],"executor":"nx:run-commands","dependsOn":["^build"]}}},"dist":{"shasum":"0e58d56102d70437cfeb75923b269e31b99acc1b","tarball":"https://registry.npmjs.org/@alagappan17/memory-soda/-/memory-soda-0.1.1.tgz","fileCount":8,"integrity":"sha512-jATKrrV4+FDhqBq0guy/ckqevplhAZVZBJMAYCvYrdhHaZIXVRe2G6lqnDumrh9dvZ9eupFbwpPhdijodxfw3w==","signatures":[{"sig":"MEUCIBDgUGpmQ/HlZbaiaB2cK6Hymkibv7h19zyGL54wsHqKAiEA+GHiCRJeFfxY0s8ckfwqSwOgf5+w58hwdnHp8+ZYPm4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":130042},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js","require":"./dist/index.cjs","@memory-soda/source":"./src/index.ts"},"./package.json":"./package.json"},"gitHead":"3c262195becb15e42f4abd4b2caf0a4bcb88d132","scripts":{"prepublishOnly":"tsup"},"_npmUser":{"name":"alagappan17","email":"alagappanforwork@gmail.com"},"_npmVersion":"11.11.0","description":"Memory layer SDK for AI agents","directories":{},"sideEffects":false,"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0"},"_npmOperationalInternal":{"tmp":"tmp/memory-soda_0.1.1_1787389164385_0.8278837604254243","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Moved to @memory-soda/sdk"},"0.2.0":{"name":"@alagappan17/memory-soda","version":"0.2.0","keywords":["ai","memory","agent","llm","sdk","ai-sdk","vercel-ai","rag"],"license":"MIT","_id":"@alagappan17/memory-soda@0.2.0","maintainers":[{"name":"alagappan17","email":"alagappanforwork@gmail.com"}],"nx":{"targets":{"test":{"options":{"command":"node --test \"packages/sdk/src/**/*.test.ts\""},"executor":"nx:run-commands"},"build":{"cache":true,"options":{"cwd":"packages/sdk","command":"tsup"},"outputs":["{projectRoot}/dist"],"executor":"nx:run-commands","dependsOn":["^build"]}}},"dist":{"shasum":"14008e798061c314bf78b6178e8f8aacc918dddb","tarball":"https://registry.npmjs.org/@alagappan17/memory-soda/-/memory-soda-0.2.0.tgz","fileCount":16,"integrity":"sha512-34vYlsbSEL+1fJFo0UUinvUTv2qnQVg5K/9BPNf/gpcJ1aIWCwxuzPq72MfLq3IEfKeKrspP93g+N+PrnJDxrA==","signatures":[{"sig":"MEQCIFZ1Kbf9z7jUvgqo+ixEIcsR+jaUHjHGFxhQWts7ZUjgAiBHSDpp+B1OGSd3UGvhEeiWRvbznw/1irSL/p/NV6Q9Fw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":201900},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js","require":"./dist/index.cjs","@memory-soda/source":"./src/index.ts"},"./ai":{"types":"./dist/ai/index.d.ts","import":"./dist/ai/index.js","default":"./dist/ai/index.js","require":"./dist/ai/index.cjs","@memory-soda/source":"./src/ai/index.ts"},"./package.json":"./package.json"},"gitHead":"542fd41b0c618ecb87a6fd8d32090f1674338fd0","scripts":{"prepublishOnly":"tsup"},"_npmUser":{"name":"alagappan17","email":"alagappanforwork@gmail.com"},"_npmVersion":"11.11.0","description":"Memory for AI agents. Threads in, recalled context out.","directories":{},"sideEffects":false,"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0"},"_npmOperationalInternal":{"tmp":"tmp/memory-soda_0.2.0_1787811753049_0.8092205342575807","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Moved to @memory-soda/sdk"}},"time":{"created":"2026-08-22T08:57:58.128Z","modified":"2026-08-29T12:12:41.535Z","0.1.0":"2026-08-22T08:57:58.438Z","0.1.1":"2026-08-22T08:59:24.528Z","0.2.0":"2026-08-27T06:22:33.212Z"},"license":"MIT","keywords":["ai","memory","agent","llm","sdk","ai-sdk","vercel-ai","rag"],"description":"Memory for AI agents. Threads in, recalled context out.","maintainers":[{"name":"alagappan17","email":"alagappanforwork@gmail.com"}],"readme":"# @alagappan17/memory-soda\n\nMemory for AI agents. Your app has the conversation; this remembers what it\nrevealed and hands it back before the next model call.\n\nSelf-hosted, Postgres-backed, no dependencies.\n\n```bash\nnpm install @alagappan17/memory-soda\n```\n\nNode 18+ (uses global `fetch` and `AbortSignal.timeout`). ESM and CJS. Types\nbundled.\n\n---\n\n## Quick start\n\n```ts\nimport { MemorySoda } from '@alagappan17/memory-soda';\n\nconst memory = new MemorySoda({\n  baseUrl: 'http://localhost:3004',\n  apiKey: 'ms_…',\n});\n```\n\nOr set `MEMORY_SODA_BASE_URL` and `MEMORY_SODA_API_KEY` and call\n`new MemorySoda()` with no arguments.\n\n### The loop\n\nMemory is written by having the conversation and read by asking for it back.\nThere is no \"extract\" call — facts are pulled out in the background, a few\nseconds after a burst of messages.\n\n```ts\n// Once per conversation. `dataset` is whose memory this is; a user id works.\nconst { threadId, dataset } = await memory.createThread({ dataset: 'user_42' });\n\n// Every turn: write what was said…\nawait memory.addMessage(threadId, { role: 'user', content: input });\n\n// …and read what matters, as a prompt-ready block.\nconst { context } = await memory.recall({ dataset, query: input });\n\nconst reply = await yourModel({\n  system: context ? `What you know about this user:\\n${context}` : undefined,\n  prompt: input,\n});\n\nawait memory.addMessage(threadId, { role: 'assistant', content: reply });\n```\n\n`context` is text, ready to paste into a system prompt:\n\n```\nKnown facts about the user, most relevant first.\n\n# FACTS  (format: fact (valid: from – to))\n- user wants to shoot cinematic travel videos  (valid: 2026-07-05 – present)\n- user finds too bulky mirrorless cameras  (valid: 2026-07-05 – present)\n\n# ENTITIES\n- dji osmo pocket 3 (PRODUCT)\n```\n\n---\n\n## With the Vercel AI SDK\n\nWrap the model once and memory becomes invisible — it recalls before every call\nand records every turn, in `generateText`, `streamText`, and any agent loop\nbuilt on them.\n\n```ts\nimport { google } from '@ai-sdk/google';\nimport { generateText, wrapLanguageModel } from 'ai';\nimport { memoryMiddleware } from '@alagappan17/memory-soda/ai';\n\nconst model = wrapLanguageModel({\n  model: google('gemini-2.5-flash'),\n  middleware: memoryMiddleware({ memory, dataset, threadId }),\n});\n\nconst { text } = await generateText({ model, prompt: 'What should I cook?' });\n```\n\nTwo things it guarantees, because breaking either makes it worse than no memory:\na recall failure degrades to an unaugmented call rather than throwing, and the\nwrite-back never blocks the response.\n\nFor agents that should decide when to look something up:\n\n```ts\nimport { memoryTool } from '@alagappan17/memory-soda/ai';\n\nawait generateText({\n  model: google('gemini-2.5-flash'),\n  tools: { recallMemory: memoryTool({ memory, dataset }) },\n  prompt: 'Book me the usual table.',\n});\n```\n\nAnd `toMemoryMessages()` converts AI SDK messages — parts, tool calls, tool\nresults and all — into what memory stores, if you would rather write the\npersistence yourself.\n\n---\n\n## The surface\n\nEvery method is on the client itself. The names carry the tiering — what a chat\nturn calls is short, what you reach for occasionally is compound.\n\n```\nmemory\n│\n│  every turn\n├── addMessage · prepare · recall · prepareAndRecall\n│\n│  conversations\n├── createThread · getThread · updateThread · endThread\n├── addMessages · listMessages · compact\n│\n│  what was learned\n├── listFacts · deleteFact · listEntities\n├── listEpisodes · searchEpisodes · getEpisode\n│\n│  whole datasets\n├── exportDataset · forgetDataset\n│\n└── health\n```\n\n```ts\nawait memory.listFacts('user_42');            // what is known, most recent first\nawait memory.deleteFact('user_42', factId);  // retire something we got wrong\nawait memory.exportDataset('user_42');       // everything held, for a SAR\nawait memory.forgetDataset('user_42');       // erase it, for real\n```\n\nFacts are bi-temporal: `validAt`/`validUntil` is when something is true in the\nworld, `invalidAt` is when the system stopped believing it. That is what makes\npoint-in-time recall work:\n\n```ts\nawait memory.recall({ dataset, query, asOf: '2026-01-01' });\n```\n\n---\n\n## Configuration\n\n```ts\nnew MemorySoda({\n  baseUrl: 'https://memory.example.com',\n  apiKey: 'ms_…',\n  timeout: 30_000,     // per request, default 60s\n  maxRetries: 2,       // for 429, 5xx and network failures. Default 2.\n  onRequest: ({ method, path }) => log(method, path),\n  onResponse: ({ status, durationMs }) => log(status, durationMs),\n});\n```\n\nRetries use exponential backoff with jitter and never apply to a 4xx — a bad\nrequest will not get better by asking again.\n\n> **Server-side only.** An API key grants full read and write access to every\n> dataset in its project. Never ship it to a browser or a mobile app.\n\n---\n\n## Errors\n\n| Class | When |\n|---|---|\n| `AuthError` | 401 or 403 — missing, invalid, or revoked key |\n| `ApiError` | any other non-2xx; carries `status` and `body` |\n| `NetworkError` | the request never got a response |\n\nAll extend `MemorySodaError`.\n\n---\n\n## Running the server\n\nRequires PostgreSQL with the [pgvector](https://github.com/pgvector/pgvector)\nextension.\n\n```bash\nnpm create memory-soda@latest\n```\n\nOr from source:\n\n```bash\ngit clone https://github.com/alagappan17/memory-soda\ncd memory-soda\nnpm install\ncp .env.example .env    # set DATABASE_URL and GOOGLE_GENERATIVE_AI_API_KEY\nnpm run db:migrate\nnpm run dev             # API on :3004, dashboard on :3000\n```\n\nThe API prints an API key on first boot. Save it — it is not shown again.\n\nFull documentation: [github.com/alagappan17/memory-soda](https://github.com/alagappan17/memory-soda)\n\nMIT licensed.\n","readmeFilename":"README.md"}