{"_id":"@bernierllc/agent-conversation-store","_rev":"3-f1fe0b106422272d8047c35693337f8e","name":"@bernierllc/agent-conversation-store","dist-tags":{"latest":"0.2.1"},"versions":{"0.0.1":{"name":"@bernierllc/agent-conversation-store","version":"0.0.1","keywords":["oidc","trusted-publishing","setup"],"_id":"@bernierllc/agent-conversation-store@0.0.1","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"dist":{"shasum":"05598d6dd62daf99a05e2566852c94c9072100d7","tarball":"https://registry.npmjs.org/@bernierllc/agent-conversation-store/-/agent-conversation-store-0.0.1.tgz","fileCount":2,"integrity":"sha512-38WTYyRJ/+S+P1i8xFAsr0NSZPVN/xOrRyVw/Dl96GCXDh9TY/bUerJkPM+gwNowfQqTlnEyoKHIyF/El3X4Cg==","signatures":[{"sig":"MEUCIHn2ZlzsQxaM0jIzEqDDwvsnAItnWiY4F0JO4MsnaMoKAiEAmKTHJx6TPYfybxEFM9s05O2FKBaCrAFR9/z36RWXBb8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2107},"_npmUser":{"name":"mkbernier","email":"mkbernier@gmail.com"},"_npmVersion":"11.12.1","description":"OIDC trusted publishing setup package for @bernierllc/agent-conversation-store","directories":{},"_nodeVersion":"25.9.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/agent-conversation-store_0.0.1_1781312353097_0.5066401283533111","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@bernierllc/agent-conversation-store","version":"0.2.0","keywords":["ai","agent","conversation","persistence","storage","bernierllc"],"author":{"name":"Bernier LLC"},"license":"Bernier LLC","_id":"@bernierllc/agent-conversation-store@0.2.0","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"homepage":"https://github.com/bernierllc/tools#readme","bugs":{"url":"https://github.com/bernierllc/tools/issues"},"dist":{"shasum":"52acaaee9af29f92df07a2ba85407e6d5b96616e","tarball":"https://registry.npmjs.org/@bernierllc/agent-conversation-store/-/agent-conversation-store-0.2.0.tgz","fileCount":23,"integrity":"sha512-Lcp9IfzIIhgn52Pni4fY0U9pzbcoXLeyPXRkkTIwKBNbneNOJOjunuVSFGhDZKijT9DMQqLODPlDzGvMcs6nVg==","signatures":[{"sig":"MEUCIEzqMgAltVUmmzCvv7uZFsto9aUFvoDbwV7Uc9vtMx9gAiEAvCPaZiXXAAPYjo0XUy8u/CFETufoXLgCcIYveynCx1k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":53589},"main":"dist/index.js","_from":"file:bernierllc-agent-conversation-store-0.2.0.tgz","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"scripts":{"lint":"eslint src/**/*.ts","test":"jest","build":"tsc","clean":"rm -rf dist","prebuild":"npm run clean","test:run":"jest","test:watch":"jest --watch","test:coverage":"jest --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ec053321-53c6-49ea-8ac5-9a2c24e7759b"}},"_resolved":"/home/runner/work/tools/tools/packages/core/agent-conversation-store/bernierllc-agent-conversation-store-0.2.0.tgz","_integrity":"sha512-Lcp9IfzIIhgn52Pni4fY0U9pzbcoXLeyPXRkkTIwKBNbneNOJOjunuVSFGhDZKijT9DMQqLODPlDzGvMcs6nVg==","repository":{"url":"git+https://github.com/bernierllc/tools.git","type":"git","directory":"packages/core/agent-conversation-store"},"_npmVersion":"11.17.0","description":"Storage-agnostic persistence contract for agent conversations and messages, with bundled InMemoryConversationStore","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@bernierllc/logger":"1.7.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.0.0","rimraf":"^5.0.0","ts-jest":"^29.1.2","typescript":"^5.3.3","@types/jest":"^29.5.12","@types/node":"^20.11.19"},"_npmOperationalInternal":{"tmp":"tmp/agent-conversation-store_0.2.0_1781313840392_0.8801564865964926","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@bernierllc/agent-conversation-store","version":"0.2.1","description":"Storage-agnostic persistence contract for agent conversations and messages, with bundled InMemoryConversationStore","main":"dist/index.js","types":"dist/index.d.ts","keywords":["ai","agent","conversation","persistence","storage","bernierllc"],"author":{"name":"Bernier LLC"},"license":"Bernier LLC","repository":{"type":"git","url":"git+https://github.com/bernierllc/tools.git","directory":"packages/core/agent-conversation-store"},"dependencies":{"@bernierllc/logger":"1.7.1"},"devDependencies":{"@types/jest":"^29.5.12","@types/node":"^20.11.19","eslint":"^8.0.0","jest":"^29.7.0","rimraf":"^5.0.0","ts-jest":"^29.1.2","typescript":"^5.3.3"},"engines":{"node":">=18.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"scripts":{"build":"tsc","test":"jest","test:watch":"jest --watch","test:coverage":"jest --coverage","lint":"eslint src/**/*.ts","clean":"rm -rf dist","prebuild":"npm run clean","test:run":"jest"},"_id":"@bernierllc/agent-conversation-store@0.2.1","bugs":{"url":"https://github.com/bernierllc/tools/issues"},"homepage":"https://github.com/bernierllc/tools#readme","_integrity":"sha512-oTVexUmdNhvxHqTNPwt8UQCjJe9U5lUOfbpTzOF0OOuKnJrsrKFveJf6iwkLt7mp6nDXmuVJflrkdglHtbJrCQ==","_resolved":"/home/runner/work/tools/tools/packages/core/agent-conversation-store/bernierllc-agent-conversation-store-0.2.1.tgz","_from":"file:bernierllc-agent-conversation-store-0.2.1.tgz","_nodeVersion":"24.18.0","_npmVersion":"12.0.1","dist":{"integrity":"sha512-oTVexUmdNhvxHqTNPwt8UQCjJe9U5lUOfbpTzOF0OOuKnJrsrKFveJf6iwkLt7mp6nDXmuVJflrkdglHtbJrCQ==","shasum":"c0f50e1b0cb4572f28f4a77d0e68387ed26d22a9","tarball":"https://registry.npmjs.org/@bernierllc/agent-conversation-store/-/agent-conversation-store-0.2.1.tgz","fileCount":23,"unpackedSize":53589,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFqebWVT2a2+01N1n1dy8OwL+orNzQRKG3jRLUzEjOfeAiBO08Th7R2D51X8PRpgKHqYHGL+urclSmo1rJ7X76ppPg=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ec053321-53c6-49ea-8ac5-9a2c24e7759b"}},"directories":{},"maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/agent-conversation-store_0.2.1_1784015466607_0.7993490331328017"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-13T00:59:12.952Z","modified":"2026-07-14T07:51:06.914Z","0.0.1":"2026-06-13T00:59:13.276Z","0.2.0":"2026-06-13T01:24:00.536Z","0.2.1":"2026-07-14T07:51:06.758Z"},"bugs":{"url":"https://github.com/bernierllc/tools/issues"},"author":{"name":"Bernier LLC"},"license":"Bernier LLC","homepage":"https://github.com/bernierllc/tools#readme","keywords":["ai","agent","conversation","persistence","storage","bernierllc"],"repository":{"type":"git","url":"git+https://github.com/bernierllc/tools.git","directory":"packages/core/agent-conversation-store"},"description":"Storage-agnostic persistence contract for agent conversations and messages, with bundled InMemoryConversationStore","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"readme":"# @bernierllc/agent-conversation-store\n\nStorage-agnostic conversation and message persistence contract for LLM agent sessions, with a bundled `InMemoryConversationStore` reference implementation.\n\nDefines the `ConversationStore` interface that agent services depend on. Database adapters (Prisma, Supabase, Redis, etc.) are separate packages that satisfy this interface; they can verify compliance via the exported `testConversationStore()` helper.\n\n## Installation\n\n```bash\nnpm install @bernierllc/agent-conversation-store\n```\n\n## Usage\n\n```typescript\nimport {\n  InMemoryConversationStore,\n  ConversationStore,\n} from '@bernierllc/agent-conversation-store';\n\n// Development / testing — zero config\nconst store: ConversationStore = new InMemoryConversationStore();\n\n// Production — inject a database adapter:\n// import { PrismaConversationStore } from '@bernierllc/agent-conversation-store-prisma';\n// const store: ConversationStore = new PrismaConversationStore(prismaClient);\n```\n\n## Core Concepts\n\n### Context + Subject Pattern\n\nEvery conversation belongs to a **context** (the agent use-case, e.g. `'admin_assistant'`) and a **subjectId** (the entity it belongs to — orgId, userId, tenantId). Together these enable `findLatest()` to resume the most recent session for a given subject.\n\n```typescript\n// Create a conversation\nconst conversation = await store.createConversation({\n  context: 'admin_assistant',\n  subjectId: orgId,\n  metadata: { userId, orgName },\n});\n\n// Resume the latest session on subsequent visits\nconst existing = await store.findLatest('admin_assistant', orgId);\nif (existing) {\n  const history = await store.loadMessages(existing.id);\n  // pass history to LLM\n}\n```\n\n### Appending Messages\n\n```typescript\n// User turn\nawait store.appendMessages(conversation.id, [{\n  conversationId: conversation.id,\n  role: 'user',\n  content: 'Show me bookings for tomorrow',\n}]);\n\n// Assistant turn with tool calls\nawait store.appendMessages(conversation.id, [{\n  conversationId: conversation.id,\n  role: 'assistant',\n  content: 'Let me look that up for you.',\n  toolCalls: [{\n    toolName: 'getBookings',\n    toolCallId: 'tc-001',\n    state: 'success',\n    input: { date: '2026-06-13' },\n    output: { success: true, message: 'Found 12 bookings', data: [] },\n  }],\n}]);\n\n// Load full history for next LLM turn\nconst messages = await store.loadMessages(conversation.id);\n```\n\n### Rating a Conversation\n\n```typescript\nawait store.rate(conversation.id, 5, 'Very helpful!');\n```\n\n## API Reference\n\n### `ConversationStore` Interface\n\n| Method | Description |\n|--------|-------------|\n| `createConversation(params)` | Create a new conversation for context + subjectId |\n| `findLatest(context, subjectId)` | Most recent conversation for context + subject, or `null` |\n| `findById(id)` | Conversation by ID, or `null` |\n| `appendMessages(conversationId, messages)` | Append messages; throws `ConversationNotFoundError` if missing |\n| `loadMessages(conversationId)` | All messages in creation order |\n| `rate(conversationId, rating, comment?)` | Rate 1–5 stars with optional comment |\n\n### Types\n\n```typescript\ninterface Conversation {\n  id: string;\n  context: string;        // agent use-case identifier\n  subjectId: string;      // owner (orgId, userId, etc.)\n  createdAt: string;      // ISO 8601\n  updatedAt: string;      // ISO 8601\n  metadata?: Record<string, unknown>;\n  rating?: 1 | 2 | 3 | 4 | 5;\n  ratingComment?: string;\n}\n\ninterface Message {\n  id: string;\n  conversationId: string;\n  role: 'user' | 'assistant' | 'tool';\n  content: string;\n  toolCalls?: ToolCallRecord[];  // assistant messages with tool use\n  createdAt: string;             // ISO 8601\n}\n\ninterface ToolCallRecord {\n  toolName: string;\n  toolCallId: string;\n  state: 'pending' | 'success' | 'error';\n  input: unknown;\n  output: { success: boolean; message: string; data?: unknown; error?: string } | null;\n}\n```\n\n### Errors\n\n```typescript\nimport {\n  ConversationStoreError,     // base class\n  ConversationNotFoundError,  // conversation ID not found; thrown by appendMessages, rate\n  MessageAppendError,         // unexpected append failure; always includes Error.cause\n} from '@bernierllc/agent-conversation-store';\n\ntry {\n  await store.appendMessages('missing-id', [...]);\n} catch (err) {\n  if (err instanceof ConversationNotFoundError) {\n    // err.context.id contains the missing ID\n  }\n}\n```\n\n## Writing an Adapter\n\nImplement the `ConversationStore` interface and verify compliance with the exported test helper:\n\n```typescript\n// In your adapter package's test file:\nimport { testConversationStore } from '@bernierllc/agent-conversation-store';\nimport { PrismaConversationStore } from '../src';\n\ndescribe('PrismaConversationStore compliance', () => {\n  testConversationStore(() => new PrismaConversationStore(testPrismaClient));\n});\n```\n\n`testConversationStore(factory)` accepts a factory function that returns a **fresh** store instance (called before each test group to ensure isolation). It runs the full compliance suite: create, findLatest, findById, appendMessages, loadMessages, rate — including error cases.\n\n## Integration Pattern\n\n```\nagent-service.chat(input, authContext)\n  → findLatest(context, subjectId)         // check for existing session\n  → createConversation() if none\n  → loadMessages(conversationId)           // prior history for LLM\n  → LLM loop runs\n  → appendMessages() per turn              // persist messages + toolCalls\n  → rate() on user feedback\n```\n\n## Integration Documentation\n\n### Logger Integration\n\nThis package uses `@bernierllc/logger` for structured debug-level logging on `createConversation` and `appendMessages` operations. Logger output is silent unless a transport is configured. This is internal and requires no configuration by consumers.\n\n### NeverHub Integration\n\n**Status: not-applicable** — This package is a core storage contract utility. It does not register with NeverHub. Service and suite packages that consume this package (e.g. `@bernierllc/admin-agent-service`) handle NeverHub registration.\n\n### Graceful Degradation\n\n`InMemoryConversationStore` has no external dependencies and operates without any network or database connectivity. It is suitable for local development and integration testing without needing a running database.\n\n## License\n\nBernier LLC limited-use license. See [LICENSE](./LICENSE).\n","readmeFilename":"README.md"}